summaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/msm/disp/dpu1
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/msm/disp/dpu1')
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.c3
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c4
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c78
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c297
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h48
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c20
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.c29
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_hw_lm.c5
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h2
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_hw_pingpong.c62
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_hw_pingpong.h28
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.c16
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_hw_top.c18
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_hw_top.h7
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c54
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h5
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_mdss.c84
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c6
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_trace.h10
19 files changed, 533 insertions, 243 deletions
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.c
index 7c230f719ad3..b36919d95362 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.c
@@ -7,6 +7,7 @@
#include <linux/debugfs.h>
#include <linux/errno.h>
#include <linux/mutex.h>
+#include <linux/pm_opp.h>
#include <linux/sort.h>
#include <linux/clk.h>
#include <linux/bitmap.h>
@@ -218,7 +219,7 @@ static int _dpu_core_perf_set_core_clk_rate(struct dpu_kms *kms, u64 rate)
rate = core_clk->max_rate;
core_clk->rate = rate;
- return msm_dss_clk_set_rate(core_clk, 1);
+ return dev_pm_opp_set_rate(&kms->pdev->dev, core_clk->rate);
}
static u64 _dpu_core_perf_get_core_clk_rate(struct dpu_kms *kms)
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
index e15b42a780e0..f272a8d0f95b 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
@@ -389,14 +389,14 @@ static void dpu_crtc_frame_event_cb(void *data, u32 event)
spin_unlock_irqrestore(&dpu_crtc->spin_lock, flags);
if (!fevent) {
- DRM_ERROR("crtc%d event %d overflow\n", crtc->base.id, event);
+ DRM_ERROR_RATELIMITED("crtc%d event %d overflow\n", crtc->base.id, event);
return;
}
fevent->event = event;
fevent->crtc = crtc;
fevent->ts = ktime_get();
- kthread_queue_work(&priv->event_thread[crtc_id].worker, &fevent->work);
+ kthread_queue_work(priv->event_thread[crtc_id].worker, &fevent->work);
}
void dpu_crtc_complete_commit(struct drm_crtc *crtc)
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
index 0946a86b37b2..a97f6d2e5a08 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
@@ -208,6 +208,36 @@ struct dpu_encoder_virt {
#define to_dpu_encoder_virt(x) container_of(x, struct dpu_encoder_virt, base)
+static u32 dither_matrix[DITHER_MATRIX_SZ] = {
+ 15, 7, 13, 5, 3, 11, 1, 9, 12, 4, 14, 6, 0, 8, 2, 10
+};
+
+static void _dpu_encoder_setup_dither(struct dpu_hw_pingpong *hw_pp, unsigned bpc)
+{
+ struct dpu_hw_dither_cfg dither_cfg = { 0 };
+
+ if (!hw_pp->ops.setup_dither)
+ return;
+
+ switch (bpc) {
+ case 6:
+ dither_cfg.c0_bitdepth = 6;
+ dither_cfg.c1_bitdepth = 6;
+ dither_cfg.c2_bitdepth = 6;
+ dither_cfg.c3_bitdepth = 6;
+ dither_cfg.temporal_en = 0;
+ break;
+ default:
+ hw_pp->ops.setup_dither(hw_pp, NULL);
+ return;
+ }
+
+ memcpy(&dither_cfg.matrix, dither_matrix,
+ sizeof(u32) * DITHER_MATRIX_SZ);
+
+ hw_pp->ops.setup_dither(hw_pp, &dither_cfg);
+}
+
void dpu_encoder_helper_report_irq_timeout(struct dpu_encoder_phys *phys_enc,
enum dpu_intr_idx intr_idx)
{
@@ -499,23 +529,6 @@ void dpu_encoder_helper_split_config(
}
}
-static void _dpu_encoder_adjust_mode(struct drm_connector *connector,
- struct drm_display_mode *adj_mode)
-{
- struct drm_display_mode *cur_mode;
-
- if (!connector || !adj_mode)
- return;
-
- list_for_each_entry(cur_mode, &connector->modes, head) {
- if (cur_mode->vdisplay == adj_mode->vdisplay &&
- cur_mode->hdisplay == adj_mode->hdisplay &&
- drm_mode_vrefresh(cur_mode) == drm_mode_vrefresh(adj_mode)) {
- adj_mode->private_flags |= cur_mode->private_flags;
- }
- }
-}
-
static struct msm_display_topology dpu_encoder_get_topology(
struct dpu_encoder_virt *dpu_enc,
struct dpu_kms *dpu_kms,
@@ -589,15 +602,6 @@ static int dpu_encoder_virt_atomic_check(
global_state = dpu_kms_get_existing_global_state(dpu_kms);
trace_dpu_enc_atomic_check(DRMID(drm_enc));
- /*
- * display drivers may populate private fields of the drm display mode
- * structure while registering possible modes of a connector with DRM.
- * These private fields are not populated back while DRM invokes
- * the mode_set callbacks. This module retrieves and populates the
- * private fields of the given mode.
- */
- _dpu_encoder_adjust_mode(conn_state->connector, adj_mode);
-
/* perform atomic check on the first physical encoder (master) */
for (i = 0; i < dpu_enc->num_phys_encs; i++) {
struct dpu_encoder_phys *phys = dpu_enc->phys_encs[i];
@@ -630,8 +634,7 @@ static int dpu_encoder_virt_atomic_check(
}
}
- trace_dpu_enc_atomic_check_flags(DRMID(drm_enc), adj_mode->flags,
- adj_mode->private_flags);
+ trace_dpu_enc_atomic_check_flags(DRMID(drm_enc), adj_mode->flags);
return ret;
}
@@ -1085,7 +1088,7 @@ static void _dpu_encoder_virt_enable_helper(struct drm_encoder *drm_enc)
{
struct dpu_encoder_virt *dpu_enc = NULL;
struct msm_drm_private *priv;
- struct dpu_kms *dpu_kms;
+ int i;
if (!drm_enc || !drm_enc->dev) {
DPU_ERROR("invalid parameters\n");
@@ -1093,7 +1096,6 @@ static void _dpu_encoder_virt_enable_helper(struct drm_encoder *drm_enc)
}
priv = drm_enc->dev->dev_private;
- dpu_kms = to_dpu_kms(priv->kms);
dpu_enc = to_dpu_encoder_virt(drm_enc);
if (!dpu_enc || !dpu_enc->cur_master) {
@@ -1101,13 +1103,17 @@ static void _dpu_encoder_virt_enable_helper(struct drm_encoder *drm_enc)
return;
}
- if (dpu_enc->cur_master->hw_mdptop &&
- dpu_enc->cur_master->hw_mdptop->ops.reset_ubwc)
- dpu_enc->cur_master->hw_mdptop->ops.reset_ubwc(
- dpu_enc->cur_master->hw_mdptop,
- dpu_kms->catalog);
-
_dpu_encoder_update_vsync_source(dpu_enc, &dpu_enc->disp_info);
+
+ if (dpu_enc->disp_info.intf_type == DRM_MODE_ENCODER_DSI &&
+ !WARN_ON(dpu_enc->num_phys_encs == 0)) {
+ unsigned bpc = dpu_enc->phys_encs[0]->connector->display_info.bpc;
+ for (i = 0; i < MAX_CHANNELS_PER_ENC; i++) {
+ if (!dpu_enc->hw_pp[i])
+ continue;
+ _dpu_encoder_setup_dither(dpu_enc->hw_pp[i], bpc);
+ }
+ }
}
void dpu_encoder_virt_runtime_resume(struct drm_encoder *drm_enc)
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c
index 29d4fde3172b..97d122eee96d 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c
@@ -43,6 +43,10 @@
#define DSPP_SC7180_MASK BIT(DPU_DSPP_PCC)
+#define INTF_SDM845_MASK (0)
+
+#define INTF_SC7180_MASK BIT(DPU_INTF_INPUT_CTRL) | BIT(DPU_INTF_TE)
+
#define DEFAULT_PIXEL_RAM_SIZE (50 * 1024)
#define DEFAULT_DPU_LINE_WIDTH 2048
#define DEFAULT_DPU_OUTPUT_LINE_WIDTH 2560
@@ -70,6 +74,10 @@ static const struct dpu_caps sdm845_dpu_caps = {
.has_dim_layer = true,
.has_idle_pc = true,
.has_3d_merge = true,
+ .max_linewidth = DEFAULT_DPU_OUTPUT_LINE_WIDTH,
+ .pixel_ram_size = DEFAULT_PIXEL_RAM_SIZE,
+ .max_hdeci_exp = MAX_HORZ_DECIMATION,
+ .max_vdeci_exp = MAX_VERT_DECIMATION,
};
static const struct dpu_caps sc7180_dpu_caps = {
@@ -80,6 +88,39 @@ static const struct dpu_caps sc7180_dpu_caps = {
.ubwc_version = DPU_HW_UBWC_VER_20,
.has_dim_layer = true,
.has_idle_pc = true,
+ .max_linewidth = DEFAULT_DPU_OUTPUT_LINE_WIDTH,
+ .pixel_ram_size = DEFAULT_PIXEL_RAM_SIZE,
+};
+
+static const struct dpu_caps sm8150_dpu_caps = {
+ .max_mixer_width = DEFAULT_DPU_OUTPUT_LINE_WIDTH,
+ .max_mixer_blendstages = 0xb,
+ .qseed_type = DPU_SSPP_SCALER_QSEED3,
+ .smart_dma_rev = DPU_SSPP_SMART_DMA_V2, /* TODO: v2.5 */
+ .ubwc_version = DPU_HW_UBWC_VER_30,
+ .has_src_split = true,
+ .has_dim_layer = true,
+ .has_idle_pc = true,
+ .has_3d_merge = true,
+ .max_linewidth = 4096,
+ .pixel_ram_size = DEFAULT_PIXEL_RAM_SIZE,
+ .max_hdeci_exp = MAX_HORZ_DECIMATION,
+ .max_vdeci_exp = MAX_VERT_DECIMATION,
+};
+
+static const struct dpu_caps sm8250_dpu_caps = {
+ .max_mixer_width = DEFAULT_DPU_OUTPUT_LINE_WIDTH,
+ .max_mixer_blendstages = 0xb,
+ .max_linewidth = 4096,
+ .qseed_type = DPU_SSPP_SCALER_QSEED3, /* TODO: qseed3 lite */
+ .smart_dma_rev = DPU_SSPP_SMART_DMA_V2, /* TODO: v2.5 */
+ .ubwc_version = DPU_HW_UBWC_VER_40,
+ .has_src_split = true,
+ .has_dim_layer = true,
+ .has_idle_pc = true,
+ .has_3d_merge = true,
+ .max_linewidth = 4096,
+ .pixel_ram_size = DEFAULT_PIXEL_RAM_SIZE,
};
static const struct dpu_mdp_cfg sdm845_mdp[] = {
@@ -117,10 +158,37 @@ static const struct dpu_mdp_cfg sc7180_mdp[] = {
.reg_off = 0x2AC, .bit_off = 0},
.clk_ctrls[DPU_CLK_CTRL_DMA0] = {
.reg_off = 0x2AC, .bit_off = 8},
- .clk_ctrls[DPU_CLK_CTRL_DMA1] = {
+ .clk_ctrls[DPU_CLK_CTRL_CURSOR0] = {
.reg_off = 0x2B4, .bit_off = 8},
+ .clk_ctrls[DPU_CLK_CTRL_CURSOR1] = {
+ .reg_off = 0x2C4, .bit_off = 8},
+ },
+};
+
+static const struct dpu_mdp_cfg sm8250_mdp[] = {
+ {
+ .name = "top_0", .id = MDP_TOP,
+ .base = 0x0, .len = 0x45C,
+ .features = 0,
+ .highest_bank_bit = 0x3, /* TODO: 2 for LP_DDR4 */
+ .clk_ctrls[DPU_CLK_CTRL_VIG0] = {
+ .reg_off = 0x2AC, .bit_off = 0},
+ .clk_ctrls[DPU_CLK_CTRL_VIG1] = {
+ .reg_off = 0x2B4, .bit_off = 0},
+ .clk_ctrls[DPU_CLK_CTRL_VIG2] = {
+ .reg_off = 0x2BC, .bit_off = 0},
+ .clk_ctrls[DPU_CLK_CTRL_VIG3] = {
+ .reg_off = 0x2C4, .bit_off = 0},
+ .clk_ctrls[DPU_CLK_CTRL_DMA0] = {
+ .reg_off = 0x2AC, .bit_off = 8},
+ .clk_ctrls[DPU_CLK_CTRL_DMA1] = {
+ .reg_off = 0x2B4, .bit_off = 8},
.clk_ctrls[DPU_CLK_CTRL_CURSOR0] = {
- .reg_off = 0x2BC, .bit_off = 8},
+ .reg_off = 0x2BC, .bit_off = 8},
+ .clk_ctrls[DPU_CLK_CTRL_CURSOR1] = {
+ .reg_off = 0x2C4, .bit_off = 8},
+ .clk_ctrls[DPU_CLK_CTRL_REG_DMA] = {
+ .reg_off = 0x2BC, .bit_off = 20},
},
};
@@ -173,21 +241,47 @@ static const struct dpu_ctl_cfg sc7180_ctl[] = {
},
};
+static const struct dpu_ctl_cfg sm8150_ctl[] = {
+ {
+ .name = "ctl_0", .id = CTL_0,
+ .base = 0x1000, .len = 0x1e0,
+ .features = BIT(DPU_CTL_ACTIVE_CFG) | BIT(DPU_CTL_SPLIT_DISPLAY)
+ },
+ {
+ .name = "ctl_1", .id = CTL_1,
+ .base = 0x1200, .len = 0x1e0,
+ .features = BIT(DPU_CTL_ACTIVE_CFG) | BIT(DPU_CTL_SPLIT_DISPLAY)
+ },
+ {
+ .name = "ctl_2", .id = CTL_2,
+ .base = 0x1400, .len = 0x1e0,
+ .features = BIT(DPU_CTL_ACTIVE_CFG)
+ },
+ {
+ .name = "ctl_3", .id = CTL_3,
+ .base = 0x1600, .len = 0x1e0,
+ .features = BIT(DPU_CTL_ACTIVE_CFG)
+ },
+ {
+ .name = "ctl_4", .id = CTL_4,
+ .base = 0x1800, .len = 0x1e0,
+ .features = BIT(DPU_CTL_ACTIVE_CFG)
+ },
+ {
+ .name = "ctl_5", .id = CTL_5,
+ .base = 0x1a00, .len = 0x1e0,
+ .features = BIT(DPU_CTL_ACTIVE_CFG)
+ },
+};
+
/*************************************************************
* SSPP sub blocks config
*************************************************************/
/* SSPP common configuration */
-static const struct dpu_sspp_blks_common sdm845_sspp_common = {
- .maxlinewidth = DEFAULT_DPU_OUTPUT_LINE_WIDTH,
- .pixel_ram_size = DEFAULT_PIXEL_RAM_SIZE,
- .maxhdeciexp = MAX_HORZ_DECIMATION,
- .maxvdeciexp = MAX_VERT_DECIMATION,
-};
#define _VIG_SBLK(num, sdma_pri, qseed_ver) \
{ \
- .common = &sdm845_sspp_common, \
.maxdwnscale = MAX_DOWNSCALE_RATIO, \
.maxupscale = MAX_UPSCALE_RATIO, \
.smart_dma_priority = sdma_pri, \
@@ -207,7 +301,6 @@ static const struct dpu_sspp_blks_common sdm845_sspp_common = {
#define _DMA_SBLK(num, sdma_pri) \
{ \
- .common = &sdm845_sspp_common, \
.maxdwnscale = SSPP_UNITY_SCALE, \
.maxupscale = SSPP_UNITY_SCALE, \
.smart_dma_priority = sdma_pri, \
@@ -272,10 +365,10 @@ static const struct dpu_sspp_cfg sc7180_sspp[] = {
sc7180_vig_sblk_0, 0, SSPP_TYPE_VIG, DPU_CLK_CTRL_VIG0),
SSPP_BLK("sspp_8", SSPP_DMA0, 0x24000, DMA_SDM845_MASK,
sdm845_dma_sblk_0, 1, SSPP_TYPE_DMA, DPU_CLK_CTRL_DMA0),
- SSPP_BLK("sspp_9", SSPP_DMA1, 0x26000, DMA_SDM845_MASK,
- sdm845_dma_sblk_1, 5, SSPP_TYPE_DMA, DPU_CLK_CTRL_DMA1),
+ SSPP_BLK("sspp_9", SSPP_DMA1, 0x26000, DMA_CURSOR_SDM845_MASK,
+ sdm845_dma_sblk_1, 5, SSPP_TYPE_DMA, DPU_CLK_CTRL_CURSOR0),
SSPP_BLK("sspp_10", SSPP_DMA2, 0x28000, DMA_CURSOR_SDM845_MASK,
- sdm845_dma_sblk_2, 9, SSPP_TYPE_DMA, DPU_CLK_CTRL_CURSOR0),
+ sdm845_dma_sblk_2, 9, SSPP_TYPE_DMA, DPU_CLK_CTRL_CURSOR1),
};
/*************************************************************
@@ -336,6 +429,23 @@ static const struct dpu_lm_cfg sc7180_lm[] = {
&sc7180_lm_sblk, PINGPONG_1, LM_0, 0),
};
+/* SM8150 */
+
+static const struct dpu_lm_cfg sm8150_lm[] = {
+ LM_BLK("lm_0", LM_0, 0x44000, MIXER_SDM845_MASK,
+ &sdm845_lm_sblk, PINGPONG_0, LM_1, 0),
+ LM_BLK("lm_1", LM_1, 0x45000, MIXER_SDM845_MASK,
+ &sdm845_lm_sblk, PINGPONG_1, LM_0, 0),
+ LM_BLK("lm_2", LM_2, 0x46000, MIXER_SDM845_MASK,
+ &sdm845_lm_sblk, PINGPONG_2, LM_3, 0),
+ LM_BLK("lm_3", LM_3, 0x47000, MIXER_SDM845_MASK,
+ &sdm845_lm_sblk, PINGPONG_3, LM_2, 0),
+ LM_BLK("lm_4", LM_4, 0x48000, MIXER_SDM845_MASK,
+ &sdm845_lm_sblk, PINGPONG_4, LM_5, 0),
+ LM_BLK("lm_5", LM_5, 0x49000, MIXER_SDM845_MASK,
+ &sdm845_lm_sblk, PINGPONG_5, LM_4, 0),
+};
+
/*************************************************************
* DSPP sub blocks config
*************************************************************/
@@ -355,6 +465,7 @@ static const struct dpu_dspp_sub_blks sc7180_dspp_sblk = {
static const struct dpu_dspp_cfg sc7180_dspp[] = {
DSPP_BLK("dspp_0", DSPP_0, 0x54000),
};
+
/*************************************************************
* PINGPONG sub blocks config
*************************************************************/
@@ -397,29 +508,45 @@ static struct dpu_pingpong_cfg sc7180_pp[] = {
PP_BLK_TE("pingpong_1", PINGPONG_1, 0x70800),
};
+static const struct dpu_pingpong_cfg sm8150_pp[] = {
+ PP_BLK_TE("pingpong_0", PINGPONG_0, 0x70000),
+ PP_BLK_TE("pingpong_1", PINGPONG_1, 0x70800),
+ PP_BLK("pingpong_2", PINGPONG_2, 0x71000),
+ PP_BLK("pingpong_3", PINGPONG_3, 0x71800),
+ PP_BLK("pingpong_4", PINGPONG_4, 0x72000),
+ PP_BLK("pingpong_5", PINGPONG_5, 0x72800),
+};
+
/*************************************************************
* INTF sub blocks config
*************************************************************/
-#define INTF_BLK(_name, _id, _base, _type, _ctrl_id) \
+#define INTF_BLK(_name, _id, _base, _type, _ctrl_id, _features) \
{\
.name = _name, .id = _id, \
.base = _base, .len = 0x280, \
- .features = BIT(DPU_CTL_ACTIVE_CFG), \
+ .features = _features, \
.type = _type, \
.controller_id = _ctrl_id, \
.prog_fetch_lines_worst_case = 24 \
}
static const struct dpu_intf_cfg sdm845_intf[] = {
- INTF_BLK("intf_0", INTF_0, 0x6A000, INTF_DP, 0),
- INTF_BLK("intf_1", INTF_1, 0x6A800, INTF_DSI, 0),
- INTF_BLK("intf_2", INTF_2, 0x6B000, INTF_DSI, 1),
- INTF_BLK("intf_3", INTF_3, 0x6B800, INTF_DP, 1),
+ INTF_BLK("intf_0", INTF_0, 0x6A000, INTF_DP, 0, INTF_SDM845_MASK),
+ INTF_BLK("intf_1", INTF_1, 0x6A800, INTF_DSI, 0, INTF_SDM845_MASK),
+ INTF_BLK("intf_2", INTF_2, 0x6B000, INTF_DSI, 1, INTF_SDM845_MASK),
+ INTF_BLK("intf_3", INTF_3, 0x6B800, INTF_DP, 1, INTF_SDM845_MASK),
};
static const struct dpu_intf_cfg sc7180_intf[] = {
- INTF_BLK("intf_0", INTF_0, 0x6A000, INTF_DP, 0),
- INTF_BLK("intf_1", INTF_1, 0x6A800, INTF_DSI, 0),
+ INTF_BLK("intf_0", INTF_0, 0x6A000, INTF_DP, 0, INTF_SC7180_MASK),
+ INTF_BLK("intf_1", INTF_1, 0x6A800, INTF_DSI, 0, INTF_SC7180_MASK),
+};
+
+static const struct dpu_intf_cfg sm8150_intf[] = {
+ INTF_BLK("intf_0", INTF_0, 0x6A000, INTF_DP, 0, INTF_SC7180_MASK),
+ INTF_BLK("intf_1", INTF_1, 0x6A800, INTF_DSI, 0, INTF_SC7180_MASK),
+ INTF_BLK("intf_2", INTF_2, 0x6B000, INTF_DSI, 1, INTF_SC7180_MASK),
+ INTF_BLK("intf_3", INTF_3, 0x6B800, INTF_DP, 1, INTF_SC7180_MASK),
};
/*************************************************************
@@ -452,6 +579,18 @@ static const struct dpu_reg_dma_cfg sdm845_regdma = {
.base = 0x0, .version = 0x1, .trigger_sel_off = 0x119c
};
+static const struct dpu_reg_dma_cfg sm8150_regdma = {
+ .base = 0x0, .version = 0x00010001, .trigger_sel_off = 0x119c
+};
+
+static const struct dpu_reg_dma_cfg sm8250_regdma = {
+ .base = 0x0,
+ .version = 0x00010002,
+ .trigger_sel_off = 0x119c,
+ .xin_id = 7,
+ .clk_ctrl = DPU_CLK_CTRL_REG_DMA,
+};
+
/*************************************************************
* PERF data config
*************************************************************/
@@ -476,6 +615,10 @@ static const struct dpu_qos_lut_entry sc7180_qos_linear[] = {
{.fl = 0, .lut = 0x0011222222335777},
};
+static const struct dpu_qos_lut_entry sm8150_qos_linear[] = {
+ {.fl = 0, .lut = 0x0011222222223357 },
+};
+
static const struct dpu_qos_lut_entry sdm845_qos_macrotile[] = {
{.fl = 10, .lut = 0x344556677},
{.fl = 11, .lut = 0x3344556677},
@@ -560,6 +703,56 @@ static const struct dpu_perf_cfg sc7180_perf_data = {
},
};
+static const struct dpu_perf_cfg sm8150_perf_data = {
+ .max_bw_low = 12800000,
+ .max_bw_high = 12800000,
+ .min_core_ib = 2400000,
+ .min_llcc_ib = 800000,
+ .min_dram_ib = 800000,
+ .danger_lut_tbl = {0xf, 0xffff, 0x0},
+ .qos_lut_tbl = {
+ {.nentry = ARRAY_SIZE(sm8150_qos_linear),
+ .entries = sm8150_qos_linear
+ },
+ {.nentry = ARRAY_SIZE(sc7180_qos_macrotile),
+ .entries = sc7180_qos_macrotile
+ },
+ {.nentry = ARRAY_SIZE(sc7180_qos_nrt),
+ .entries = sc7180_qos_nrt
+ },
+ /* TODO: macrotile-qseed is different from macrotile */
+ },
+ .cdp_cfg = {
+ {.rd_enable = 1, .wr_enable = 1},
+ {.rd_enable = 1, .wr_enable = 0}
+ },
+};
+
+static const struct dpu_perf_cfg sm8250_perf_data = {
+ .max_bw_low = 13700000,
+ .max_bw_high = 16600000,
+ .min_core_ib = 4800000,
+ .min_llcc_ib = 0,
+ .min_dram_ib = 800000,
+ .danger_lut_tbl = {0xf, 0xffff, 0x0},
+ .qos_lut_tbl = {
+ {.nentry = ARRAY_SIZE(sc7180_qos_linear),
+ .entries = sc7180_qos_linear
+ },
+ {.nentry = ARRAY_SIZE(sc7180_qos_macrotile),
+ .entries = sc7180_qos_macrotile
+ },
+ {.nentry = ARRAY_SIZE(sc7180_qos_nrt),
+ .entries = sc7180_qos_nrt
+ },
+ /* TODO: macrotile-qseed is different from macrotile */
+ },
+ .cdp_cfg = {
+ {.rd_enable = 1, .wr_enable = 1},
+ {.rd_enable = 1, .wr_enable = 0}
+ },
+};
+
/*************************************************************
* Hardware catalog init
*************************************************************/
@@ -624,9 +817,71 @@ static void sc7180_cfg_init(struct dpu_mdss_cfg *dpu_cfg)
};
}
+/*
+ * sm8150_cfg_init(): populate sm8150 dpu sub-blocks reg offsets
+ * and instance counts.
+ */
+static void sm8150_cfg_init(struct dpu_mdss_cfg *dpu_cfg)
+{
+ *dpu_cfg = (struct dpu_mdss_cfg){
+ .caps = &sm8150_dpu_caps,
+ .mdp_count = ARRAY_SIZE(sdm845_mdp),
+ .mdp = sdm845_mdp,
+ .ctl_count = ARRAY_SIZE(sm8150_ctl),
+ .ctl = sm8150_ctl,
+ .sspp_count = ARRAY_SIZE(sdm845_sspp),
+ .sspp = sdm845_sspp,
+ .mixer_count = ARRAY_SIZE(sm8150_lm),
+ .mixer = sm8150_lm,
+ .pingpong_count = ARRAY_SIZE(sm8150_pp),
+ .pingpong = sm8150_pp,
+ .intf_count = ARRAY_SIZE(sm8150_intf),
+ .intf = sm8150_intf,
+ .vbif_count = ARRAY_SIZE(sdm845_vbif),
+ .vbif = sdm845_vbif,
+ .reg_dma_count = 1,
+ .dma_cfg = sm8150_regdma,
+ .perf = sm8150_perf_data,
+ .mdss_irqs = 0x3ff,
+ };
+}
+
+/*
+ * sm8250_cfg_init(): populate sm8250 dpu sub-blocks reg offsets
+ * and instance counts.
+ */
+static void sm8250_cfg_init(struct dpu_mdss_cfg *dpu_cfg)
+{
+ *dpu_cfg = (struct dpu_mdss_cfg){
+ .caps = &sm8250_dpu_caps,
+ .mdp_count = ARRAY_SIZE(sm8250_mdp),
+ .mdp = sm8250_mdp,
+ .ctl_count = ARRAY_SIZE(sm8150_ctl),
+ .ctl = sm8150_ctl,
+ /* TODO: sspp qseed version differs from 845 */
+ .sspp_count = ARRAY_SIZE(sdm845_sspp),
+ .sspp = sdm845_sspp,
+ .mixer_count = ARRAY_SIZE(sm8150_lm),
+ .mixer = sm8150_lm,
+ .pingpong_count = ARRAY_SIZE(sm8150_pp),
+ .pingpong = sm8150_pp,
+ .intf_count = ARRAY_SIZE(sm8150_intf),
+ .intf = sm8150_intf,
+ .vbif_count = ARRAY_SIZE(sdm845_vbif),
+ .vbif = sdm845_vbif,
+ .reg_dma_count = 1,
+ .dma_cfg = sm8250_regdma,
+ .perf = sm8250_perf_data,
+ .mdss_irqs = 0xff,
+ };
+}
+
static const struct dpu_mdss_hw_cfg_handler cfg_handler[] = {
{ .hw_rev = DPU_HW_VER_400, .cfg_init = sdm845_cfg_init},
{ .hw_rev = DPU_HW_VER_401, .cfg_init = sdm845_cfg_init},
+ { .hw_rev = DPU_HW_VER_500, .cfg_init = sm8150_cfg_init},
+ { .hw_rev = DPU_HW_VER_501, .cfg_init = sm8150_cfg_init},
+ { .hw_rev = DPU_HW_VER_600, .cfg_init = sm8250_cfg_init},
{ .hw_rev = DPU_HW_VER_620, .cfg_init = sc7180_cfg_init},
};
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h
index f7de43838c69..1b7a9213a756 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h
@@ -37,7 +37,9 @@
#define DPU_HW_VER_400 DPU_HW_VER(4, 0, 0) /* sdm845 v1.0 */
#define DPU_HW_VER_401 DPU_HW_VER(4, 0, 1) /* sdm845 v2.0 */
#define DPU_HW_VER_410 DPU_HW_VER(4, 1, 0) /* sdm670 v1.0 */
-#define DPU_HW_VER_500 DPU_HW_VER(5, 0, 0) /* sdm855 v1.0 */
+#define DPU_HW_VER_500 DPU_HW_VER(5, 0, 0) /* sm8150 v1.0 */
+#define DPU_HW_VER_501 DPU_HW_VER(5, 0, 1) /* sm8150 v2.0 */
+#define DPU_HW_VER_600 DPU_HW_VER(6, 0, 0) /* sm8250 */
#define DPU_HW_VER_620 DPU_HW_VER(6, 2, 0) /* sc7180 v1.0 */
@@ -65,10 +67,9 @@ enum {
DPU_HW_UBWC_VER_10 = 0x100,
DPU_HW_UBWC_VER_20 = 0x200,
DPU_HW_UBWC_VER_30 = 0x300,
+ DPU_HW_UBWC_VER_40 = 0x400,
};
-#define IS_UBWC_20_SUPPORTED(rev) ((rev) >= DPU_HW_UBWC_VER_20)
-
/**
* MDP TOP BLOCK features
* @DPU_MDP_PANIC_PER_PIPE Panic configuration needs to be be done per pipe
@@ -186,6 +187,19 @@ enum {
};
/**
+ * INTF sub-blocks
+ * @DPU_INTF_INPUT_CTRL Supports the setting of pp block from which
+ * pixel data arrives to this INTF
+ * @DPU_INTF_TE INTF block has TE configuration support
+ * @DPU_INTF_MAX
+ */
+enum {
+ DPU_INTF_INPUT_CTRL = 0x1,
+ DPU_INTF_TE,
+ DPU_INTF_MAX
+};
+
+/**
* VBIF sub-blocks and features
* @DPU_VBIF_QOS_OTLIM VBIF supports OT Limit
* @DPU_VBIF_QOS_REMAP VBIF supports QoS priority remap
@@ -300,6 +314,10 @@ struct dpu_qos_lut_tbl {
* @has_dim_layer dim layer feature status
* @has_idle_pc indicate if idle power collapse feature is supported
* @has_3d_merge indicate if 3D merge is supported
+ * @max_linewidth max linewidth for sspp
+ * @pixel_ram_size size of latency hiding and de-tiling buffer in bytes
+ * @max_hdeci_exp max horizontal decimation supported (max is 2^value)
+ * @max_vdeci_exp max vertical decimation supported (max is 2^value)
*/
struct dpu_caps {
u32 max_mixer_width;
@@ -311,22 +329,11 @@ struct dpu_caps {
bool has_dim_layer;
bool has_idle_pc;
bool has_3d_merge;
-};
-
-/**
- * struct dpu_sspp_blks_common : SSPP sub-blocks common configuration
- * @maxwidth: max pixelwidth supported by this pipe
- * @pixel_ram_size: size of latency hiding and de-tiling buffer in bytes
- * @maxhdeciexp: max horizontal decimation supported by this pipe
- * (max is 2^value)
- * @maxvdeciexp: max vertical decimation supported by this pipe
- * (max is 2^value)
- */
-struct dpu_sspp_blks_common {
- u32 maxlinewidth;
+ /* SSPP limits */
+ u32 max_linewidth;
u32 pixel_ram_size;
- u32 maxhdeciexp;
- u32 maxvdeciexp;
+ u32 max_hdeci_exp;
+ u32 max_vdeci_exp;
};
/**
@@ -352,7 +359,6 @@ struct dpu_sspp_blks_common {
* @virt_num_formats: Number of supported formats for virtual planes
*/
struct dpu_sspp_sub_blks {
- const struct dpu_sspp_blks_common *common;
u32 creq_vblank;
u32 danger_vblank;
u32 maxdwnscale;
@@ -423,6 +429,7 @@ enum dpu_clk_ctrl_type {
DPU_CLK_CTRL_CURSOR0,
DPU_CLK_CTRL_CURSOR1,
DPU_CLK_CTRL_INLINE_ROT0_SSPP,
+ DPU_CLK_CTRL_REG_DMA,
DPU_CLK_CTRL_MAX,
};
@@ -447,7 +454,6 @@ struct dpu_clk_ctrl_reg {
struct dpu_mdp_cfg {
DPU_HW_BLK_INFO;
u32 highest_bank_bit;
- u32 ubwc_static;
u32 ubwc_swizzle;
struct dpu_clk_ctrl_reg clk_ctrls[DPU_CLK_CTRL_MAX];
};
@@ -607,6 +613,8 @@ struct dpu_reg_dma_cfg {
DPU_HW_BLK_INFO;
u32 version;
u32 trigger_sel_off;
+ u32 xin_id;
+ enum dpu_clk_ctrl_type clk_ctrl;
};
/**
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c
index 613ae8f0cfcd..758c355b4fd8 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c
@@ -245,30 +245,14 @@ static int dpu_hw_ctl_get_bitmask_intf(struct dpu_hw_ctl *ctx,
static int dpu_hw_ctl_get_bitmask_intf_v1(struct dpu_hw_ctl *ctx,
u32 *flushbits, enum dpu_intf intf)
{
- switch (intf) {
- case INTF_0:
- case INTF_1:
- *flushbits |= BIT(31);
- break;
- default:
- return 0;
- }
+ *flushbits |= BIT(31);
return 0;
}
static int dpu_hw_ctl_active_get_bitmask_intf(struct dpu_hw_ctl *ctx,
u32 *flushbits, enum dpu_intf intf)
{
- switch (intf) {
- case INTF_0:
- *flushbits |= BIT(0);
- break;
- case INTF_1:
- *flushbits |= BIT(1);
- break;
- default:
- return 0;
- }
+ *flushbits |= BIT(intf - INTF_0);
return 0;
}
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.c
index efe9a5719c6b..6f0f54588124 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.c
@@ -107,11 +107,6 @@ static void dpu_hw_intf_setup_timing_engine(struct dpu_hw_intf *ctx,
display_v_end = ((vsync_period - p->v_front_porch) * hsync_period) +
p->hsync_skew - 1;
- if (ctx->cap->type == INTF_EDP || ctx->cap->type == INTF_DP) {
- display_v_start += p->hsync_pulse_width + p->h_back_porch;
- display_v_end -= p->h_front_porch;
- }
-
hsync_start_x = p->h_back_porch + p->hsync_pulse_width;
hsync_end_x = hsync_period - p->h_front_porch - 1;
@@ -144,10 +139,25 @@ static void dpu_hw_intf_setup_timing_engine(struct dpu_hw_intf *ctx,
hsync_ctl = (hsync_period << 16) | p->hsync_pulse_width;
display_hctl = (hsync_end_x << 16) | hsync_start_x;
+ if (ctx->cap->type == INTF_EDP || ctx->cap->type == INTF_DP) {
+ active_h_start = hsync_start_x;
+ active_h_end = active_h_start + p->xres - 1;
+ active_v_start = display_v_start;
+ active_v_end = active_v_start + (p->yres * hsync_period) - 1;
+
+ display_v_start += p->hsync_pulse_width + p->h_back_porch;
+
+ active_hctl = (active_h_end << 16) | active_h_start;
+ display_hctl = active_hctl;
+ }
+
den_polarity = 0;
if (ctx->cap->type == INTF_HDMI) {
hsync_polarity = p->yres >= 720 ? 0 : 1;
vsync_polarity = p->yres >= 720 ? 0 : 1;
+ } else if (ctx->cap->type == INTF_DP) {
+ hsync_polarity = p->hsync_polarity;
+ vsync_polarity = p->vsync_polarity;
} else {
hsync_polarity = 0;
vsync_polarity = 0;
@@ -225,14 +235,9 @@ static void dpu_hw_intf_bind_pingpong_blk(
bool enable,
const enum dpu_pingpong pp)
{
- struct dpu_hw_blk_reg_map *c;
+ struct dpu_hw_blk_reg_map *c = &intf->hw;
u32 mux_cfg;
- if (!intf)
- return;
-
- c = &intf->hw;
-
mux_cfg = DPU_REG_READ(c, INTF_MUX);
mux_cfg &= ~0xf;
@@ -280,7 +285,7 @@ static void _setup_intf_ops(struct dpu_hw_intf_ops *ops,
ops->get_status = dpu_hw_intf_get_status;
ops->enable_timing = dpu_hw_intf_enable_timing_engine;
ops->get_line_count = dpu_hw_intf_get_line_count;
- if (cap & BIT(DPU_CTL_ACTIVE_CFG))
+ if (cap & BIT(DPU_INTF_INPUT_CTRL))
ops->bind_pingpong_blk = dpu_hw_intf_bind_pingpong_blk;
}
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_lm.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_lm.c
index 37becd43bd54..4b8baf71423f 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_lm.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_lm.c
@@ -152,14 +152,13 @@ static void _setup_mixer_ops(const struct dpu_mdss_cfg *m,
unsigned long features)
{
ops->setup_mixer_out = dpu_hw_lm_setup_out;
- if (IS_SDM845_TARGET(m->hwversion) || IS_SDM670_TARGET(m->hwversion)
- || IS_SC7180_TARGET(m->hwversion))
+ if (m->hwversion >= DPU_HW_VER_400)
ops->setup_blend_config = dpu_hw_lm_setup_blend_config_sdm845;
else
ops->setup_blend_config = dpu_hw_lm_setup_blend_config;
ops->setup_alpha_out = dpu_hw_lm_setup_color3;
ops->setup_border_color = dpu_hw_lm_setup_border_color;
-};
+}
static struct dpu_hw_blk_ops dpu_hw_ops;
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h
index 402dc5832361..979fd2c60aa0 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h
@@ -171,6 +171,7 @@ enum dpu_ctl {
CTL_2,
CTL_3,
CTL_4,
+ CTL_5,
CTL_MAX
};
@@ -180,6 +181,7 @@ enum dpu_pingpong {
PINGPONG_2,
PINGPONG_3,
PINGPONG_4,
+ PINGPONG_5,
PINGPONG_S0,
PINGPONG_MAX
};
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_pingpong.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_pingpong.c
index d110a40f0e73..bea4ab5c58c5 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_pingpong.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_pingpong.c
@@ -28,6 +28,16 @@
#define PP_FBC_BUDGET_CTL 0x038
#define PP_FBC_LOSSY_MODE 0x03C
+#define PP_DITHER_EN 0x000
+#define PP_DITHER_BITDEPTH 0x004
+#define PP_DITHER_MATRIX 0x008
+
+#define DITHER_DEPTH_MAP_INDEX 9
+
+static u32 dither_depth_map[DITHER_DEPTH_MAP_INDEX] = {
+ 0, 0, 0, 0, 0, 0, 0, 1, 2
+};
+
static const struct dpu_pingpong_cfg *_pingpong_offset(enum dpu_pingpong pp,
const struct dpu_mdss_cfg *m,
void __iomem *addr,
@@ -49,6 +59,37 @@ static const struct dpu_pingpong_cfg *_pingpong_offset(enum dpu_pingpong pp,
return ERR_PTR(-EINVAL);
}
+static void dpu_hw_pp_setup_dither(struct dpu_hw_pingpong *pp,
+ struct dpu_hw_dither_cfg *cfg)
+{
+ struct dpu_hw_blk_reg_map *c;
+ u32 i, base, data = 0;
+
+ c = &pp->hw;
+ base = pp->caps->sblk->dither.base;
+ if (!cfg) {
+ DPU_REG_WRITE(c, base + PP_DITHER_EN, 0);
+ return;
+ }
+
+ data = dither_depth_map[cfg->c0_bitdepth] & REG_MASK(2);
+ data |= (dither_depth_map[cfg->c1_bitdepth] & REG_MASK(2)) << 2;
+ data |= (dither_depth_map[cfg->c2_bitdepth] & REG_MASK(2)) << 4;
+ data |= (dither_depth_map[cfg->c3_bitdepth] & REG_MASK(2)) << 6;
+ data |= (cfg->temporal_en) ? (1 << 8) : 0;
+
+ DPU_REG_WRITE(c, base + PP_DITHER_BITDEPTH, data);
+
+ for (i = 0; i < DITHER_MATRIX_SZ - 3; i += 4) {
+ data = (cfg->matrix[i] & REG_MASK(4)) |
+ ((cfg->matrix[i + 1] & REG_MASK(4)) << 4) |
+ ((cfg->matrix[i + 2] & REG_MASK(4)) << 8) |
+ ((cfg->matrix[i + 3] & REG_MASK(4)) << 12);
+ DPU_REG_WRITE(c, base + PP_DITHER_MATRIX + i, data);
+ }
+ DPU_REG_WRITE(c, base + PP_DITHER_EN, 1);
+}
+
static int dpu_hw_pp_setup_te_config(struct dpu_hw_pingpong *pp,
struct dpu_hw_tear_check *te)
{
@@ -180,15 +221,18 @@ static u32 dpu_hw_pp_get_line_count(struct dpu_hw_pingpong *pp)
return line;
}
-static void _setup_pingpong_ops(struct dpu_hw_pingpong_ops *ops,
- const struct dpu_pingpong_cfg *hw_cap)
+static void _setup_pingpong_ops(struct dpu_hw_pingpong *c,
+ unsigned long features)
{
- ops->setup_tearcheck = dpu_hw_pp_setup_te_config;
- ops->enable_tearcheck = dpu_hw_pp_enable_te;
- ops->connect_external_te = dpu_hw_pp_connect_external_te;
- ops->get_vsync_info = dpu_hw_pp_get_vsync_info;
- ops->poll_timeout_wr_ptr = dpu_hw_pp_poll_timeout_wr_ptr;
- ops->get_line_count = dpu_hw_pp_get_line_count;
+ c->ops.setup_tearcheck = dpu_hw_pp_setup_te_config;
+ c->ops.enable_tearcheck = dpu_hw_pp_enable_te;
+ c->ops.connect_external_te = dpu_hw_pp_connect_external_te;
+ c->ops.get_vsync_info = dpu_hw_pp_get_vsync_info;
+ c->ops.poll_timeout_wr_ptr = dpu_hw_pp_poll_timeout_wr_ptr;
+ c->ops.get_line_count = dpu_hw_pp_get_line_count;
+
+ if (test_bit(DPU_PINGPONG_DITHER, &features))
+ c->ops.setup_dither = dpu_hw_pp_setup_dither;
};
static struct dpu_hw_blk_ops dpu_hw_ops;
@@ -212,7 +256,7 @@ struct dpu_hw_pingpong *dpu_hw_pingpong_init(enum dpu_pingpong idx,
c->idx = idx;
c->caps = cfg;
- _setup_pingpong_ops(&c->ops, c->caps);
+ _setup_pingpong_ops(c, c->caps->features);
dpu_hw_blk_init(&c->base, DPU_HW_BLK_PINGPONG, idx, &dpu_hw_ops);
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_pingpong.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_pingpong.h
index d73cb73e938b..065996b3ece9 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_pingpong.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_pingpong.h
@@ -10,6 +10,8 @@
#include "dpu_hw_util.h"
#include "dpu_hw_blk.h"
+#define DITHER_MATRIX_SZ 16
+
struct dpu_hw_pingpong;
struct dpu_hw_tear_check {
@@ -35,6 +37,26 @@ struct dpu_hw_pp_vsync_info {
};
/**
+ * struct dpu_hw_dither_cfg - dither feature structure
+ * @flags: for customizing operations
+ * @temporal_en: temperal dither enable
+ * @c0_bitdepth: c0 component bit depth
+ * @c1_bitdepth: c1 component bit depth
+ * @c2_bitdepth: c2 component bit depth
+ * @c3_bitdepth: c2 component bit depth
+ * @matrix: dither strength matrix
+ */
+struct dpu_hw_dither_cfg {
+ u64 flags;
+ u32 temporal_en;
+ u32 c0_bitdepth;
+ u32 c1_bitdepth;
+ u32 c2_bitdepth;
+ u32 c3_bitdepth;
+ u32 matrix[DITHER_MATRIX_SZ];
+};
+
+/**
*
* struct dpu_hw_pingpong_ops : Interface to the pingpong Hw driver functions
* Assumption is these functions will be called after clocks are enabled
@@ -82,6 +104,12 @@ struct dpu_hw_pingpong_ops {
* Obtain current vertical line counter
*/
u32 (*get_line_count)(struct dpu_hw_pingpong *pp);
+
+ /**
+ * Setup dither matix for pingpong block
+ */
+ void (*setup_dither)(struct dpu_hw_pingpong *pp,
+ struct dpu_hw_dither_cfg *cfg);
};
struct dpu_hw_pingpong {
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.c
index 82c5dbfdabc7..c940b69435e1 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.c
@@ -303,11 +303,25 @@ static void dpu_hw_sspp_setup_format(struct dpu_hw_pipe *ctx,
DPU_REG_WRITE(c, SSPP_FETCH_CONFIG,
DPU_FETCH_CONFIG_RESET_VALUE |
ctx->mdp->highest_bank_bit << 18);
- if (IS_UBWC_20_SUPPORTED(ctx->catalog->caps->ubwc_version)) {
+ switch (ctx->catalog->caps->ubwc_version) {
+ case DPU_HW_UBWC_VER_10:
+ /* TODO: UBWC v1 case */
+ break;
+ case DPU_HW_UBWC_VER_20:
fast_clear = fmt->alpha_enable ? BIT(31) : 0;
DPU_REG_WRITE(c, SSPP_UBWC_STATIC_CTRL,
fast_clear | (ctx->mdp->ubwc_swizzle) |
(ctx->mdp->highest_bank_bit << 4));
+ break;
+ case DPU_HW_UBWC_VER_30:
+ DPU_REG_WRITE(c, SSPP_UBWC_STATIC_CTRL,
+ BIT(30) | (ctx->mdp->ubwc_swizzle) |
+ (ctx->mdp->highest_bank_bit << 4));
+ break;
+ case DPU_HW_UBWC_VER_40:
+ DPU_REG_WRITE(c, SSPP_UBWC_STATIC_CTRL,
+ DPU_FORMAT_IS_YUV(fmt) ? 0 : BIT(30));
+ break;
}
}
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_top.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_top.c
index f9af52ae9f3e..01b76766a9a8 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_top.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_top.c
@@ -8,7 +8,6 @@
#include "dpu_kms.h"
#define SSPP_SPARE 0x28
-#define UBWC_STATIC 0x144
#define FLD_SPLIT_DISPLAY_CMD BIT(1)
#define FLD_SMART_PANEL_FREE_RUN BIT(2)
@@ -249,22 +248,6 @@ static void dpu_hw_get_safe_status(struct dpu_hw_mdp *mdp,
status->sspp[SSPP_CURSOR1] = (value >> 26) & 0x1;
}
-static void dpu_hw_reset_ubwc(struct dpu_hw_mdp *mdp, struct dpu_mdss_cfg *m)
-{
- struct dpu_hw_blk_reg_map c;
-
- if (!mdp || !m)
- return;
-
- if (!IS_UBWC_20_SUPPORTED(m->caps->ubwc_version))
- return;
-
- /* force blk offset to zero to access beginning of register region */
- c = mdp->hw;
- c.blk_off = 0x0;
- DPU_REG_WRITE(&c, UBWC_STATIC, m->mdp[0].ubwc_static);
-}
-
static void dpu_hw_intf_audio_select(struct dpu_hw_mdp *mdp)
{
struct dpu_hw_blk_reg_map *c;
@@ -285,7 +268,6 @@ static void _setup_mdp_ops(struct dpu_hw_mdp_ops *ops,
ops->get_danger_status = dpu_hw_get_danger_status;
ops->setup_vsync_source = dpu_hw_setup_vsync_source;
ops->get_safe_status = dpu_hw_get_safe_status;
- ops->reset_ubwc = dpu_hw_reset_ubwc;
ops->intf_audio_select = dpu_hw_intf_audio_select;
}
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_top.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_top.h
index 1d9d32edf619..8018fff5667a 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_top.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_top.h
@@ -127,13 +127,6 @@ struct dpu_hw_mdp_ops {
struct dpu_danger_safe_status *status);
/**
- * reset_ubwc - reset top level UBWC configuration
- * @mdp: mdp top context driver
- * @m: pointer to mdss catalog data
- */
- void (*reset_ubwc)(struct dpu_hw_mdp *mdp, struct dpu_mdss_cfg *m);
-
- /**
* intf_audio_select - select the external interface for audio
* @mdp: mdp top context driver
*/
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
index 680527e28d09..c0a4d4e16d82 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
@@ -10,6 +10,7 @@
#include <linux/debugfs.h>
#include <linux/dma-buf.h>
#include <linux/of_irq.h>
+#include <linux/pm_opp.h>
#include <drm/drm_crtc.h>
#include <drm/drm_file.h>
@@ -45,20 +46,6 @@
static int dpu_kms_hw_init(struct msm_kms *kms);
static void _dpu_kms_mmu_destroy(struct dpu_kms *dpu_kms);
-static unsigned long dpu_iomap_size(struct platform_device *pdev,
- const char *name)
-{
- struct resource *res;
-
- res = platform_get_resource_byname(pdev, IORESOURCE_MEM, name);
- if (!res) {
- DRM_ERROR("failed to get memory resource: %s\n", name);
- return 0;
- }
-
- return resource_size(res);
-}
-
#ifdef CONFIG_DEBUG_FS
static int _dpu_danger_signal_status(struct seq_file *s,
bool danger_status)
@@ -844,7 +831,6 @@ static int dpu_kms_hw_init(struct msm_kms *kms)
goto error;
}
DRM_DEBUG("mapped dpu address space @%pK\n", dpu_kms->mmio);
- dpu_kms->mmio_len = dpu_iomap_size(dpu_kms->pdev, "mdp");
dpu_kms->vbif[VBIF_RT] = msm_ioremap(dpu_kms->pdev, "vbif", "vbif");
if (IS_ERR(dpu_kms->vbif[VBIF_RT])) {
@@ -853,22 +839,16 @@ static int dpu_kms_hw_init(struct msm_kms *kms)
dpu_kms->vbif[VBIF_RT] = NULL;
goto error;
}
- dpu_kms->vbif_len[VBIF_RT] = dpu_iomap_size(dpu_kms->pdev, "vbif");
- dpu_kms->vbif[VBIF_NRT] = msm_ioremap(dpu_kms->pdev, "vbif_nrt", "vbif_nrt");
+ dpu_kms->vbif[VBIF_NRT] = msm_ioremap_quiet(dpu_kms->pdev, "vbif_nrt", "vbif_nrt");
if (IS_ERR(dpu_kms->vbif[VBIF_NRT])) {
dpu_kms->vbif[VBIF_NRT] = NULL;
DPU_DEBUG("VBIF NRT is not defined");
- } else {
- dpu_kms->vbif_len[VBIF_NRT] = dpu_iomap_size(dpu_kms->pdev,
- "vbif_nrt");
}
- dpu_kms->reg_dma = msm_ioremap(dpu_kms->pdev, "regdma", "regdma");
+ dpu_kms->reg_dma = msm_ioremap_quiet(dpu_kms->pdev, "regdma", "regdma");
if (IS_ERR(dpu_kms->reg_dma)) {
dpu_kms->reg_dma = NULL;
DPU_DEBUG("REG_DMA is not defined");
- } else {
- dpu_kms->reg_dma_len = dpu_iomap_size(dpu_kms->pdev, "regdma");
}
pm_runtime_get_sync(&dpu_kms->pdev->dev);
@@ -1025,11 +1005,24 @@ static int dpu_bind(struct device *dev, struct device *master, void *data)
if (!dpu_kms)
return -ENOMEM;
+ dpu_kms->opp_table = dev_pm_opp_set_clkname(dev, "core");
+ if (IS_ERR(dpu_kms->opp_table))
+ return PTR_ERR(dpu_kms->opp_table);
+ /* OPP table is optional */
+ ret = dev_pm_opp_of_add_table(dev);
+ if (!ret) {
+ dpu_kms->has_opp_table = true;
+ } else if (ret != -ENODEV) {
+ dev_err(dev, "invalid OPP table in device tree\n");
+ dev_pm_opp_put_clkname(dpu_kms->opp_table);
+ return ret;
+ }
+
mp = &dpu_kms->mp;
ret = msm_dss_parse_clock(pdev, mp);
if (ret) {
DPU_ERROR("failed to parse clocks, ret=%d\n", ret);
- return ret;
+ goto err;
}
platform_set_drvdata(pdev, dpu_kms);
@@ -1043,6 +1036,11 @@ static int dpu_bind(struct device *dev, struct device *master, void *data)
priv->kms = &dpu_kms->base;
return ret;
+err:
+ if (dpu_kms->has_opp_table)
+ dev_pm_opp_of_remove_table(dev);
+ dev_pm_opp_put_clkname(dpu_kms->opp_table);
+ return ret;
}
static void dpu_unbind(struct device *dev, struct device *master, void *data)
@@ -1057,6 +1055,10 @@ static void dpu_unbind(struct device *dev, struct device *master, void *data)
if (dpu_kms->rpm_enabled)
pm_runtime_disable(&pdev->dev);
+
+ if (dpu_kms->has_opp_table)
+ dev_pm_opp_of_remove_table(dev);
+ dev_pm_opp_put_clkname(dpu_kms->opp_table);
}
static const struct component_ops dpu_ops = {
@@ -1082,6 +1084,8 @@ static int __maybe_unused dpu_runtime_suspend(struct device *dev)
struct dpu_kms *dpu_kms = platform_get_drvdata(pdev);
struct dss_module_power *mp = &dpu_kms->mp;
+ /* Drop the performance state vote */
+ dev_pm_opp_set_rate(dev, 0);
rc = msm_dss_enable_clk(mp->clk_config, mp->num_clk, false);
if (rc)
DPU_ERROR("clock disable failed rc:%d\n", rc);
@@ -1115,6 +1119,8 @@ static int __maybe_unused dpu_runtime_resume(struct device *dev)
static const struct dev_pm_ops dpu_pm_ops = {
SET_RUNTIME_PM_OPS(dpu_runtime_suspend, dpu_runtime_resume, NULL)
+ SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
+ pm_runtime_force_resume)
};
static const struct of_device_id dpu_dt_match[] = {
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h
index a3b122bfb676..e140cd633071 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h
@@ -100,7 +100,6 @@ struct dpu_kms {
/* io/register spaces: */
void __iomem *mmio, *vbif[VBIF_MAX], *reg_dma;
- unsigned long mmio_len, vbif_len[VBIF_MAX], reg_dma_len;
struct regulator *vdd;
struct regulator *mmagic;
@@ -128,6 +127,10 @@ struct dpu_kms {
struct platform_device *pdev;
bool rpm_enabled;
+
+ struct opp_table *opp_table;
+ bool has_opp_table;
+
struct dss_module_power mp;
/* reference count bandwidth requests, so we know when we can
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_mdss.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_mdss.c
index 80d3cfc14007..7d3fdbb00e7e 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_mdss.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_mdss.c
@@ -15,6 +15,10 @@
#define HW_REV 0x0
#define HW_INTR_STATUS 0x0010
+#define UBWC_STATIC 0x144
+#define UBWC_CTRL_2 0x150
+#define UBWC_PREDICTION_MODE 0x154
+
/* Max BW defined in KBps */
#define MAX_BW 6800000
@@ -23,65 +27,15 @@ struct dpu_irq_controller {
struct irq_domain *domain;
};
-struct dpu_hw_cfg {
- u32 val;
- u32 offset;
-};
-
-struct dpu_mdss_hw_init_handler {
- u32 hw_rev;
- u32 hw_reg_count;
- struct dpu_hw_cfg* hw_cfg;
-};
-
struct dpu_mdss {
struct msm_mdss base;
void __iomem *mmio;
- unsigned long mmio_len;
struct dss_module_power mp;
struct dpu_irq_controller irq_controller;
struct icc_path *path[2];
u32 num_paths;
};
-static struct dpu_hw_cfg hw_cfg[] = {
- {
- /* UBWC global settings */
- .val = 0x1E,
- .offset = 0x144,
- }
-};
-
-static struct dpu_mdss_hw_init_handler cfg_handler[] = {
- { .hw_rev = DPU_HW_VER_620,
- .hw_reg_count = ARRAY_SIZE(hw_cfg),
- .hw_cfg = hw_cfg
- },
-};
-
-static void dpu_mdss_hw_init(struct dpu_mdss *dpu_mdss, u32 hw_rev)
-{
- int i;
- u32 count = 0;
- struct dpu_hw_cfg *hw_cfg = NULL;
-
- for (i = 0; i < ARRAY_SIZE(cfg_handler); i++) {
- if (cfg_handler[i].hw_rev == hw_rev) {
- hw_cfg = cfg_handler[i].hw_cfg;
- count = cfg_handler[i].hw_reg_count;
- break;
- }
- }
-
- for (i = 0; i < count; i++ ) {
- writel_relaxed(hw_cfg->val,
- dpu_mdss->mmio + hw_cfg->offset);
- hw_cfg++;
- }
-
- return;
-}
-
static int dpu_mdss_parse_data_bus_icc_path(struct drm_device *dev,
struct dpu_mdss *dpu_mdss)
{
@@ -224,7 +178,6 @@ static int dpu_mdss_enable(struct msm_mdss *mdss)
struct dpu_mdss *dpu_mdss = to_dpu_mdss(mdss);
struct dss_module_power *mp = &dpu_mdss->mp;
int ret;
- u32 mdss_rev;
dpu_mdss_icc_request_bw(mdss);
@@ -234,8 +187,25 @@ static int dpu_mdss_enable(struct msm_mdss *mdss)
return ret;
}
- mdss_rev = readl_relaxed(dpu_mdss->mmio + HW_REV);
- dpu_mdss_hw_init(dpu_mdss, mdss_rev);
+ /*
+ * ubwc config is part of the "mdss" region which is not accessible
+ * from the rest of the driver. hardcode known configurations here
+ */
+ switch (readl_relaxed(dpu_mdss->mmio + HW_REV)) {
+ case DPU_HW_VER_500:
+ case DPU_HW_VER_501:
+ writel_relaxed(0x420, dpu_mdss->mmio + UBWC_STATIC);
+ break;
+ case DPU_HW_VER_600:
+ /* TODO: 0x102e for LP_DDR4 */
+ writel_relaxed(0x103e, dpu_mdss->mmio + UBWC_STATIC);
+ writel_relaxed(2, dpu_mdss->mmio + UBWC_CTRL_2);
+ writel_relaxed(1, dpu_mdss->mmio + UBWC_PREDICTION_MODE);
+ break;
+ case DPU_HW_VER_620:
+ writel_relaxed(0x1e, dpu_mdss->mmio + UBWC_STATIC);
+ break;
+ }
return ret;
}
@@ -292,7 +262,6 @@ int dpu_mdss_init(struct drm_device *dev)
{
struct platform_device *pdev = to_platform_device(dev->dev);
struct msm_drm_private *priv = dev->dev_private;
- struct resource *res;
struct dpu_mdss *dpu_mdss;
struct dss_module_power *mp;
int ret = 0;
@@ -308,13 +277,6 @@ int dpu_mdss_init(struct drm_device *dev)
DRM_DEBUG("mapped mdss address space @%pK\n", dpu_mdss->mmio);
- res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "mdss");
- if (!res) {
- DRM_ERROR("failed to get memory resource for mdss\n");
- return -ENOMEM;
- }
- dpu_mdss->mmio_len = resource_size(res);
-
ret = dpu_mdss_parse_data_bus_icc_path(dev, dpu_mdss);
if (ret)
return ret;
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c
index 3b9c33e694bf..33f6c56f01ed 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c
@@ -153,7 +153,7 @@ static int _dpu_plane_calc_fill_level(struct drm_plane *plane,
pdpu = to_dpu_plane(plane);
pstate = to_dpu_plane_state(plane->state);
- fixed_buff_size = pdpu->pipe_sblk->common->pixel_ram_size;
+ fixed_buff_size = pdpu->catalog->caps->pixel_ram_size;
list_for_each_entry(tmp, &pdpu->mplane_list, mplane_list) {
if (!tmp->base.state->visible)
@@ -709,7 +709,7 @@ int dpu_plane_validate_multirect_v2(struct dpu_multirect_plane_states *plane)
* So we cannot support more than half of the supported SSPP
* width for tiled formats.
*/
- width_threshold = dpu_plane[i]->pipe_sblk->common->maxlinewidth;
+ width_threshold = dpu_plane[i]->catalog->caps->max_linewidth;
if (has_tiled_rect)
width_threshold /= 2;
@@ -887,7 +887,7 @@ static int dpu_plane_atomic_check(struct drm_plane *plane,
fb_rect.x2 = state->fb->width;
fb_rect.y2 = state->fb->height;
- max_linewidth = pdpu->pipe_sblk->common->maxlinewidth;
+ max_linewidth = pdpu->catalog->caps->max_linewidth;
fmt = to_dpu_format(msm_framebuffer_format(state->fb));
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_trace.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_trace.h
index eecfe9b3199e..6714b088970f 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_trace.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_trace.h
@@ -327,20 +327,18 @@ DEFINE_EVENT(dpu_enc_keyval_template, dpu_enc_trigger_start,
);
TRACE_EVENT(dpu_enc_atomic_check_flags,
- TP_PROTO(uint32_t drm_id, unsigned int flags, int private_flags),
- TP_ARGS(drm_id, flags, private_flags),
+ TP_PROTO(uint32_t drm_id, unsigned int flags),
+ TP_ARGS(drm_id, flags),
TP_STRUCT__entry(
__field( uint32_t, drm_id )
__field( unsigned int, flags )
- __field( int, private_flags )
),
TP_fast_assign(
__entry->drm_id = drm_id;
__entry->flags = flags;
- __entry->private_flags = private_flags;
),
- TP_printk("id=%u, flags=%u, private_flags=%d",
- __entry->drm_id, __entry->flags, __entry->private_flags)
+ TP_printk("id=%u, flags=%u",
+ __entry->drm_id, __entry->flags)
);
DECLARE_EVENT_CLASS(dpu_enc_id_enable_template,