Merge tag 'drm-msm-next-2017-08-22' of git://people.freedesktop.org/~robclark/linux into drm-next
Updates for 4.14.. I have some further patches from Jordan to add multiple priority levels and pre-emption, but those will probably be for 4.15 to give me time for the mesa parts. * tag 'drm-msm-next-2017-08-22' of git://people.freedesktop.org/~robclark/linux: drm/msm/mdp5: mark runtime_pm functions as __maybe_unused drm/msm: remove unused variable drm/msm/mdp5: make helper function static drm/msm: make msm_framebuffer_init() static drm/msm: add helper to allocate stolen fb drm/msm: don't track fbdev's gem object separately drm/msm: add modeset module param drm/msm/mdp5: add tracking for clk enable-count drm/msm: remove unused define drm/msm: Add a helper function for in-kernel buffer allocations drm/msm: Attach the GPU MMU when it is created drm/msm: Add A5XX hardware fault detection drm/msm: Remove uneeded platform dev members drm/msm/mdp5: Set up runtime PM for MDSS drm/msm/mdp5: Write to SMP registers even if allocations don't change drm/msm/mdp5: Don't use mode_set helper funcs for encoders and CRTCs drm/msm/dsi: Implement RPM suspend/resume callbacks drm/msm/dsi: Set up runtime PM for DSI drm/msm/hdmi: Set up runtime PM for HDMI drm/msm/mdp5: Use runtime PM get/put API instead of toggling clocks
This commit is contained in:
@@ -192,6 +192,7 @@ int mdp5_cmd_encoder_set_split_display(struct drm_encoder *encoder,
|
||||
{
|
||||
struct mdp5_encoder *mdp5_cmd_enc = to_mdp5_encoder(encoder);
|
||||
struct mdp5_kms *mdp5_kms;
|
||||
struct device *dev;
|
||||
int intf_num;
|
||||
u32 data = 0;
|
||||
|
||||
@@ -214,14 +215,16 @@ int mdp5_cmd_encoder_set_split_display(struct drm_encoder *encoder,
|
||||
/* Smart Panel, Sync mode */
|
||||
data |= MDP5_SPLIT_DPL_UPPER_SMART_PANEL;
|
||||
|
||||
dev = &mdp5_kms->pdev->dev;
|
||||
|
||||
/* Make sure clocks are on when connectors calling this function. */
|
||||
mdp5_enable(mdp5_kms);
|
||||
pm_runtime_get_sync(dev);
|
||||
mdp5_write(mdp5_kms, REG_MDP5_SPLIT_DPL_UPPER, data);
|
||||
|
||||
mdp5_write(mdp5_kms, REG_MDP5_SPLIT_DPL_LOWER,
|
||||
MDP5_SPLIT_DPL_LOWER_SMART_PANEL);
|
||||
mdp5_write(mdp5_kms, REG_MDP5_SPLIT_DPL_EN, 1);
|
||||
mdp5_disable(mdp5_kms);
|
||||
pm_runtime_put_autosuspend(dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@@ -415,6 +415,7 @@ static void mdp5_crtc_atomic_disable(struct drm_crtc *crtc,
|
||||
struct mdp5_crtc *mdp5_crtc = to_mdp5_crtc(crtc);
|
||||
struct mdp5_crtc_state *mdp5_cstate = to_mdp5_crtc_state(crtc->state);
|
||||
struct mdp5_kms *mdp5_kms = get_kms(crtc);
|
||||
struct device *dev = &mdp5_kms->pdev->dev;
|
||||
|
||||
DBG("%s", crtc->name);
|
||||
|
||||
@@ -425,7 +426,7 @@ static void mdp5_crtc_atomic_disable(struct drm_crtc *crtc,
|
||||
mdp_irq_unregister(&mdp5_kms->base, &mdp5_crtc->pp_done);
|
||||
|
||||
mdp_irq_unregister(&mdp5_kms->base, &mdp5_crtc->err);
|
||||
mdp5_disable(mdp5_kms);
|
||||
pm_runtime_put_autosuspend(dev);
|
||||
|
||||
mdp5_crtc->enabled = false;
|
||||
}
|
||||
@@ -436,13 +437,17 @@ static void mdp5_crtc_atomic_enable(struct drm_crtc *crtc,
|
||||
struct mdp5_crtc *mdp5_crtc = to_mdp5_crtc(crtc);
|
||||
struct mdp5_crtc_state *mdp5_cstate = to_mdp5_crtc_state(crtc->state);
|
||||
struct mdp5_kms *mdp5_kms = get_kms(crtc);
|
||||
struct device *dev = &mdp5_kms->pdev->dev;
|
||||
|
||||
DBG("%s", crtc->name);
|
||||
|
||||
if (WARN_ON(mdp5_crtc->enabled))
|
||||
return;
|
||||
|
||||
mdp5_enable(mdp5_kms);
|
||||
pm_runtime_get_sync(dev);
|
||||
|
||||
mdp5_crtc_mode_set_nofb(crtc);
|
||||
|
||||
mdp_irq_register(&mdp5_kms->base, &mdp5_crtc->err);
|
||||
|
||||
if (mdp5_cstate->cmd_mode)
|
||||
@@ -533,7 +538,7 @@ static bool is_fullscreen(struct drm_crtc_state *cstate,
|
||||
((pstate->crtc_y + pstate->crtc_h) >= cstate->mode.vdisplay);
|
||||
}
|
||||
|
||||
enum mdp_mixer_stage_id get_start_stage(struct drm_crtc *crtc,
|
||||
static enum mdp_mixer_stage_id get_start_stage(struct drm_crtc *crtc,
|
||||
struct drm_crtc_state *new_crtc_state,
|
||||
struct drm_plane_state *bpstate)
|
||||
{
|
||||
@@ -727,6 +732,7 @@ static int mdp5_crtc_cursor_set(struct drm_crtc *crtc,
|
||||
struct mdp5_pipeline *pipeline = &mdp5_cstate->pipeline;
|
||||
struct drm_device *dev = crtc->dev;
|
||||
struct mdp5_kms *mdp5_kms = get_kms(crtc);
|
||||
struct platform_device *pdev = mdp5_kms->pdev;
|
||||
struct msm_kms *kms = &mdp5_kms->base.base;
|
||||
struct drm_gem_object *cursor_bo, *old_bo = NULL;
|
||||
uint32_t blendcfg, stride;
|
||||
@@ -755,7 +761,7 @@ static int mdp5_crtc_cursor_set(struct drm_crtc *crtc,
|
||||
if (!handle) {
|
||||
DBG("Cursor off");
|
||||
cursor_enable = false;
|
||||
mdp5_enable(mdp5_kms);
|
||||
pm_runtime_get_sync(&pdev->dev);
|
||||
goto set_cursor;
|
||||
}
|
||||
|
||||
@@ -770,6 +776,8 @@ static int mdp5_crtc_cursor_set(struct drm_crtc *crtc,
|
||||
lm = mdp5_cstate->pipeline.mixer->lm;
|
||||
stride = width * drm_format_plane_cpp(DRM_FORMAT_ARGB8888, 0);
|
||||
|
||||
pm_runtime_get_sync(&pdev->dev);
|
||||
|
||||
spin_lock_irqsave(&mdp5_crtc->cursor.lock, flags);
|
||||
old_bo = mdp5_crtc->cursor.scanout_bo;
|
||||
|
||||
@@ -779,8 +787,6 @@ static int mdp5_crtc_cursor_set(struct drm_crtc *crtc,
|
||||
|
||||
get_roi(crtc, &roi_w, &roi_h);
|
||||
|
||||
mdp5_enable(mdp5_kms);
|
||||
|
||||
mdp5_write(mdp5_kms, REG_MDP5_LM_CURSOR_STRIDE(lm), stride);
|
||||
mdp5_write(mdp5_kms, REG_MDP5_LM_CURSOR_FORMAT(lm),
|
||||
MDP5_LM_CURSOR_FORMAT_FORMAT(CURSOR_FMT_ARGB8888));
|
||||
@@ -798,6 +804,8 @@ static int mdp5_crtc_cursor_set(struct drm_crtc *crtc,
|
||||
|
||||
spin_unlock_irqrestore(&mdp5_crtc->cursor.lock, flags);
|
||||
|
||||
pm_runtime_put_autosuspend(&pdev->dev);
|
||||
|
||||
set_cursor:
|
||||
ret = mdp5_ctl_set_cursor(ctl, pipeline, 0, cursor_enable);
|
||||
if (ret) {
|
||||
@@ -809,7 +817,7 @@ set_cursor:
|
||||
crtc_flush(crtc, flush_mask);
|
||||
|
||||
end:
|
||||
mdp5_disable(mdp5_kms);
|
||||
pm_runtime_put_autosuspend(&pdev->dev);
|
||||
if (old_bo) {
|
||||
drm_flip_work_queue(&mdp5_crtc->unref_cursor_work, old_bo);
|
||||
/* enable vblank to complete cursor work: */
|
||||
@@ -842,7 +850,7 @@ static int mdp5_crtc_cursor_move(struct drm_crtc *crtc, int x, int y)
|
||||
|
||||
get_roi(crtc, &roi_w, &roi_h);
|
||||
|
||||
mdp5_enable(mdp5_kms);
|
||||
pm_runtime_get_sync(&mdp5_kms->pdev->dev);
|
||||
|
||||
spin_lock_irqsave(&mdp5_crtc->cursor.lock, flags);
|
||||
mdp5_write(mdp5_kms, REG_MDP5_LM_CURSOR_SIZE(lm),
|
||||
@@ -855,7 +863,7 @@ static int mdp5_crtc_cursor_move(struct drm_crtc *crtc, int x, int y)
|
||||
|
||||
crtc_flush(crtc, flush_mask);
|
||||
|
||||
mdp5_disable(mdp5_kms);
|
||||
pm_runtime_put_autosuspend(&mdp5_kms->pdev->dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@@ -297,6 +297,10 @@ static void mdp5_encoder_enable(struct drm_encoder *encoder)
|
||||
{
|
||||
struct mdp5_encoder *mdp5_encoder = to_mdp5_encoder(encoder);
|
||||
struct mdp5_interface *intf = mdp5_encoder->intf;
|
||||
/* this isn't right I think */
|
||||
struct drm_crtc_state *cstate = encoder->crtc->state;
|
||||
|
||||
mdp5_encoder_mode_set(encoder, &cstate->mode, &cstate->adjusted_mode);
|
||||
|
||||
if (intf->mode == MDP5_INTF_DSI_MODE_COMMAND)
|
||||
mdp5_cmd_encoder_enable(encoder);
|
||||
@@ -320,7 +324,6 @@ static int mdp5_encoder_atomic_check(struct drm_encoder *encoder,
|
||||
}
|
||||
|
||||
static const struct drm_encoder_helper_funcs mdp5_encoder_helper_funcs = {
|
||||
.mode_set = mdp5_encoder_mode_set,
|
||||
.disable = mdp5_encoder_disable,
|
||||
.enable = mdp5_encoder_enable,
|
||||
.atomic_check = mdp5_encoder_atomic_check,
|
||||
@@ -350,6 +353,7 @@ int mdp5_vid_encoder_set_split_display(struct drm_encoder *encoder,
|
||||
struct mdp5_encoder *mdp5_encoder = to_mdp5_encoder(encoder);
|
||||
struct mdp5_encoder *mdp5_slave_enc = to_mdp5_encoder(slave_encoder);
|
||||
struct mdp5_kms *mdp5_kms;
|
||||
struct device *dev;
|
||||
int intf_num;
|
||||
u32 data = 0;
|
||||
|
||||
@@ -369,8 +373,10 @@ int mdp5_vid_encoder_set_split_display(struct drm_encoder *encoder,
|
||||
else
|
||||
return -EINVAL;
|
||||
|
||||
dev = &mdp5_kms->pdev->dev;
|
||||
/* Make sure clocks are on when connectors calling this function. */
|
||||
mdp5_enable(mdp5_kms);
|
||||
pm_runtime_get_sync(dev);
|
||||
|
||||
/* Dumb Panel, Sync mode */
|
||||
mdp5_write(mdp5_kms, REG_MDP5_SPLIT_DPL_UPPER, 0);
|
||||
mdp5_write(mdp5_kms, REG_MDP5_SPLIT_DPL_LOWER, data);
|
||||
@@ -378,7 +384,7 @@ int mdp5_vid_encoder_set_split_display(struct drm_encoder *encoder,
|
||||
|
||||
mdp5_ctl_pair(mdp5_encoder->ctl, mdp5_slave_enc->ctl, true);
|
||||
|
||||
mdp5_disable(mdp5_kms);
|
||||
pm_runtime_put_autosuspend(dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@@ -49,16 +49,19 @@ static void mdp5_irq_error_handler(struct mdp_irq *irq, uint32_t irqstatus)
|
||||
void mdp5_irq_preinstall(struct msm_kms *kms)
|
||||
{
|
||||
struct mdp5_kms *mdp5_kms = to_mdp5_kms(to_mdp_kms(kms));
|
||||
mdp5_enable(mdp5_kms);
|
||||
struct device *dev = &mdp5_kms->pdev->dev;
|
||||
|
||||
pm_runtime_get_sync(dev);
|
||||
mdp5_write(mdp5_kms, REG_MDP5_INTR_CLEAR, 0xffffffff);
|
||||
mdp5_write(mdp5_kms, REG_MDP5_INTR_EN, 0x00000000);
|
||||
mdp5_disable(mdp5_kms);
|
||||
pm_runtime_put_autosuspend(dev);
|
||||
}
|
||||
|
||||
int mdp5_irq_postinstall(struct msm_kms *kms)
|
||||
{
|
||||
struct mdp_kms *mdp_kms = to_mdp_kms(kms);
|
||||
struct mdp5_kms *mdp5_kms = to_mdp5_kms(mdp_kms);
|
||||
struct device *dev = &mdp5_kms->pdev->dev;
|
||||
struct mdp_irq *error_handler = &mdp5_kms->error_handler;
|
||||
|
||||
error_handler->irq = mdp5_irq_error_handler;
|
||||
@@ -67,9 +70,9 @@ int mdp5_irq_postinstall(struct msm_kms *kms)
|
||||
MDP5_IRQ_INTF2_UNDER_RUN |
|
||||
MDP5_IRQ_INTF3_UNDER_RUN;
|
||||
|
||||
mdp5_enable(mdp5_kms);
|
||||
pm_runtime_get_sync(dev);
|
||||
mdp_irq_register(mdp_kms, error_handler);
|
||||
mdp5_disable(mdp5_kms);
|
||||
pm_runtime_put_autosuspend(dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -77,9 +80,11 @@ int mdp5_irq_postinstall(struct msm_kms *kms)
|
||||
void mdp5_irq_uninstall(struct msm_kms *kms)
|
||||
{
|
||||
struct mdp5_kms *mdp5_kms = to_mdp5_kms(to_mdp_kms(kms));
|
||||
mdp5_enable(mdp5_kms);
|
||||
struct device *dev = &mdp5_kms->pdev->dev;
|
||||
|
||||
pm_runtime_get_sync(dev);
|
||||
mdp5_write(mdp5_kms, REG_MDP5_INTR_EN, 0x00000000);
|
||||
mdp5_disable(mdp5_kms);
|
||||
pm_runtime_put_autosuspend(dev);
|
||||
}
|
||||
|
||||
irqreturn_t mdp5_irq(struct msm_kms *kms)
|
||||
@@ -109,11 +114,12 @@ irqreturn_t mdp5_irq(struct msm_kms *kms)
|
||||
int mdp5_enable_vblank(struct msm_kms *kms, struct drm_crtc *crtc)
|
||||
{
|
||||
struct mdp5_kms *mdp5_kms = to_mdp5_kms(to_mdp_kms(kms));
|
||||
struct device *dev = &mdp5_kms->pdev->dev;
|
||||
|
||||
mdp5_enable(mdp5_kms);
|
||||
pm_runtime_get_sync(dev);
|
||||
mdp_update_vblank_mask(to_mdp_kms(kms),
|
||||
mdp5_crtc_vblank(crtc), true);
|
||||
mdp5_disable(mdp5_kms);
|
||||
pm_runtime_put_autosuspend(dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -121,9 +127,10 @@ int mdp5_enable_vblank(struct msm_kms *kms, struct drm_crtc *crtc)
|
||||
void mdp5_disable_vblank(struct msm_kms *kms, struct drm_crtc *crtc)
|
||||
{
|
||||
struct mdp5_kms *mdp5_kms = to_mdp5_kms(to_mdp_kms(kms));
|
||||
struct device *dev = &mdp5_kms->pdev->dev;
|
||||
|
||||
mdp5_enable(mdp5_kms);
|
||||
pm_runtime_get_sync(dev);
|
||||
mdp_update_vblank_mask(to_mdp_kms(kms),
|
||||
mdp5_crtc_vblank(crtc), false);
|
||||
mdp5_disable(mdp5_kms);
|
||||
pm_runtime_put_autosuspend(dev);
|
||||
}
|
||||
|
@@ -30,11 +30,10 @@ static const char *iommu_ports[] = {
|
||||
static int mdp5_hw_init(struct msm_kms *kms)
|
||||
{
|
||||
struct mdp5_kms *mdp5_kms = to_mdp5_kms(to_mdp_kms(kms));
|
||||
struct platform_device *pdev = mdp5_kms->pdev;
|
||||
struct device *dev = &mdp5_kms->pdev->dev;
|
||||
unsigned long flags;
|
||||
|
||||
pm_runtime_get_sync(&pdev->dev);
|
||||
mdp5_enable(mdp5_kms);
|
||||
pm_runtime_get_sync(dev);
|
||||
|
||||
/* Magic unknown register writes:
|
||||
*
|
||||
@@ -66,8 +65,7 @@ static int mdp5_hw_init(struct msm_kms *kms)
|
||||
|
||||
mdp5_ctlm_hw_reset(mdp5_kms->ctlm);
|
||||
|
||||
mdp5_disable(mdp5_kms);
|
||||
pm_runtime_put_sync(&pdev->dev);
|
||||
pm_runtime_put_sync(dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -111,8 +109,9 @@ static void mdp5_swap_state(struct msm_kms *kms, struct drm_atomic_state *state)
|
||||
static void mdp5_prepare_commit(struct msm_kms *kms, struct drm_atomic_state *state)
|
||||
{
|
||||
struct mdp5_kms *mdp5_kms = to_mdp5_kms(to_mdp_kms(kms));
|
||||
struct device *dev = &mdp5_kms->pdev->dev;
|
||||
|
||||
mdp5_enable(mdp5_kms);
|
||||
pm_runtime_get_sync(dev);
|
||||
|
||||
if (mdp5_kms->smp)
|
||||
mdp5_smp_prepare_commit(mdp5_kms->smp, &mdp5_kms->state->smp);
|
||||
@@ -121,11 +120,12 @@ static void mdp5_prepare_commit(struct msm_kms *kms, struct drm_atomic_state *st
|
||||
static void mdp5_complete_commit(struct msm_kms *kms, struct drm_atomic_state *state)
|
||||
{
|
||||
struct mdp5_kms *mdp5_kms = to_mdp5_kms(to_mdp_kms(kms));
|
||||
struct device *dev = &mdp5_kms->pdev->dev;
|
||||
|
||||
if (mdp5_kms->smp)
|
||||
mdp5_smp_complete_commit(mdp5_kms->smp, &mdp5_kms->state->smp);
|
||||
|
||||
mdp5_disable(mdp5_kms);
|
||||
pm_runtime_put_autosuspend(dev);
|
||||
}
|
||||
|
||||
static void mdp5_wait_for_crtc_commit_done(struct msm_kms *kms,
|
||||
@@ -249,6 +249,9 @@ int mdp5_disable(struct mdp5_kms *mdp5_kms)
|
||||
{
|
||||
DBG("");
|
||||
|
||||
mdp5_kms->enable_count--;
|
||||
WARN_ON(mdp5_kms->enable_count < 0);
|
||||
|
||||
clk_disable_unprepare(mdp5_kms->ahb_clk);
|
||||
clk_disable_unprepare(mdp5_kms->axi_clk);
|
||||
clk_disable_unprepare(mdp5_kms->core_clk);
|
||||
@@ -262,6 +265,8 @@ int mdp5_enable(struct mdp5_kms *mdp5_kms)
|
||||
{
|
||||
DBG("");
|
||||
|
||||
mdp5_kms->enable_count++;
|
||||
|
||||
clk_prepare_enable(mdp5_kms->ahb_clk);
|
||||
clk_prepare_enable(mdp5_kms->axi_clk);
|
||||
clk_prepare_enable(mdp5_kms->core_clk);
|
||||
@@ -486,11 +491,12 @@ fail:
|
||||
static void read_mdp_hw_revision(struct mdp5_kms *mdp5_kms,
|
||||
u32 *major, u32 *minor)
|
||||
{
|
||||
struct device *dev = &mdp5_kms->pdev->dev;
|
||||
u32 version;
|
||||
|
||||
mdp5_enable(mdp5_kms);
|
||||
pm_runtime_get_sync(dev);
|
||||
version = mdp5_read(mdp5_kms, REG_MDP5_HW_VERSION);
|
||||
mdp5_disable(mdp5_kms);
|
||||
pm_runtime_put_autosuspend(dev);
|
||||
|
||||
*major = FIELD(version, MDP5_HW_VERSION_MAJOR);
|
||||
*minor = FIELD(version, MDP5_HW_VERSION_MINOR);
|
||||
@@ -643,7 +649,7 @@ struct msm_kms *mdp5_kms_init(struct drm_device *dev)
|
||||
* have left things on, in which case we'll start getting faults if
|
||||
* we don't disable):
|
||||
*/
|
||||
mdp5_enable(mdp5_kms);
|
||||
pm_runtime_get_sync(&pdev->dev);
|
||||
for (i = 0; i < MDP5_INTF_NUM_MAX; i++) {
|
||||
if (mdp5_cfg_intf_is_virtual(config->hw->intf.connect[i]) ||
|
||||
!config->hw->intf.base[i])
|
||||
@@ -652,7 +658,6 @@ struct msm_kms *mdp5_kms_init(struct drm_device *dev)
|
||||
|
||||
mdp5_write(mdp5_kms, REG_MDP5_INTF_FRAME_LINE_COUNT_EN(i), 0x3);
|
||||
}
|
||||
mdp5_disable(mdp5_kms);
|
||||
mdelay(16);
|
||||
|
||||
if (config->platform.iommu) {
|
||||
@@ -678,6 +683,8 @@ struct msm_kms *mdp5_kms_init(struct drm_device *dev)
|
||||
aspace = NULL;;
|
||||
}
|
||||
|
||||
pm_runtime_put_autosuspend(&pdev->dev);
|
||||
|
||||
ret = modeset_init(mdp5_kms);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "modeset_init failed: %d\n", ret);
|
||||
@@ -1005,6 +1012,30 @@ static int mdp5_dev_remove(struct platform_device *pdev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static __maybe_unused int mdp5_runtime_suspend(struct device *dev)
|
||||
{
|
||||
struct platform_device *pdev = to_platform_device(dev);
|
||||
struct mdp5_kms *mdp5_kms = platform_get_drvdata(pdev);
|
||||
|
||||
DBG("");
|
||||
|
||||
return mdp5_disable(mdp5_kms);
|
||||
}
|
||||
|
||||
static __maybe_unused int mdp5_runtime_resume(struct device *dev)
|
||||
{
|
||||
struct platform_device *pdev = to_platform_device(dev);
|
||||
struct mdp5_kms *mdp5_kms = platform_get_drvdata(pdev);
|
||||
|
||||
DBG("");
|
||||
|
||||
return mdp5_enable(mdp5_kms);
|
||||
}
|
||||
|
||||
static const struct dev_pm_ops mdp5_pm_ops = {
|
||||
SET_RUNTIME_PM_OPS(mdp5_runtime_suspend, mdp5_runtime_resume, NULL)
|
||||
};
|
||||
|
||||
static const struct of_device_id mdp5_dt_match[] = {
|
||||
{ .compatible = "qcom,mdp5", },
|
||||
/* to support downstream DT files */
|
||||
@@ -1019,6 +1050,7 @@ static struct platform_driver mdp5_driver = {
|
||||
.driver = {
|
||||
.name = "msm_mdp",
|
||||
.of_match_table = mdp5_dt_match,
|
||||
.pm = &mdp5_pm_ops,
|
||||
},
|
||||
};
|
||||
|
||||
|
@@ -76,6 +76,8 @@ struct mdp5_kms {
|
||||
bool rpm_enabled;
|
||||
|
||||
struct mdp_irq error_handler;
|
||||
|
||||
int enable_count;
|
||||
};
|
||||
#define to_mdp5_kms(x) container_of(x, struct mdp5_kms, base)
|
||||
|
||||
@@ -167,11 +169,13 @@ struct mdp5_encoder {
|
||||
|
||||
static inline void mdp5_write(struct mdp5_kms *mdp5_kms, u32 reg, u32 data)
|
||||
{
|
||||
WARN_ON(mdp5_kms->enable_count <= 0);
|
||||
msm_writel(data, mdp5_kms->mmio + reg);
|
||||
}
|
||||
|
||||
static inline u32 mdp5_read(struct mdp5_kms *mdp5_kms, u32 reg)
|
||||
{
|
||||
WARN_ON(mdp5_kms->enable_count <= 0);
|
||||
return msm_readl(mdp5_kms->mmio + reg);
|
||||
}
|
||||
|
||||
@@ -255,9 +259,6 @@ static inline uint32_t lm2ppdone(struct mdp5_hw_mixer *mixer)
|
||||
return MDP5_IRQ_PING_PONG_0_DONE << mixer->pp;
|
||||
}
|
||||
|
||||
int mdp5_disable(struct mdp5_kms *mdp5_kms);
|
||||
int mdp5_enable(struct mdp5_kms *mdp5_kms);
|
||||
|
||||
void mdp5_set_irqmask(struct mdp_kms *mdp_kms, uint32_t irqmask,
|
||||
uint32_t old_irqmask);
|
||||
void mdp5_irq_preinstall(struct msm_kms *kms);
|
||||
|
@@ -31,6 +31,10 @@ struct msm_mdss {
|
||||
|
||||
struct regulator *vdd;
|
||||
|
||||
struct clk *ahb_clk;
|
||||
struct clk *axi_clk;
|
||||
struct clk *vsync_clk;
|
||||
|
||||
struct {
|
||||
volatile unsigned long enabled_mask;
|
||||
struct irq_domain *domain;
|
||||
@@ -140,6 +144,51 @@ static int mdss_irq_domain_init(struct msm_mdss *mdss)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int msm_mdss_enable(struct msm_mdss *mdss)
|
||||
{
|
||||
DBG("");
|
||||
|
||||
clk_prepare_enable(mdss->ahb_clk);
|
||||
if (mdss->axi_clk)
|
||||
clk_prepare_enable(mdss->axi_clk);
|
||||
if (mdss->vsync_clk)
|
||||
clk_prepare_enable(mdss->vsync_clk);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int msm_mdss_disable(struct msm_mdss *mdss)
|
||||
{
|
||||
DBG("");
|
||||
|
||||
if (mdss->vsync_clk)
|
||||
clk_disable_unprepare(mdss->vsync_clk);
|
||||
if (mdss->axi_clk)
|
||||
clk_disable_unprepare(mdss->axi_clk);
|
||||
clk_disable_unprepare(mdss->ahb_clk);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int msm_mdss_get_clocks(struct msm_mdss *mdss)
|
||||
{
|
||||
struct platform_device *pdev = to_platform_device(mdss->dev->dev);
|
||||
|
||||
mdss->ahb_clk = msm_clk_get(pdev, "iface");
|
||||
if (IS_ERR(mdss->ahb_clk))
|
||||
mdss->ahb_clk = NULL;
|
||||
|
||||
mdss->axi_clk = msm_clk_get(pdev, "bus");
|
||||
if (IS_ERR(mdss->axi_clk))
|
||||
mdss->axi_clk = NULL;
|
||||
|
||||
mdss->vsync_clk = msm_clk_get(pdev, "vsync");
|
||||
if (IS_ERR(mdss->vsync_clk))
|
||||
mdss->vsync_clk = NULL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void msm_mdss_destroy(struct drm_device *dev)
|
||||
{
|
||||
struct msm_drm_private *priv = dev->dev_private;
|
||||
@@ -153,8 +202,6 @@ void msm_mdss_destroy(struct drm_device *dev)
|
||||
|
||||
regulator_disable(mdss->vdd);
|
||||
|
||||
pm_runtime_put_sync(dev->dev);
|
||||
|
||||
pm_runtime_disable(dev->dev);
|
||||
}
|
||||
|
||||
@@ -190,6 +237,12 @@ int msm_mdss_init(struct drm_device *dev)
|
||||
goto fail;
|
||||
}
|
||||
|
||||
ret = msm_mdss_get_clocks(mdss);
|
||||
if (ret) {
|
||||
dev_err(dev->dev, "failed to get clocks: %d\n", ret);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* Regulator to enable GDSCs in downstream kernels */
|
||||
mdss->vdd = devm_regulator_get(dev->dev, "vdd");
|
||||
if (IS_ERR(mdss->vdd)) {
|
||||
@@ -221,12 +274,6 @@ int msm_mdss_init(struct drm_device *dev)
|
||||
|
||||
pm_runtime_enable(dev->dev);
|
||||
|
||||
/*
|
||||
* TODO: This is needed as the MDSS GDSC is only tied to MDSS's power
|
||||
* domain. Remove this once runtime PM is adapted for all the devices.
|
||||
*/
|
||||
pm_runtime_get_sync(dev->dev);
|
||||
|
||||
return 0;
|
||||
fail_irq:
|
||||
regulator_disable(mdss->vdd);
|
||||
|
@@ -28,6 +28,13 @@ struct mdp5_smp {
|
||||
|
||||
int blk_cnt;
|
||||
int blk_size;
|
||||
|
||||
/* register cache */
|
||||
u32 alloc_w[22];
|
||||
u32 alloc_r[22];
|
||||
u32 pipe_reqprio_fifo_wm0[SSPP_MAX];
|
||||
u32 pipe_reqprio_fifo_wm1[SSPP_MAX];
|
||||
u32 pipe_reqprio_fifo_wm2[SSPP_MAX];
|
||||
};
|
||||
|
||||
static inline
|
||||
@@ -98,16 +105,15 @@ static int smp_request_block(struct mdp5_smp *smp,
|
||||
static void set_fifo_thresholds(struct mdp5_smp *smp,
|
||||
enum mdp5_pipe pipe, int nblks)
|
||||
{
|
||||
struct mdp5_kms *mdp5_kms = get_kms(smp);
|
||||
u32 smp_entries_per_blk = smp->blk_size / (128 / BITS_PER_BYTE);
|
||||
u32 val;
|
||||
|
||||
/* 1/4 of SMP pool that is being fetched */
|
||||
val = (nblks * smp_entries_per_blk) / 4;
|
||||
|
||||
mdp5_write(mdp5_kms, REG_MDP5_PIPE_REQPRIO_FIFO_WM_0(pipe), val * 1);
|
||||
mdp5_write(mdp5_kms, REG_MDP5_PIPE_REQPRIO_FIFO_WM_1(pipe), val * 2);
|
||||
mdp5_write(mdp5_kms, REG_MDP5_PIPE_REQPRIO_FIFO_WM_2(pipe), val * 3);
|
||||
smp->pipe_reqprio_fifo_wm0[pipe] = val * 1;
|
||||
smp->pipe_reqprio_fifo_wm1[pipe] = val * 2;
|
||||
smp->pipe_reqprio_fifo_wm2[pipe] = val * 3;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -222,7 +228,6 @@ void mdp5_smp_release(struct mdp5_smp *smp, struct mdp5_smp_state *state,
|
||||
static unsigned update_smp_state(struct mdp5_smp *smp,
|
||||
u32 cid, mdp5_smp_state_t *assigned)
|
||||
{
|
||||
struct mdp5_kms *mdp5_kms = get_kms(smp);
|
||||
int cnt = smp->blk_cnt;
|
||||
unsigned nblks = 0;
|
||||
u32 blk, val;
|
||||
@@ -231,7 +236,7 @@ static unsigned update_smp_state(struct mdp5_smp *smp,
|
||||
int idx = blk / 3;
|
||||
int fld = blk % 3;
|
||||
|
||||
val = mdp5_read(mdp5_kms, REG_MDP5_SMP_ALLOC_W_REG(idx));
|
||||
val = smp->alloc_w[idx];
|
||||
|
||||
switch (fld) {
|
||||
case 0:
|
||||
@@ -248,8 +253,8 @@ static unsigned update_smp_state(struct mdp5_smp *smp,
|
||||
break;
|
||||
}
|
||||
|
||||
mdp5_write(mdp5_kms, REG_MDP5_SMP_ALLOC_W_REG(idx), val);
|
||||
mdp5_write(mdp5_kms, REG_MDP5_SMP_ALLOC_R_REG(idx), val);
|
||||
smp->alloc_w[idx] = val;
|
||||
smp->alloc_r[idx] = val;
|
||||
|
||||
nblks++;
|
||||
}
|
||||
@@ -257,6 +262,39 @@ static unsigned update_smp_state(struct mdp5_smp *smp,
|
||||
return nblks;
|
||||
}
|
||||
|
||||
static void write_smp_alloc_regs(struct mdp5_smp *smp)
|
||||
{
|
||||
struct mdp5_kms *mdp5_kms = get_kms(smp);
|
||||
int i, num_regs;
|
||||
|
||||
num_regs = smp->blk_cnt / 3 + 1;
|
||||
|
||||
for (i = 0; i < num_regs; i++) {
|
||||
mdp5_write(mdp5_kms, REG_MDP5_SMP_ALLOC_W_REG(i),
|
||||
smp->alloc_w[i]);
|
||||
mdp5_write(mdp5_kms, REG_MDP5_SMP_ALLOC_R_REG(i),
|
||||
smp->alloc_r[i]);
|
||||
}
|
||||
}
|
||||
|
||||
static void write_smp_fifo_regs(struct mdp5_smp *smp)
|
||||
{
|
||||
struct mdp5_kms *mdp5_kms = get_kms(smp);
|
||||
int i;
|
||||
|
||||
for (i = 0; i < mdp5_kms->num_hwpipes; i++) {
|
||||
struct mdp5_hw_pipe *hwpipe = mdp5_kms->hwpipes[i];
|
||||
enum mdp5_pipe pipe = hwpipe->pipe;
|
||||
|
||||
mdp5_write(mdp5_kms, REG_MDP5_PIPE_REQPRIO_FIFO_WM_0(pipe),
|
||||
smp->pipe_reqprio_fifo_wm0[pipe]);
|
||||
mdp5_write(mdp5_kms, REG_MDP5_PIPE_REQPRIO_FIFO_WM_1(pipe),
|
||||
smp->pipe_reqprio_fifo_wm1[pipe]);
|
||||
mdp5_write(mdp5_kms, REG_MDP5_PIPE_REQPRIO_FIFO_WM_2(pipe),
|
||||
smp->pipe_reqprio_fifo_wm2[pipe]);
|
||||
}
|
||||
}
|
||||
|
||||
void mdp5_smp_prepare_commit(struct mdp5_smp *smp, struct mdp5_smp_state *state)
|
||||
{
|
||||
enum mdp5_pipe pipe;
|
||||
@@ -277,6 +315,9 @@ void mdp5_smp_prepare_commit(struct mdp5_smp *smp, struct mdp5_smp_state *state)
|
||||
set_fifo_thresholds(smp, pipe, nblks);
|
||||
}
|
||||
|
||||
write_smp_alloc_regs(smp);
|
||||
write_smp_fifo_regs(smp);
|
||||
|
||||
state->assigned = 0;
|
||||
}
|
||||
|
||||
@@ -289,6 +330,8 @@ void mdp5_smp_complete_commit(struct mdp5_smp *smp, struct mdp5_smp_state *state
|
||||
set_fifo_thresholds(smp, pipe, 0);
|
||||
}
|
||||
|
||||
write_smp_fifo_regs(smp);
|
||||
|
||||
state->released = 0;
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user