Commit 9a69a9ac authored by Maarten Lankhorst's avatar Maarten Lankhorst Committed by Daniel Vetter

drm: Make the connector dpms callback return a value, v2.

This is required to properly handle failing dpms calls.
When making a wait in i915 interruptible, I've noticed
that the dpms sequence could fail with -ERESTARTSYS because
it was waiting interruptibly for flips. So from now on
allow drivers to fail in their connector dpms callback.

Encoder and crtc dpms callbacks are unaffected.

Changes since v1:
- Update kerneldoc for the drm helper functions.
Signed-off-by: default avatarMaarten Lankhorst <maarten.lankhorst@linux.intel.com>
[danvet: Resolve conflicts due to different merge order.]
Signed-off-by: default avatarDaniel Vetter <daniel.vetter@ffwll.ch>
parent 613d2b27
......@@ -1974,8 +1974,11 @@ EXPORT_SYMBOL(drm_atomic_helper_page_flip);
* implementing the legacy DPMS connector interface. It computes the new desired
* ->active state for the corresponding CRTC (if the connector is enabled) and
* updates it.
*
* Returns:
* Returns 0 on success, negative errno numbers on failure.
*/
void drm_atomic_helper_connector_dpms(struct drm_connector *connector,
int drm_atomic_helper_connector_dpms(struct drm_connector *connector,
int mode)
{
struct drm_mode_config *config = &connector->dev->mode_config;
......@@ -1985,6 +1988,7 @@ void drm_atomic_helper_connector_dpms(struct drm_connector *connector,
struct drm_connector *tmp_connector;
int ret;
bool active = false;
int old_mode = connector->dpms;
if (mode != DRM_MODE_DPMS_ON)
mode = DRM_MODE_DPMS_OFF;
......@@ -1993,18 +1997,19 @@ void drm_atomic_helper_connector_dpms(struct drm_connector *connector,
crtc = connector->state->crtc;
if (!crtc)
return;
return 0;
/* FIXME: ->dpms has no return value so can't forward the -ENOMEM. */
state = drm_atomic_state_alloc(connector->dev);
if (!state)
return;
return -ENOMEM;
state->acquire_ctx = drm_modeset_legacy_acquire_ctx(crtc);
retry:
crtc_state = drm_atomic_get_crtc_state(state, crtc);
if (IS_ERR(crtc_state))
return;
if (IS_ERR(crtc_state)) {
ret = PTR_ERR(crtc_state);
goto fail;
}
WARN_ON(!drm_modeset_is_locked(&config->connection_mutex));
......@@ -2023,17 +2028,16 @@ void drm_atomic_helper_connector_dpms(struct drm_connector *connector,
if (ret != 0)
goto fail;
/* Driver takes ownership of state on successful async commit. */
return;
/* Driver takes ownership of state on successful commit. */
return 0;
fail:
if (ret == -EDEADLK)
goto backoff;
connector->dpms = old_mode;
drm_atomic_state_free(state);
WARN(1, "Driver bug: Changing ->active failed with ret=%i\n", ret);
return;
return ret;
backoff:
drm_atomic_state_clear(state);
drm_atomic_legacy_backoff(state);
......
......@@ -4753,9 +4753,9 @@ static int drm_mode_connector_set_obj_prop(struct drm_mode_object *obj,
/* Do DPMS ourselves */
if (property == connector->dev->mode_config.dpms_property) {
if (connector->funcs->dpms)
(*connector->funcs->dpms)(connector, (int)value);
ret = 0;
if (connector->funcs->dpms)
ret = (*connector->funcs->dpms)(connector, (int)value);
} else if (connector->funcs->set_property)
ret = connector->funcs->set_property(connector, property, value);
......
......@@ -762,15 +762,18 @@ static int drm_helper_choose_crtc_dpms(struct drm_crtc *crtc)
* implementing the DPMS connector attribute. It computes the new desired DPMS
* state for all encoders and crtcs in the output mesh and calls the ->dpms()
* callback provided by the driver appropriately.
*
* Returns:
* Always returns 0.
*/
void drm_helper_connector_dpms(struct drm_connector *connector, int mode)
int drm_helper_connector_dpms(struct drm_connector *connector, int mode)
{
struct drm_encoder *encoder = connector->encoder;
struct drm_crtc *crtc = encoder ? encoder->crtc : NULL;
int old_dpms, encoder_dpms = DRM_MODE_DPMS_OFF;
if (mode == connector->dpms)
return;
return 0;
old_dpms = connector->dpms;
connector->dpms = mode;
......@@ -802,7 +805,7 @@ void drm_helper_connector_dpms(struct drm_connector *connector, int mode)
}
}
return;
return 0;
}
EXPORT_SYMBOL(drm_helper_connector_dpms);
......
......@@ -237,7 +237,7 @@ static void intel_enable_crt(struct intel_encoder *encoder)
}
/* Special dpms function to support cloning between dvo/sdvo/crt. */
static void intel_crt_dpms(struct drm_connector *connector, int mode)
static int intel_crt_dpms(struct drm_connector *connector, int mode)
{
struct drm_device *dev = connector->dev;
struct intel_encoder *encoder = intel_attached_encoder(connector);
......@@ -249,7 +249,7 @@ static void intel_crt_dpms(struct drm_connector *connector, int mode)
mode = DRM_MODE_DPMS_OFF;
if (mode == connector->dpms)
return;
return 0;
old_dpms = connector->dpms;
connector->dpms = mode;
......@@ -258,7 +258,7 @@ static void intel_crt_dpms(struct drm_connector *connector, int mode)
crtc = encoder->base.crtc;
if (!crtc) {
encoder->connectors_active = false;
return;
return 0;
}
/* We need the pipe to run for anything but OFF. */
......@@ -281,6 +281,8 @@ static void intel_crt_dpms(struct drm_connector *connector, int mode)
}
intel_modeset_check_state(connector->dev);
return 0;
}
static enum drm_mode_status
......
......@@ -6429,14 +6429,14 @@ struct intel_connector *intel_connector_alloc(void)
/* Even simpler default implementation, if there's really no special case to
* consider. */
void intel_connector_dpms(struct drm_connector *connector, int mode)
int intel_connector_dpms(struct drm_connector *connector, int mode)
{
/* All the simple cases only support two dpms states. */
if (mode != DRM_MODE_DPMS_ON)
mode = DRM_MODE_DPMS_OFF;
if (mode == connector->dpms)
return;
return 0;
connector->dpms = mode;
......@@ -6445,6 +6445,8 @@ void intel_connector_dpms(struct drm_connector *connector, int mode)
intel_encoder_dpms(to_intel_encoder(connector->encoder), mode);
intel_modeset_check_state(connector->dev);
return 0;
}
/* Simple connector->get_hw_state implementation for encoders that support only
......
......@@ -997,7 +997,7 @@ void intel_crtc_update_dpms(struct drm_crtc *crtc);
void intel_encoder_destroy(struct drm_encoder *encoder);
int intel_connector_init(struct intel_connector *);
struct intel_connector *intel_connector_alloc(void);
void intel_connector_dpms(struct drm_connector *, int mode);
int intel_connector_dpms(struct drm_connector *, int mode);
bool intel_connector_get_hw_state(struct intel_connector *connector);
void intel_modeset_check_state(struct drm_device *dev);
bool ibx_digital_port_connected(struct drm_i915_private *dev_priv,
......
......@@ -197,7 +197,7 @@ static void intel_enable_dvo(struct intel_encoder *encoder)
}
/* Special dpms function to support cloning between dvo/sdvo/crt. */
static void intel_dvo_dpms(struct drm_connector *connector, int mode)
static int intel_dvo_dpms(struct drm_connector *connector, int mode)
{
struct intel_dvo *intel_dvo = intel_attached_dvo(connector);
struct drm_crtc *crtc;
......@@ -208,7 +208,7 @@ static void intel_dvo_dpms(struct drm_connector *connector, int mode)
mode = DRM_MODE_DPMS_OFF;
if (mode == connector->dpms)
return;
return 0;
connector->dpms = mode;
......@@ -216,7 +216,7 @@ static void intel_dvo_dpms(struct drm_connector *connector, int mode)
crtc = intel_dvo->base.base.crtc;
if (!crtc) {
intel_dvo->base.connectors_active = false;
return;
return 0;
}
/* We call connector dpms manually below in case pipe dpms doesn't
......@@ -238,6 +238,8 @@ static void intel_dvo_dpms(struct drm_connector *connector, int mode)
}
intel_modeset_check_state(connector->dev);
return 0;
}
static enum drm_mode_status
......
......@@ -1509,7 +1509,7 @@ static void intel_enable_sdvo(struct intel_encoder *encoder)
}
/* Special dpms function to support cloning between dvo/sdvo/crt. */
static void intel_sdvo_dpms(struct drm_connector *connector, int mode)
static int intel_sdvo_dpms(struct drm_connector *connector, int mode)
{
struct drm_crtc *crtc;
struct intel_sdvo *intel_sdvo = intel_attached_sdvo(connector);
......@@ -1519,7 +1519,7 @@ static void intel_sdvo_dpms(struct drm_connector *connector, int mode)
mode = DRM_MODE_DPMS_OFF;
if (mode == connector->dpms)
return;
return 0;
connector->dpms = mode;
......@@ -1527,7 +1527,7 @@ static void intel_sdvo_dpms(struct drm_connector *connector, int mode)
crtc = intel_sdvo->base.base.crtc;
if (!crtc) {
intel_sdvo->base.connectors_active = false;
return;
return 0;
}
/* We set active outputs manually below in case pipe dpms doesn't change
......@@ -1551,6 +1551,8 @@ static void intel_sdvo_dpms(struct drm_connector *connector, int mode)
}
intel_modeset_check_state(connector->dev);
return 0;
}
static enum drm_mode_status
......
......@@ -919,7 +919,7 @@ nouveau_connector_funcs_lvds = {
.force = nouveau_connector_force
};
static void
static int
nouveau_connector_dp_dpms(struct drm_connector *connector, int mode)
{
struct nouveau_encoder *nv_encoder = NULL;
......@@ -938,7 +938,7 @@ nouveau_connector_dp_dpms(struct drm_connector *connector, int mode)
}
}
drm_helper_connector_dpms(connector, mode);
return drm_helper_connector_dpms(connector, mode);
}
static const struct drm_connector_funcs
......
......@@ -246,9 +246,10 @@ radeon_dp_mst_connector_destroy(struct drm_connector *connector)
kfree(radeon_connector);
}
static void radeon_connector_dpms(struct drm_connector *connector, int mode)
static int radeon_connector_dpms(struct drm_connector *connector, int mode)
{
DRM_DEBUG_KMS("\n");
return 0;
}
static const struct drm_connector_funcs radeon_dp_mst_connector_funcs = {
......
......@@ -726,8 +726,9 @@ static void tegra_dsi_soft_reset(struct tegra_dsi *dsi)
tegra_dsi_soft_reset(dsi->slave);
}
static void tegra_dsi_connector_dpms(struct drm_connector *connector, int mode)
static int tegra_dsi_connector_dpms(struct drm_connector *connector, int mode)
{
return 0;
}
static void tegra_dsi_connector_reset(struct drm_connector *connector)
......
......@@ -772,9 +772,10 @@ static bool tegra_output_is_hdmi(struct tegra_output *output)
return drm_detect_hdmi_monitor(edid);
}
static void tegra_hdmi_connector_dpms(struct drm_connector *connector,
static int tegra_hdmi_connector_dpms(struct drm_connector *connector,
int mode)
{
return 0;
}
static const struct drm_connector_funcs tegra_hdmi_connector_funcs = {
......
......@@ -88,9 +88,10 @@ static void tegra_dc_write_regs(struct tegra_dc *dc,
tegra_dc_writel(dc, table[i].value, table[i].offset);
}
static void tegra_rgb_connector_dpms(struct drm_connector *connector,
static int tegra_rgb_connector_dpms(struct drm_connector *connector,
int mode)
{
return 0;
}
static const struct drm_connector_funcs tegra_rgb_connector_funcs = {
......
......@@ -866,8 +866,9 @@ static void tegra_sor_debugfs_exit(struct tegra_sor *sor)
sor->debugfs_files = NULL;
}
static void tegra_sor_connector_dpms(struct drm_connector *connector, int mode)
static int tegra_sor_connector_dpms(struct drm_connector *connector, int mode)
{
return 0;
}
static enum drm_connector_status
......
......@@ -1808,8 +1808,9 @@ void vmw_du_crtc_gamma_set(struct drm_crtc *crtc,
}
}
void vmw_du_connector_dpms(struct drm_connector *connector, int mode)
int vmw_du_connector_dpms(struct drm_connector *connector, int mode)
{
return 0;
}
void vmw_du_connector_save(struct drm_connector *connector)
......
......@@ -133,7 +133,7 @@ void vmw_du_crtc_gamma_set(struct drm_crtc *crtc,
int vmw_du_crtc_cursor_set(struct drm_crtc *crtc, struct drm_file *file_priv,
uint32_t handle, uint32_t width, uint32_t height);
int vmw_du_crtc_cursor_move(struct drm_crtc *crtc, int x, int y);
void vmw_du_connector_dpms(struct drm_connector *connector, int mode);
int vmw_du_connector_dpms(struct drm_connector *connector, int mode);
void vmw_du_connector_save(struct drm_connector *connector);
void vmw_du_connector_restore(struct drm_connector *connector);
enum drm_connector_status
......
......@@ -87,7 +87,7 @@ int drm_atomic_helper_page_flip(struct drm_crtc *crtc,
struct drm_framebuffer *fb,
struct drm_pending_vblank_event *event,
uint32_t flags);
void drm_atomic_helper_connector_dpms(struct drm_connector *connector,
int drm_atomic_helper_connector_dpms(struct drm_connector *connector,
int mode);
/* default implementations for state handling */
......
......@@ -527,7 +527,7 @@ struct drm_connector_state {
* etc.
*/
struct drm_connector_funcs {
void (*dpms)(struct drm_connector *connector, int mode);
int (*dpms)(struct drm_connector *connector, int mode);
void (*save)(struct drm_connector *connector);
void (*restore)(struct drm_connector *connector);
void (*reset)(struct drm_connector *connector);
......
......@@ -189,7 +189,7 @@ extern bool drm_crtc_helper_set_mode(struct drm_crtc *crtc,
extern bool drm_helper_crtc_in_use(struct drm_crtc *crtc);
extern bool drm_helper_encoder_in_use(struct drm_encoder *encoder);
extern void drm_helper_connector_dpms(struct drm_connector *connector, int mode);
extern int drm_helper_connector_dpms(struct drm_connector *connector, int mode);
extern void drm_helper_move_panel_connectors_to_head(struct drm_device *);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment