diff options
Diffstat (limited to 'drivers/gpu/drm/msm/disp/dpu1')
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, |