Loading drivers/gpu/drm/msm/msm_drv.h +1 −0 Original line number Diff line number Diff line Loading @@ -165,6 +165,7 @@ enum msm_mdp_conn_property { CONNECTOR_PROP_TOPOLOGY_NAME, CONNECTOR_PROP_TOPOLOGY_CONTROL, CONNECTOR_PROP_AUTOREFRESH, CONNECTOR_PROP_LP, /* total # of properties */ CONNECTOR_PROP_COUNT Loading drivers/gpu/drm/msm/sde/sde_connector.c +136 −7 Original line number Diff line number Diff line Loading @@ -10,7 +10,7 @@ * GNU General Public License for more details. */ #define pr_fmt(fmt) "sde-drm:[%s] " fmt, __func__ #define pr_fmt(fmt) "[drm:%s:%d] " fmt, __func__, __LINE__ #include "msm_drv.h" #include "sde_kms.h" Loading Loading @@ -44,6 +44,12 @@ static const struct drm_prop_enum_list e_topology_control[] = { {SDE_RM_TOPCTL_FORCE_TILING, "force_tiling"}, {SDE_RM_TOPCTL_PPSPLIT, "ppsplit"} }; static const struct drm_prop_enum_list e_power_mode[] = { {SDE_MODE_DPMS_ON, "ON"}, {SDE_MODE_DPMS_LP1, "LP1"}, {SDE_MODE_DPMS_LP2, "LP2"}, {SDE_MODE_DPMS_OFF, "OFF"}, }; static int sde_backlight_device_update_status(struct backlight_device *bd) { Loading Loading @@ -294,6 +300,7 @@ static void sde_connector_destroy(struct drm_connector *connector) msm_property_destroy(&c_conn->property_info); drm_connector_unregister(connector); mutex_destroy(&c_conn->lock); sde_fence_deinit(&c_conn->retire_fence); drm_connector_cleanup(connector); kfree(c_conn); Loading Loading @@ -541,6 +548,56 @@ static int _sde_connector_set_roi_v1( return 0; } static int _sde_connector_update_power_locked(struct sde_connector *c_conn) { struct drm_connector *connector; void *display; int (*set_power)(struct drm_connector *, int, void *); int mode, rc = 0; if (!c_conn) return -EINVAL; connector = &c_conn->base; mode = c_conn->lp_mode; if (c_conn->dpms_mode != DRM_MODE_DPMS_ON) mode = SDE_MODE_DPMS_OFF; switch (c_conn->dpms_mode) { case DRM_MODE_DPMS_ON: mode = c_conn->lp_mode; break; case DRM_MODE_DPMS_STANDBY: mode = SDE_MODE_DPMS_STANDBY; break; case DRM_MODE_DPMS_SUSPEND: mode = SDE_MODE_DPMS_SUSPEND; break; case DRM_MODE_DPMS_OFF: mode = SDE_MODE_DPMS_OFF; break; default: mode = c_conn->lp_mode; SDE_ERROR("conn %d dpms set to unrecognized mode %d\n", connector->base.id, mode); break; } SDE_DEBUG("conn %d - dpms %d, lp %d, panel %d\n", connector->base.id, c_conn->dpms_mode, c_conn->lp_mode, mode); if (mode != c_conn->last_panel_power_mode && c_conn->ops.set_power) { display = c_conn->display; set_power = c_conn->ops.set_power; mutex_unlock(&c_conn->lock); rc = set_power(connector, mode, display); mutex_lock(&c_conn->lock); } c_conn->last_panel_power_mode = mode; return rc; } static int sde_connector_atomic_set_property(struct drm_connector *connector, struct drm_connector_state *state, struct drm_property *property, Loading @@ -567,8 +624,8 @@ static int sde_connector_atomic_set_property(struct drm_connector *connector, /* connector-specific property handling */ idx = msm_property_index(&c_conn->property_info, property); if (idx == CONNECTOR_PROP_OUT_FB) { switch (idx) { case CONNECTOR_PROP_OUT_FB: /* clear old fb, if present */ if (c_state->out_fb) _sde_connector_destroy_fb(c_conn, c_state); Loading Loading @@ -598,12 +655,20 @@ static int sde_connector_atomic_set_property(struct drm_connector *connector, if (rc) SDE_ERROR("prep fb failed, %d\n", rc); } } if (idx == CONNECTOR_PROP_TOPOLOGY_CONTROL) { break; case CONNECTOR_PROP_TOPOLOGY_CONTROL: rc = sde_rm_check_property_topctl(val); if (rc) SDE_ERROR("invalid topology_control: 0x%llX\n", val); break; case CONNECTOR_PROP_LP: mutex_lock(&c_conn->lock); c_conn->lp_mode = val; _sde_connector_update_power_locked(c_conn); mutex_unlock(&c_conn->lock); break; default: break; } if (idx == CONNECTOR_PROP_ROI_V1) { Loading Loading @@ -719,6 +784,59 @@ sde_connector_detect(struct drm_connector *connector, bool force) return status; } static int sde_connector_dpms(struct drm_connector *connector, int mode) { struct sde_connector *c_conn; if (!connector) { SDE_ERROR("invalid connector\n"); return -EINVAL; } c_conn = to_sde_connector(connector); /* validate incoming dpms request */ switch (mode) { case DRM_MODE_DPMS_ON: case DRM_MODE_DPMS_STANDBY: case DRM_MODE_DPMS_SUSPEND: case DRM_MODE_DPMS_OFF: SDE_DEBUG("conn %d dpms set to %d\n", connector->base.id, mode); break; default: SDE_ERROR("conn %d dpms set to unrecognized mode %d\n", connector->base.id, mode); break; } mutex_lock(&c_conn->lock); c_conn->dpms_mode = mode; _sde_connector_update_power_locked(c_conn); mutex_unlock(&c_conn->lock); /* use helper for boilerplate handling */ return drm_atomic_helper_connector_dpms(connector, mode); } int sde_connector_get_dpms(struct drm_connector *connector) { struct sde_connector *c_conn; int rc; if (!connector) { SDE_DEBUG("invalid connector\n"); return DRM_MODE_DPMS_OFF; } c_conn = to_sde_connector(connector); mutex_lock(&c_conn->lock); rc = c_conn->dpms_mode; mutex_unlock(&c_conn->lock); return rc; } #ifdef CONFIG_DEBUG_FS /** * sde_connector_init_debugfs - initialize connector debugfs Loading Loading @@ -761,7 +879,7 @@ static void sde_connector_early_unregister(struct drm_connector *connector) } static const struct drm_connector_funcs sde_connector_ops = { .dpms = drm_atomic_helper_connector_dpms, .dpms = sde_connector_dpms, .reset = sde_connector_atomic_reset, .detect = sde_connector_detect, .destroy = sde_connector_destroy, Loading Loading @@ -885,6 +1003,10 @@ struct drm_connector *sde_connector_init(struct drm_device *dev, c_conn->panel = panel; c_conn->display = display; c_conn->dpms_mode = DRM_MODE_DPMS_ON; c_conn->lp_mode = 0; c_conn->last_panel_power_mode = SDE_MODE_DPMS_ON; /* cache mmu_id's for later */ sde_kms = to_sde_kms(priv->kms); if (sde_kms->vbif[VBIF_NRT]) { Loading Loading @@ -919,6 +1041,8 @@ struct drm_connector *sde_connector_init(struct drm_device *dev, goto error_cleanup_conn; } mutex_init(&c_conn->lock); rc = drm_mode_connector_attach_encoder(&c_conn->base, encoder); if (rc) { SDE_ERROR("failed to attach encoder to connector, %d\n", rc); Loading Loading @@ -1006,6 +1130,10 @@ struct drm_connector *sde_connector_init(struct drm_device *dev, 0, 1, e_topology_control, ARRAY_SIZE(e_topology_control), CONNECTOR_PROP_TOPOLOGY_CONTROL); msm_property_install_enum(&c_conn->property_info, "LP", 0, 0, e_power_mode, ARRAY_SIZE(e_power_mode), CONNECTOR_PROP_LP); rc = msm_property_install_get_status(&c_conn->property_info); if (rc) { Loading @@ -1027,6 +1155,7 @@ struct drm_connector *sde_connector_init(struct drm_device *dev, drm_property_unreference_blob(c_conn->blob_hdr); msm_property_destroy(&c_conn->property_info); error_cleanup_fence: mutex_destroy(&c_conn->lock); sde_fence_deinit(&c_conn->retire_fence); error_cleanup_conn: drm_connector_cleanup(&c_conn->base); Loading drivers/gpu/drm/msm/sde/sde_connector.h +29 −0 Original line number Diff line number Diff line Loading @@ -169,6 +169,20 @@ struct sde_connector_ops { * @enable: State of clks */ int (*clk_ctrl)(void *handle, u32 type, u32 state); /** * set_power - update dpms setting * @connector: Pointer to drm connector structure * @power_mode: One of the following, * SDE_MODE_DPMS_ON * SDE_MODE_DPMS_LP1 * SDE_MODE_DPMS_LP2 * SDE_MODE_DPMS_OFF * @display: Pointer to private display structure * Returns: Zero on success */ int (*set_power)(struct drm_connector *connector, int power_mode, void *display); }; /** Loading Loading @@ -203,8 +217,12 @@ struct sde_connector_evt { * @mmu_secure: MMU id for secure buffers * @mmu_unsecure: MMU id for unsecure buffers * @name: ASCII name of connector * @lock: Mutex lock object for this structure * @retire_fence: Retire fence context reference * @ops: Local callback function pointer table * @dpms_mode: DPMS property setting from user space * @lp_mode: LP property setting from user space * @last_panel_power_mode: Last consolidated dpms/lp mode setting * @property_info: Private structure for generic property handling * @property_data: Array of private data for generic property handling * @blob_caps: Pointer to blob structure for 'capabilities' property Loading @@ -226,8 +244,12 @@ struct sde_connector { char name[SDE_CONNECTOR_NAME_SIZE]; struct mutex lock; struct sde_fence_context retire_fence; struct sde_connector_ops ops; int dpms_mode; int lp_mode; int last_panel_power_mode; struct msm_property_info property_info; struct msm_property_data property_data[CONNECTOR_PROP_COUNT]; Loading Loading @@ -391,6 +413,13 @@ int sde_connector_get_info(struct drm_connector *connector, */ void sde_connector_clk_ctrl(struct drm_connector *connector, bool enable); /** * sde_connector_get_dpms - query dpms setting * @connector: Pointer to drm connector structure * Returns: Current DPMS setting for connector */ int sde_connector_get_dpms(struct drm_connector *connector); /** * sde_connector_trigger_event - indicate that an event has occurred * Any callbacks that have been registered against this event will Loading drivers/gpu/drm/msm/sde/sde_crtc.c +12 −0 Original line number Diff line number Diff line Loading @@ -1946,6 +1946,14 @@ void sde_crtc_commit_kickoff(struct drm_crtc *crtc) priv = sde_kms->dev->dev_private; cstate = to_sde_crtc_state(crtc->state); /* * If no mixers has been allocated in sde_crtc_atomic_check(), * it means we are trying to start a CRTC whose state is disabled: * nothing else needs to be done. */ if (unlikely(!sde_crtc->num_mixers)) return; list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { struct sde_encoder_kickoff_params params = { 0 }; Loading Loading @@ -2409,6 +2417,10 @@ static int sde_crtc_atomic_check(struct drm_crtc *crtc, mode = &state->adjusted_mode; SDE_DEBUG("%s: check", sde_crtc->name); /* force a full mode set if active state changed */ if (state->active_changed) state->mode_changed = true; memset(pipe_staged, 0, sizeof(pipe_staged)); mixer_width = sde_crtc_mixer_width(sde_crtc, mode); Loading include/uapi/drm/sde_drm.h +10 −0 Original line number Diff line number Diff line Loading @@ -356,4 +356,14 @@ struct sde_drm_roi_v1 { struct drm_clip_rect roi[SDE_MAX_ROI_V1]; }; /** * Define extended power modes supported by the SDE connectors. */ #define SDE_MODE_DPMS_ON 0 #define SDE_MODE_DPMS_LP1 1 #define SDE_MODE_DPMS_LP2 2 #define SDE_MODE_DPMS_STANDBY 3 #define SDE_MODE_DPMS_SUSPEND 4 #define SDE_MODE_DPMS_OFF 5 #endif /* _SDE_DRM_H_ */ Loading
drivers/gpu/drm/msm/msm_drv.h +1 −0 Original line number Diff line number Diff line Loading @@ -165,6 +165,7 @@ enum msm_mdp_conn_property { CONNECTOR_PROP_TOPOLOGY_NAME, CONNECTOR_PROP_TOPOLOGY_CONTROL, CONNECTOR_PROP_AUTOREFRESH, CONNECTOR_PROP_LP, /* total # of properties */ CONNECTOR_PROP_COUNT Loading
drivers/gpu/drm/msm/sde/sde_connector.c +136 −7 Original line number Diff line number Diff line Loading @@ -10,7 +10,7 @@ * GNU General Public License for more details. */ #define pr_fmt(fmt) "sde-drm:[%s] " fmt, __func__ #define pr_fmt(fmt) "[drm:%s:%d] " fmt, __func__, __LINE__ #include "msm_drv.h" #include "sde_kms.h" Loading Loading @@ -44,6 +44,12 @@ static const struct drm_prop_enum_list e_topology_control[] = { {SDE_RM_TOPCTL_FORCE_TILING, "force_tiling"}, {SDE_RM_TOPCTL_PPSPLIT, "ppsplit"} }; static const struct drm_prop_enum_list e_power_mode[] = { {SDE_MODE_DPMS_ON, "ON"}, {SDE_MODE_DPMS_LP1, "LP1"}, {SDE_MODE_DPMS_LP2, "LP2"}, {SDE_MODE_DPMS_OFF, "OFF"}, }; static int sde_backlight_device_update_status(struct backlight_device *bd) { Loading Loading @@ -294,6 +300,7 @@ static void sde_connector_destroy(struct drm_connector *connector) msm_property_destroy(&c_conn->property_info); drm_connector_unregister(connector); mutex_destroy(&c_conn->lock); sde_fence_deinit(&c_conn->retire_fence); drm_connector_cleanup(connector); kfree(c_conn); Loading Loading @@ -541,6 +548,56 @@ static int _sde_connector_set_roi_v1( return 0; } static int _sde_connector_update_power_locked(struct sde_connector *c_conn) { struct drm_connector *connector; void *display; int (*set_power)(struct drm_connector *, int, void *); int mode, rc = 0; if (!c_conn) return -EINVAL; connector = &c_conn->base; mode = c_conn->lp_mode; if (c_conn->dpms_mode != DRM_MODE_DPMS_ON) mode = SDE_MODE_DPMS_OFF; switch (c_conn->dpms_mode) { case DRM_MODE_DPMS_ON: mode = c_conn->lp_mode; break; case DRM_MODE_DPMS_STANDBY: mode = SDE_MODE_DPMS_STANDBY; break; case DRM_MODE_DPMS_SUSPEND: mode = SDE_MODE_DPMS_SUSPEND; break; case DRM_MODE_DPMS_OFF: mode = SDE_MODE_DPMS_OFF; break; default: mode = c_conn->lp_mode; SDE_ERROR("conn %d dpms set to unrecognized mode %d\n", connector->base.id, mode); break; } SDE_DEBUG("conn %d - dpms %d, lp %d, panel %d\n", connector->base.id, c_conn->dpms_mode, c_conn->lp_mode, mode); if (mode != c_conn->last_panel_power_mode && c_conn->ops.set_power) { display = c_conn->display; set_power = c_conn->ops.set_power; mutex_unlock(&c_conn->lock); rc = set_power(connector, mode, display); mutex_lock(&c_conn->lock); } c_conn->last_panel_power_mode = mode; return rc; } static int sde_connector_atomic_set_property(struct drm_connector *connector, struct drm_connector_state *state, struct drm_property *property, Loading @@ -567,8 +624,8 @@ static int sde_connector_atomic_set_property(struct drm_connector *connector, /* connector-specific property handling */ idx = msm_property_index(&c_conn->property_info, property); if (idx == CONNECTOR_PROP_OUT_FB) { switch (idx) { case CONNECTOR_PROP_OUT_FB: /* clear old fb, if present */ if (c_state->out_fb) _sde_connector_destroy_fb(c_conn, c_state); Loading Loading @@ -598,12 +655,20 @@ static int sde_connector_atomic_set_property(struct drm_connector *connector, if (rc) SDE_ERROR("prep fb failed, %d\n", rc); } } if (idx == CONNECTOR_PROP_TOPOLOGY_CONTROL) { break; case CONNECTOR_PROP_TOPOLOGY_CONTROL: rc = sde_rm_check_property_topctl(val); if (rc) SDE_ERROR("invalid topology_control: 0x%llX\n", val); break; case CONNECTOR_PROP_LP: mutex_lock(&c_conn->lock); c_conn->lp_mode = val; _sde_connector_update_power_locked(c_conn); mutex_unlock(&c_conn->lock); break; default: break; } if (idx == CONNECTOR_PROP_ROI_V1) { Loading Loading @@ -719,6 +784,59 @@ sde_connector_detect(struct drm_connector *connector, bool force) return status; } static int sde_connector_dpms(struct drm_connector *connector, int mode) { struct sde_connector *c_conn; if (!connector) { SDE_ERROR("invalid connector\n"); return -EINVAL; } c_conn = to_sde_connector(connector); /* validate incoming dpms request */ switch (mode) { case DRM_MODE_DPMS_ON: case DRM_MODE_DPMS_STANDBY: case DRM_MODE_DPMS_SUSPEND: case DRM_MODE_DPMS_OFF: SDE_DEBUG("conn %d dpms set to %d\n", connector->base.id, mode); break; default: SDE_ERROR("conn %d dpms set to unrecognized mode %d\n", connector->base.id, mode); break; } mutex_lock(&c_conn->lock); c_conn->dpms_mode = mode; _sde_connector_update_power_locked(c_conn); mutex_unlock(&c_conn->lock); /* use helper for boilerplate handling */ return drm_atomic_helper_connector_dpms(connector, mode); } int sde_connector_get_dpms(struct drm_connector *connector) { struct sde_connector *c_conn; int rc; if (!connector) { SDE_DEBUG("invalid connector\n"); return DRM_MODE_DPMS_OFF; } c_conn = to_sde_connector(connector); mutex_lock(&c_conn->lock); rc = c_conn->dpms_mode; mutex_unlock(&c_conn->lock); return rc; } #ifdef CONFIG_DEBUG_FS /** * sde_connector_init_debugfs - initialize connector debugfs Loading Loading @@ -761,7 +879,7 @@ static void sde_connector_early_unregister(struct drm_connector *connector) } static const struct drm_connector_funcs sde_connector_ops = { .dpms = drm_atomic_helper_connector_dpms, .dpms = sde_connector_dpms, .reset = sde_connector_atomic_reset, .detect = sde_connector_detect, .destroy = sde_connector_destroy, Loading Loading @@ -885,6 +1003,10 @@ struct drm_connector *sde_connector_init(struct drm_device *dev, c_conn->panel = panel; c_conn->display = display; c_conn->dpms_mode = DRM_MODE_DPMS_ON; c_conn->lp_mode = 0; c_conn->last_panel_power_mode = SDE_MODE_DPMS_ON; /* cache mmu_id's for later */ sde_kms = to_sde_kms(priv->kms); if (sde_kms->vbif[VBIF_NRT]) { Loading Loading @@ -919,6 +1041,8 @@ struct drm_connector *sde_connector_init(struct drm_device *dev, goto error_cleanup_conn; } mutex_init(&c_conn->lock); rc = drm_mode_connector_attach_encoder(&c_conn->base, encoder); if (rc) { SDE_ERROR("failed to attach encoder to connector, %d\n", rc); Loading Loading @@ -1006,6 +1130,10 @@ struct drm_connector *sde_connector_init(struct drm_device *dev, 0, 1, e_topology_control, ARRAY_SIZE(e_topology_control), CONNECTOR_PROP_TOPOLOGY_CONTROL); msm_property_install_enum(&c_conn->property_info, "LP", 0, 0, e_power_mode, ARRAY_SIZE(e_power_mode), CONNECTOR_PROP_LP); rc = msm_property_install_get_status(&c_conn->property_info); if (rc) { Loading @@ -1027,6 +1155,7 @@ struct drm_connector *sde_connector_init(struct drm_device *dev, drm_property_unreference_blob(c_conn->blob_hdr); msm_property_destroy(&c_conn->property_info); error_cleanup_fence: mutex_destroy(&c_conn->lock); sde_fence_deinit(&c_conn->retire_fence); error_cleanup_conn: drm_connector_cleanup(&c_conn->base); Loading
drivers/gpu/drm/msm/sde/sde_connector.h +29 −0 Original line number Diff line number Diff line Loading @@ -169,6 +169,20 @@ struct sde_connector_ops { * @enable: State of clks */ int (*clk_ctrl)(void *handle, u32 type, u32 state); /** * set_power - update dpms setting * @connector: Pointer to drm connector structure * @power_mode: One of the following, * SDE_MODE_DPMS_ON * SDE_MODE_DPMS_LP1 * SDE_MODE_DPMS_LP2 * SDE_MODE_DPMS_OFF * @display: Pointer to private display structure * Returns: Zero on success */ int (*set_power)(struct drm_connector *connector, int power_mode, void *display); }; /** Loading Loading @@ -203,8 +217,12 @@ struct sde_connector_evt { * @mmu_secure: MMU id for secure buffers * @mmu_unsecure: MMU id for unsecure buffers * @name: ASCII name of connector * @lock: Mutex lock object for this structure * @retire_fence: Retire fence context reference * @ops: Local callback function pointer table * @dpms_mode: DPMS property setting from user space * @lp_mode: LP property setting from user space * @last_panel_power_mode: Last consolidated dpms/lp mode setting * @property_info: Private structure for generic property handling * @property_data: Array of private data for generic property handling * @blob_caps: Pointer to blob structure for 'capabilities' property Loading @@ -226,8 +244,12 @@ struct sde_connector { char name[SDE_CONNECTOR_NAME_SIZE]; struct mutex lock; struct sde_fence_context retire_fence; struct sde_connector_ops ops; int dpms_mode; int lp_mode; int last_panel_power_mode; struct msm_property_info property_info; struct msm_property_data property_data[CONNECTOR_PROP_COUNT]; Loading Loading @@ -391,6 +413,13 @@ int sde_connector_get_info(struct drm_connector *connector, */ void sde_connector_clk_ctrl(struct drm_connector *connector, bool enable); /** * sde_connector_get_dpms - query dpms setting * @connector: Pointer to drm connector structure * Returns: Current DPMS setting for connector */ int sde_connector_get_dpms(struct drm_connector *connector); /** * sde_connector_trigger_event - indicate that an event has occurred * Any callbacks that have been registered against this event will Loading
drivers/gpu/drm/msm/sde/sde_crtc.c +12 −0 Original line number Diff line number Diff line Loading @@ -1946,6 +1946,14 @@ void sde_crtc_commit_kickoff(struct drm_crtc *crtc) priv = sde_kms->dev->dev_private; cstate = to_sde_crtc_state(crtc->state); /* * If no mixers has been allocated in sde_crtc_atomic_check(), * it means we are trying to start a CRTC whose state is disabled: * nothing else needs to be done. */ if (unlikely(!sde_crtc->num_mixers)) return; list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { struct sde_encoder_kickoff_params params = { 0 }; Loading Loading @@ -2409,6 +2417,10 @@ static int sde_crtc_atomic_check(struct drm_crtc *crtc, mode = &state->adjusted_mode; SDE_DEBUG("%s: check", sde_crtc->name); /* force a full mode set if active state changed */ if (state->active_changed) state->mode_changed = true; memset(pipe_staged, 0, sizeof(pipe_staged)); mixer_width = sde_crtc_mixer_width(sde_crtc, mode); Loading
include/uapi/drm/sde_drm.h +10 −0 Original line number Diff line number Diff line Loading @@ -356,4 +356,14 @@ struct sde_drm_roi_v1 { struct drm_clip_rect roi[SDE_MAX_ROI_V1]; }; /** * Define extended power modes supported by the SDE connectors. */ #define SDE_MODE_DPMS_ON 0 #define SDE_MODE_DPMS_LP1 1 #define SDE_MODE_DPMS_LP2 2 #define SDE_MODE_DPMS_STANDBY 3 #define SDE_MODE_DPMS_SUSPEND 4 #define SDE_MODE_DPMS_OFF 5 #endif /* _SDE_DRM_H_ */