aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThierry Reding <treding@nvidia.com>2015-12-02 11:50:04 -0500
committerDaniel Vetter <daniel.vetter@ffwll.ch>2015-12-02 17:11:17 -0500
commit1494276000db789c6d2acd85747be4707051c801 (patch)
treebf2dda38924cfcb41ae23374ab670640c951f754
parent06eaae46381737a6236ad6fe81e5358fad3bbbe5 (diff)
drm/atomic-helper: Implement subsystem-level suspend/resume
Provide subsystem-level suspend and resume helpers that can be used to implement suspend/resume on atomic mode-setting enabled drivers. v2: simplify locking, enhance kerneldoc comments v3: pass lock acquisition context by parameter, improve kerneldoc v4: - remove redundant code (already provided by atomic helpers) (Maarten Lankhorst) - move backoff dance from drm_modeset_lock_all_ctx() into suspend helper (Daniel Vetter) v5: handle potential EDEADLK from drm_atomic_helper_duplicate_state() and drm_atomic_helper_disable_all() (Daniel Vetter) Signed-off-by: Thierry Reding <treding@nvidia.com> Link: http://patchwork.freedesktop.org/patch/msgid/1449075005-13937-2-git-send-email-thierry.reding@gmail.com Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
-rw-r--r--drivers/gpu/drm/drm_atomic_helper.c162
-rw-r--r--drivers/gpu/drm/drm_crtc_helper.c6
-rw-r--r--include/drm/drm_atomic_helper.h6
3 files changed, 173 insertions, 1 deletions
diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c
index a800b2c75522..d9053ebf4903 100644
--- a/drivers/gpu/drm/drm_atomic_helper.c
+++ b/drivers/gpu/drm/drm_atomic_helper.c
@@ -1861,6 +1861,161 @@ commit:
1861} 1861}
1862 1862
1863/** 1863/**
1864 * drm_atomic_helper_disable_all - disable all currently active outputs
1865 * @dev: DRM device
1866 * @ctx: lock acquisition context
1867 *
1868 * Loops through all connectors, finding those that aren't turned off and then
1869 * turns them off by setting their DPMS mode to OFF and deactivating the CRTC
1870 * that they are connected to.
1871 *
1872 * This is used for example in suspend/resume to disable all currently active
1873 * functions when suspending.
1874 *
1875 * Note that if callers haven't already acquired all modeset locks this might
1876 * return -EDEADLK, which must be handled by calling drm_modeset_backoff().
1877 *
1878 * Returns:
1879 * 0 on success or a negative error code on failure.
1880 *
1881 * See also:
1882 * drm_atomic_helper_suspend(), drm_atomic_helper_resume()
1883 */
1884int drm_atomic_helper_disable_all(struct drm_device *dev,
1885 struct drm_modeset_acquire_ctx *ctx)
1886{
1887 struct drm_atomic_state *state;
1888 struct drm_connector *conn;
1889 int err;
1890
1891 state = drm_atomic_state_alloc(dev);
1892 if (!state)
1893 return -ENOMEM;
1894
1895 state->acquire_ctx = ctx;
1896
1897 drm_for_each_connector(conn, dev) {
1898 struct drm_crtc *crtc = conn->state->crtc;
1899 struct drm_crtc_state *crtc_state;
1900
1901 if (!crtc || conn->dpms != DRM_MODE_DPMS_ON)
1902 continue;
1903
1904 crtc_state = drm_atomic_get_crtc_state(state, crtc);
1905 if (IS_ERR(crtc_state)) {
1906 err = PTR_ERR(crtc_state);
1907 goto free;
1908 }
1909
1910 crtc_state->active = false;
1911 }
1912
1913 err = drm_atomic_commit(state);
1914
1915free:
1916 if (err < 0)
1917 drm_atomic_state_free(state);
1918
1919 return err;
1920}
1921EXPORT_SYMBOL(drm_atomic_helper_disable_all);
1922
1923/**
1924 * drm_atomic_helper_suspend - subsystem-level suspend helper
1925 * @dev: DRM device
1926 *
1927 * Duplicates the current atomic state, disables all active outputs and then
1928 * returns a pointer to the original atomic state to the caller. Drivers can
1929 * pass this pointer to the drm_atomic_helper_resume() helper upon resume to
1930 * restore the output configuration that was active at the time the system
1931 * entered suspend.
1932 *
1933 * Note that it is potentially unsafe to use this. The atomic state object
1934 * returned by this function is assumed to be persistent. Drivers must ensure
1935 * that this holds true. Before calling this function, drivers must make sure
1936 * to suspend fbdev emulation so that nothing can be using the device.
1937 *
1938 * Returns:
1939 * A pointer to a copy of the state before suspend on success or an ERR_PTR()-
1940 * encoded error code on failure. Drivers should store the returned atomic
1941 * state object and pass it to the drm_atomic_helper_resume() helper upon
1942 * resume.
1943 *
1944 * See also:
1945 * drm_atomic_helper_duplicate_state(), drm_atomic_helper_disable_all(),
1946 * drm_atomic_helper_resume()
1947 */
1948struct drm_atomic_state *drm_atomic_helper_suspend(struct drm_device *dev)
1949{
1950 struct drm_modeset_acquire_ctx ctx;
1951 struct drm_atomic_state *state;
1952 int err;
1953
1954 drm_modeset_acquire_init(&ctx, 0);
1955
1956retry:
1957 err = drm_modeset_lock_all_ctx(dev, &ctx);
1958 if (err < 0) {
1959 state = ERR_PTR(err);
1960 goto unlock;
1961 }
1962
1963 state = drm_atomic_helper_duplicate_state(dev, &ctx);
1964 if (IS_ERR(state))
1965 goto unlock;
1966
1967 err = drm_atomic_helper_disable_all(dev, &ctx);
1968 if (err < 0) {
1969 drm_atomic_state_free(state);
1970 state = ERR_PTR(err);
1971 goto unlock;
1972 }
1973
1974unlock:
1975 if (PTR_ERR(state) == -EDEADLK) {
1976 drm_modeset_backoff(&ctx);
1977 goto retry;
1978 }
1979
1980 drm_modeset_drop_locks(&ctx);
1981 drm_modeset_acquire_fini(&ctx);
1982 return state;
1983}
1984EXPORT_SYMBOL(drm_atomic_helper_suspend);
1985
1986/**
1987 * drm_atomic_helper_resume - subsystem-level resume helper
1988 * @dev: DRM device
1989 * @state: atomic state to resume to
1990 *
1991 * Calls drm_mode_config_reset() to synchronize hardware and software states,
1992 * grabs all modeset locks and commits the atomic state object. This can be
1993 * used in conjunction with the drm_atomic_helper_suspend() helper to
1994 * implement suspend/resume for drivers that support atomic mode-setting.
1995 *
1996 * Returns:
1997 * 0 on success or a negative error code on failure.
1998 *
1999 * See also:
2000 * drm_atomic_helper_suspend()
2001 */
2002int drm_atomic_helper_resume(struct drm_device *dev,
2003 struct drm_atomic_state *state)
2004{
2005 struct drm_mode_config *config = &dev->mode_config;
2006 int err;
2007
2008 drm_mode_config_reset(dev);
2009 drm_modeset_lock_all(dev);
2010 state->acquire_ctx = config->acquire_ctx;
2011 err = drm_atomic_commit(state);
2012 drm_modeset_unlock_all(dev);
2013
2014 return err;
2015}
2016EXPORT_SYMBOL(drm_atomic_helper_resume);
2017
2018/**
1864 * drm_atomic_helper_crtc_set_property - helper for crtc properties 2019 * drm_atomic_helper_crtc_set_property - helper for crtc properties
1865 * @crtc: DRM crtc 2020 * @crtc: DRM crtc
1866 * @property: DRM property 2021 * @property: DRM property
@@ -2472,7 +2627,9 @@ EXPORT_SYMBOL(drm_atomic_helper_connector_duplicate_state);
2472 * @ctx: lock acquisition context 2627 * @ctx: lock acquisition context
2473 * 2628 *
2474 * Makes a copy of the current atomic state by looping over all objects and 2629 * Makes a copy of the current atomic state by looping over all objects and
2475 * duplicating their respective states. 2630 * duplicating their respective states. This is used for example by suspend/
2631 * resume support code to save the state prior to suspend such that it can
2632 * be restored upon resume.
2476 * 2633 *
2477 * Note that this treats atomic state as persistent between save and restore. 2634 * Note that this treats atomic state as persistent between save and restore.
2478 * Drivers must make sure that this is possible and won't result in confusion 2635 * Drivers must make sure that this is possible and won't result in confusion
@@ -2484,6 +2641,9 @@ EXPORT_SYMBOL(drm_atomic_helper_connector_duplicate_state);
2484 * Returns: 2641 * Returns:
2485 * A pointer to the copy of the atomic state object on success or an 2642 * A pointer to the copy of the atomic state object on success or an
2486 * ERR_PTR()-encoded error code on failure. 2643 * ERR_PTR()-encoded error code on failure.
2644 *
2645 * See also:
2646 * drm_atomic_helper_suspend(), drm_atomic_helper_resume()
2487 */ 2647 */
2488struct drm_atomic_state * 2648struct drm_atomic_state *
2489drm_atomic_helper_duplicate_state(struct drm_device *dev, 2649drm_atomic_helper_duplicate_state(struct drm_device *dev,
diff --git a/drivers/gpu/drm/drm_crtc_helper.c b/drivers/gpu/drm/drm_crtc_helper.c
index 6b4cf25fed12..10d0989db273 100644
--- a/drivers/gpu/drm/drm_crtc_helper.c
+++ b/drivers/gpu/drm/drm_crtc_helper.c
@@ -855,6 +855,12 @@ EXPORT_SYMBOL(drm_helper_mode_fill_fb_struct);
855 * due to slight differences in allocating shared resources when the 855 * due to slight differences in allocating shared resources when the
856 * configuration is restored in a different order than when userspace set it up) 856 * configuration is restored in a different order than when userspace set it up)
857 * need to use their own restore logic. 857 * need to use their own restore logic.
858 *
859 * This function is deprecated. New drivers should implement atomic mode-
860 * setting and use the atomic suspend/resume helpers.
861 *
862 * See also:
863 * drm_atomic_helper_suspend(), drm_atomic_helper_resume()
858 */ 864 */
859void drm_helper_resume_force_mode(struct drm_device *dev) 865void drm_helper_resume_force_mode(struct drm_device *dev)
860{ 866{
diff --git a/include/drm/drm_atomic_helper.h b/include/drm/drm_atomic_helper.h
index b7d423732f47..a286cce98720 100644
--- a/include/drm/drm_atomic_helper.h
+++ b/include/drm/drm_atomic_helper.h
@@ -83,6 +83,12 @@ int drm_atomic_helper_set_config(struct drm_mode_set *set);
83int __drm_atomic_helper_set_config(struct drm_mode_set *set, 83int __drm_atomic_helper_set_config(struct drm_mode_set *set,
84 struct drm_atomic_state *state); 84 struct drm_atomic_state *state);
85 85
86int drm_atomic_helper_disable_all(struct drm_device *dev,
87 struct drm_modeset_acquire_ctx *ctx);
88struct drm_atomic_state *drm_atomic_helper_suspend(struct drm_device *dev);
89int drm_atomic_helper_resume(struct drm_device *dev,
90 struct drm_atomic_state *state);
91
86int drm_atomic_helper_crtc_set_property(struct drm_crtc *crtc, 92int drm_atomic_helper_crtc_set_property(struct drm_crtc *crtc,
87 struct drm_property *property, 93 struct drm_property *property,
88 uint64_t val); 94 uint64_t val);