From 791916962183d648d71f9b45125fa656696084fd Mon Sep 17 00:00:00 2001 From: Thomas White Date: Thu, 2 Jul 2009 23:44:07 +0100 Subject: Initial suspend/resume Doesn't work yet... Signed-off-by: Thomas White --- drivers/mfd/glamo/glamo-cmdq.c | 12 +++++++ drivers/mfd/glamo/glamo-cmdq.h | 2 ++ drivers/mfd/glamo/glamo-display.c | 66 +++++++++++++++++++++++++++++++++++ drivers/mfd/glamo/glamo-display.h | 6 +++- drivers/mfd/glamo/glamo-drm-drv.c | 14 +++++++- drivers/mfd/glamo/glamo-drm-private.h | 20 +++++++++++ drivers/mfd/glamo/glamo-kms-fb.c | 13 +++++++ drivers/mfd/glamo/glamo-kms-fb.h | 4 +++ 8 files changed, 135 insertions(+), 2 deletions(-) diff --git a/drivers/mfd/glamo/glamo-cmdq.c b/drivers/mfd/glamo/glamo-cmdq.c index f24d6814849..bdae9859854 100644 --- a/drivers/mfd/glamo/glamo-cmdq.c +++ b/drivers/mfd/glamo/glamo-cmdq.c @@ -385,3 +385,15 @@ int glamo_cmdq_init(struct glamodrm_handle *gdrm) return 0; } + + +void glamo_cmdq_suspend(struct glamodrm_handle *gdrm) +{ + /* Placeholder... */ +} + + +void glamo_cmdq_resume(struct glamodrm_handle *gdrm) +{ + glamo_cmdq_init(gdrm); +} diff --git a/drivers/mfd/glamo/glamo-cmdq.h b/drivers/mfd/glamo/glamo-cmdq.h index f5d5ce6ae5a..4bc6b717115 100644 --- a/drivers/mfd/glamo/glamo-cmdq.h +++ b/drivers/mfd/glamo/glamo-cmdq.h @@ -34,6 +34,8 @@ extern int glamo_ioctl_cmdbuf(struct drm_device *dev, void *data, struct drm_file *file_priv); extern int glamo_cmdq_init(struct glamodrm_handle *gdrm); +extern void glamo_cmdq_suspend(struct glamodrm_handle *gdrm); +extern void glamo_cmdq_resume(struct glamodrm_handle *gdrm); #endif /* __GLAMO_CMDQ_H */ diff --git a/drivers/mfd/glamo/glamo-display.c b/drivers/mfd/glamo/glamo-display.c index 4a39534dfdf..a5be9236b66 100644 --- a/drivers/mfd/glamo/glamo-display.c +++ b/drivers/mfd/glamo/glamo-display.c @@ -319,6 +319,7 @@ static void glamo_crtc_mode_set(struct drm_crtc *crtc, glamo_lcd_cmd_mode(gdrm, 1); glamo_engine_reclock(gdrm->glamo_core, GLAMO_ENGINE_LCD, mode->clock); + gdrm->saved_clock = mode->clock; reg_set_bit_mask_lcd(gdrm, GLAMO_REG_LCD_WIDTH, GLAMO_LCD_WIDTH_MASK, mode->hdisplay); @@ -831,3 +832,68 @@ int glamo_display_init(struct drm_device *dev) return 0; } + + +void glamo_display_suspend(struct glamodrm_handle *gdrm) +{ + jbt6k74_action(0); + + gdrm->saved_width = reg_read_lcd(gdrm, GLAMO_REG_LCD_WIDTH); + gdrm->saved_height = reg_read_lcd(gdrm, GLAMO_REG_LCD_HEIGHT); + gdrm->saved_pitch = reg_read_lcd(gdrm, GLAMO_REG_LCD_PITCH); + gdrm->saved_htotal = reg_read_lcd(gdrm, GLAMO_REG_LCD_HORIZ_TOTAL); + gdrm->saved_hrtrst = reg_read_lcd(gdrm, GLAMO_REG_LCD_HORIZ_RETR_START); + gdrm->saved_hrtren = reg_read_lcd(gdrm, GLAMO_REG_LCD_HORIZ_RETR_END); + gdrm->saved_hdspst = reg_read_lcd(gdrm, GLAMO_REG_LCD_HORIZ_DISP_START); + gdrm->saved_hdspen = reg_read_lcd(gdrm, GLAMO_REG_LCD_HORIZ_DISP_END); + gdrm->saved_vtotal = reg_read_lcd(gdrm, GLAMO_REG_LCD_VERT_TOTAL); + gdrm->saved_vrtrst = reg_read_lcd(gdrm, GLAMO_REG_LCD_VERT_RETR_START); + gdrm->saved_vrtren = reg_read_lcd(gdrm, GLAMO_REG_LCD_VERT_RETR_END); + gdrm->saved_vdspst = reg_read_lcd(gdrm, GLAMO_REG_LCD_VERT_DISP_START); + gdrm->saved_vdspen = reg_read_lcd(gdrm, GLAMO_REG_LCD_VERT_DISP_END); +} + + +void glamo_display_resume(struct glamodrm_handle *gdrm) +{ + /* Reinitialise the LCD controller */ + jbt6k74_action(0); + mdelay(5); + + glamo_engine_enable(gdrm->glamo_core, GLAMO_ENGINE_LCD); + glamo_engine_reset(gdrm->glamo_core, GLAMO_ENGINE_LCD); + glamo_run_lcd_script(gdrm, lcd_init_script, + ARRAY_SIZE(lcd_init_script)); + + /* Restore timings */ + glamo_lcd_cmd_mode(gdrm, 1); + glamo_engine_reclock(gdrm->glamo_core, GLAMO_ENGINE_LCD, + gdrm->saved_clock); + reg_set_bit_mask_lcd(gdrm, GLAMO_REG_LCD_HORIZ_TOTAL, + GLAMO_LCD_HV_TOTAL_MASK, gdrm->saved_htotal); + reg_set_bit_mask_lcd(gdrm, GLAMO_REG_LCD_HORIZ_RETR_START, + GLAMO_LCD_HV_RETR_START_MASK, gdrm->saved_vrtrst); + reg_set_bit_mask_lcd(gdrm, GLAMO_REG_LCD_HORIZ_RETR_END, + GLAMO_LCD_HV_RETR_END_MASK, gdrm->saved_vrtren); + reg_set_bit_mask_lcd(gdrm, GLAMO_REG_LCD_HORIZ_DISP_START, + GLAMO_LCD_HV_RETR_DISP_START_MASK, + gdrm->saved_hdspst); + reg_set_bit_mask_lcd(gdrm, GLAMO_REG_LCD_HORIZ_DISP_END, + GLAMO_LCD_HV_RETR_DISP_END_MASK, + gdrm->saved_hdspen); + reg_set_bit_mask_lcd(gdrm, GLAMO_REG_LCD_VERT_TOTAL, + GLAMO_LCD_HV_TOTAL_MASK, gdrm->saved_vtotal); + reg_set_bit_mask_lcd(gdrm, GLAMO_REG_LCD_VERT_RETR_START, + GLAMO_LCD_HV_RETR_START_MASK, gdrm->saved_vrtrst); + reg_set_bit_mask_lcd(gdrm, GLAMO_REG_LCD_VERT_RETR_END, + GLAMO_LCD_HV_RETR_END_MASK, gdrm->saved_vrtren); + reg_set_bit_mask_lcd(gdrm, GLAMO_REG_LCD_VERT_DISP_START, + GLAMO_LCD_HV_RETR_DISP_START_MASK, + gdrm->saved_vdspst); + reg_set_bit_mask_lcd(gdrm, GLAMO_REG_LCD_VERT_DISP_END, + GLAMO_LCD_HV_RETR_DISP_END_MASK, + gdrm->saved_vdspen); + glamo_lcd_cmd_mode(gdrm, 0); + + jbt6k74_action(1); +} diff --git a/drivers/mfd/glamo/glamo-display.h b/drivers/mfd/glamo/glamo-display.h index c8f526d747d..d6f21bcb0c0 100644 --- a/drivers/mfd/glamo/glamo-display.h +++ b/drivers/mfd/glamo/glamo-display.h @@ -24,6 +24,7 @@ #define __GLAMO_DISPLAY_H #include +#include "glamo-drm-private.h" extern int glamo_display_init(struct drm_device *dev); @@ -31,5 +32,8 @@ extern int glamo_framebuffer_create(struct drm_device *dev, struct drm_mode_fb_cmd *mode_cmd, struct drm_framebuffer **fb, struct drm_gem_object *obj); - + +extern void glamo_display_suspend(struct glamodrm_handle *gdrm); +extern void glamo_display_resume(struct glamodrm_handle *gdrm); + #endif /* __GLAMO_DISPLAY_H */ diff --git a/drivers/mfd/glamo/glamo-drm-drv.c b/drivers/mfd/glamo/glamo-drm-drv.c index 97d058f57d6..d71da8850ac 100644 --- a/drivers/mfd/glamo/glamo-drm-drv.c +++ b/drivers/mfd/glamo/glamo-drm-drv.c @@ -33,6 +33,7 @@ #include "glamo-buffer.h" #include "glamo-drm-private.h" #include "glamo-display.h" +#include "glamo-kms-fb.h" #define DRIVER_AUTHOR "Openmoko, Inc." #define DRIVER_NAME "glamo-drm" @@ -354,7 +355,14 @@ static int glamodrm_remove(struct platform_device *pdev) static int glamodrm_suspend(struct platform_device *pdev, pm_message_t state) { + struct glamodrm_handle *gdrm = platform_get_drvdata(pdev); + + glamo_kmsfb_suspend(gdrm); + glamo_display_suspend(gdrm); + glamo_cmdq_suspend(gdrm); + /* glamo_core.c will suspend the engines for us */ + return 0; } @@ -362,7 +370,11 @@ static int glamodrm_suspend(struct platform_device *pdev, pm_message_t state) static int glamodrm_resume(struct platform_device *pdev) { struct glamodrm_handle *gdrm = platform_get_drvdata(pdev); - glamo_cmdq_init(gdrm); + + glamo_cmdq_resume(gdrm); + glamo_display_resume(gdrm); + glamo_kmsfb_resume(gdrm); + return 0; } diff --git a/drivers/mfd/glamo/glamo-drm-private.h b/drivers/mfd/glamo/glamo-drm-private.h index ec4b67c084d..b7a9932e6ca 100644 --- a/drivers/mfd/glamo/glamo-drm-private.h +++ b/drivers/mfd/glamo/glamo-drm-private.h @@ -37,9 +37,13 @@ struct glamodrm_handle { /* This device */ struct device *dev; + /* The parent device handle */ struct glamo_core *glamo_core; + /* Framebuffer handle for the console (i.e. /dev/fb0) */ + struct fb_info *fb; + /* Command queue registers */ struct resource *reg; char __iomem *reg_base; @@ -60,6 +64,22 @@ struct glamodrm_handle { /* Memory management */ struct drm_mm *mmgr; + + /* Saved state */ + u_int16_t saved_clock; + u_int16_t saved_width; + u_int16_t saved_height; + u_int16_t saved_pitch; + u_int16_t saved_htotal; + u_int16_t saved_hrtrst; + u_int16_t saved_hrtren; + u_int16_t saved_hdspst; + u_int16_t saved_hdspen; + u_int16_t saved_vtotal; + u_int16_t saved_vrtrst; + u_int16_t saved_vrtren; + u_int16_t saved_vdspst; + u_int16_t saved_vdspen; }; diff --git a/drivers/mfd/glamo/glamo-kms-fb.c b/drivers/mfd/glamo/glamo-kms-fb.c index 0c828831bb0..13dce09d615 100644 --- a/drivers/mfd/glamo/glamo-kms-fb.c +++ b/drivers/mfd/glamo/glamo-kms-fb.c @@ -522,6 +522,7 @@ int glamofb_create(struct drm_device *dev, uint32_t fb_width, fb->fbdev = info; par->glamo_fb = glamo_fb; par->dev = dev; + gdrm->fb = info; info->var.pixclock = -1; @@ -536,3 +537,15 @@ out_unref: out: return ret; } + + +void glamo_kmsfb_suspend(struct glamodrm_handle *gdrm) +{ + fb_set_suspend(gdrm->fb, 1); +} + + +void glamo_kmsfb_resume(struct glamodrm_handle *gdrm) +{ + fb_set_suspend(gdrm->fb, 0); +} diff --git a/drivers/mfd/glamo/glamo-kms-fb.h b/drivers/mfd/glamo/glamo-kms-fb.h index f98bf6540aa..9ae597bd366 100644 --- a/drivers/mfd/glamo/glamo-kms-fb.h +++ b/drivers/mfd/glamo/glamo-kms-fb.h @@ -28,10 +28,14 @@ #define __GLAMO_KMS_FB_H #include +#include "glamo-drm-private.h" extern int glamofb_create(struct drm_device *dev, uint32_t fb_width, uint32_t fb_height, uint32_t surface_width, uint32_t surface_height, struct glamo_framebuffer **glamo_fb_p); +extern void glamo_kmsfb_suspend(struct glamodrm_handle *gdrm); +extern void glamo_kmsfb_resume(struct glamodrm_handle *gdrm); + #endif /* __GLAMO_KMS_FB_H */ -- cgit v1.2.3