Skip to content

Commit

Permalink
drm/atmel-hlcdc: Fix suspend/resume implementation
Browse files Browse the repository at this point in the history
The current suspend resume implementation is assuming register values are
kept when entering suspend, which is no longer the case with the
suspend-to-RAM on the sama5d2.

While at it, switch to the generic infrastructure to enter suspend mode
(drm_atomic_helper_suspend/resume()).

Signed-off-by: Boris Brezillon <[email protected]>
Acked-by: Daniel Vetter <[email protected]>
Tested-by: Sylvain Rochet <[email protected]>
Link: http://patchwork.freedesktop.org/patch/msgid/1488371461-22243-1-git-send-email-boris.brezillon@free-electrons.com
  • Loading branch information
Boris Brezillon committed Mar 16, 2017
1 parent 82c8e02 commit 99ed4d7
Show file tree
Hide file tree
Showing 3 changed files with 21 additions and 51 deletions.
33 changes: 0 additions & 33 deletions drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c
Original file line number Diff line number Diff line change
Expand Up @@ -55,14 +55,12 @@ drm_crtc_state_to_atmel_hlcdc_crtc_state(struct drm_crtc_state *state)
* @hlcdc: pointer to the atmel_hlcdc structure provided by the MFD device
* @event: pointer to the current page flip event
* @id: CRTC id (returned by drm_crtc_index)
* @enabled: CRTC state
*/
struct atmel_hlcdc_crtc {
struct drm_crtc base;
struct atmel_hlcdc_dc *dc;
struct drm_pending_vblank_event *event;
int id;
bool enabled;
};

static inline struct atmel_hlcdc_crtc *
Expand Down Expand Up @@ -158,9 +156,6 @@ static void atmel_hlcdc_crtc_disable(struct drm_crtc *c)
struct regmap *regmap = crtc->dc->hlcdc->regmap;
unsigned int status;

if (!crtc->enabled)
return;

drm_crtc_vblank_off(c);

pm_runtime_get_sync(dev->dev);
Expand All @@ -186,8 +181,6 @@ static void atmel_hlcdc_crtc_disable(struct drm_crtc *c)
pm_runtime_allow(dev->dev);

pm_runtime_put_sync(dev->dev);

crtc->enabled = false;
}

static void atmel_hlcdc_crtc_enable(struct drm_crtc *c)
Expand All @@ -197,9 +190,6 @@ static void atmel_hlcdc_crtc_enable(struct drm_crtc *c)
struct regmap *regmap = crtc->dc->hlcdc->regmap;
unsigned int status;

if (crtc->enabled)
return;

pm_runtime_get_sync(dev->dev);

pm_runtime_forbid(dev->dev);
Expand All @@ -226,29 +216,6 @@ static void atmel_hlcdc_crtc_enable(struct drm_crtc *c)
pm_runtime_put_sync(dev->dev);

drm_crtc_vblank_on(c);

crtc->enabled = true;
}

void atmel_hlcdc_crtc_suspend(struct drm_crtc *c)
{
struct atmel_hlcdc_crtc *crtc = drm_crtc_to_atmel_hlcdc_crtc(c);

if (crtc->enabled) {
atmel_hlcdc_crtc_disable(c);
/* save enable state for resume */
crtc->enabled = true;
}
}

void atmel_hlcdc_crtc_resume(struct drm_crtc *c)
{
struct atmel_hlcdc_crtc *crtc = drm_crtc_to_atmel_hlcdc_crtc(c);

if (crtc->enabled) {
crtc->enabled = false;
atmel_hlcdc_crtc_enable(c);
}
}

#define ATMEL_HLCDC_RGB444_OUTPUT BIT(0)
Expand Down
31 changes: 16 additions & 15 deletions drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c
Original file line number Diff line number Diff line change
Expand Up @@ -800,31 +800,32 @@ static int atmel_hlcdc_dc_drm_remove(struct platform_device *pdev)
static int atmel_hlcdc_dc_drm_suspend(struct device *dev)
{
struct drm_device *drm_dev = dev_get_drvdata(dev);
struct drm_crtc *crtc;
struct atmel_hlcdc_dc *dc = drm_dev->dev_private;
struct regmap *regmap = dc->hlcdc->regmap;
struct drm_atomic_state *state;

state = drm_atomic_helper_suspend(drm_dev);
if (IS_ERR(state))
return PTR_ERR(state);

if (pm_runtime_suspended(dev))
return 0;
dc->suspend.state = state;

regmap_read(regmap, ATMEL_HLCDC_IMR, &dc->suspend.imr);
regmap_write(regmap, ATMEL_HLCDC_IDR, dc->suspend.imr);
clk_disable_unprepare(dc->hlcdc->periph_clk);

drm_modeset_lock_all(drm_dev);
list_for_each_entry(crtc, &drm_dev->mode_config.crtc_list, head)
atmel_hlcdc_crtc_suspend(crtc);
drm_modeset_unlock_all(drm_dev);
return 0;
}

static int atmel_hlcdc_dc_drm_resume(struct device *dev)
{
struct drm_device *drm_dev = dev_get_drvdata(dev);
struct drm_crtc *crtc;
struct atmel_hlcdc_dc *dc = drm_dev->dev_private;

if (pm_runtime_suspended(dev))
return 0;
clk_prepare_enable(dc->hlcdc->periph_clk);
regmap_write(dc->hlcdc->regmap, ATMEL_HLCDC_IER, dc->suspend.imr);

drm_modeset_lock_all(drm_dev);
list_for_each_entry(crtc, &drm_dev->mode_config.crtc_list, head)
atmel_hlcdc_crtc_resume(crtc);
drm_modeset_unlock_all(drm_dev);
return 0;
return drm_atomic_helper_resume(drm_dev, dc->suspend.state);
}
#endif

Expand Down
8 changes: 5 additions & 3 deletions drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.h
Original file line number Diff line number Diff line change
Expand Up @@ -358,6 +358,7 @@ struct atmel_hlcdc_plane_properties {
* @planes: instantiated planes
* @layers: active HLCDC layers
* @wq: display controller workqueue
* @suspend: used to store the HLCDC state when entering suspend
* @commit: used for async commit handling
*/
struct atmel_hlcdc_dc {
Expand All @@ -368,6 +369,10 @@ struct atmel_hlcdc_dc {
struct drm_crtc *crtc;
struct atmel_hlcdc_layer *layers[ATMEL_HLCDC_MAX_LAYERS];
struct workqueue_struct *wq;
struct {
u32 imr;
struct drm_atomic_state *state;
} suspend;
struct {
wait_queue_head_t wait;
bool pending;
Expand Down Expand Up @@ -428,9 +433,6 @@ int atmel_hlcdc_plane_prepare_ahb_routing(struct drm_crtc_state *c_state);

void atmel_hlcdc_crtc_irq(struct drm_crtc *c);

void atmel_hlcdc_crtc_suspend(struct drm_crtc *crtc);
void atmel_hlcdc_crtc_resume(struct drm_crtc *crtc);

int atmel_hlcdc_crtc_create(struct drm_device *dev);

int atmel_hlcdc_create_outputs(struct drm_device *dev);
Expand Down

0 comments on commit 99ed4d7

Please sign in to comment.