aboutsummaryrefslogtreecommitdiff
path: root/drivers/mfd
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/mfd')
-rw-r--r--drivers/mfd/glamo/glamo-display.c116
-rw-r--r--drivers/mfd/glamo/glamo-display.h2
-rw-r--r--drivers/mfd/glamo/glamo-drm-private.h10
-rw-r--r--drivers/mfd/glamo/glamo-kms-fb.c54
4 files changed, 79 insertions, 103 deletions
diff --git a/drivers/mfd/glamo/glamo-display.c b/drivers/mfd/glamo/glamo-display.c
index 34a665a6430..a384c8be5c9 100644
--- a/drivers/mfd/glamo/glamo-display.c
+++ b/drivers/mfd/glamo/glamo-display.c
@@ -239,14 +239,6 @@ static int glamo_run_lcd_script(struct glamodrm_handle *gdrm,
}
-extern void jbt6k74_action(int val);
-
-/* Power on/off */
-static void glamo_crtc_dpms(struct drm_crtc *crtc, int mode)
-{
-}
-
-
static bool glamo_crtc_mode_fixup(struct drm_crtc *crtc,
struct drm_display_mode *mode,
struct drm_display_mode *adjusted_mode)
@@ -275,6 +267,12 @@ static int glamo_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y,
gcrtc = to_glamo_crtc(crtc);
gdrm = gcrtc->gdrm; /* Here it is! */
+ if ( !gcrtc->pixel_clock_on ) {
+ printk(KERN_WARNING "[glamo-drm] Refusing to set base while "
+ "pixel clock is off.\n");
+ return -EBUSY;
+ }
+
gfb = to_glamo_framebuffer(crtc->fb);
obj = gfb->obj;
gobj = obj->driver_private;
@@ -306,6 +304,12 @@ static int glamo_crtc_mode_set(struct drm_crtc *crtc,
gcrtc = to_glamo_crtc(crtc);
gdrm = gcrtc->gdrm; /* Here it is! */
+ if ( !gcrtc->pixel_clock_on ) {
+ printk(KERN_WARNING "[glamo-drm] Refusing to set mode while "
+ "pixel clock is off.\n");
+ return -EBUSY;
+ }
+
glamo_lcd_cmd_mode(gdrm, 1);
glamo_engine_reclock(gdrm->glamo_core, GLAMO_ENGINE_LCD, mode->clock);
@@ -354,10 +358,47 @@ static int glamo_crtc_mode_set(struct drm_crtc *crtc,
glamo_crtc_mode_set_base(crtc, 0, 0, old_fb);
+ gcrtc->current_mode = *mode;
+ gcrtc->current_mode_set = 1;
+ gcrtc->current_fb = old_fb;
+
return 0;
}
+extern void jbt6k74_action(int val);
+
+/* This is not the right place to switch power on/off, because the helper
+ * stuff ends up calling this before/after setting the mode. We can't
+ * set modes with the display off (although backlight off would be OK) */
+static void glamo_crtc_dpms(struct drm_crtc *crtc, int mode)
+{
+ /* do nothing */
+}
+
+
+void glamo_lcd_power(struct glamodrm_handle *gdrm, int mode)
+{
+ struct drm_crtc *crtc = gdrm->crtc;
+ struct glamo_crtc *gcrtc = to_glamo_crtc(crtc);
+
+ if ( mode ) {
+ glamo_engine_enable(gdrm->glamo_core, GLAMO_ENGINE_LCD);
+ gcrtc->pixel_clock_on = 1;
+ jbt6k74_action(1);
+ if ( gcrtc->current_mode_set ) {
+ glamo_crtc_mode_set(crtc, &gcrtc->current_mode,
+ &gcrtc->current_mode, 0, 0,
+ gcrtc->current_fb);
+ }
+ } else {
+ jbt6k74_action(0);
+ glamo_engine_suspend(gdrm->glamo_core, GLAMO_ENGINE_LCD);
+ gcrtc->pixel_clock_on = 0;
+ }
+}
+
+
static void glamo_crtc_prepare(struct drm_crtc *crtc)
{
}
@@ -725,6 +766,8 @@ int glamo_display_init(struct drm_device *dev)
+ sizeof(struct drm_connector *), GFP_KERNEL);
if (glamo_crtc == NULL) return 1;
glamo_crtc->gdrm = gdrm;
+ gdrm->crtc = (struct drm_crtc *)glamo_crtc;
+ glamo_crtc->pixel_clock_on = 1;
glamo_crtc->blank_mode = DRM_MODE_DPMS_OFF;
drm_crtc_init(dev, &glamo_crtc->base, &glamo_crtc_funcs);
drm_crtc_helper_add(&glamo_crtc->base, &glamo_crtc_helper_funcs);
@@ -808,62 +851,23 @@ int glamo_display_init(struct drm_device *dev)
void glamo_display_suspend(struct glamodrm_handle *gdrm)
{
- 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);
+ /* do nothing */
}
void glamo_display_resume(struct glamodrm_handle *gdrm)
{
+ struct drm_crtc *crtc = gdrm->crtc;
+ struct glamo_crtc *gcrtc = to_glamo_crtc(crtc);
+
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_WIDTH, GLAMO_LCD_WIDTH_MASK,
- gdrm->saved_width);
- reg_set_bit_mask_lcd(gdrm, GLAMO_REG_LCD_HEIGHT, GLAMO_LCD_HEIGHT_MASK,
- gdrm->saved_height);
- reg_set_bit_mask_lcd(gdrm, GLAMO_REG_LCD_PITCH, GLAMO_LCD_PITCH_MASK,
- gdrm->saved_pitch);
- 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_hrtrst);
- reg_set_bit_mask_lcd(gdrm, GLAMO_REG_LCD_HORIZ_RETR_END,
- GLAMO_LCD_HV_RETR_END_MASK, gdrm->saved_hrtren);
- 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);
+ if ( gcrtc->current_mode_set ) {
+ glamo_crtc_mode_set(crtc, &gcrtc->current_mode,
+ &gcrtc->current_mode, 0, 0,
+ gcrtc->current_fb);
+ }
}
diff --git a/drivers/mfd/glamo/glamo-display.h b/drivers/mfd/glamo/glamo-display.h
index d6f21bcb0c0..728bba56a37 100644
--- a/drivers/mfd/glamo/glamo-display.h
+++ b/drivers/mfd/glamo/glamo-display.h
@@ -36,4 +36,6 @@ extern int glamo_framebuffer_create(struct drm_device *dev,
extern void glamo_display_suspend(struct glamodrm_handle *gdrm);
extern void glamo_display_resume(struct glamodrm_handle *gdrm);
+extern void glamo_lcd_power(struct glamodrm_handle *gdrm, int mode);
+
#endif /* __GLAMO_DISPLAY_H */
diff --git a/drivers/mfd/glamo/glamo-drm-private.h b/drivers/mfd/glamo/glamo-drm-private.h
index 7949a2e47b9..4e24019672e 100644
--- a/drivers/mfd/glamo/glamo-drm-private.h
+++ b/drivers/mfd/glamo/glamo-drm-private.h
@@ -106,6 +106,9 @@ struct glamodrm_handle {
/* A scratch block */
struct drm_mm_node *scratch;
+
+ /* We only have one */
+ struct drm_crtc *crtc;
};
@@ -118,11 +121,18 @@ struct drm_glamo_gem_object {
struct glamo_crtc {
+
struct drm_crtc base;
struct glamodrm_handle *gdrm;
/* a mode_set for fbdev users on this crtc */
struct drm_mode_set mode_set;
int blank_mode;
+
+ int pixel_clock_on;
+
+ int current_mode_set;
+ struct drm_display_mode current_mode;
+ struct drm_framebuffer *current_fb;
};
diff --git a/drivers/mfd/glamo/glamo-kms-fb.c b/drivers/mfd/glamo/glamo-kms-fb.c
index 61cd6054eb8..57680eddccc 100644
--- a/drivers/mfd/glamo/glamo-kms-fb.c
+++ b/drivers/mfd/glamo/glamo-kms-fb.c
@@ -253,64 +253,24 @@ static void glamofb_on(struct fb_info *info)
{
struct glamofb_par *par = info->par;
struct drm_device *dev = par->dev;
- struct drm_crtc *crtc;
- struct drm_encoder *encoder;
- int i;
+ struct glamodrm_handle *gdrm = dev->dev_private;
- /*
- * For each CRTC in this fb, find all associated encoders
- * and turn them off, then turn off the CRTC.
- */
- list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
- struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private;
+ printk(KERN_CRIT "Turning on display...\n");
- for (i = 0; i < par->crtc_count; i++)
- if (crtc->base.id == par->crtc_ids[i])
- break;
-
- crtc_funcs->dpms(crtc, DRM_MODE_DPMS_ON);
+ gdrm = dev->dev_private;
- /* Found a CRTC on this fb, now find encoders */
- list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
- if (encoder->crtc == crtc) {
- struct drm_encoder_helper_funcs *encoder_funcs;
- encoder_funcs = encoder->helper_private;
- encoder_funcs->dpms(encoder, DRM_MODE_DPMS_ON);
- }
- }
- }
+ glamo_lcd_power(gdrm, 1);
}
static void glamofb_off(struct fb_info *info, int dpms_mode)
{
struct glamofb_par *par = info->par;
struct drm_device *dev = par->dev;
- struct drm_crtc *crtc;
- struct drm_encoder *encoder;
- int i;
+ struct glamodrm_handle *gdrm = dev->dev_private;
- /*
- * For each CRTC in this fb, find all associated encoders
- * and turn them off, then turn off the CRTC.
- */
- list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
- struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private;
-
- for (i = 0; i < par->crtc_count; i++)
- if (crtc->base.id == par->crtc_ids[i])
- break;
+ printk(KERN_CRIT "Turning off display...\n");
- /* Found a CRTC on this fb, now find encoders */
- list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
- if (encoder->crtc == crtc) {
- struct drm_encoder_helper_funcs *encoder_funcs;
- encoder_funcs = encoder->helper_private;
- encoder_funcs->dpms(encoder, dpms_mode);
- }
- }
- if (dpms_mode == DRM_MODE_DPMS_OFF)
- crtc_funcs->dpms(crtc, dpms_mode);
- }
+ glamo_lcd_power(gdrm, 0);
}
static int glamofb_blank(int blank, struct fb_info *info)