From 5f6aee341959eeb735eaec9244d7dcd662ca624b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20=C3=85dahl?= Date: Wed, 21 Oct 2020 17:38:44 +0200 Subject: [PATCH] kms/update: Make power saving an update wide change This makes "power save" (i.e. when you make a monitor go into power save mode, or make it come out of power save mode), a per device action when turning on power saving (power save being set to 'off'), and implicitly handled when turning off power saving (power save being set to 'on') when doing a mode set. This is needed as with atomic mode setting, the configuration of DPMS (Display Power Management Signaling), is replaced by directly turning on or off CRTCs, and via the CRTC drm properties. Thus in order to handle both with a common API, make that API high level enough for both cases being covered. Part-of: --- src/backends/native/meta-crtc-kms.c | 19 --- src/backends/native/meta-gpu-kms.c | 29 ---- .../native/meta-kms-impl-device-simple.c | 151 +++++++++++++++--- src/backends/native/meta-kms-impl-device.c | 9 ++ src/backends/native/meta-kms-impl-device.h | 2 + src/backends/native/meta-kms-update-private.h | 7 +- src/backends/native/meta-kms-update.c | 31 ++-- src/backends/native/meta-kms-update.h | 4 +- .../native/meta-monitor-manager-kms.c | 7 +- src/backends/native/meta-output-kms.c | 14 -- 10 files changed, 165 insertions(+), 108 deletions(-) diff --git a/src/backends/native/meta-crtc-kms.c b/src/backends/native/meta-crtc-kms.c index e37619b1c..d5e469e7a 100644 --- a/src/backends/native/meta-crtc-kms.c +++ b/src/backends/native/meta-crtc-kms.c @@ -227,30 +227,11 @@ meta_crtc_kms_set_mode (MetaCrtcKms *crtc_kms, { const MetaCrtcConfig *crtc_config = meta_crtc_get_config (crtc); MetaCrtcModeKms *crtc_mode_kms = META_CRTC_MODE_KMS (crtc_config->mode); - MetaBackend *backend = meta_gpu_get_backend (gpu); - MetaMonitorManager *monitor_manager = - meta_backend_get_monitor_manager (backend); - MetaPowerSave power_save; - uint64_t dpms_state; - GList *l; kms_mode = meta_crtc_mode_kms_get_kms_mode (crtc_mode_kms); g_debug ("Setting CRTC (%" G_GUINT64_FORMAT ") mode to %s", meta_crtc_get_id (crtc), meta_kms_mode_get_name (kms_mode)); - - power_save = meta_monitor_manager_get_power_save_mode (monitor_manager); - g_warn_if_fail (power_save == META_POWER_SAVE_ON); - - dpms_state = meta_power_save_to_dpms_state (power_save); - for (l = connectors; l; l = l->next) - { - MetaKmsConnector *kms_connector = l->data; - - meta_kms_update_set_dpms_state (kms_update, - kms_connector, - dpms_state); - } } else { diff --git a/src/backends/native/meta-gpu-kms.c b/src/backends/native/meta-gpu-kms.c index 3df26ff3e..643c25882 100644 --- a/src/backends/native/meta-gpu-kms.c +++ b/src/backends/native/meta-gpu-kms.c @@ -143,35 +143,6 @@ meta_gpu_kms_get_current_time_ns (MetaGpuKms *gpu_kms) return timespec_to_nanoseconds (&ts); } -void -meta_gpu_kms_set_power_save_mode (MetaGpuKms *gpu_kms, - uint64_t state, - MetaKmsUpdate *kms_update) -{ - MetaGpu *gpu = META_GPU (gpu_kms); - GList *l; - - g_return_if_fail (state != DRM_MODE_DPMS_ON); - - for (l = meta_gpu_get_outputs (gpu); l; l = l->next) - { - MetaOutput *output = l->data; - - meta_output_kms_set_power_save_mode (META_OUTPUT_KMS (output), - state, kms_update); - } - - /* Turn off CRTCs for DPMS */ - for (l = meta_gpu_get_crtcs (gpu); l; l = l->next) - { - MetaCrtcKms *crtc_kms = META_CRTC_KMS (l->data); - - meta_kms_update_mode_set (kms_update, - meta_crtc_kms_get_kms_crtc (crtc_kms), - NULL, NULL); - } -} - gboolean meta_gpu_kms_is_boot_vga (MetaGpuKms *gpu_kms) { diff --git a/src/backends/native/meta-kms-impl-device-simple.c b/src/backends/native/meta-kms-impl-device-simple.c index a045f8df6..1b6efa984 100644 --- a/src/backends/native/meta-kms-impl-device-simple.c +++ b/src/backends/native/meta-kms-impl-device-simple.c @@ -66,6 +66,65 @@ G_DEFINE_TYPE_WITH_CODE (MetaKmsImplDeviceSimple, meta_kms_impl_device_simple, static void flush_postponed_page_flip_datas (MetaKmsImplDeviceSimple *impl_device_simple); +static gboolean +get_connector_property (MetaKmsImplDevice *impl_device, + MetaKmsConnector *connector, + MetaKmsConnectorProp prop, + uint64_t *value, + GError **error) +{ + uint32_t prop_id; + int fd; + drmModeConnector *drm_connector; + int i; + gboolean found; + + prop_id = meta_kms_connector_get_prop_id (connector, prop); + if (!prop_id) + { + g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED, + "Property (%s) not found on connector %u", + meta_kms_connector_get_prop_name (connector, prop), + meta_kms_connector_get_id (connector)); + return FALSE; + } + + fd = meta_kms_impl_device_get_fd (impl_device); + + drm_connector = drmModeGetConnector (fd, + meta_kms_connector_get_id (connector)); + if (!drm_connector) + { + g_set_error (error, G_IO_ERROR, g_io_error_from_errno (errno), + "Failed to get connector %u resources: %s", + meta_kms_connector_get_id (connector), + g_strerror (errno)); + return FALSE; + } + + found = FALSE; + for (i = 0; i < drm_connector->count_props; i++) + { + if (drm_connector->props[i] == prop_id) + { + *value = drm_connector->prop_values[i]; + found = TRUE; + break; + } + } + + drmModeFreeConnector (drm_connector); + + if (!found) + { + g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND, + "Connector property %u not found", prop_id); + return FALSE; + } + + return TRUE; +} + static gboolean set_connector_property (MetaKmsImplDevice *impl_device, MetaKmsConnector *connector, @@ -107,6 +166,32 @@ set_connector_property (MetaKmsImplDevice *impl_device, return TRUE; } +static gboolean +process_power_save (MetaKmsImplDevice *impl_device, + GError **error) +{ + GList *l; + + for (l = meta_kms_impl_device_peek_connectors (impl_device); l; l = l->next) + { + MetaKmsConnector *connector = l->data; + + meta_topic (META_DEBUG_KMS, + "[simple] Setting DPMS of connector %u (%s) to OFF", + meta_kms_connector_get_id (connector), + meta_kms_impl_device_get_path (impl_device)); + + if (!set_connector_property (impl_device, + connector, + META_KMS_CONNECTOR_PROP_DPMS, + DRM_MODE_DPMS_OFF, + error)) + return FALSE; + } + + return TRUE; +} + static gboolean process_connector_update (MetaKmsImplDevice *impl_device, MetaKmsUpdate *update, @@ -116,23 +201,6 @@ process_connector_update (MetaKmsImplDevice *impl_device, MetaKmsConnectorUpdate *connector_update = update_entry; MetaKmsConnector *connector = connector_update->connector; - if (connector_update->dpms.has_update) - { - meta_topic (META_DEBUG_KMS, - "[simple] Setting DPMS on connector %u (%s) to %" - G_GUINT64_FORMAT, - meta_kms_connector_get_id (connector), - meta_kms_impl_device_get_path (impl_device), - connector_update->dpms.state); - - if (!set_connector_property (impl_device, - connector, - META_KMS_CONNECTOR_PROP_DPMS, - connector_update->dpms.state, - error)) - return FALSE; - } - if (connector_update->underscanning.has_update && connector_update->underscanning.is_active) { @@ -288,6 +356,7 @@ process_mode_set (MetaKmsImplDevice *impl_device, if (mode_set->mode) { MetaDrmBuffer *buffer; + GList *l; drm_mode = g_alloca (sizeof *drm_mode); *drm_mode = *meta_kms_mode_get_drm_mode (mode_set->mode); @@ -321,6 +390,34 @@ process_mode_set (MetaKmsImplDevice *impl_device, buffer = plane_assignment->buffer; fb_id = meta_drm_buffer_get_fb_id (buffer); + for (l = mode_set->connectors; l; l = l->next) + { + MetaKmsConnector *connector = l->data; + uint64_t dpms_value; + + if (!get_connector_property (impl_device, + connector, + META_KMS_CONNECTOR_PROP_DPMS, + &dpms_value, + error)) + return FALSE; + + if (dpms_value != DRM_MODE_DPMS_ON) + { + meta_topic (META_DEBUG_KMS, + "[simple] Setting DPMS of connector %u (%s) to ON", + meta_kms_connector_get_id (connector), + meta_kms_impl_device_get_path (impl_device)); + + if (!set_connector_property (impl_device, + connector, + META_KMS_CONNECTOR_PROP_DPMS, + DRM_MODE_DPMS_ON, + error)) + return FALSE; + } + } + meta_topic (META_DEBUG_KMS, "[simple] Setting mode of CRTC %u (%s) to %s", meta_kms_crtc_get_id (crtc), @@ -1256,12 +1353,12 @@ meta_kms_impl_device_simple_process_update (MetaKmsImplDevice *impl_device, "[simple] Processing update %" G_GUINT64_FORMAT, meta_kms_update_get_sequence_number (update)); - if (!process_entries (impl_device, - update, - meta_kms_update_get_connector_updates (update), - process_connector_update, - &error)) - goto err; + if (meta_kms_update_is_power_save (update)) + { + if (!process_power_save (impl_device, &error)) + goto err; + goto out; + } if (!process_entries (impl_device, update, @@ -1270,6 +1367,13 @@ meta_kms_impl_device_simple_process_update (MetaKmsImplDevice *impl_device, &error)) goto err; + if (!process_entries (impl_device, + update, + meta_kms_update_get_connector_updates (update), + process_connector_update, + &error)) + goto err; + if (!process_entries (impl_device, update, meta_kms_update_get_crtc_gammas (update), @@ -1283,6 +1387,7 @@ meta_kms_impl_device_simple_process_update (MetaKmsImplDevice *impl_device, if (!maybe_dispatch_page_flips (impl_device, update, &failed_planes, &error)) goto err; +out: return meta_kms_feedback_new_passed (failed_planes); err: diff --git a/src/backends/native/meta-kms-impl-device.c b/src/backends/native/meta-kms-impl-device.c index d944b6c07..c762e5ee2 100644 --- a/src/backends/native/meta-kms-impl-device.c +++ b/src/backends/native/meta-kms-impl-device.c @@ -120,6 +120,15 @@ meta_kms_impl_device_copy_planes (MetaKmsImplDevice *impl_device) return g_list_copy (priv->planes); } +GList * +meta_kms_impl_device_peek_connectors (MetaKmsImplDevice *impl_device) +{ + MetaKmsImplDevicePrivate *priv = + meta_kms_impl_device_get_instance_private (impl_device); + + return priv->connectors; +} + const MetaKmsDeviceCaps * meta_kms_impl_device_get_caps (MetaKmsImplDevice *impl_device) { diff --git a/src/backends/native/meta-kms-impl-device.h b/src/backends/native/meta-kms-impl-device.h index c378b78c3..79db8a575 100644 --- a/src/backends/native/meta-kms-impl-device.h +++ b/src/backends/native/meta-kms-impl-device.h @@ -78,6 +78,8 @@ GList * meta_kms_impl_device_copy_crtcs (MetaKmsImplDevice *impl_device); GList * meta_kms_impl_device_copy_planes (MetaKmsImplDevice *impl_device); +GList * meta_kms_impl_device_peek_connectors (MetaKmsImplDevice *impl_device); + const MetaKmsDeviceCaps * meta_kms_impl_device_get_caps (MetaKmsImplDevice *impl_device); GList * meta_kms_impl_device_copy_fallback_modes (MetaKmsImplDevice *impl_device); diff --git a/src/backends/native/meta-kms-update-private.h b/src/backends/native/meta-kms-update-private.h index 02afdc934..6546eb915 100644 --- a/src/backends/native/meta-kms-update-private.h +++ b/src/backends/native/meta-kms-update-private.h @@ -70,11 +70,6 @@ typedef struct _MetaKmsConnectorUpdate uint64_t hborder; uint64_t vborder; } underscanning; - - struct { - gboolean has_update; - uint64_t state; - } dpms; } MetaKmsConnectorUpdate; typedef struct _MetaKmsPageFlipListener @@ -127,6 +122,8 @@ GList * meta_kms_update_get_connector_updates (MetaKmsUpdate *update); GList * meta_kms_update_get_crtc_gammas (MetaKmsUpdate *update); +gboolean meta_kms_update_is_power_save (MetaKmsUpdate *update); + void meta_kms_update_get_custom_page_flip_func (MetaKmsUpdate *update, MetaKmsCustomPageFlipFunc *custom_page_flip_func, gpointer *custom_page_flip_user_data); diff --git a/src/backends/native/meta-kms-update.c b/src/backends/native/meta-kms-update.c index 450883865..36c1761c3 100644 --- a/src/backends/native/meta-kms-update.c +++ b/src/backends/native/meta-kms-update.c @@ -35,7 +35,8 @@ struct _MetaKmsUpdate gboolean is_locked; uint64_t sequence_number; - MetaPowerSave power_save; + gboolean power_save; + GList *mode_sets; GList *plane_assignments; GList *connector_updates; @@ -188,6 +189,7 @@ meta_kms_update_assign_plane (MetaKmsUpdate *update, g_assert (!meta_kms_update_is_locked (update)); g_assert (meta_kms_crtc_get_device (crtc) == update->device); + g_assert (!update->power_save); g_assert (meta_kms_plane_get_device (plane) == update->device); g_assert (meta_kms_plane_get_plane_type (plane) != META_KMS_PLANE_TYPE_PRIMARY || @@ -226,6 +228,7 @@ meta_kms_update_unassign_plane (MetaKmsUpdate *update, g_assert (!meta_kms_update_is_locked (update)); g_assert (meta_kms_crtc_get_device (crtc) == update->device); g_assert (meta_kms_plane_get_device (plane) == update->device); + g_assert (!update->power_save); plane_assignment = g_new0 (MetaKmsPlaneAssignment, 1); *plane_assignment = (MetaKmsPlaneAssignment) { @@ -251,6 +254,7 @@ meta_kms_update_mode_set (MetaKmsUpdate *update, g_assert (!meta_kms_update_is_locked (update)); g_assert (meta_kms_crtc_get_device (crtc) == update->device); + g_assert (!update->power_save); mode_set = g_new0 (MetaKmsModeSet, 1); *mode_set = (MetaKmsModeSet) { @@ -296,6 +300,7 @@ meta_kms_update_set_underscanning (MetaKmsUpdate *update, g_assert (!meta_kms_update_is_locked (update)); g_assert (meta_kms_connector_get_device (connector) == update->device); + g_assert (!update->power_save); connector_update = ensure_connector_update (update, connector); connector_update->underscanning.has_update = TRUE; @@ -312,6 +317,7 @@ meta_kms_update_unset_underscanning (MetaKmsUpdate *update, g_assert (!meta_kms_update_is_locked (update)); g_assert (meta_kms_connector_get_device (connector) == update->device); + g_assert (!update->power_save); connector_update = ensure_connector_update (update, connector); connector_update->underscanning.has_update = TRUE; @@ -319,18 +325,15 @@ meta_kms_update_unset_underscanning (MetaKmsUpdate *update, } void -meta_kms_update_set_dpms_state (MetaKmsUpdate *update, - MetaKmsConnector *connector, - uint64_t state) +meta_kms_update_set_power_save (MetaKmsUpdate *update) { - MetaKmsConnectorUpdate *connector_update; - g_assert (!meta_kms_update_is_locked (update)); - g_assert (meta_kms_connector_get_device (connector) == update->device); + g_assert (!update->mode_sets); + g_assert (!update->plane_assignments); + g_assert (!update->connector_updates); + g_assert (!update->crtc_gammas); - connector_update = ensure_connector_update (update, connector); - connector_update->dpms.has_update = TRUE; - connector_update->dpms.state = state; + update->power_save = TRUE; } void @@ -375,6 +378,7 @@ meta_kms_update_set_crtc_gamma (MetaKmsUpdate *update, g_assert (!meta_kms_update_is_locked (update)); g_assert (meta_kms_crtc_get_device (crtc) == update->device); + g_assert (!update->power_save); gamma = meta_kms_crtc_gamma_new (crtc, size, red, green, blue); @@ -409,6 +413,7 @@ meta_kms_update_set_custom_page_flip (MetaKmsUpdate *update, gpointer user_data) { g_assert (!meta_kms_update_is_locked (update)); + g_assert (!update->power_save); update->custom_page_flip_func = func; update->custom_page_flip_user_data = user_data; @@ -523,6 +528,12 @@ meta_kms_update_get_crtc_gammas (MetaKmsUpdate *update) return update->crtc_gammas; } +gboolean +meta_kms_update_is_power_save (MetaKmsUpdate *update) +{ + return update->power_save; +} + void meta_kms_update_lock (MetaKmsUpdate *update) { diff --git a/src/backends/native/meta-kms-update.h b/src/backends/native/meta-kms-update.h index 2274b3791..6438ff99b 100644 --- a/src/backends/native/meta-kms-update.h +++ b/src/backends/native/meta-kms-update.h @@ -95,9 +95,7 @@ void meta_kms_update_set_underscanning (MetaKmsUpdate *update, void meta_kms_update_unset_underscanning (MetaKmsUpdate *update, MetaKmsConnector *connector); -void meta_kms_update_set_dpms_state (MetaKmsUpdate *update, - MetaKmsConnector *connector, - uint64_t state); +void meta_kms_update_set_power_save (MetaKmsUpdate *update); void meta_kms_update_mode_set (MetaKmsUpdate *update, MetaKmsCrtc *crtc, diff --git a/src/backends/native/meta-monitor-manager-kms.c b/src/backends/native/meta-monitor-manager-kms.c index 72bdc91d0..13fb196a1 100644 --- a/src/backends/native/meta-monitor-manager-kms.c +++ b/src/backends/native/meta-monitor-manager-kms.c @@ -143,7 +143,6 @@ meta_monitor_manager_kms_set_power_save_mode (MetaMonitorManager *manager, MetaBackend *backend = meta_monitor_manager_get_backend (manager); MetaBackendNative *backend_native = META_BACKEND_NATIVE (backend); MetaKms *kms = meta_backend_native_get_kms (backend_native); - uint64_t state; GList *l; switch (mode) @@ -158,8 +157,6 @@ meta_monitor_manager_kms_set_power_save_mode (MetaMonitorManager *manager, break; } - state = meta_power_save_to_dpms_state (mode); - for (l = meta_backend_get_gpus (backend); l; l = l->next) { MetaGpuKms *gpu_kms = l->data; @@ -169,7 +166,7 @@ meta_monitor_manager_kms_set_power_save_mode (MetaMonitorManager *manager, g_autoptr (MetaKmsFeedback) kms_feedback = NULL; kms_update = meta_kms_ensure_pending_update (kms, kms_device); - meta_gpu_kms_set_power_save_mode (gpu_kms, state, kms_update); + meta_kms_update_set_power_save (kms_update); flags = META_KMS_UPDATE_FLAG_NONE; kms_feedback = meta_kms_post_pending_update_sync (kms, @@ -178,7 +175,7 @@ meta_monitor_manager_kms_set_power_save_mode (MetaMonitorManager *manager, if (meta_kms_feedback_get_result (kms_feedback) != META_KMS_FEEDBACK_PASSED) { - g_warning ("Failed to set DPMS: %s", + g_warning ("Failed to enter power saving mode: %s", meta_kms_feedback_get_error (kms_feedback)->message); } } diff --git a/src/backends/native/meta-output-kms.c b/src/backends/native/meta-output-kms.c index ca744ba41..16d33d601 100644 --- a/src/backends/native/meta-output-kms.c +++ b/src/backends/native/meta-output-kms.c @@ -102,20 +102,6 @@ meta_output_kms_get_connector_id (MetaOutputKms *output_kms) return meta_kms_connector_get_id (output_kms->kms_connector); } -void -meta_output_kms_set_power_save_mode (MetaOutputKms *output_kms, - uint64_t dpms_state, - MetaKmsUpdate *kms_update) -{ - g_debug ("Setting DPMS state of connector %s to %" G_GUINT64_FORMAT, - meta_kms_connector_get_name (output_kms->kms_connector), - dpms_state); - - meta_kms_update_set_dpms_state (kms_update, - output_kms->kms_connector, - dpms_state); -} - gboolean meta_output_kms_can_clone (MetaOutputKms *output_kms, MetaOutputKms *other_output_kms)