Sorry that was a typo on my part. I'm using radeon.runpm=1 I can see audio is switched off
[drm] Disabling audio 0 support When I use DRI_PRIME=1 I see the DRM initialisation for my card each time I fire up an application or run glxinfo There isn't any explicit messages that the card is on of off however How can I tell if I have a powerxpress card? Thanks again Mike On 20 Sep 2013 22:05, "Alex Deucher" <alexdeucher at gmail.com> wrote: > On Fri, Sep 20, 2013 at 4:25 PM, Mike Lothian <mike at fireburn.co.uk> wrote: > > Hi > > > > Is there an easy way to check this is on? > > It's on by default if your system is a powerxpress system (hybrid laptop). > > > > > I have radeon.dynpm=1 in grub but usually when I use switcheroo I see > > messages saying the card if now off at the moment I can old see messages > > saying when the card gets powered up > > > > The option is radeon.runpm for this. Note that only powerxpress > systems are supported. There is no support for powering down > arbitrary cards yet. > > > Is it possible to have the on and off messages appearing? > > On a supported system, you will see suspend and resume messages when > when the card is powered down/up. > > Alex > > > > > Cheers > > > > Mike > > > > > > On 20 September 2013 18:18, Alex Deucher <alexdeucher at gmail.com> wrote: > >> > >> From: Dave Airlie <airlied at redhat.com> > >> > >> This hooks radeon up to the runtime PM system to enable > >> dynamic power management for secondary GPUs in switchable > >> and powerxpress laptops. > >> > >> v2: agd5f: clean up, add module parameter > >> > >> Signed-off-by: Dave Airlie <airlied at redhat.com> > >> Signed-off-by: Alex Deucher <alexander.deucher at amd.com> > >> --- > >> drivers/gpu/drm/radeon/radeon.h | 8 +- > >> drivers/gpu/drm/radeon/radeon_atpx_handler.c | 4 + > >> drivers/gpu/drm/radeon/radeon_connectors.c | 63 ++++++++++++-- > >> drivers/gpu/drm/radeon/radeon_device.c | 52 +++++++++--- > >> drivers/gpu/drm/radeon/radeon_display.c | 47 ++++++++++- > >> drivers/gpu/drm/radeon/radeon_drv.c | 122 > >> +++++++++++++++++++++++++-- > >> drivers/gpu/drm/radeon/radeon_drv.h | 3 + > >> drivers/gpu/drm/radeon/radeon_ioc32.c | 2 +- > >> drivers/gpu/drm/radeon/radeon_irq_kms.c | 8 +- > >> drivers/gpu/drm/radeon/radeon_kms.c | 26 +++++- > >> 10 files changed, 299 insertions(+), 36 deletions(-) > >> > >> diff --git a/drivers/gpu/drm/radeon/radeon.h > >> b/drivers/gpu/drm/radeon/radeon.h > >> index 986100a..ad54525 100644 > >> --- a/drivers/gpu/drm/radeon/radeon.h > >> +++ b/drivers/gpu/drm/radeon/radeon.h > >> @@ -98,6 +98,7 @@ extern int radeon_lockup_timeout; > >> extern int radeon_fastfb; > >> extern int radeon_dpm; > >> extern int radeon_aspm; > >> +extern int radeon_runtime_pm; > >> > >> /* > >> * Copy from radeon_drv.h so we don't have to include both and have > >> conflicting > >> @@ -2212,6 +2213,9 @@ struct radeon_device { > >> /* clock, powergating flags */ > >> u32 cg_flags; > >> u32 pg_flags; > >> + > >> + struct dev_pm_domain vga_pm_domain; > >> + bool have_disp_power_ref; > >> }; > >> > >> int radeon_device_init(struct radeon_device *rdev, > >> @@ -2673,8 +2677,8 @@ extern void > radeon_ttm_placement_from_domain(struct > >> radeon_bo *rbo, u32 domain); > >> extern bool radeon_ttm_bo_is_radeon_bo(struct ttm_buffer_object *bo); > >> extern void radeon_vram_location(struct radeon_device *rdev, struct > >> radeon_mc *mc, u64 base); > >> extern void radeon_gtt_location(struct radeon_device *rdev, struct > >> radeon_mc *mc); > >> -extern int radeon_resume_kms(struct drm_device *dev, bool resume); > >> -extern int radeon_suspend_kms(struct drm_device *dev, bool suspend); > >> +extern int radeon_resume_kms(struct drm_device *dev, bool resume, bool > >> fbcon); > >> +extern int radeon_suspend_kms(struct drm_device *dev, bool suspend, > bool > >> fbcon); > >> extern void radeon_ttm_set_active_vram_size(struct radeon_device *rdev, > >> u64 size); > >> extern void radeon_program_register_sequence(struct radeon_device > *rdev, > >> const u32 *registers, > >> diff --git a/drivers/gpu/drm/radeon/radeon_atpx_handler.c > >> b/drivers/gpu/drm/radeon/radeon_atpx_handler.c > >> index d96070b..6153ec1 100644 > >> --- a/drivers/gpu/drm/radeon/radeon_atpx_handler.c > >> +++ b/drivers/gpu/drm/radeon/radeon_atpx_handler.c > >> @@ -59,6 +59,10 @@ struct atpx_mux { > >> u16 mux; > >> } __packed; > >> > >> +bool radeon_is_px(void) { > >> + return radeon_atpx_priv.atpx_detected; > >> +} > >> + > >> /** > >> * radeon_atpx_call - call an ATPX method > >> * > >> diff --git a/drivers/gpu/drm/radeon/radeon_connectors.c > >> b/drivers/gpu/drm/radeon/radeon_connectors.c > >> index 79159b5..5855b5b 100644 > >> --- a/drivers/gpu/drm/radeon/radeon_connectors.c > >> +++ b/drivers/gpu/drm/radeon/radeon_connectors.c > >> @@ -31,6 +31,8 @@ > >> #include "radeon.h" > >> #include "atom.h" > >> > >> +#include <linux/pm_runtime.h> > >> + > >> extern void > >> radeon_combios_connected_scratch_regs(struct drm_connector *connector, > >> struct drm_encoder *encoder, > >> @@ -626,6 +628,11 @@ radeon_lvds_detect(struct drm_connector *connector, > >> bool force) > >> struct radeon_connector *radeon_connector = > >> to_radeon_connector(connector); > >> struct drm_encoder *encoder = > >> radeon_best_single_encoder(connector); > >> enum drm_connector_status ret = connector_status_disconnected; > >> + int r; > >> + > >> + r = pm_runtime_get_sync(connector->dev->dev); > >> + if (r < 0) > >> + return connector_status_disconnected; > >> > >> if (encoder) { > >> struct radeon_encoder *radeon_encoder = > >> to_radeon_encoder(encoder); > >> @@ -651,6 +658,8 @@ radeon_lvds_detect(struct drm_connector *connector, > >> bool force) > >> /* check acpi lid status ??? */ > >> > >> radeon_connector_update_scratch_regs(connector, ret); > >> + pm_runtime_mark_last_busy(connector->dev->dev); > >> + pm_runtime_put_autosuspend(connector->dev->dev); > >> return ret; > >> } > >> > >> @@ -750,6 +759,11 @@ radeon_vga_detect(struct drm_connector *connector, > >> bool force) > >> struct drm_encoder_helper_funcs *encoder_funcs; > >> bool dret = false; > >> enum drm_connector_status ret = connector_status_disconnected; > >> + int r; > >> + > >> + r = pm_runtime_get_sync(connector->dev->dev); > >> + if (r < 0) > >> + return connector_status_disconnected; > >> > >> encoder = radeon_best_single_encoder(connector); > >> if (!encoder) > >> @@ -790,9 +804,8 @@ radeon_vga_detect(struct drm_connector *connector, > >> bool force) > >> * detected a monitor via load. > >> */ > >> if (radeon_connector->detected_by_load) > >> - return connector->status; > >> - else > >> - return ret; > >> + ret = connector->status; > >> + goto out; > >> } > >> > >> if (radeon_connector->dac_load_detect && encoder) { > >> @@ -817,6 +830,11 @@ radeon_vga_detect(struct drm_connector *connector, > >> bool force) > >> } > >> > >> radeon_connector_update_scratch_regs(connector, ret); > >> + > >> +out: > >> + pm_runtime_mark_last_busy(connector->dev->dev); > >> + pm_runtime_put_autosuspend(connector->dev->dev); > >> + > >> return ret; > >> } > >> > >> @@ -873,10 +891,15 @@ radeon_tv_detect(struct drm_connector *connector, > >> bool force) > >> struct drm_encoder_helper_funcs *encoder_funcs; > >> struct radeon_connector *radeon_connector = > >> to_radeon_connector(connector); > >> enum drm_connector_status ret = connector_status_disconnected; > >> + int r; > >> > >> if (!radeon_connector->dac_load_detect) > >> return ret; > >> > >> + r = pm_runtime_get_sync(connector->dev->dev); > >> + if (r < 0) > >> + return connector_status_disconnected; > >> + > >> encoder = radeon_best_single_encoder(connector); > >> if (!encoder) > >> ret = connector_status_disconnected; > >> @@ -887,6 +910,8 @@ radeon_tv_detect(struct drm_connector *connector, > bool > >> force) > >> if (ret == connector_status_connected) > >> ret = > >> radeon_connector_analog_encoder_conflict_solve(connector, encoder, ret, > >> false); > >> radeon_connector_update_scratch_regs(connector, ret); > >> + pm_runtime_mark_last_busy(connector->dev->dev); > >> + pm_runtime_put_autosuspend(connector->dev->dev); > >> return ret; > >> } > >> > >> @@ -954,12 +979,18 @@ radeon_dvi_detect(struct drm_connector *connector, > >> bool force) > >> struct drm_encoder *encoder = NULL; > >> struct drm_encoder_helper_funcs *encoder_funcs; > >> struct drm_mode_object *obj; > >> - int i; > >> + int i, r; > >> enum drm_connector_status ret = connector_status_disconnected; > >> bool dret = false, broken_edid = false; > >> > >> - if (!force && radeon_check_hpd_status_unchanged(connector)) > >> - return connector->status; > >> + r = pm_runtime_get_sync(connector->dev->dev); > >> + if (r < 0) > >> + return connector_status_disconnected; > >> + > >> + if (!force && radeon_check_hpd_status_unchanged(connector)) { > >> + ret = connector->status; > >> + goto exit; > >> + } > >> > >> if (radeon_connector->ddc_bus) > >> dret = radeon_ddc_probe(radeon_connector, false); > >> @@ -1110,6 +1141,11 @@ out: > >> > >> /* updated in get modes as well since we need to know if it's > >> analog or digital */ > >> radeon_connector_update_scratch_regs(connector, ret); > >> + > >> +exit: > >> + pm_runtime_mark_last_busy(connector->dev->dev); > >> + pm_runtime_put_autosuspend(connector->dev->dev); > >> + > >> return ret; > >> } > >> > >> @@ -1377,9 +1413,16 @@ radeon_dp_detect(struct drm_connector *connector, > >> bool force) > >> enum drm_connector_status ret = connector_status_disconnected; > >> struct radeon_connector_atom_dig *radeon_dig_connector = > >> radeon_connector->con_priv; > >> struct drm_encoder *encoder = > >> radeon_best_single_encoder(connector); > >> + int r; > >> > >> - if (!force && radeon_check_hpd_status_unchanged(connector)) > >> - return connector->status; > >> + r = pm_runtime_get_sync(connector->dev->dev); > >> + if (r < 0) > >> + return connector_status_disconnected; > >> + > >> + if (!force && radeon_check_hpd_status_unchanged(connector)) { > >> + ret = connector->status; > >> + goto out; > >> + } > >> > >> if (radeon_connector->edid) { > >> kfree(radeon_connector->edid); > >> @@ -1443,6 +1486,10 @@ radeon_dp_detect(struct drm_connector *connector, > >> bool force) > >> } > >> > >> radeon_connector_update_scratch_regs(connector, ret); > >> +out: > >> + pm_runtime_mark_last_busy(connector->dev->dev); > >> + pm_runtime_put_autosuspend(connector->dev->dev); > >> + > >> return ret; > >> } > >> > >> diff --git a/drivers/gpu/drm/radeon/radeon_device.c > >> b/drivers/gpu/drm/radeon/radeon_device.c > >> index 37cfcee..b9b9dfd 100644 > >> --- a/drivers/gpu/drm/radeon/radeon_device.c > >> +++ b/drivers/gpu/drm/radeon/radeon_device.c > >> @@ -101,6 +101,12 @@ static const char radeon_family_name[][16] = { > >> "LAST", > >> }; > >> > >> +#if defined(CONFIG_VGA_SWITCHEROO) > >> +bool radeon_is_px(void); > >> +#else > >> +static inline bool radeon_is_px(void) { return false; } > >> +#endif > >> + > >> /** > >> * radeon_program_register_sequence - program an array of registers. > >> * > >> @@ -1076,6 +1082,10 @@ static bool > >> radeon_switcheroo_quirk_long_wakeup(struct pci_dev *pdev) > >> static void radeon_switcheroo_set_state(struct pci_dev *pdev, enum > >> vga_switcheroo_state state) > >> { > >> struct drm_device *dev = pci_get_drvdata(pdev); > >> + > >> + if (radeon_is_px() && state == VGA_SWITCHEROO_OFF) > >> + return; > >> + > >> if (state == VGA_SWITCHEROO_ON) { > >> unsigned d3_delay = dev->pdev->d3_delay; > >> > >> @@ -1086,7 +1096,7 @@ static void radeon_switcheroo_set_state(struct > >> pci_dev *pdev, enum vga_switchero > >> if (d3_delay < 20 && > >> radeon_switcheroo_quirk_long_wakeup(pdev)) > >> dev->pdev->d3_delay = 20; > >> > >> - radeon_resume_kms(dev, 1); > >> + radeon_resume_kms(dev, true, true); > >> > >> dev->pdev->d3_delay = d3_delay; > >> > >> @@ -1096,7 +1106,7 @@ static void radeon_switcheroo_set_state(struct > >> pci_dev *pdev, enum vga_switchero > >> printk(KERN_INFO "radeon: switched off\n"); > >> drm_kms_helper_poll_disable(dev); > >> dev->switch_power_state = DRM_SWITCH_POWER_CHANGING; > >> - radeon_suspend_kms(dev, 1); > >> + radeon_suspend_kms(dev, true, true); > >> dev->switch_power_state = DRM_SWITCH_POWER_OFF; > >> } > >> } > >> @@ -1146,6 +1156,7 @@ int radeon_device_init(struct radeon_device *rdev, > >> { > >> int r, i; > >> int dma_bits; > >> + bool runtime = false; > >> > >> rdev->shutdown = false; > >> rdev->dev = &pdev->dev; > >> @@ -1292,7 +1303,14 @@ int radeon_device_init(struct radeon_device > *rdev, > >> /* this will fail for cards that aren't VGA class devices, just > >> * ignore it */ > >> vga_client_register(rdev->pdev, rdev, NULL, > >> radeon_vga_set_decode); > >> - vga_switcheroo_register_client(rdev->pdev, > &radeon_switcheroo_ops, > >> false); > >> + > >> + if (radeon_runtime_pm == 1) > >> + runtime = true; > >> + if ((radeon_runtime_pm == -1) && radeon_is_px()) > >> + runtime = true; > >> + vga_switcheroo_register_client(rdev->pdev, > &radeon_switcheroo_ops, > >> runtime); > >> + if (runtime) > >> + vga_switcheroo_init_domain_pm_ops(rdev->dev, > >> &rdev->vga_pm_domain); > >> > >> r = radeon_init(rdev); > >> if (r) > >> @@ -1373,7 +1391,7 @@ void radeon_device_fini(struct radeon_device > *rdev) > >> * Returns 0 for success or an error on failure. > >> * Called at driver suspend. > >> */ > >> -int radeon_suspend_kms(struct drm_device *dev, bool suspend) > >> +int radeon_suspend_kms(struct drm_device *dev, bool suspend, bool > fbcon) > >> { > >> struct radeon_device *rdev; > >> struct drm_crtc *crtc; > >> @@ -1448,9 +1466,12 @@ int radeon_suspend_kms(struct drm_device *dev, > bool > >> suspend) > >> pci_disable_device(dev->pdev); > >> pci_set_power_state(dev->pdev, PCI_D3hot); > >> } > >> - console_lock(); > >> - radeon_fbdev_set_suspend(rdev, 1); > >> - console_unlock(); > >> + > >> + if (fbcon) { > >> + console_lock(); > >> + radeon_fbdev_set_suspend(rdev, 1); > >> + console_unlock(); > >> + } > >> return 0; > >> } > >> > >> @@ -1463,7 +1484,7 @@ int radeon_suspend_kms(struct drm_device *dev, > bool > >> suspend) > >> * Returns 0 for success or an error on failure. > >> * Called at driver resume. > >> */ > >> -int radeon_resume_kms(struct drm_device *dev, bool resume) > >> +int radeon_resume_kms(struct drm_device *dev, bool resume, bool fbcon) > >> { > >> struct drm_connector *connector; > >> struct radeon_device *rdev = dev->dev_private; > >> @@ -1472,12 +1493,15 @@ int radeon_resume_kms(struct drm_device *dev, > bool > >> resume) > >> if (dev->switch_power_state == DRM_SWITCH_POWER_OFF) > >> return 0; > >> > >> - console_lock(); > >> + if (fbcon) { > >> + console_lock(); > >> + } > >> if (resume) { > >> pci_set_power_state(dev->pdev, PCI_D0); > >> pci_restore_state(dev->pdev); > >> if (pci_enable_device(dev->pdev)) { > >> - console_unlock(); > >> + if (fbcon) > >> + console_unlock(); > >> return -1; > >> } > >> } > >> @@ -1492,9 +1516,11 @@ int radeon_resume_kms(struct drm_device *dev, > bool > >> resume) > >> radeon_pm_resume(rdev); > >> radeon_restore_bios_scratch_regs(rdev); > >> > >> - radeon_fbdev_set_suspend(rdev, 0); > >> - console_unlock(); > >> - > >> + if (fbcon) { > >> + radeon_fbdev_set_suspend(rdev, 0); > >> + console_unlock(); > >> + } > >> + > >> /* init dig PHYs, disp eng pll */ > >> if (rdev->is_atom_bios) { > >> radeon_atom_encoder_init(rdev); > >> diff --git a/drivers/gpu/drm/radeon/radeon_display.c > >> b/drivers/gpu/drm/radeon/radeon_display.c > >> index 0d1aa05..bc37e33 100644 > >> --- a/drivers/gpu/drm/radeon/radeon_display.c > >> +++ b/drivers/gpu/drm/radeon/radeon_display.c > >> @@ -30,6 +30,7 @@ > >> #include "atom.h" > >> #include <asm/div64.h> > >> > >> +#include <linux/pm_runtime.h> > >> #include <drm/drm_crtc_helper.h> > >> #include <drm/drm_edid.h> > >> > >> @@ -494,11 +495,55 @@ unlock_free: > >> return r; > >> } > >> > >> +static int > >> +radeon_crtc_set_config(struct drm_mode_set *set) > >> +{ > >> + struct drm_device *dev; > >> + struct radeon_device *rdev; > >> + struct drm_crtc *crtc; > >> + bool active = false; > >> + int ret; > >> + > >> + if (!set || !set->crtc) > >> + return -EINVAL; > >> + > >> + dev = set->crtc->dev; > >> + > >> + ret = pm_runtime_get_sync(dev->dev); > >> + if (ret < 0) > >> + return ret; > >> + > >> + ret = drm_crtc_helper_set_config(set); > >> + > >> + list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) > >> + if (crtc->enabled) > >> + active = true; > >> + > >> + pm_runtime_mark_last_busy(dev->dev); > >> + > >> + rdev = dev->dev_private; > >> + /* if we have active crtcs and we don't have a power ref, > >> + take the current one */ > >> + if (active && !rdev->have_disp_power_ref) { > >> + rdev->have_disp_power_ref = true; > >> + return ret; > >> + } > >> + /* if we have no active crtcs, then drop the power ref > >> + we got before */ > >> + if (!active && rdev->have_disp_power_ref) { > >> + pm_runtime_put_autosuspend(dev->dev); > >> + rdev->have_disp_power_ref = false; > >> + } > >> + > >> + /* drop the power reference we got coming in here */ > >> + pm_runtime_put_autosuspend(dev->dev); > >> + return ret; > >> +} > >> static const struct drm_crtc_funcs radeon_crtc_funcs = { > >> .cursor_set = radeon_crtc_cursor_set, > >> .cursor_move = radeon_crtc_cursor_move, > >> .gamma_set = radeon_crtc_gamma_set, > >> - .set_config = drm_crtc_helper_set_config, > >> + .set_config = radeon_crtc_set_config, > >> .destroy = radeon_crtc_destroy, > >> .page_flip = radeon_crtc_page_flip, > >> }; > >> diff --git a/drivers/gpu/drm/radeon/radeon_drv.c > >> b/drivers/gpu/drm/radeon/radeon_drv.c > >> index 788bfb0..427c64f 100644 > >> --- a/drivers/gpu/drm/radeon/radeon_drv.c > >> +++ b/drivers/gpu/drm/radeon/radeon_drv.c > >> @@ -36,8 +36,9 @@ > >> #include <drm/drm_pciids.h> > >> #include <linux/console.h> > >> #include <linux/module.h> > >> - > >> - > >> +#include <linux/pm_runtime.h> > >> +#include <linux/vga_switcheroo.h> > >> +#include "drm_crtc_helper.h" > >> /* > >> * KMS wrapper. > >> * - 2.0.0 - initial interface > >> @@ -87,8 +88,8 @@ void radeon_driver_postclose_kms(struct drm_device > *dev, > >> struct drm_file *file_priv); > >> void radeon_driver_preclose_kms(struct drm_device *dev, > >> struct drm_file *file_priv); > >> -int radeon_suspend_kms(struct drm_device *dev, bool suspend); > >> -int radeon_resume_kms(struct drm_device *dev, bool resume); > >> +int radeon_suspend_kms(struct drm_device *dev, bool suspend, bool > fbcon); > >> +int radeon_resume_kms(struct drm_device *dev, bool resume, bool fbcon); > >> u32 radeon_get_vblank_counter_kms(struct drm_device *dev, int crtc); > >> int radeon_enable_vblank_kms(struct drm_device *dev, int crtc); > >> void radeon_disable_vblank_kms(struct drm_device *dev, int crtc); > >> @@ -137,9 +138,11 @@ void radeon_debugfs_cleanup(struct drm_minor > *minor); > >> #if defined(CONFIG_VGA_SWITCHEROO) > >> void radeon_register_atpx_handler(void); > >> void radeon_unregister_atpx_handler(void); > >> +bool radeon_is_px(void); > >> #else > >> static inline void radeon_register_atpx_handler(void) {} > >> static inline void radeon_unregister_atpx_handler(void) {} > >> +static inline bool radeon_is_px(void) { return false; } > >> #endif > >> > >> int radeon_no_wb; > >> @@ -162,6 +165,7 @@ int radeon_lockup_timeout = 10000; > >> int radeon_fastfb = 0; > >> int radeon_dpm = -1; > >> int radeon_aspm = -1; > >> +int radeon_runtime_pm = -1; > >> > >> MODULE_PARM_DESC(no_wb, "Disable AGP writeback for scratch registers"); > >> module_param_named(no_wb, radeon_no_wb, int, 0444); > >> @@ -223,6 +227,9 @@ module_param_named(dpm, radeon_dpm, int, 0444); > >> MODULE_PARM_DESC(aspm, "ASPM support (1 = enable, 0 = disable, -1 = > >> auto)"); > >> module_param_named(aspm, radeon_aspm, int, 0444); > >> > >> +MODULE_PARM_DESC(runpm, "PX runtime pm (1 = force enable, 0 = disable, > -1 > >> = PX only default)"); > >> +module_param_named(runpm, radeon_runtime_pm, int, 0444); > >> + > >> static struct pci_device_id pciidlist[] = { > >> radeon_PCI_IDS > >> }; > >> @@ -259,6 +266,7 @@ static int radeon_resume(struct drm_device *dev) > >> return 0; > >> } > >> > >> + > >> static const struct file_operations radeon_driver_old_fops = { > >> .owner = THIS_MODULE, > >> .open = drm_open, > >> @@ -357,28 +365,121 @@ static int radeon_pmops_suspend(struct device > *dev) > >> { > >> struct pci_dev *pdev = to_pci_dev(dev); > >> struct drm_device *drm_dev = pci_get_drvdata(pdev); > >> - return radeon_suspend_kms(drm_dev, 1); > >> + return radeon_suspend_kms(drm_dev, true, true); > >> } > >> > >> static int radeon_pmops_resume(struct device *dev) > >> { > >> struct pci_dev *pdev = to_pci_dev(dev); > >> struct drm_device *drm_dev = pci_get_drvdata(pdev); > >> - return radeon_resume_kms(drm_dev, 1); > >> + return radeon_resume_kms(drm_dev, true, true); > >> } > >> > >> static int radeon_pmops_freeze(struct device *dev) > >> { > >> struct pci_dev *pdev = to_pci_dev(dev); > >> struct drm_device *drm_dev = pci_get_drvdata(pdev); > >> - return radeon_suspend_kms(drm_dev, 0); > >> + return radeon_suspend_kms(drm_dev, false, true); > >> } > >> > >> static int radeon_pmops_thaw(struct device *dev) > >> { > >> struct pci_dev *pdev = to_pci_dev(dev); > >> struct drm_device *drm_dev = pci_get_drvdata(pdev); > >> - return radeon_resume_kms(drm_dev, 0); > >> + return radeon_resume_kms(drm_dev, false, true); > >> +} > >> + > >> +static int radeon_pmops_runtime_suspend(struct device *dev) > >> +{ > >> + struct pci_dev *pdev = to_pci_dev(dev); > >> + struct drm_device *drm_dev = pci_get_drvdata(pdev); > >> + int ret; > >> + > >> + if (radeon_runtime_pm == 0) > >> + return -EINVAL; > >> + > >> + drm_dev->switch_power_state = DRM_SWITCH_POWER_CHANGING; > >> + drm_kms_helper_poll_disable(drm_dev); > >> + vga_switcheroo_set_dynamic_switch(pdev, VGA_SWITCHEROO_OFF); > >> + > >> + ret = radeon_suspend_kms(drm_dev, false, false); > >> + pci_save_state(pdev); > >> + pci_disable_device(pdev); > >> + pci_set_power_state(pdev, PCI_D3cold); > >> + drm_dev->switch_power_state = DRM_SWITCH_POWER_DYNAMIC_OFF; > >> + > >> + return 0; > >> +} > >> + > >> +static int radeon_pmops_runtime_resume(struct device *dev) > >> +{ > >> + struct pci_dev *pdev = to_pci_dev(dev); > >> + struct drm_device *drm_dev = pci_get_drvdata(pdev); > >> + int ret; > >> + > >> + if (radeon_runtime_pm == 0) > >> + return -EINVAL; > >> + > >> + drm_dev->switch_power_state = DRM_SWITCH_POWER_CHANGING; > >> + > >> + pci_set_power_state(pdev, PCI_D0); > >> + pci_restore_state(pdev); > >> + ret = pci_enable_device(pdev); > >> + if (ret) > >> + return ret; > >> + pci_set_master(pdev); > >> + > >> + ret = radeon_resume_kms(drm_dev, false, false); > >> + drm_kms_helper_poll_enable(drm_dev); > >> + vga_switcheroo_set_dynamic_switch(pdev, VGA_SWITCHEROO_ON); > >> + drm_dev->switch_power_state = DRM_SWITCH_POWER_ON; > >> + return 0; > >> +} > >> + > >> +static int radeon_pmops_runtime_idle(struct device *dev) > >> +{ > >> + struct pci_dev *pdev = to_pci_dev(dev); > >> + struct drm_device *drm_dev = pci_get_drvdata(pdev); > >> + struct drm_crtc *crtc; > >> + > >> + if (radeon_runtime_pm == 0) > >> + return -EBUSY; > >> + > >> + /* are we PX enabled? */ > >> + if (radeon_runtime_pm == -1 && !radeon_is_px()) { > >> + DRM_DEBUG_DRIVER("failing to power off - not px\n"); > >> + return -EBUSY; > >> + } > >> + > >> + list_for_each_entry(crtc, &drm_dev->mode_config.crtc_list, > head) { > >> + if (crtc->enabled) { > >> + DRM_DEBUG_DRIVER("failing to power off - crtc > >> active\n"); > >> + return -EBUSY; > >> + } > >> + } > >> + > >> + pm_runtime_mark_last_busy(dev); > >> + pm_runtime_autosuspend(dev); > >> + /* we don't want the main rpm_idle to call suspend - we want to > >> autosuspend */ > >> + return 1; > >> +} > >> + > >> +long radeon_drm_ioctl(struct file *filp, > >> + unsigned int cmd, unsigned long arg) > >> +{ > >> + struct drm_file *file_priv = filp->private_data; > >> + struct drm_device *dev; > >> + long ret; > >> + dev = file_priv->minor->dev; > >> + ret = pm_runtime_get_sync(dev->dev); > >> + if (ret < 0) > >> + return ret; > >> + > >> + ret = drm_ioctl(filp, cmd, arg); > >> + > >> + pm_runtime_mark_last_busy(dev->dev); > >> + pm_runtime_put_autosuspend(dev->dev); > >> + return ret; > >> } > >> > >> static const struct dev_pm_ops radeon_pm_ops = { > >> @@ -388,13 +489,16 @@ static const struct dev_pm_ops radeon_pm_ops = { > >> .thaw = radeon_pmops_thaw, > >> .poweroff = radeon_pmops_freeze, > >> .restore = radeon_pmops_resume, > >> + .runtime_suspend = radeon_pmops_runtime_suspend, > >> + .runtime_resume = radeon_pmops_runtime_resume, > >> + .runtime_idle = radeon_pmops_runtime_idle, > >> }; > >> > >> static const struct file_operations radeon_driver_kms_fops = { > >> .owner = THIS_MODULE, > >> .open = drm_open, > >> .release = drm_release, > >> - .unlocked_ioctl = drm_ioctl, > >> + .unlocked_ioctl = radeon_drm_ioctl, > >> .mmap = radeon_mmap, > >> .poll = drm_poll, > >> .read = drm_read, > >> diff --git a/drivers/gpu/drm/radeon/radeon_drv.h > >> b/drivers/gpu/drm/radeon/radeon_drv.h > >> index b369d42..543dcfa 100644 > >> --- a/drivers/gpu/drm/radeon/radeon_drv.h > >> +++ b/drivers/gpu/drm/radeon/radeon_drv.h > >> @@ -113,6 +113,9 @@ > >> #define DRIVER_MINOR 33 > >> #define DRIVER_PATCHLEVEL 0 > >> > >> +long radeon_drm_ioctl(struct file *filp, > >> + unsigned int cmd, unsigned long arg); > >> + > >> /* The rest of the file is DEPRECATED! */ > >> #ifdef CONFIG_DRM_RADEON_UMS > >> > >> diff --git a/drivers/gpu/drm/radeon/radeon_ioc32.c > >> b/drivers/gpu/drm/radeon/radeon_ioc32.c > >> index c180df8..bdb0f93 100644 > >> --- a/drivers/gpu/drm/radeon/radeon_ioc32.c > >> +++ b/drivers/gpu/drm/radeon/radeon_ioc32.c > >> @@ -418,7 +418,7 @@ long radeon_kms_compat_ioctl(struct file *filp, > >> unsigned int cmd, unsigned long > >> if (nr < DRM_COMMAND_BASE) > >> return drm_compat_ioctl(filp, cmd, arg); > >> > >> - ret = drm_ioctl(filp, cmd, arg); > >> + ret = radeon_drm_ioctl(filp, cmd, arg); > >> > >> return ret; > >> } > >> diff --git a/drivers/gpu/drm/radeon/radeon_irq_kms.c > >> b/drivers/gpu/drm/radeon/radeon_irq_kms.c > >> index cc9e848..ec6240b 100644 > >> --- a/drivers/gpu/drm/radeon/radeon_irq_kms.c > >> +++ b/drivers/gpu/drm/radeon/radeon_irq_kms.c > >> @@ -32,6 +32,8 @@ > >> #include "radeon.h" > >> #include "atom.h" > >> > >> +#include <linux/pm_runtime.h> > >> + > >> #define RADEON_WAIT_IDLE_TIMEOUT 200 > >> > >> /** > >> @@ -47,8 +49,12 @@ irqreturn_t > radeon_driver_irq_handler_kms(DRM_IRQ_ARGS) > >> { > >> struct drm_device *dev = (struct drm_device *) arg; > >> struct radeon_device *rdev = dev->dev_private; > >> + irqreturn_t ret; > >> > >> - return radeon_irq_process(rdev); > >> + ret = radeon_irq_process(rdev); > >> + if (ret == IRQ_HANDLED) > >> + pm_runtime_mark_last_busy(dev->dev); > >> + return ret; > >> } > >> > >> /* > >> diff --git a/drivers/gpu/drm/radeon/radeon_kms.c > >> b/drivers/gpu/drm/radeon/radeon_kms.c > >> index 61580dd..bffff51 100644 > >> --- a/drivers/gpu/drm/radeon/radeon_kms.c > >> +++ b/drivers/gpu/drm/radeon/radeon_kms.c > >> @@ -32,7 +32,7 @@ > >> > >> #include <linux/vga_switcheroo.h> > >> #include <linux/slab.h> > >> - > >> +#include <linux/pm_runtime.h> > >> /** > >> * radeon_driver_unload_kms - Main unload function for KMS. > >> * > >> @@ -50,9 +50,14 @@ int radeon_driver_unload_kms(struct drm_device *dev) > >> > >> if (rdev == NULL) > >> return 0; > >> + > >> if (rdev->rmmio == NULL) > >> goto done_free; > >> + > >> + pm_runtime_get_sync(dev->dev); > >> + > >> radeon_acpi_fini(rdev); > >> + > >> radeon_modeset_fini(rdev); > >> radeon_device_fini(rdev); > >> > >> @@ -125,9 +130,20 @@ int radeon_driver_load_kms(struct drm_device *dev, > >> unsigned long flags) > >> "Error during ACPI methods call\n"); > >> } > >> > >> + if (radeon_runtime_pm != 0) { > >> + pm_runtime_use_autosuspend(dev->dev); > >> + pm_runtime_set_autosuspend_delay(dev->dev, 5000); > >> + pm_runtime_set_active(dev->dev); > >> + pm_runtime_allow(dev->dev); > >> + pm_runtime_mark_last_busy(dev->dev); > >> + pm_runtime_put_autosuspend(dev->dev); > >> + } > >> + > >> out: > >> if (r) > >> radeon_driver_unload_kms(dev); > >> + > >> + > >> return r; > >> } > >> > >> @@ -475,9 +491,14 @@ void radeon_driver_lastclose_kms(struct drm_device > >> *dev) > >> int radeon_driver_open_kms(struct drm_device *dev, struct drm_file > >> *file_priv) > >> { > >> struct radeon_device *rdev = dev->dev_private; > >> + int r; > >> > >> file_priv->driver_priv = NULL; > >> > >> + r = pm_runtime_get_sync(dev->dev); > >> + if (r < 0) > >> + return r; > >> + > >> /* new gpu have virtual address space support */ > >> if (rdev->family >= CHIP_CAYMAN) { > >> struct radeon_fpriv *fpriv; > >> @@ -506,6 +527,9 @@ int radeon_driver_open_kms(struct drm_device *dev, > >> struct drm_file *file_priv) > >> > >> file_priv->driver_priv = fpriv; > >> } > >> + > >> + pm_runtime_mark_last_busy(dev->dev); > >> + pm_runtime_put_autosuspend(dev->dev); > >> return 0; > >> } > >> > >> -- > >> 1.8.3.1 > >> > >> _______________________________________________ > >> dri-devel mailing list > >> dri-devel at lists.freedesktop.org > >> http://lists.freedesktop.org/mailman/listinfo/dri-devel > > > > > -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.freedesktop.org/archives/dri-devel/attachments/20130920/d5d3b5d7/attachment-0001.html>