Loading msm/sde/sde_encoder.c +136 −101 Original line number Diff line number Diff line Loading @@ -2066,54 +2066,13 @@ static void sde_encoder_virt_mode_switch(struct drm_encoder *drm_enc, } } static void sde_encoder_virt_mode_set(struct drm_encoder *drm_enc, struct drm_display_mode *mode, struct drm_display_mode *adj_mode) static struct drm_connector *_sde_encoder_get_connector( struct drm_device *dev, struct drm_encoder *drm_enc) { struct sde_encoder_virt *sde_enc; struct sde_kms *sde_kms; struct drm_connector_list_iter conn_iter; struct drm_connector *conn = NULL, *conn_search; struct sde_rm_hw_iter dsc_iter, pp_iter, qdss_iter; struct sde_rm_hw_iter vdc_iter; struct sde_rm_hw_request request_hw; enum sde_intf_mode intf_mode; bool is_cmd_mode = false; int i = 0, ret; if (!drm_enc) { SDE_ERROR("invalid encoder\n"); return; } if (!sde_kms_power_resource_is_enabled(drm_enc->dev)) { SDE_ERROR("power resource is not enabled\n"); return; } sde_enc = to_sde_encoder_virt(drm_enc); SDE_DEBUG_ENC(sde_enc, "\n"); if (sde_encoder_check_curr_mode(drm_enc, MSM_DISPLAY_CMD_MODE)) is_cmd_mode = true; sde_kms = sde_encoder_get_kms(drm_enc); if (!sde_kms) return; SDE_EVT32(DRMID(drm_enc)); /* * cache the crtc in sde_enc on enable for duration of use case * for correctly servicing asynchronous irq events and timers */ if (!drm_enc->crtc) { SDE_ERROR("invalid crtc\n"); return; } sde_enc->crtc = drm_enc->crtc; drm_connector_list_iter_begin(sde_kms->dev, &conn_iter); drm_connector_list_iter_begin(dev, &conn_iter); drm_for_each_connector_iter(conn_search, &conn_iter) { if (conn_search->encoder == drm_enc) { conn = conn_search; Loading @@ -2122,56 +2081,17 @@ static void sde_encoder_virt_mode_set(struct drm_encoder *drm_enc, } drm_connector_list_iter_end(&conn_iter); sde_crtc_set_qos_dirty(sde_enc->crtc); if (!conn) { SDE_ERROR_ENC(sde_enc, "failed to find attached connector\n"); return; } else if (!conn->state) { SDE_ERROR_ENC(sde_enc, "invalid connector state\n"); return; } intf_mode = sde_encoder_get_intf_mode(drm_enc); /* store the mode_info */ sde_connector_state_get_mode_info(conn->state, &sde_enc->mode_info); sde_encoder_dce_set_bpp(sde_enc->mode_info, sde_enc->crtc); /* release resources before seamless mode change */ if (msm_is_mode_seamless_dms(adj_mode) || (msm_is_mode_seamless_dyn_clk(adj_mode) && is_cmd_mode)) { /* restore resource state before releasing them */ ret = sde_encoder_resource_control(drm_enc, SDE_ENC_RC_EVENT_PRE_MODESET); if (ret) { SDE_ERROR_ENC(sde_enc, "sde resource control failed: %d\n", ret); return; } /* * Disable dce before switch the mode and after pre_modeset, * to guarantee that previous kickoff finished. */ sde_encoder_dce_disable(sde_enc); } else if (msm_is_mode_seamless_poms(adj_mode)) { _sde_encoder_modeset_helper_locked(drm_enc, SDE_ENC_RC_EVENT_PRE_MODESET); sde_encoder_virt_mode_switch(drm_enc, intf_mode, adj_mode); return conn; } /* Reserve dynamic resources now. Indicating non-AtomicTest phase */ ret = sde_rm_reserve(&sde_kms->rm, drm_enc, drm_enc->crtc->state, conn->state, false); if (ret) { SDE_ERROR_ENC(sde_enc, "failed to reserve hw resources, %d\n", ret); return; } static void _sde_encoder_virt_populate_hw_res(struct drm_encoder *drm_enc) { struct sde_encoder_virt *sde_enc = to_sde_encoder_virt(drm_enc); struct sde_kms *sde_kms = sde_encoder_get_kms(drm_enc); struct sde_rm_hw_iter pp_iter, qdss_iter; struct sde_rm_hw_iter dsc_iter, vdc_iter; struct sde_rm_hw_request request_hw; int i; sde_rm_init_hw_iter(&pp_iter, drm_enc->base.id, SDE_HW_BLK_PINGPONG); for (i = 0; i < MAX_CHANNELS_PER_ENC; i++) { Loading Loading @@ -2233,7 +2153,129 @@ static void sde_encoder_virt_mode_set(struct drm_encoder *drm_enc, else sde_enc->hw_dsc_pp[i] = NULL; } } static int sde_encoder_virt_modeset_rc(struct drm_encoder *drm_enc, struct drm_display_mode *adj_mode, bool pre_modeset) { struct sde_encoder_virt *sde_enc = to_sde_encoder_virt(drm_enc); enum sde_intf_mode intf_mode; int ret; bool is_cmd_mode; if (sde_encoder_check_curr_mode(drm_enc, MSM_DISPLAY_CMD_MODE)) is_cmd_mode = true; if (pre_modeset) { intf_mode = sde_encoder_get_intf_mode(drm_enc); if (msm_is_mode_seamless_dms(adj_mode) || (msm_is_mode_seamless_dyn_clk(adj_mode) && is_cmd_mode)) { /* restore resource state before releasing them */ ret = sde_encoder_resource_control(drm_enc, SDE_ENC_RC_EVENT_PRE_MODESET); if (ret) { SDE_ERROR_ENC(sde_enc, "sde resource control failed: %d\n", ret); return ret; } /* * Disable dce before switching the mode and after pre- * modeset to guarantee previous kickoff has finished. */ sde_encoder_dce_disable(sde_enc); } else if (msm_is_mode_seamless_poms(adj_mode)) { _sde_encoder_modeset_helper_locked(drm_enc, SDE_ENC_RC_EVENT_PRE_MODESET); sde_encoder_virt_mode_switch(drm_enc, intf_mode, adj_mode); } } else { if (msm_is_mode_seamless_dms(adj_mode) || (msm_is_mode_seamless_dyn_clk(adj_mode) && is_cmd_mode)) sde_encoder_resource_control(&sde_enc->base, SDE_ENC_RC_EVENT_POST_MODESET); else if (msm_is_mode_seamless_poms(adj_mode)) _sde_encoder_modeset_helper_locked(drm_enc, SDE_ENC_RC_EVENT_POST_MODESET); } return 0; } static void sde_encoder_virt_mode_set(struct drm_encoder *drm_enc, struct drm_display_mode *mode, struct drm_display_mode *adj_mode) { struct sde_encoder_virt *sde_enc; struct sde_kms *sde_kms; struct drm_connector *conn; int i = 0, ret; if (!drm_enc) { SDE_ERROR("invalid encoder\n"); return; } if (!sde_kms_power_resource_is_enabled(drm_enc->dev)) { SDE_ERROR("power resource is not enabled\n"); return; } sde_kms = sde_encoder_get_kms(drm_enc); if (!sde_kms) return; sde_enc = to_sde_encoder_virt(drm_enc); SDE_DEBUG_ENC(sde_enc, "\n"); SDE_EVT32(DRMID(drm_enc)); /* * cache the crtc in sde_enc on enable for duration of use case * for correctly servicing asynchronous irq events and timers */ if (!drm_enc->crtc) { SDE_ERROR("invalid crtc\n"); return; } sde_enc->crtc = drm_enc->crtc; sde_crtc_set_qos_dirty(drm_enc->crtc); /* get and store the mode_info */ conn = _sde_encoder_get_connector(sde_kms->dev, drm_enc); if (!conn) { SDE_ERROR_ENC(sde_enc, "failed to find attached connector\n"); return; } else if (!conn->state) { SDE_ERROR_ENC(sde_enc, "invalid connector state\n"); return; } sde_connector_state_get_mode_info(conn->state, &sde_enc->mode_info); sde_encoder_dce_set_bpp(sde_enc->mode_info, sde_enc->crtc); /* release resources before seamless mode change */ ret = sde_encoder_virt_modeset_rc(drm_enc, adj_mode, true); if (ret) return; /* reserve dynamic resources now, indicating non test-only */ ret = sde_rm_reserve(&sde_kms->rm, drm_enc, drm_enc->crtc->state, conn->state, false); if (ret) { SDE_ERROR_ENC(sde_enc, "failed to reserve hw resources, %d\n", ret); return; } /* assign the reserved HW blocks to this encoder */ _sde_encoder_virt_populate_hw_res(drm_enc); /* perform mode_set on phys_encs */ for (i = 0; i < sde_enc->num_phys_encs; i++) { struct sde_encoder_phys *phys = sde_enc->phys_encs[i]; Loading @@ -2251,14 +2293,7 @@ static void sde_encoder_virt_mode_set(struct drm_encoder *drm_enc, } /* update resources after seamless mode change */ if (msm_is_mode_seamless_dms(adj_mode) || (msm_is_mode_seamless_dyn_clk(adj_mode) && is_cmd_mode)) sde_encoder_resource_control(&sde_enc->base, SDE_ENC_RC_EVENT_POST_MODESET); else if (msm_is_mode_seamless_poms(adj_mode)) _sde_encoder_modeset_helper_locked(drm_enc, SDE_ENC_RC_EVENT_POST_MODESET); sde_encoder_virt_modeset_rc(drm_enc, adj_mode, false); } void sde_encoder_control_te(struct drm_encoder *drm_enc, bool enable) Loading Loading
msm/sde/sde_encoder.c +136 −101 Original line number Diff line number Diff line Loading @@ -2066,54 +2066,13 @@ static void sde_encoder_virt_mode_switch(struct drm_encoder *drm_enc, } } static void sde_encoder_virt_mode_set(struct drm_encoder *drm_enc, struct drm_display_mode *mode, struct drm_display_mode *adj_mode) static struct drm_connector *_sde_encoder_get_connector( struct drm_device *dev, struct drm_encoder *drm_enc) { struct sde_encoder_virt *sde_enc; struct sde_kms *sde_kms; struct drm_connector_list_iter conn_iter; struct drm_connector *conn = NULL, *conn_search; struct sde_rm_hw_iter dsc_iter, pp_iter, qdss_iter; struct sde_rm_hw_iter vdc_iter; struct sde_rm_hw_request request_hw; enum sde_intf_mode intf_mode; bool is_cmd_mode = false; int i = 0, ret; if (!drm_enc) { SDE_ERROR("invalid encoder\n"); return; } if (!sde_kms_power_resource_is_enabled(drm_enc->dev)) { SDE_ERROR("power resource is not enabled\n"); return; } sde_enc = to_sde_encoder_virt(drm_enc); SDE_DEBUG_ENC(sde_enc, "\n"); if (sde_encoder_check_curr_mode(drm_enc, MSM_DISPLAY_CMD_MODE)) is_cmd_mode = true; sde_kms = sde_encoder_get_kms(drm_enc); if (!sde_kms) return; SDE_EVT32(DRMID(drm_enc)); /* * cache the crtc in sde_enc on enable for duration of use case * for correctly servicing asynchronous irq events and timers */ if (!drm_enc->crtc) { SDE_ERROR("invalid crtc\n"); return; } sde_enc->crtc = drm_enc->crtc; drm_connector_list_iter_begin(sde_kms->dev, &conn_iter); drm_connector_list_iter_begin(dev, &conn_iter); drm_for_each_connector_iter(conn_search, &conn_iter) { if (conn_search->encoder == drm_enc) { conn = conn_search; Loading @@ -2122,56 +2081,17 @@ static void sde_encoder_virt_mode_set(struct drm_encoder *drm_enc, } drm_connector_list_iter_end(&conn_iter); sde_crtc_set_qos_dirty(sde_enc->crtc); if (!conn) { SDE_ERROR_ENC(sde_enc, "failed to find attached connector\n"); return; } else if (!conn->state) { SDE_ERROR_ENC(sde_enc, "invalid connector state\n"); return; } intf_mode = sde_encoder_get_intf_mode(drm_enc); /* store the mode_info */ sde_connector_state_get_mode_info(conn->state, &sde_enc->mode_info); sde_encoder_dce_set_bpp(sde_enc->mode_info, sde_enc->crtc); /* release resources before seamless mode change */ if (msm_is_mode_seamless_dms(adj_mode) || (msm_is_mode_seamless_dyn_clk(adj_mode) && is_cmd_mode)) { /* restore resource state before releasing them */ ret = sde_encoder_resource_control(drm_enc, SDE_ENC_RC_EVENT_PRE_MODESET); if (ret) { SDE_ERROR_ENC(sde_enc, "sde resource control failed: %d\n", ret); return; } /* * Disable dce before switch the mode and after pre_modeset, * to guarantee that previous kickoff finished. */ sde_encoder_dce_disable(sde_enc); } else if (msm_is_mode_seamless_poms(adj_mode)) { _sde_encoder_modeset_helper_locked(drm_enc, SDE_ENC_RC_EVENT_PRE_MODESET); sde_encoder_virt_mode_switch(drm_enc, intf_mode, adj_mode); return conn; } /* Reserve dynamic resources now. Indicating non-AtomicTest phase */ ret = sde_rm_reserve(&sde_kms->rm, drm_enc, drm_enc->crtc->state, conn->state, false); if (ret) { SDE_ERROR_ENC(sde_enc, "failed to reserve hw resources, %d\n", ret); return; } static void _sde_encoder_virt_populate_hw_res(struct drm_encoder *drm_enc) { struct sde_encoder_virt *sde_enc = to_sde_encoder_virt(drm_enc); struct sde_kms *sde_kms = sde_encoder_get_kms(drm_enc); struct sde_rm_hw_iter pp_iter, qdss_iter; struct sde_rm_hw_iter dsc_iter, vdc_iter; struct sde_rm_hw_request request_hw; int i; sde_rm_init_hw_iter(&pp_iter, drm_enc->base.id, SDE_HW_BLK_PINGPONG); for (i = 0; i < MAX_CHANNELS_PER_ENC; i++) { Loading Loading @@ -2233,7 +2153,129 @@ static void sde_encoder_virt_mode_set(struct drm_encoder *drm_enc, else sde_enc->hw_dsc_pp[i] = NULL; } } static int sde_encoder_virt_modeset_rc(struct drm_encoder *drm_enc, struct drm_display_mode *adj_mode, bool pre_modeset) { struct sde_encoder_virt *sde_enc = to_sde_encoder_virt(drm_enc); enum sde_intf_mode intf_mode; int ret; bool is_cmd_mode; if (sde_encoder_check_curr_mode(drm_enc, MSM_DISPLAY_CMD_MODE)) is_cmd_mode = true; if (pre_modeset) { intf_mode = sde_encoder_get_intf_mode(drm_enc); if (msm_is_mode_seamless_dms(adj_mode) || (msm_is_mode_seamless_dyn_clk(adj_mode) && is_cmd_mode)) { /* restore resource state before releasing them */ ret = sde_encoder_resource_control(drm_enc, SDE_ENC_RC_EVENT_PRE_MODESET); if (ret) { SDE_ERROR_ENC(sde_enc, "sde resource control failed: %d\n", ret); return ret; } /* * Disable dce before switching the mode and after pre- * modeset to guarantee previous kickoff has finished. */ sde_encoder_dce_disable(sde_enc); } else if (msm_is_mode_seamless_poms(adj_mode)) { _sde_encoder_modeset_helper_locked(drm_enc, SDE_ENC_RC_EVENT_PRE_MODESET); sde_encoder_virt_mode_switch(drm_enc, intf_mode, adj_mode); } } else { if (msm_is_mode_seamless_dms(adj_mode) || (msm_is_mode_seamless_dyn_clk(adj_mode) && is_cmd_mode)) sde_encoder_resource_control(&sde_enc->base, SDE_ENC_RC_EVENT_POST_MODESET); else if (msm_is_mode_seamless_poms(adj_mode)) _sde_encoder_modeset_helper_locked(drm_enc, SDE_ENC_RC_EVENT_POST_MODESET); } return 0; } static void sde_encoder_virt_mode_set(struct drm_encoder *drm_enc, struct drm_display_mode *mode, struct drm_display_mode *adj_mode) { struct sde_encoder_virt *sde_enc; struct sde_kms *sde_kms; struct drm_connector *conn; int i = 0, ret; if (!drm_enc) { SDE_ERROR("invalid encoder\n"); return; } if (!sde_kms_power_resource_is_enabled(drm_enc->dev)) { SDE_ERROR("power resource is not enabled\n"); return; } sde_kms = sde_encoder_get_kms(drm_enc); if (!sde_kms) return; sde_enc = to_sde_encoder_virt(drm_enc); SDE_DEBUG_ENC(sde_enc, "\n"); SDE_EVT32(DRMID(drm_enc)); /* * cache the crtc in sde_enc on enable for duration of use case * for correctly servicing asynchronous irq events and timers */ if (!drm_enc->crtc) { SDE_ERROR("invalid crtc\n"); return; } sde_enc->crtc = drm_enc->crtc; sde_crtc_set_qos_dirty(drm_enc->crtc); /* get and store the mode_info */ conn = _sde_encoder_get_connector(sde_kms->dev, drm_enc); if (!conn) { SDE_ERROR_ENC(sde_enc, "failed to find attached connector\n"); return; } else if (!conn->state) { SDE_ERROR_ENC(sde_enc, "invalid connector state\n"); return; } sde_connector_state_get_mode_info(conn->state, &sde_enc->mode_info); sde_encoder_dce_set_bpp(sde_enc->mode_info, sde_enc->crtc); /* release resources before seamless mode change */ ret = sde_encoder_virt_modeset_rc(drm_enc, adj_mode, true); if (ret) return; /* reserve dynamic resources now, indicating non test-only */ ret = sde_rm_reserve(&sde_kms->rm, drm_enc, drm_enc->crtc->state, conn->state, false); if (ret) { SDE_ERROR_ENC(sde_enc, "failed to reserve hw resources, %d\n", ret); return; } /* assign the reserved HW blocks to this encoder */ _sde_encoder_virt_populate_hw_res(drm_enc); /* perform mode_set on phys_encs */ for (i = 0; i < sde_enc->num_phys_encs; i++) { struct sde_encoder_phys *phys = sde_enc->phys_encs[i]; Loading @@ -2251,14 +2293,7 @@ static void sde_encoder_virt_mode_set(struct drm_encoder *drm_enc, } /* update resources after seamless mode change */ if (msm_is_mode_seamless_dms(adj_mode) || (msm_is_mode_seamless_dyn_clk(adj_mode) && is_cmd_mode)) sde_encoder_resource_control(&sde_enc->base, SDE_ENC_RC_EVENT_POST_MODESET); else if (msm_is_mode_seamless_poms(adj_mode)) _sde_encoder_modeset_helper_locked(drm_enc, SDE_ENC_RC_EVENT_POST_MODESET); sde_encoder_virt_modeset_rc(drm_enc, adj_mode, false); } void sde_encoder_control_te(struct drm_encoder *drm_enc, bool enable) Loading