diff options
author | Dave Airlie <airlied@redhat.com> | 2020-09-29 03:18:49 +0300 |
---|---|---|
committer | Dave Airlie <airlied@redhat.com> | 2020-09-29 03:18:49 +0300 |
commit | 91d0ca3d6b523ec409b9af62468886d4e1a7d0dd (patch) | |
tree | 9556284724dd2e4a41d88ed6720e7634bba38db2 /drivers/gpu/drm/msm/disp | |
parent | 32e4d9df60f71d641fbe628a9afbe2f44d7e9a37 (diff) | |
parent | d1ea914925856d397b0b3241428f20b945e31434 (diff) | |
download | linux-91d0ca3d6b523ec409b9af62468886d4e1a7d0dd.tar.xz |
Merge tag 'drm-msm-next-2020-09-27' of https://gitlab.freedesktop.org/drm/msm into drm-next
* DSI support for sm8150/sm8250
* Support for per-process GPU pagetables (finally!) for a6xx.
There are still some iommu/arm-smmu changes required to
enable, without which it will fallback to the current single
pgtable state. The first part (ie. what doesn't depend on
drm side patches) is queued up for v5.10[1].
* DisplayPort support. Userspace DP compliance tool support
is already merged in IGT[2]
* The usual assortment of smaller fixes/cleanups
Signed-off-by: Dave Airlie <airlied@redhat.com>
From: Rob Clark <robdclark@gmail.com>
Link: https://patchwork.freedesktop.org/patch/msgid/CAF6AEGvqjuzH=Po_9EzzFsp2Xq3tqJUTKfsA2g09XY7_+6Ypfw@mail.gmail.com
Diffstat (limited to 'drivers/gpu/drm/msm/disp')
-rw-r--r-- | drivers/gpu/drm/msm/disp/dpu1/dpu_core_irq.c | 15 | ||||
-rw-r--r-- | drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.c | 109 | ||||
-rw-r--r-- | drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c | 132 | ||||
-rw-r--r-- | drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 55 | ||||
-rw-r--r-- | drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c | 14 | ||||
-rw-r--r-- | drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c | 5 | ||||
-rw-r--r-- | drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h | 4 | ||||
-rw-r--r-- | drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c | 145 | ||||
-rw-r--r-- | drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h | 4 | ||||
-rw-r--r-- | drivers/gpu/drm/msm/disp/dpu1/dpu_mdss.c | 9 | ||||
-rw-r--r-- | drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c | 84 | ||||
-rw-r--r-- | drivers/gpu/drm/msm/disp/dpu1/dpu_plane.h | 4 | ||||
-rw-r--r-- | drivers/gpu/drm/msm/disp/mdp4/mdp4_dtv_encoder.c | 51 | ||||
-rw-r--r-- | drivers/gpu/drm/msm/disp/mdp4/mdp4_kms.h | 13 | ||||
-rw-r--r-- | drivers/gpu/drm/msm/disp/mdp4/mdp4_lcdc_encoder.c | 47 | ||||
-rw-r--r-- | drivers/gpu/drm/msm/disp/mdp5/mdp5_cmd_encoder.c | 24 | ||||
-rw-r--r-- | drivers/gpu/drm/msm/disp/mdp5/mdp5_encoder.c | 68 |
17 files changed, 386 insertions, 397 deletions
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_core_irq.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_core_irq.c index f1bc6a1af7a7..84ea09d9692f 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_core_irq.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_core_irq.c @@ -288,19 +288,6 @@ static void dpu_disable_all_irqs(struct dpu_kms *dpu_kms) } #ifdef CONFIG_DEBUG_FS -#define DEFINE_DPU_DEBUGFS_SEQ_FOPS(__prefix) \ -static int __prefix ## _open(struct inode *inode, struct file *file) \ -{ \ - return single_open(file, __prefix ## _show, inode->i_private); \ -} \ -static const struct file_operations __prefix ## _fops = { \ - .owner = THIS_MODULE, \ - .open = __prefix ## _open, \ - .release = single_release, \ - .read = seq_read, \ - .llseek = seq_lseek, \ -} - static int dpu_debugfs_core_irq_show(struct seq_file *s, void *v) { struct dpu_irq *irq_obj = s->private; @@ -328,7 +315,7 @@ static int dpu_debugfs_core_irq_show(struct seq_file *s, void *v) return 0; } -DEFINE_DPU_DEBUGFS_SEQ_FOPS(dpu_debugfs_core_irq); +DEFINE_SHOW_ATTRIBUTE(dpu_debugfs_core_irq); void dpu_debugfs_core_irq_init(struct dpu_kms *dpu_kms, struct dentry *parent) 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 b36919d95362..393858ef8a83 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.c @@ -30,6 +30,74 @@ enum dpu_perf_mode { DPU_PERF_MODE_MAX }; +/** + * @_dpu_core_perf_calc_bw() - to calculate BW per crtc + * @kms - pointer to the dpu_kms + * @crtc - pointer to a crtc + * Return: returns aggregated BW for all planes in crtc. + */ +static u64 _dpu_core_perf_calc_bw(struct dpu_kms *kms, + struct drm_crtc *crtc) +{ + struct drm_plane *plane; + struct dpu_plane_state *pstate; + u64 crtc_plane_bw = 0; + u32 bw_factor; + + drm_atomic_crtc_for_each_plane(plane, crtc) { + pstate = to_dpu_plane_state(plane->state); + if (!pstate) + continue; + + crtc_plane_bw += pstate->plane_fetch_bw; + } + + bw_factor = kms->catalog->perf.bw_inefficiency_factor; + if (bw_factor) { + crtc_plane_bw *= bw_factor; + do_div(crtc_plane_bw, 100); + } + + return crtc_plane_bw; +} + +/** + * _dpu_core_perf_calc_clk() - to calculate clock per crtc + * @kms - pointer to the dpu_kms + * @crtc - pointer to a crtc + * @state - pointer to a crtc state + * Return: returns max clk for all planes in crtc. + */ +static u64 _dpu_core_perf_calc_clk(struct dpu_kms *kms, + struct drm_crtc *crtc, struct drm_crtc_state *state) +{ + struct drm_plane *plane; + struct dpu_plane_state *pstate; + struct drm_display_mode *mode; + u64 crtc_clk; + u32 clk_factor; + + mode = &state->adjusted_mode; + + crtc_clk = mode->vtotal * mode->hdisplay * drm_mode_vrefresh(mode); + + drm_atomic_crtc_for_each_plane(plane, crtc) { + pstate = to_dpu_plane_state(plane->state); + if (!pstate) + continue; + + crtc_clk = max(pstate->plane_clk, crtc_clk); + } + + clk_factor = kms->catalog->perf.clk_inefficiency_factor; + if (clk_factor) { + crtc_clk *= clk_factor; + do_div(crtc_clk, 100); + } + + return crtc_clk; +} + static struct dpu_kms *_dpu_crtc_get_kms(struct drm_crtc *crtc) { struct msm_drm_private *priv; @@ -52,12 +120,7 @@ static void _dpu_core_perf_calc_crtc(struct dpu_kms *kms, dpu_cstate = to_dpu_crtc_state(state); memset(perf, 0, sizeof(struct dpu_core_perf_params)); - if (!dpu_cstate->bw_control) { - perf->bw_ctl = kms->catalog->perf.max_bw_high * - 1000ULL; - perf->max_per_pipe_ib = perf->bw_ctl; - perf->core_clk_rate = kms->perf.max_core_clk_rate; - } else if (kms->perf.perf_tune.mode == DPU_PERF_MODE_MINIMUM) { + if (kms->perf.perf_tune.mode == DPU_PERF_MODE_MINIMUM) { perf->bw_ctl = 0; perf->max_per_pipe_ib = 0; perf->core_clk_rate = 0; @@ -65,6 +128,10 @@ static void _dpu_core_perf_calc_crtc(struct dpu_kms *kms, perf->bw_ctl = kms->perf.fix_core_ab_vote; perf->max_per_pipe_ib = kms->perf.fix_core_ib_vote; perf->core_clk_rate = kms->perf.fix_core_clk_rate; + } else { + perf->bw_ctl = _dpu_core_perf_calc_bw(kms, crtc); + perf->max_per_pipe_ib = kms->catalog->perf.min_dram_ib; + perf->core_clk_rate = _dpu_core_perf_calc_clk(kms, crtc, state); } DPU_DEBUG( @@ -116,11 +183,7 @@ int dpu_core_perf_crtc_check(struct drm_crtc *crtc, DPU_DEBUG("crtc:%d bw:%llu ctrl:%d\n", tmp_crtc->base.id, tmp_cstate->new_perf.bw_ctl, tmp_cstate->bw_control); - /* - * For bw check only use the bw if the - * atomic property has been already set - */ - if (tmp_cstate->bw_control) + bw_sum_of_intfs += tmp_cstate->new_perf.bw_ctl; } @@ -132,9 +195,7 @@ int dpu_core_perf_crtc_check(struct drm_crtc *crtc, DPU_DEBUG("final threshold bw limit = %d\n", threshold); - if (!dpu_cstate->bw_control) { - DPU_DEBUG("bypass bandwidth check\n"); - } else if (!threshold) { + if (!threshold) { DPU_ERROR("no bandwidth limits specified\n"); return -E2BIG; } else if (bw > threshold) { @@ -155,7 +216,11 @@ static int _dpu_core_perf_crtc_update_bus(struct dpu_kms *kms, = dpu_crtc_get_client_type(crtc); struct drm_crtc *tmp_crtc; struct dpu_crtc_state *dpu_cstate; - int ret = 0; + int i, ret = 0; + u64 avg_bw; + + if (!kms->num_paths) + return -EINVAL; drm_for_each_crtc(tmp_crtc, crtc->dev) { if (tmp_crtc->enabled && @@ -166,10 +231,20 @@ static int _dpu_core_perf_crtc_update_bus(struct dpu_kms *kms, perf.max_per_pipe_ib = max(perf.max_per_pipe_ib, dpu_cstate->new_perf.max_per_pipe_ib); - DPU_DEBUG("crtc=%d bw=%llu\n", tmp_crtc->base.id, - dpu_cstate->new_perf.bw_ctl); + perf.bw_ctl += dpu_cstate->new_perf.bw_ctl; + + DPU_DEBUG("crtc=%d bw=%llu paths:%d\n", + tmp_crtc->base.id, + dpu_cstate->new_perf.bw_ctl, kms->num_paths); } } + + avg_bw = perf.bw_ctl; + do_div(avg_bw, (kms->num_paths * 1000)); /*Bps_to_icc*/ + + for (i = 0; i < kms->num_paths; i++) + icc_set_bw(kms->path[i], avg_bw, perf.max_per_pipe_ib); + return ret; } diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c index c2729f71e2fa..f56414a06ec4 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c @@ -265,11 +265,6 @@ enum dpu_intf_mode dpu_crtc_get_intf_mode(struct drm_crtc *crtc) { struct drm_encoder *encoder; - if (!crtc) { - DPU_ERROR("invalid crtc\n"); - return INTF_MODE_NONE; - } - /* * TODO: This function is called from dpu debugfs and as part of atomic * check. When called from debugfs, the crtc->mutex must be held to @@ -297,7 +292,6 @@ void dpu_crtc_vblank_callback(struct drm_crtc *crtc) dpu_crtc->vblank_cb_time = ktime_get(); else dpu_crtc->vblank_cb_count++; - _dpu_crtc_complete_flip(crtc); drm_crtc_handle_vblank(crtc); trace_dpu_crtc_vblank_cb(DRMID(crtc)); } @@ -402,6 +396,7 @@ static void dpu_crtc_frame_event_cb(void *data, u32 event) void dpu_crtc_complete_commit(struct drm_crtc *crtc) { trace_dpu_crtc_complete_commit(DRMID(crtc)); + _dpu_crtc_complete_flip(crtc); } static void _dpu_crtc_setup_lm_bounds(struct drm_crtc *crtc, @@ -421,8 +416,6 @@ static void _dpu_crtc_setup_lm_bounds(struct drm_crtc *crtc, trace_dpu_crtc_setup_lm_bounds(DRMID(crtc), i, r); } - - drm_mode_debug_printmodeline(adj_mode); } static void _dpu_crtc_get_pcc_coeff(struct drm_crtc_state *state, @@ -457,7 +450,6 @@ static void _dpu_crtc_setup_cp_blocks(struct drm_crtc *crtc) struct dpu_crtc_mixer *mixer = cstate->mixers; struct dpu_hw_pcc_cfg cfg; struct dpu_hw_ctl *ctl; - struct dpu_hw_mixer *lm; struct dpu_hw_dspp *dspp; int i; @@ -467,7 +459,6 @@ static void _dpu_crtc_setup_cp_blocks(struct drm_crtc *crtc) for (i = 0; i < cstate->num_mixers; i++) { ctl = mixer[i].lm_ctl; - lm = mixer[i].hw_lm; dspp = mixer[i].hw_dspp; if (!dspp || !dspp->ops.setup_pcc) @@ -496,16 +487,8 @@ static void _dpu_crtc_setup_cp_blocks(struct drm_crtc *crtc) static void dpu_crtc_atomic_begin(struct drm_crtc *crtc, struct drm_crtc_state *old_state) { - struct dpu_crtc *dpu_crtc; - struct dpu_crtc_state *cstate; + struct dpu_crtc_state *cstate = to_dpu_crtc_state(crtc->state); struct drm_encoder *encoder; - struct drm_device *dev; - unsigned long flags; - - if (!crtc) { - DPU_ERROR("invalid crtc\n"); - return; - } if (!crtc->state->enable) { DPU_DEBUG("crtc%d -> enable %d, skip atomic_begin\n", @@ -515,21 +498,8 @@ static void dpu_crtc_atomic_begin(struct drm_crtc *crtc, DPU_DEBUG("crtc%d\n", crtc->base.id); - dpu_crtc = to_dpu_crtc(crtc); - cstate = to_dpu_crtc_state(crtc->state); - dev = crtc->dev; - _dpu_crtc_setup_lm_bounds(crtc, crtc->state); - if (dpu_crtc->event) { - WARN_ON(dpu_crtc->event); - } else { - spin_lock_irqsave(&dev->event_lock, flags); - dpu_crtc->event = crtc->state->event; - crtc->state->event = NULL; - spin_unlock_irqrestore(&dev->event_lock, flags); - } - /* encoder will trigger pending mask now */ drm_for_each_encoder_mask(encoder, crtc->dev, crtc->state->encoder_mask) dpu_encoder_trigger_kickoff_pending(encoder); @@ -583,14 +553,11 @@ static void dpu_crtc_atomic_flush(struct drm_crtc *crtc, return; } - if (dpu_crtc->event) { - DPU_DEBUG("already received dpu_crtc->event\n"); - } else { - spin_lock_irqsave(&dev->event_lock, flags); - dpu_crtc->event = crtc->state->event; - crtc->state->event = NULL; - spin_unlock_irqrestore(&dev->event_lock, flags); - } + WARN_ON(dpu_crtc->event); + spin_lock_irqsave(&dev->event_lock, flags); + dpu_crtc->event = crtc->state->event; + crtc->state->event = NULL; + spin_unlock_irqrestore(&dev->event_lock, flags); /* * If no mixers has been allocated in dpu_crtc_atomic_check(), @@ -635,14 +602,7 @@ static void dpu_crtc_atomic_flush(struct drm_crtc *crtc, static void dpu_crtc_destroy_state(struct drm_crtc *crtc, struct drm_crtc_state *state) { - struct dpu_crtc_state *cstate; - - if (!crtc || !state) { - DPU_ERROR("invalid argument(s)\n"); - return; - } - - cstate = to_dpu_crtc_state(state); + struct dpu_crtc_state *cstate = to_dpu_crtc_state(state); DPU_DEBUG("crtc%d\n", crtc->base.id); @@ -731,14 +691,8 @@ static void dpu_crtc_reset(struct drm_crtc *crtc) */ static struct drm_crtc_state *dpu_crtc_duplicate_state(struct drm_crtc *crtc) { - struct dpu_crtc_state *cstate, *old_cstate; + struct dpu_crtc_state *cstate, *old_cstate = to_dpu_crtc_state(crtc->state); - if (!crtc || !crtc->state) { - DPU_ERROR("invalid argument(s)\n"); - return NULL; - } - - old_cstate = to_dpu_crtc_state(crtc->state); cstate = kmemdup(old_cstate, sizeof(*old_cstate), GFP_KERNEL); if (!cstate) { DPU_ERROR("failed to allocate state\n"); @@ -754,19 +708,12 @@ static struct drm_crtc_state *dpu_crtc_duplicate_state(struct drm_crtc *crtc) static void dpu_crtc_disable(struct drm_crtc *crtc, struct drm_crtc_state *old_crtc_state) { - struct dpu_crtc *dpu_crtc; - struct dpu_crtc_state *cstate; + struct dpu_crtc *dpu_crtc = to_dpu_crtc(crtc); + struct dpu_crtc_state *cstate = to_dpu_crtc_state(crtc->state); struct drm_encoder *encoder; unsigned long flags; bool release_bandwidth = false; - if (!crtc || !crtc->state) { - DPU_ERROR("invalid crtc\n"); - return; - } - dpu_crtc = to_dpu_crtc(crtc); - cstate = to_dpu_crtc_state(crtc->state); - DRM_DEBUG_KMS("crtc%d\n", crtc->base.id); /* Disable/save vblank irq handling */ @@ -825,19 +772,13 @@ static void dpu_crtc_disable(struct drm_crtc *crtc, static void dpu_crtc_enable(struct drm_crtc *crtc, struct drm_crtc_state *old_crtc_state) { - struct dpu_crtc *dpu_crtc; + struct dpu_crtc *dpu_crtc = to_dpu_crtc(crtc); struct drm_encoder *encoder; bool request_bandwidth = false; - if (!crtc) { - DPU_ERROR("invalid crtc\n"); - return; - } - pm_runtime_get_sync(crtc->dev->dev); DRM_DEBUG_KMS("crtc%d\n", crtc->base.id); - dpu_crtc = to_dpu_crtc(crtc); drm_for_each_encoder_mask(encoder, crtc->dev, crtc->state->encoder_mask) { /* in video mode, we hold an extra bandwidth reference @@ -873,15 +814,15 @@ struct plane_state { static int dpu_crtc_atomic_check(struct drm_crtc *crtc, struct drm_crtc_state *state) { - struct dpu_crtc *dpu_crtc; + struct dpu_crtc *dpu_crtc = to_dpu_crtc(crtc); + struct dpu_crtc_state *cstate = to_dpu_crtc_state(state); struct plane_state *pstates; - struct dpu_crtc_state *cstate; const struct drm_plane_state *pstate; struct drm_plane *plane; struct drm_display_mode *mode; - int cnt = 0, rc = 0, mixer_width, i, z_pos; + int cnt = 0, rc = 0, mixer_width = 0, i, z_pos; struct dpu_multirect_plane_states multirect_plane[DPU_STAGE_MAX * 2]; int multirect_count = 0; @@ -889,16 +830,8 @@ static int dpu_crtc_atomic_check(struct drm_crtc *crtc, int left_zpos_cnt = 0, right_zpos_cnt = 0; struct drm_rect crtc_rect = { 0 }; - if (!crtc) { - DPU_ERROR("invalid crtc\n"); - return -EINVAL; - } - pstates = kzalloc(sizeof(*pstates) * DPU_STAGE_MAX * 4, GFP_KERNEL); - dpu_crtc = to_dpu_crtc(crtc); - cstate = to_dpu_crtc_state(state); - if (!state->enable || !state->active) { DPU_DEBUG("crtc%d -> enable %d, active %d, skip atomic_check\n", crtc->base.id, state->enable, state->active); @@ -914,9 +847,11 @@ static int dpu_crtc_atomic_check(struct drm_crtc *crtc, memset(pipe_staged, 0, sizeof(pipe_staged)); - mixer_width = mode->hdisplay / cstate->num_mixers; + if (cstate->num_mixers) { + mixer_width = mode->hdisplay / cstate->num_mixers; - _dpu_crtc_setup_lm_bounds(crtc, state); + _dpu_crtc_setup_lm_bounds(crtc, state); + } crtc_rect.x2 = mode->hdisplay; crtc_rect.y2 = mode->vdisplay; @@ -1242,23 +1177,7 @@ static int _dpu_debugfs_status_show(struct seq_file *s, void *data) return 0; } -static int _dpu_debugfs_status_open(struct inode *inode, struct file *file) -{ - return single_open(file, _dpu_debugfs_status_show, inode->i_private); -} - -#define DEFINE_DPU_DEBUGFS_SEQ_FOPS(__prefix) \ -static int __prefix ## _open(struct inode *inode, struct file *file) \ -{ \ - return single_open(file, __prefix ## _show, inode->i_private); \ -} \ -static const struct file_operations __prefix ## _fops = { \ - .owner = THIS_MODULE, \ - .open = __prefix ## _open, \ - .release = single_release, \ - .read = seq_read, \ - .llseek = seq_lseek, \ -} +DEFINE_SHOW_ATTRIBUTE(_dpu_debugfs_status); static int dpu_crtc_debugfs_state_show(struct seq_file *s, void *v) { @@ -1275,25 +1194,18 @@ static int dpu_crtc_debugfs_state_show(struct seq_file *s, void *v) return 0; } -DEFINE_DPU_DEBUGFS_SEQ_FOPS(dpu_crtc_debugfs_state); +DEFINE_SHOW_ATTRIBUTE(dpu_crtc_debugfs_state); static int _dpu_crtc_init_debugfs(struct drm_crtc *crtc) { struct dpu_crtc *dpu_crtc = to_dpu_crtc(crtc); - static const struct file_operations debugfs_status_fops = { - .open = _dpu_debugfs_status_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, - }; - dpu_crtc->debugfs_root = debugfs_create_dir(dpu_crtc->name, crtc->dev->primary->debugfs_root); debugfs_create_file("status", 0400, dpu_crtc->debugfs_root, - dpu_crtc, &debugfs_status_fops); + dpu_crtc, &_dpu_debugfs_status_fops); debugfs_create_file("state", 0600, dpu_crtc->debugfs_root, &dpu_crtc->base, diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c index bd6def436c65..f7f5c258b553 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c @@ -1001,6 +1001,9 @@ static void dpu_encoder_virt_mode_set(struct drm_encoder *drm_enc, trace_dpu_enc_mode_set(DRMID(drm_enc)); + if (drm_enc->encoder_type == DRM_MODE_ENCODER_TMDS && priv->dp) + msm_dp_display_mode_set(priv->dp, drm_enc, mode, adj_mode); + list_for_each_entry(conn_iter, connector_list, head) if (conn_iter->encoder == drm_enc) conn = conn_iter; @@ -1109,6 +1112,13 @@ static void _dpu_encoder_virt_enable_helper(struct drm_encoder *drm_enc) return; } + + if (dpu_enc->disp_info.intf_type == DRM_MODE_CONNECTOR_DisplayPort && + dpu_enc->cur_master->hw_mdptop && + dpu_enc->cur_master->hw_mdptop->ops.intf_audio_select) + dpu_enc->cur_master->hw_mdptop->ops.intf_audio_select( + dpu_enc->cur_master->hw_mdptop); + _dpu_encoder_update_vsync_source(dpu_enc, &dpu_enc->disp_info); if (dpu_enc->disp_info.intf_type == DRM_MODE_ENCODER_DSI && @@ -1146,6 +1156,7 @@ static void dpu_encoder_virt_enable(struct drm_encoder *drm_enc) { struct dpu_encoder_virt *dpu_enc = NULL; int ret = 0; + struct msm_drm_private *priv; struct drm_display_mode *cur_mode = NULL; if (!drm_enc) { @@ -1156,6 +1167,7 @@ static void dpu_encoder_virt_enable(struct drm_encoder *drm_enc) mutex_lock(&dpu_enc->enc_lock); cur_mode = &dpu_enc->base.crtc->state->adjusted_mode; + priv = drm_enc->dev->dev_private; trace_dpu_enc_enable(DRMID(drm_enc), cur_mode->hdisplay, cur_mode->vdisplay); @@ -1176,6 +1188,15 @@ static void dpu_encoder_virt_enable(struct drm_encoder *drm_enc) _dpu_encoder_virt_enable_helper(drm_enc); + if (drm_enc->encoder_type == DRM_MODE_ENCODER_TMDS && priv->dp) { + ret = msm_dp_display_enable(priv->dp, + drm_enc); + if (ret) { + DPU_ERROR_ENC(dpu_enc, "dp display enable failed: %d\n", + ret); + goto out; + } + } dpu_enc->enabled = true; out: @@ -1211,6 +1232,11 @@ static void dpu_encoder_virt_disable(struct drm_encoder *drm_enc) /* wait for idle */ dpu_encoder_wait_for_event(drm_enc, MSM_ENC_TX_COMPLETE); + if (drm_enc->encoder_type == DRM_MODE_ENCODER_TMDS && priv->dp) { + if (msm_dp_display_pre_disable(priv->dp, drm_enc)) + DPU_ERROR_ENC(dpu_enc, "dp display push idle failed\n"); + } + dpu_encoder_resource_control(drm_enc, DPU_ENC_RC_EVENT_PRE_STOP); for (i = 0; i < dpu_enc->num_phys_encs; i++) { @@ -1220,6 +1246,7 @@ static void dpu_encoder_virt_disable(struct drm_encoder *drm_enc) phys->ops.disable(phys); } + /* after phys waits for frame-done, should be no more frames pending */ if (atomic_xchg(&dpu_enc->frame_done_timeout_ms, 0)) { DPU_ERROR("enc%d timeout pending\n", drm_enc->base.id); @@ -1234,6 +1261,11 @@ static void dpu_encoder_virt_disable(struct drm_encoder *drm_enc) DPU_DEBUG_ENC(dpu_enc, "encoder disabled\n"); + if (drm_enc->encoder_type == DRM_MODE_ENCODER_TMDS && priv->dp) { + if (msm_dp_display_disable(priv->dp, drm_enc)) + DPU_ERROR_ENC(dpu_enc, "dp display disable failed\n"); + } + mutex_unlock(&dpu_enc->enc_lock); } @@ -1880,24 +1912,13 @@ static int _dpu_encoder_status_show(struct seq_file *s, void *data) return 0; } -static int _dpu_encoder_debugfs_status_open(struct inode *inode, - struct file *file) -{ - return single_open(file, _dpu_encoder_status_show, inode->i_private); -} +DEFINE_SHOW_ATTRIBUTE(_dpu_encoder_status); static int _dpu_encoder_init_debugfs(struct drm_encoder *drm_enc) { struct dpu_encoder_virt *dpu_enc = to_dpu_encoder_virt(drm_enc); int i; - static const struct file_operations debugfs_status_fops = { - .open = _dpu_encoder_debugfs_status_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, - }; - char name[DPU_NAME_SIZE]; if (!drm_enc->dev) { @@ -1913,7 +1934,7 @@ static int _dpu_encoder_init_debugfs(struct drm_encoder *drm_enc) /* don't error check these */ debugfs_create_file("status", 0600, - dpu_enc->debugfs_root, dpu_enc, &debugfs_status_fops); + dpu_enc->debugfs_root, dpu_enc, &_dpu_encoder_status_fops); for (i = 0; i < dpu_enc->num_phys_encs; i++) if (dpu_enc->phys_encs[i]->ops.late_register) @@ -2008,7 +2029,7 @@ static int dpu_encoder_setup_display(struct dpu_encoder_virt *dpu_enc, { int ret = 0; int i = 0; - enum dpu_intf_type intf_type; + enum dpu_intf_type intf_type = INTF_NONE; struct dpu_enc_phys_init_params phys_params; if (!dpu_enc) { @@ -2030,9 +2051,9 @@ static int dpu_encoder_setup_display(struct dpu_encoder_virt *dpu_enc, case DRM_MODE_ENCODER_DSI: intf_type = INTF_DSI; break; - default: - DPU_ERROR_ENC(dpu_enc, "unsupported display interface type\n"); - return -EINVAL; + case DRM_MODE_ENCODER_TMDS: + intf_type = INTF_DP; + break; } WARN_ON(disp_info->num_of_h_tiles < 1); diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c index b5a49050d131..805e059b50b7 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c @@ -100,6 +100,14 @@ static void drm_mode_to_intf_timing_params( * display_v_end -= mode->hsync_start - mode->hdisplay; * } */ + /* for DP/EDP, Shift timings to align it to bottom right */ + if ((phys_enc->hw_intf->cap->type == INTF_DP) || + (phys_enc->hw_intf->cap->type == INTF_EDP)) { + timing->h_back_porch += timing->h_front_porch; + timing->h_front_porch = 0; + timing->v_back_porch += timing->v_front_porch; + timing->v_front_porch = 0; + } } static u32 get_horizontal_total(const struct intf_timing_params *timing) @@ -298,7 +306,6 @@ static void dpu_encoder_phys_vid_vblank_irq(void *arg, int irq_idx) struct dpu_hw_ctl *hw_ctl; unsigned long lock_flags; u32 flush_register = 0; - int new_cnt = -1, old_cnt = -1; hw_ctl = phys_enc->hw_ctl; @@ -308,7 +315,7 @@ static void dpu_encoder_phys_vid_vblank_irq(void *arg, int irq_idx) phys_enc->parent_ops->handle_vblank_virt(phys_enc->parent, phys_enc); - old_cnt = atomic_read(&phys_enc->pending_kickoff_cnt); + atomic_read(&phys_enc->pending_kickoff_cnt); /* * only decrement the pending flush count if we've actually flushed @@ -320,8 +327,7 @@ static void dpu_encoder_phys_vid_vblank_irq(void *arg, int irq_idx) flush_register = hw_ctl->ops.get_flush_register(hw_ctl); if (!(flush_register & hw_ctl->ops.get_pending_flush(hw_ctl))) - new_cnt = atomic_add_unless(&phys_enc->pending_kickoff_cnt, - -1, 0); + atomic_add_unless(&phys_enc->pending_kickoff_cnt, -1, 0); spin_unlock_irqrestore(phys_enc->enc_spinlock, lock_flags); /* Signal any waiting atomic commit thread */ 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 97d122eee96d..60b304b72b7c 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c @@ -684,7 +684,8 @@ static const struct dpu_perf_cfg sc7180_perf_data = { .max_bw_high = 6800000, .min_core_ib = 2400000, .min_llcc_ib = 800000, - .min_dram_ib = 800000, + .min_dram_ib = 1600000, + .min_prefill_lines = 24, .danger_lut_tbl = {0xff, 0xffff, 0x0}, .qos_lut_tbl = { {.nentry = ARRAY_SIZE(sc7180_qos_linear), @@ -701,6 +702,8 @@ static const struct dpu_perf_cfg sc7180_perf_data = { {.rd_enable = 1, .wr_enable = 1}, {.rd_enable = 1, .wr_enable = 0} }, + .clk_inefficiency_factor = 105, + .bw_inefficiency_factor = 120, }; static const struct dpu_perf_cfg sm8150_perf_data = { 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 1b7a9213a756..3544af1a45c5 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h @@ -659,6 +659,8 @@ struct dpu_perf_cdp_cfg { * @downscaling_prefill_lines downscaling latency in lines * @amortizable_theshold minimum y position for traffic shaping prefill * @min_prefill_lines minimum pipeline latency in lines + * @clk_inefficiency_factor DPU src clock inefficiency factor + * @bw_inefficiency_factor DPU axi bus bw inefficiency factor * @safe_lut_tbl: LUT tables for safe signals * @danger_lut_tbl: LUT tables for danger signals * @qos_lut_tbl: LUT tables for QoS signals @@ -683,6 +685,8 @@ struct dpu_perf_cfg { u32 downscaling_prefill_lines; u32 amortizable_threshold; u32 min_prefill_lines; + u32 clk_inefficiency_factor; + u32 bw_inefficiency_factor; u32 safe_lut_tbl[DPU_QOS_LUT_USAGE_MAX]; u32 danger_lut_tbl[DPU_QOS_LUT_USAGE_MAX]; struct dpu_qos_lut_tbl qos_lut_tbl[DPU_QOS_LUT_USAGE_MAX]; diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c index c0a4d4e16d82..d93c44f6996d 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c @@ -85,30 +85,17 @@ static int _dpu_danger_signal_status(struct seq_file *s, return 0; } -#define DEFINE_DPU_DEBUGFS_SEQ_FOPS(__prefix) \ -static int __prefix ## _open(struct inode *inode, struct file *file) \ -{ \ - return single_open(file, __prefix ## _show, inode->i_private); \ -} \ -static const struct file_operations __prefix ## _fops = { \ - .owner = THIS_MODULE, \ - .open = __prefix ## _open, \ - .release = single_release, \ - .read = seq_read, \ - .llseek = seq_lseek, \ -} - static int dpu_debugfs_danger_stats_show(struct seq_file *s, void *v) { return _dpu_danger_signal_status(s, true); } -DEFINE_DPU_DEBUGFS_SEQ_FOPS(dpu_debugfs_danger_stats); +DEFINE_SHOW_ATTRIBUTE(dpu_debugfs_danger_stats); static int dpu_debugfs_safe_stats_show(struct seq_file *s, void *v) { return _dpu_danger_signal_status(s, false); } -DEFINE_DPU_DEBUGFS_SEQ_FOPS(dpu_debugfs_safe_stats); +DEFINE_SHOW_ATTRIBUTE(dpu_debugfs_safe_stats); static void dpu_debugfs_danger_init(struct dpu_kms *dpu_kms, struct dentry *parent) @@ -195,10 +182,15 @@ static int dpu_kms_debugfs_init(struct msm_kms *kms, struct drm_minor *minor) struct dpu_kms *dpu_kms = to_dpu_kms(kms); void *p = dpu_hw_util_get_log_mask_ptr(); struct dentry *entry; + struct drm_device *dev; + struct msm_drm_private *priv; if (!p) return -EINVAL; + dev = dpu_kms->dev; + priv = dev->dev_private; + entry = debugfs_create_dir("debug", minor->debugfs_root); debugfs_create_x32(DPU_DEBUGFS_HWMASKNAME, 0600, entry, p); @@ -207,6 +199,9 @@ static int dpu_kms_debugfs_init(struct msm_kms *kms, struct drm_minor *minor) dpu_debugfs_vbif_init(dpu_kms, entry); dpu_debugfs_core_irq_init(dpu_kms, entry); + if (priv->dp) + msm_dp_debugfs_init(priv->dp, minor); + return dpu_core_perf_debugfs_init(dpu_kms, entry); } #endif @@ -290,6 +285,28 @@ static int dpu_kms_global_obj_init(struct dpu_kms *dpu_kms) return 0; } +static int dpu_kms_parse_data_bus_icc_path(struct dpu_kms *dpu_kms) +{ + struct icc_path *path0; + struct icc_path *path1; + struct drm_device *dev = dpu_kms->dev; + + path0 = of_icc_get(dev->dev, "mdp0-mem"); + path1 = of_icc_get(dev->dev, "mdp1-mem"); + + if (IS_ERR_OR_NULL(path0)) + return PTR_ERR_OR_ZERO(path0); + + dpu_kms->path[0] = path0; + dpu_kms->num_paths = 1; + + if (!IS_ERR_OR_NULL(path1)) { + dpu_kms->path[1] = path1; + dpu_kms->num_paths++; + } + return 0; +} + static int dpu_kms_enable_vblank(struct msm_kms *kms, struct drm_crtc *crtc) { return dpu_crtc_vblank(crtc, true); @@ -479,6 +496,33 @@ static int _dpu_kms_initialize_dsi(struct drm_device *dev, return rc; } +static int _dpu_kms_initialize_displayport(struct drm_device *dev, + struct msm_drm_private *priv, + struct dpu_kms *dpu_kms) +{ + struct drm_encoder *encoder = NULL; + int rc = 0; + + if (!priv->dp) + return rc; + + encoder = dpu_encoder_init(dev, DRM_MODE_ENCODER_TMDS); + if (IS_ERR(encoder)) { + DPU_ERROR("encoder init failed for dsi display\n"); + return PTR_ERR(encoder); + } + + rc = msm_dp_modeset_init(priv->dp, dev, encoder); + if (rc) { + DPU_ERROR("modeset_init failed for DP, rc = %d\n", rc); + drm_encoder_cleanup(encoder); + return rc; + } + + priv->encoders[priv->num_encoders++] = encoder; + return rc; +} + /** * _dpu_kms_setup_displays - create encoders, bridges and connectors * for underlying displays @@ -491,12 +535,21 @@ static int _dpu_kms_setup_displays(struct drm_device *dev, struct msm_drm_private *priv, struct dpu_kms *dpu_kms) { - /** - * Extend this function to initialize other - * types of displays - */ + int rc = 0; - return _dpu_kms_initialize_dsi(dev, priv, dpu_kms); + rc = _dpu_kms_initialize_dsi(dev, priv, dpu_kms); + if (rc) { + DPU_ERROR("initialize_dsi failed, rc = %d\n", rc); + return rc; + } + + rc = _dpu_kms_initialize_displayport(dev, priv, dpu_kms); + if (rc) { + DPU_ERROR("initialize_DP failed, rc = %d\n", rc); + return rc; + } + + return rc; } static void _dpu_kms_drm_obj_destroy(struct dpu_kms *dpu_kms) @@ -681,13 +734,20 @@ static void _dpu_kms_set_encoder_mode(struct msm_kms *kms, info.capabilities = cmd_mode ? MSM_DISPLAY_CAP_CMD_MODE : MSM_DISPLAY_CAP_VID_MODE; - /* TODO: No support for DSI swap */ - for (i = 0; i < ARRAY_SIZE(priv->dsi); i++) { - if (priv->dsi[i]) { - info.h_tile_instance[info.num_of_h_tiles] = i; - info.num_of_h_tiles++; + switch (info.intf_type) { + case DRM_MODE_ENCODER_DSI: + /* TODO: No support for DSI swap */ + for (i = 0; i < ARRAY_SIZE(priv->dsi); i++) { + if (priv->dsi[i]) { + info.h_tile_instance[info.num_of_h_tiles] = i; + info.num_of_h_tiles++; + } } - } + break; + case DRM_MODE_ENCODER_TMDS: + info.num_of_h_tiles = 1; + break; + }; rc = dpu_encoder_setup(encoder->dev, encoder, &info); if (rc) @@ -709,6 +769,23 @@ static void dpu_irq_preinstall(struct msm_kms *kms) dpu_core_irq_preinstall(dpu_kms); } +static int dpu_irq_postinstall(struct msm_kms *kms) +{ + struct msm_drm_private *priv; + struct dpu_kms *dpu_kms = to_dpu_kms(kms); + + if (!dpu_kms || !dpu_kms->dev) + return -EINVAL; + + priv = dpu_kms->dev->dev_private; + if (!priv) + return -EINVAL; + + msm_dp_irq_postinstall(priv->dp); + + return 0; +} + static void dpu_irq_uninstall(struct msm_kms *kms) { struct dpu_kms *dpu_kms = to_dpu_kms(kms); @@ -719,6 +796,7 @@ static void dpu_irq_uninstall(struct msm_kms *kms) static const struct msm_kms_funcs kms_funcs = { .hw_init = dpu_kms_hw_init, .irq_preinstall = dpu_irq_preinstall, + .irq_postinstall = dpu_irq_postinstall, .irq_uninstall = dpu_irq_uninstall, .irq = dpu_irq, .enable_commit = dpu_kms_enable_commit, @@ -952,6 +1030,9 @@ static int dpu_kms_hw_init(struct msm_kms *kms) dpu_vbif_init_memtypes(dpu_kms); + if (of_device_is_compatible(dev->dev->of_node, "qcom,sc7180-mdss")) + dpu_kms_parse_data_bus_icc_path(dpu_kms); + pm_runtime_put_sync(&dpu_kms->pdev->dev); return 0; @@ -1079,7 +1160,7 @@ static int dpu_dev_remove(struct platform_device *pdev) static int __maybe_unused dpu_runtime_suspend(struct device *dev) { - int rc = -1; + int i, rc = -1; struct platform_device *pdev = to_platform_device(dev); struct dpu_kms *dpu_kms = platform_get_drvdata(pdev); struct dss_module_power *mp = &dpu_kms->mp; @@ -1090,6 +1171,9 @@ static int __maybe_unused dpu_runtime_suspend(struct device *dev) if (rc) DPU_ERROR("clock disable failed rc:%d\n", rc); + for (i = 0; i < dpu_kms->num_paths; i++) + icc_set_bw(dpu_kms->path[i], 0, 0); + return rc; } @@ -1101,8 +1185,15 @@ static int __maybe_unused dpu_runtime_resume(struct device *dev) struct drm_encoder *encoder; struct drm_device *ddev; struct dss_module_power *mp = &dpu_kms->mp; + int i; ddev = dpu_kms->dev; + + /* Min vote of BW is required before turning on AXI clk */ + for (i = 0; i < dpu_kms->num_paths; i++) + icc_set_bw(dpu_kms->path[i], 0, + dpu_kms->catalog->perf.min_dram_ib); + rc = msm_dss_enable_clk(mp->clk_config, mp->num_clk, true); if (rc) { DPU_ERROR("clock enable failed rc:%d\n", rc); diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h index e140cd633071..1c0e4c0c9ffb 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h @@ -8,6 +8,8 @@ #ifndef __DPU_KMS_H__ #define __DPU_KMS_H__ +#include <linux/interconnect.h> + #include <drm/drm_drv.h> #include "msm_drv.h" @@ -140,6 +142,8 @@ struct dpu_kms { * when disabled. */ atomic_t bandwidth_ref; + struct icc_path *path[2]; + u32 num_paths; }; struct vsync_info { diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_mdss.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_mdss.c index 7d3fdbb00e7e..cd4078807db1 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_mdss.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_mdss.c @@ -8,7 +8,6 @@ #include <linux/irqdesc.h> #include <linux/irqchip/chained_irq.h> #include "dpu_kms.h" -#include <linux/interconnect.h> #define to_dpu_mdss(x) container_of(x, struct dpu_mdss, base) @@ -277,9 +276,11 @@ int dpu_mdss_init(struct drm_device *dev) DRM_DEBUG("mapped mdss address space @%pK\n", dpu_mdss->mmio); - ret = dpu_mdss_parse_data_bus_icc_path(dev, dpu_mdss); - if (ret) - return ret; + if (!of_device_is_compatible(dev->dev->of_node, "qcom,sc7180-mdss")) { + ret = dpu_mdss_parse_data_bus_icc_path(dev, dpu_mdss); + if (ret) + return ret; + } mp = &dpu_mdss->mp; ret = msm_dss_parse_clock(pdev, mp); diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c index 29e373d2e7b5..7ea90d25a3b6 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c @@ -132,6 +132,86 @@ static struct dpu_kms *_dpu_plane_get_kms(struct drm_plane *plane) } /** + * _dpu_plane_calc_bw - calculate bandwidth required for a plane + * @Plane: Pointer to drm plane. + * Result: Updates calculated bandwidth in the plane state. + * BW Equation: src_w * src_h * bpp * fps * (v_total / v_dest) + * Prefill BW Equation: line src bytes * line_time + */ +static void _dpu_plane_calc_bw(struct drm_plane *plane, + struct drm_framebuffer *fb) +{ + struct dpu_plane *pdpu = to_dpu_plane(plane); + struct dpu_plane_state *pstate; + struct drm_display_mode *mode; + const struct dpu_format *fmt = NULL; + struct dpu_kms *dpu_kms = _dpu_plane_get_kms(plane); + int src_width, src_height, dst_height, fps; + u64 plane_prefill_bw; + u64 plane_bw; + u32 hw_latency_lines; + u64 scale_factor; + int vbp, vpw; + + pstate = to_dpu_plane_state(plane->state); + mode = &plane->state->crtc->mode; + + fmt = dpu_get_dpu_format_ext(fb->format->format, fb->modifier); + + src_width = drm_rect_width(&pdpu->pipe_cfg.src_rect); + src_height = drm_rect_height(&pdpu->pipe_cfg.src_rect); + dst_height = drm_rect_height(&pdpu->pipe_cfg.dst_rect); + fps = drm_mode_vrefresh(mode); + vbp = mode->vtotal - mode->vsync_end; + vpw = mode->vsync_end - mode->vsync_start; + hw_latency_lines = dpu_kms->catalog->perf.min_prefill_lines; + scale_factor = src_height > dst_height ? + mult_frac(src_height, 1, dst_height) : 1; + + plane_bw = + src_width * mode->vtotal * fps * fmt->bpp * + scale_factor; + + plane_prefill_bw = + src_width * hw_latency_lines * fps * fmt->bpp * + scale_factor * mode->vtotal; + + do_div(plane_prefill_bw, (vbp+vpw)); + + pstate->plane_fetch_bw = max(plane_bw, plane_prefill_bw); +} + +/** + * _dpu_plane_calc_clk - calculate clock required for a plane + * @Plane: Pointer to drm plane. + * Result: Updates calculated clock in the plane state. + * Clock equation: dst_w * v_total * fps * (src_h / dst_h) + */ +static void _dpu_plane_calc_clk(struct drm_plane *plane) +{ + struct dpu_plane *pdpu = to_dpu_plane(plane); + struct dpu_plane_state *pstate; + struct drm_display_mode *mode; + int dst_width, src_height, dst_height, fps; + + pstate = to_dpu_plane_state(plane->state); + mode = &plane->state->crtc->mode; + + src_height = drm_rect_height(&pdpu->pipe_cfg.src_rect); + dst_width = drm_rect_width(&pdpu->pipe_cfg.dst_rect); + dst_height = drm_rect_height(&pdpu->pipe_cfg.dst_rect); + fps = drm_mode_vrefresh(mode); + + pstate->plane_clk = + dst_width * mode->vtotal * fps; + + if (src_height > dst_height) { + pstate->plane_clk *= src_height; + do_div(pstate->plane_clk, dst_height); + } +} + +/** * _dpu_plane_calc_fill_level - calculate fill level of the given source format * @plane: Pointer to drm plane * @fmt: Pointer to source buffer format @@ -1102,6 +1182,10 @@ static void dpu_plane_sspp_atomic_update(struct drm_plane *plane) } _dpu_plane_set_qos_remap(plane); + + _dpu_plane_calc_bw(plane, fb); + + _dpu_plane_calc_clk(plane); } static void _dpu_plane_atomic_disable(struct drm_plane *plane) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.h index 456949713e90..ca83b8753d59 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.h +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.h @@ -25,6 +25,8 @@ * @scaler3_cfg: configuration data for scaler3 * @pixel_ext: configuration data for pixel extensions * @cdp_cfg: CDP configuration + * @plane_fetch_bw: calculated BW per plane + * @plane_clk: calculated clk per plane */ struct dpu_plane_state { struct drm_plane_state base; @@ -39,6 +41,8 @@ struct dpu_plane_state { struct dpu_hw_pixel_ext pixel_ext; struct dpu_hw_pipe_cdp_cfg cdp_cfg; + u64 plane_fetch_bw; + u64 plane_clk; }; /** diff --git a/drivers/gpu/drm/msm/disp/mdp4/mdp4_dtv_encoder.c b/drivers/gpu/drm/msm/disp/mdp4/mdp4_dtv_encoder.c index 5d8956055286..88645dbc3785 100644 --- a/drivers/gpu/drm/msm/disp/mdp4/mdp4_dtv_encoder.c +++ b/drivers/gpu/drm/msm/disp/mdp4/mdp4_dtv_encoder.c @@ -25,54 +25,9 @@ static struct mdp4_kms *get_kms(struct drm_encoder *encoder) return to_mdp4_kms(to_mdp_kms(priv->kms)); } -#ifdef DOWNSTREAM_CONFIG_MSM_BUS_SCALING -#include <mach/board.h> -/* not ironically named at all.. no, really.. */ -static void bs_init(struct mdp4_dtv_encoder *mdp4_dtv_encoder) -{ - struct drm_device *dev = mdp4_dtv_encoder->base.dev; - struct lcdc_platform_data *dtv_pdata = mdp4_find_pdata("dtv.0"); - - if (!dtv_pdata) { - DRM_DEV_ERROR(dev->dev, "could not find dtv pdata\n"); - return; - } - - if (dtv_pdata->bus_scale_table) { - mdp4_dtv_encoder->bsc = msm_bus_scale_register_client( - dtv_pdata->bus_scale_table); - DBG("bus scale client: %08x", mdp4_dtv_encoder->bsc); - DBG("lcdc_power_save: %p", dtv_pdata->lcdc_power_save); - if (dtv_pdata->lcdc_power_save) - dtv_pdata->lcdc_power_save(1); - } -} - -static void bs_fini(struct mdp4_dtv_encoder *mdp4_dtv_encoder) -{ - if (mdp4_dtv_encoder->bsc) { - msm_bus_scale_unregister_client(mdp4_dtv_encoder->bsc); - mdp4_dtv_encoder->bsc = 0; - } -} - -static void bs_set(struct mdp4_dtv_encoder *mdp4_dtv_encoder, int idx) -{ - if (mdp4_dtv_encoder->bsc) { - DBG("set bus scaling: %d", idx); - msm_bus_scale_client_update_request(mdp4_dtv_encoder->bsc, idx); - } -} -#else -static void bs_init(struct mdp4_dtv_encoder *mdp4_dtv_encoder) {} -static void bs_fini(struct mdp4_dtv_encoder *mdp4_dtv_encoder) {} -static void bs_set(struct mdp4_dtv_encoder *mdp4_dtv_encoder, int idx) {} -#endif - static void mdp4_dtv_encoder_destroy(struct drm_encoder *encoder) { struct mdp4_dtv_encoder *mdp4_dtv_encoder = to_mdp4_dtv_encoder(encoder); - bs_fini(mdp4_dtv_encoder); drm_encoder_cleanup(encoder); kfree(mdp4_dtv_encoder); } @@ -162,8 +117,6 @@ static void mdp4_dtv_encoder_disable(struct drm_encoder *encoder) clk_disable_unprepare(mdp4_dtv_encoder->hdmi_clk); clk_disable_unprepare(mdp4_dtv_encoder->mdp_clk); - bs_set(mdp4_dtv_encoder, 0); - mdp4_dtv_encoder->enabled = false; } @@ -185,8 +138,6 @@ static void mdp4_dtv_encoder_enable(struct drm_encoder *encoder) MDP4_DMA_CONFIG_PACK(0x21)); mdp4_crtc_set_intf(encoder->crtc, INTF_LCDC_DTV, 1); - bs_set(mdp4_dtv_encoder, 1); - DBG("setting mdp_clk=%lu", pc); ret = clk_set_rate(mdp4_dtv_encoder->mdp_clk, pc); @@ -252,8 +203,6 @@ struct drm_encoder *mdp4_dtv_encoder_init(struct drm_device *dev) goto fail; } - bs_init(mdp4_dtv_encoder); - return encoder; fail: diff --git a/drivers/gpu/drm/msm/disp/mdp4/mdp4_kms.h b/drivers/gpu/drm/msm/disp/mdp4/mdp4_kms.h index 18933bd81c77..e8ee92ab7956 100644 --- a/drivers/gpu/drm/msm/disp/mdp4/mdp4_kms.h +++ b/drivers/gpu/drm/msm/disp/mdp4/mdp4_kms.h @@ -222,17 +222,4 @@ static inline struct clk *mpd4_lvds_pll_init(struct drm_device *dev) } #endif -#ifdef DOWNSTREAM_CONFIG_MSM_BUS_SCALING -/* bus scaling data is associated with extra pointless platform devices, - * "dtv", etc.. this is a bit of a hack, but we need a way for encoders - * to find their pdata to make the bus-scaling stuff work. - */ -static inline void *mdp4_find_pdata(const char *devname) -{ - struct device *dev; - dev = bus_find_device_by_name(&platform_bus_type, NULL, devname); - return dev ? dev->platform_data : NULL; -} -#endif - #endif /* __MDP4_KMS_H__ */ diff --git a/drivers/gpu/drm/msm/disp/mdp4/mdp4_lcdc_encoder.c b/drivers/gpu/drm/msm/disp/mdp4/mdp4_lcdc_encoder.c index 871f3514ef69..10eb3e5b218e 100644 --- a/drivers/gpu/drm/msm/disp/mdp4/mdp4_lcdc_encoder.c +++ b/drivers/gpu/drm/msm/disp/mdp4/mdp4_lcdc_encoder.c @@ -30,51 +30,10 @@ static struct mdp4_kms *get_kms(struct drm_encoder *encoder) return to_mdp4_kms(to_mdp_kms(priv->kms)); } -#ifdef DOWNSTREAM_CONFIG_MSM_BUS_SCALING -#include <mach/board.h> -static void bs_init(struct mdp4_lcdc_encoder *mdp4_lcdc_encoder) -{ - struct drm_device *dev = mdp4_lcdc_encoder->base.dev; - struct lcdc_platform_data *lcdc_pdata = mdp4_find_pdata("lvds.0"); - - if (!lcdc_pdata) { - DRM_DEV_ERROR(dev->dev, "could not find lvds pdata\n"); - return; - } - - if (lcdc_pdata->bus_scale_table) { - mdp4_lcdc_encoder->bsc = msm_bus_scale_register_client( - lcdc_pdata->bus_scale_table); - DBG("lvds : bus scale client: %08x", mdp4_lcdc_encoder->bsc); - } -} - -static void bs_fini(struct mdp4_lcdc_encoder *mdp4_lcdc_encoder) -{ - if (mdp4_lcdc_encoder->bsc) { - msm_bus_scale_unregister_client(mdp4_lcdc_encoder->bsc); - mdp4_lcdc_encoder->bsc = 0; - } -} - -static void bs_set(struct mdp4_lcdc_encoder *mdp4_lcdc_encoder, int idx) -{ - if (mdp4_lcdc_encoder->bsc) { - DBG("set bus scaling: %d", idx); - msm_bus_scale_client_update_request(mdp4_lcdc_encoder->bsc, idx); - } -} -#else -static void bs_init(struct mdp4_lcdc_encoder *mdp4_lcdc_encoder) {} -static void bs_fini(struct mdp4_lcdc_encoder *mdp4_lcdc_encoder) {} -static void bs_set(struct mdp4_lcdc_encoder *mdp4_lcdc_encoder, int idx) {} -#endif - static void mdp4_lcdc_encoder_destroy(struct drm_encoder *encoder) { struct mdp4_lcdc_encoder *mdp4_lcdc_encoder = to_mdp4_lcdc_encoder(encoder); - bs_fini(mdp4_lcdc_encoder); drm_encoder_cleanup(encoder); kfree(mdp4_lcdc_encoder); } @@ -348,8 +307,6 @@ static void mdp4_lcdc_encoder_disable(struct drm_encoder *encoder) DRM_DEV_ERROR(dev->dev, "failed to disable regulator: %d\n", ret); } - bs_set(mdp4_lcdc_encoder, 0); - mdp4_lcdc_encoder->enabled = false; } @@ -382,8 +339,6 @@ static void mdp4_lcdc_encoder_enable(struct drm_encoder *encoder) mdp4_crtc_set_config(encoder->crtc, config); mdp4_crtc_set_intf(encoder->crtc, INTF_LCDC_DTV, 0); - bs_set(mdp4_lcdc_encoder, 1); - for (i = 0; i < ARRAY_SIZE(mdp4_lcdc_encoder->regs); i++) { ret = regulator_enable(mdp4_lcdc_encoder->regs[i]); if (ret) @@ -480,8 +435,6 @@ struct drm_encoder *mdp4_lcdc_encoder_init(struct drm_device *dev, } mdp4_lcdc_encoder->regs[2] = reg; - bs_init(mdp4_lcdc_encoder); - return encoder; fail: diff --git a/drivers/gpu/drm/msm/disp/mdp5/mdp5_cmd_encoder.c b/drivers/gpu/drm/msm/disp/mdp5/mdp5_cmd_encoder.c index eeef41fcd4e1..ff2c1d583c79 100644 --- a/drivers/gpu/drm/msm/disp/mdp5/mdp5_cmd_encoder.c +++ b/drivers/gpu/drm/msm/disp/mdp5/mdp5_cmd_encoder.c @@ -14,27 +14,6 @@ static struct mdp5_kms *get_kms(struct drm_encoder *encoder) return to_mdp5_kms(to_mdp_kms(priv->kms)); } -#ifdef DOWNSTREAM_CONFIG_MSM_BUS_SCALING -#include <mach/board.h> -#include <linux/msm-bus.h> -#include <linux/msm-bus-board.h> - -static void bs_set(struct mdp5_encoder *mdp5_cmd_enc, int idx) -{ - if (mdp5_cmd_enc->bsc) { - DBG("set bus scaling: %d", idx); - /* HACK: scaling down, and then immediately back up - * seems to leave things broken (underflow).. so - * never disable: - */ - idx = 1; - msm_bus_scale_client_update_request(mdp5_cmd_enc->bsc, idx); - } -} -#else -static void bs_set(struct mdp5_encoder *mdp5_cmd_enc, int idx) {} -#endif - #define VSYNC_CLK_RATE 19200000 static int pingpong_tearcheck_setup(struct drm_encoder *encoder, struct drm_display_mode *mode) @@ -146,8 +125,6 @@ void mdp5_cmd_encoder_disable(struct drm_encoder *encoder) mdp5_ctl_set_encoder_state(ctl, pipeline, false); mdp5_ctl_commit(ctl, pipeline, mdp_ctl_flush_mask_encoder(intf), true); - bs_set(mdp5_cmd_enc, 0); - mdp5_cmd_enc->enabled = false; } @@ -161,7 +138,6 @@ void mdp5_cmd_encoder_enable(struct drm_encoder *encoder) if (WARN_ON(mdp5_cmd_enc->enabled)) return; - bs_set(mdp5_cmd_enc, 1); if (pingpong_tearcheck_enable(encoder)) return; diff --git a/drivers/gpu/drm/msm/disp/mdp5/mdp5_encoder.c b/drivers/gpu/drm/msm/disp/mdp5/mdp5_encoder.c index f48827283c2b..79d67c495780 100644 --- a/drivers/gpu/drm/msm/disp/mdp5/mdp5_encoder.c +++ b/drivers/gpu/drm/msm/disp/mdp5/mdp5_encoder.c @@ -16,72 +16,9 @@ static struct mdp5_kms *get_kms(struct drm_encoder *encoder) return to_mdp5_kms(to_mdp_kms(priv->kms)); } -#ifdef DOWNSTREAM_CONFIG_MSM_BUS_SCALING -#include <mach/board.h> -#include <mach/msm_bus.h> -#include <mach/msm_bus_board.h> -#define MDP_BUS_VECTOR_ENTRY(ab_val, ib_val) \ - { \ - .src = MSM_BUS_MASTER_MDP_PORT0, \ - .dst = MSM_BUS_SLAVE_EBI_CH0, \ - .ab = (ab_val), \ - .ib = (ib_val), \ - } - -static struct msm_bus_vectors mdp_bus_vectors[] = { - MDP_BUS_VECTOR_ENTRY(0, 0), - MDP_BUS_VECTOR_ENTRY(2000000000, 2000000000), -}; -static struct msm_bus_paths mdp_bus_usecases[] = { { - .num_paths = 1, - .vectors = &mdp_bus_vectors[0], -}, { - .num_paths = 1, - .vectors = &mdp_bus_vectors[1], -} }; -static struct msm_bus_scale_pdata mdp_bus_scale_table = { - .usecase = mdp_bus_usecases, - .num_usecases = ARRAY_SIZE(mdp_bus_usecases), - .name = "mdss_mdp", -}; - -static void bs_init(struct mdp5_encoder *mdp5_encoder) -{ - mdp5_encoder->bsc = msm_bus_scale_register_client( - &mdp_bus_scale_table); - DBG("bus scale client: %08x", mdp5_encoder->bsc); -} - -static void bs_fini(struct mdp5_encoder *mdp5_encoder) -{ - if (mdp5_encoder->bsc) { - msm_bus_scale_unregister_client(mdp5_encoder->bsc); - mdp5_encoder->bsc = 0; - } -} - -static void bs_set(struct mdp5_encoder *mdp5_encoder, int idx) -{ - if (mdp5_encoder->bsc) { - DBG("set bus scaling: %d", idx); - /* HACK: scaling down, and then immediately back up - * seems to leave things broken (underflow).. so - * never disable: - */ - idx = 1; - msm_bus_scale_client_update_request(mdp5_encoder->bsc, idx); - } -} -#else -static void bs_init(struct mdp5_encoder *mdp5_encoder) {} -static void bs_fini(struct mdp5_encoder *mdp5_encoder) {} -static void bs_set(struct mdp5_encoder *mdp5_encoder, int idx) {} -#endif - static void mdp5_encoder_destroy(struct drm_encoder *encoder) { struct mdp5_encoder *mdp5_encoder = to_mdp5_encoder(encoder); - bs_fini(mdp5_encoder); drm_encoder_cleanup(encoder); kfree(mdp5_encoder); } @@ -222,8 +159,6 @@ static void mdp5_vid_encoder_disable(struct drm_encoder *encoder) */ mdp_irq_wait(&mdp5_kms->base, intf2vblank(mixer, intf)); - bs_set(mdp5_encoder, 0); - mdp5_encoder->enabled = false; } @@ -240,7 +175,6 @@ static void mdp5_vid_encoder_enable(struct drm_encoder *encoder) if (WARN_ON(mdp5_encoder->enabled)) return; - bs_set(mdp5_encoder, 1); spin_lock_irqsave(&mdp5_encoder->intf_lock, flags); mdp5_write(mdp5_kms, REG_MDP5_INTF_TIMING_ENGINE_EN(intfn), 1); spin_unlock_irqrestore(&mdp5_encoder->intf_lock, flags); @@ -426,8 +360,6 @@ struct drm_encoder *mdp5_encoder_init(struct drm_device *dev, drm_encoder_helper_add(encoder, &mdp5_encoder_helper_funcs); - bs_init(mdp5_encoder); - return encoder; fail: |