diff --git a/msm/msm_drv.c b/msm/msm_drv.c index 65dd98fd5e..2c582ef0f0 100644 --- a/msm/msm_drv.c +++ b/msm/msm_drv.c @@ -897,7 +897,7 @@ static int msm_drm_component_init(struct device *dev) drm_mode_config_reset(ddev); if (kms && kms->funcs && kms->funcs->cont_splash_config) { - ret = kms->funcs->cont_splash_config(kms); + ret = kms->funcs->cont_splash_config(kms, NULL); if (ret) { dev_err(dev, "kms cont_splash config failed.\n"); goto fail; diff --git a/msm/msm_kms.h b/msm/msm_kms.h index b383e016ed..3e70dcf2e5 100644 --- a/msm/msm_kms.h +++ b/msm/msm_kms.h @@ -121,7 +121,8 @@ struct msm_kms_funcs { /* destroys debugfs */ void (*debugfs_destroy)(struct msm_kms *kms); /* handle continuous splash */ - int (*cont_splash_config)(struct msm_kms *kms); + int (*cont_splash_config)(struct msm_kms *kms, + struct drm_atomic_state *state); /* check for continuous splash status */ bool (*check_for_splash)(struct msm_kms *kms); /* topology lm information */ diff --git a/msm/sde/sde_kms.c b/msm/sde/sde_kms.c index e8682ac1c5..990bba6161 100644 --- a/msm/sde/sde_kms.c +++ b/msm/sde/sde_kms.c @@ -2645,6 +2645,9 @@ static int sde_kms_check_vm_request(struct msm_kms *kms, vm_ops->vm_owns_hw(sde_kms), rc); goto end; } + + if (vm_ops->vm_resource_init) + rc = vm_ops->vm_resource_init(sde_kms, state); } end: @@ -3045,7 +3048,44 @@ static int sde_kms_vm_trusted_cont_splash_res_init(struct sde_kms *sde_kms) return 0; } -static int sde_kms_cont_splash_config(struct msm_kms *kms) +static struct drm_display_mode *_sde_kms_get_splash_mode( + struct sde_kms *sde_kms, struct drm_connector *connector, + struct drm_atomic_state *state) +{ + struct drm_display_mode *mode, *cur_mode = NULL; + struct drm_crtc *crtc; + struct drm_crtc_state *new_cstate, *old_cstate; + u32 i = 0; + + if (sde_kms->splash_data.type == SDE_SPLASH_HANDOFF) { + list_for_each_entry(mode, &connector->modes, head) { + if (mode->type & DRM_MODE_TYPE_PREFERRED) { + cur_mode = mode; + break; + } + } + } else if (state) { + /* get the mode from first atomic_check phase for trusted_vm*/ + for_each_oldnew_crtc_in_state(state, crtc, old_cstate, + new_cstate, i) { + + if (!new_cstate->active && !old_cstate->active) + continue; + + list_for_each_entry(mode, &connector->modes, head) { + if (drm_mode_equal(&new_cstate->mode, mode)) { + cur_mode = mode; + break; + } + } + } + } + + return cur_mode; +} + +static int sde_kms_cont_splash_config(struct msm_kms *kms, + struct drm_atomic_state *state) { void *display; struct dsi_display *dsi_display; @@ -3160,12 +3200,16 @@ static int sde_kms_cont_splash_config(struct msm_kms *kms) crtc->state->encoder_mask = (1 << drm_encoder_index(encoder)); - /* currently consider modes[0] as the preferred mode */ - drm_mode = list_first_entry(&connector->modes, - struct drm_display_mode, head); - SDE_DEBUG("drm_mode->name = %s, type=0x%x, flags=0x%x\n", + drm_mode = _sde_kms_get_splash_mode(sde_kms, connector, state); + if (!drm_mode) { + SDE_ERROR("drm_mode not found; handoff_type:%d\n", + sde_kms->splash_data.type); + return -EINVAL; + } + SDE_DEBUG( + "drm_mode->name:%s, type:0x%x, flags:0x%x, handoff_type:%d\n", drm_mode->name, drm_mode->type, - drm_mode->flags); + drm_mode->flags, sde_kms->splash_data.type); /* Update CRTC drm structure */ crtc->state->active = true; @@ -4547,7 +4591,8 @@ void sde_kms_vm_trusted_resource_deinit(struct sde_kms *sde_kms) memset(&sde_kms->splash_data, 0, sizeof(struct sde_splash_data)); } -int sde_kms_vm_trusted_resource_init(struct sde_kms *sde_kms) +int sde_kms_vm_trusted_resource_init(struct sde_kms *sde_kms, + struct drm_atomic_state *state) { struct drm_device *dev; struct msm_drm_private *priv; @@ -4588,7 +4633,7 @@ int sde_kms_vm_trusted_resource_init(struct sde_kms *sde_kms) goto error; } - ret = sde_kms_cont_splash_config(&sde_kms->base); + ret = sde_kms_cont_splash_config(&sde_kms->base, state); if (ret) { SDE_ERROR("error in setting handoff configs\n"); goto error; @@ -4603,8 +4648,6 @@ int sde_kms_vm_trusted_resource_init(struct sde_kms *sde_kms) return 0; error: - sde_kms_vm_trusted_resource_deinit(sde_kms); - return ret; } diff --git a/msm/sde/sde_kms.h b/msm/sde/sde_kms.h index 232ea057fc..560b53ee1c 100644 --- a/msm/sde/sde_kms.h +++ b/msm/sde/sde_kms.h @@ -704,9 +704,11 @@ int sde_kms_get_io_resources(struct sde_kms *kms, struct msm_io_res *io_res); /** * sde_kms_vm_trusted_resource_init - reserve/initialize the HW/SW resources * @sde_kms: poiner to sde_kms structure + * @state: current update atomic commit state * return: 0 on success; error code otherwise */ -int sde_kms_vm_trusted_resource_init(struct sde_kms *sde_kms); +int sde_kms_vm_trusted_resource_init(struct sde_kms *sde_kms, + struct drm_atomic_state *state); /** * sde_kms_vm_trusted_resource_deinit - release the HW/SW resources diff --git a/msm/sde/sde_vm.h b/msm/sde/sde_vm.h index bf69e2720c..718b7e654a 100644 --- a/msm/sde/sde_vm.h +++ b/msm/sde/sde_vm.h @@ -166,6 +166,15 @@ struct sde_vm_ops { * @return - 0 on success, errorcode otherwise */ int (*vm_msg_send)(struct sde_vm *sde_vm, void *msg, size_t msg_size); + + /** + * vm_resource_init - hook to the handler when resource + * accept/reclaim fails. + * @sde_kms - handle to sde_kms + * @state: current update atomic commit state + */ + int (*vm_resource_init)(struct sde_kms *sde_kms, + struct drm_atomic_state *state); }; /** diff --git a/msm/sde/sde_vm_trusted.c b/msm/sde/sde_vm_trusted.c index 7e0457e299..3fd46daf8a 100644 --- a/msm/sde/sde_vm_trusted.c +++ b/msm/sde/sde_vm_trusted.c @@ -190,6 +190,18 @@ end: return rc; } +int _sde_vm_resource_init(struct sde_kms *sde_kms, + struct drm_atomic_state *state) +{ + int rc = 0; + + rc = sde_kms_vm_trusted_resource_init(sde_kms, state); + if (rc) + SDE_ERROR("vm resource init failed\n"); + + return rc; +} + int _sde_vm_populate_res(struct sde_kms *sde_kms, struct sde_vm_trusted *vm) { struct msm_io_res io_res; @@ -384,18 +396,12 @@ static int _sde_vm_accept(struct sde_kms *kms) if (rc) goto res_accept_fail; - rc = sde_kms_vm_trusted_resource_init(kms); - if (rc) { - SDE_ERROR("vm resource init failed\n"); - goto res_accept_fail; - } - - goto end; + return 0; res_accept_fail: _sde_vm_release_irq(kms->vm); _sde_vm_release_mem(kms->vm); -end: + return rc; } @@ -414,6 +420,7 @@ static void _sde_vm_set_ops(struct sde_vm_ops *ops) ops->vm_request_valid = sde_vm_request_valid; ops->vm_acquire_fail_handler = _sde_vm_release; ops->vm_msg_send = sde_vm_msg_send; + ops->vm_resource_init = _sde_vm_resource_init; } int sde_vm_trusted_init(struct sde_kms *kms)