diff options
author | Thomas White <taw@bitwiz.org.uk> | 2009-06-30 10:15:49 +0100 |
---|---|---|
committer | Thomas White <taw@bitwiz.org.uk> | 2009-06-30 10:15:49 +0100 |
commit | 32babb5ddf8c7ca02bd8e64482c2a5d9eb727724 (patch) | |
tree | 9b2aeff28e85ee137d311d872032e75a35113975 /drivers | |
parent | ee66b72542a996ee8f161221713125ef93f8e105 (diff) |
Program the LCD registers
This also alters some debug lines.
Signed-off-by: Thomas White <taw@bitwiz.org.uk>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/mfd/glamo/glamo-display.c | 211 | ||||
-rw-r--r-- | drivers/mfd/glamo/glamo-drm-private.h | 1 | ||||
-rw-r--r-- | drivers/mfd/glamo/glamo-kms-fb.c | 11 |
3 files changed, 201 insertions, 22 deletions
diff --git a/drivers/mfd/glamo/glamo-display.c b/drivers/mfd/glamo/glamo-display.c index debcd0706f9..9c498010725 100644 --- a/drivers/mfd/glamo/glamo-display.c +++ b/drivers/mfd/glamo/glamo-display.c @@ -63,6 +63,17 @@ #include "glamo-drm-private.h" #include "glamo-regs.h" #include "glamo-kms-fb.h" +#include <linux/glamofb.h> + + +#define GLAMO_LCD_WIDTH_MASK 0x03FF +#define GLAMO_LCD_HEIGHT_MASK 0x03FF +#define GLAMO_LCD_PITCH_MASK 0x07FE +#define GLAMO_LCD_HV_TOTAL_MASK 0x03FF +#define GLAMO_LCD_HV_RETR_START_MASK 0x03FF +#define GLAMO_LCD_HV_RETR_END_MASK 0x03FF +#define GLAMO_LCD_HV_RETR_DISP_START_MASK 0x03FF +#define GLAMO_LCD_HV_RETR_DISP_END_MASK 0x03FF struct glamofb_par { @@ -75,8 +86,7 @@ struct glamofb_par { }; -#if 0 -static int reg_read(struct glamodrm_handle *gdrm, u_int16_t reg) +static int reg_read_lcd(struct glamodrm_handle *gdrm, u_int16_t reg) { int i = 0; @@ -85,11 +95,10 @@ static int reg_read(struct glamodrm_handle *gdrm, u_int16_t reg) return ioread16(gdrm->lcd_base + reg); } -#endif -static void reg_write(struct glamodrm_handle *gdrm, - u_int16_t reg, u_int16_t val) +static void reg_write_lcd(struct glamodrm_handle *gdrm, + u_int16_t reg, u_int16_t val) { int i = 0; @@ -100,6 +109,96 @@ static void reg_write(struct glamodrm_handle *gdrm, } +static void reg_set_bit_mask_lcd(struct glamodrm_handle *gdrm, + u_int16_t reg, u_int16_t mask, + u_int16_t val) +{ + u_int16_t tmp; + + val &= mask; + + tmp = reg_read_lcd(gdrm, reg); + tmp &= ~mask; + tmp |= val; + reg_write_lcd(gdrm, reg, tmp); +} + + +/* Note that this has nothing at all to do with the engine command queue + * in glamo-cmdq.c */ +static inline int glamo_lcd_cmdq_empty(struct glamodrm_handle *gdrm) +{ + /* DGCMdQempty -- 1 == command queue is empty */ + return reg_read_lcd(gdrm, GLAMO_REG_LCD_STATUS1) & (1 << 15); +} + + +/* call holding gfb->lock_cmd when locking, until you unlock */ +int glamo_lcd_cmd_mode(struct glamodrm_handle *gdrm, int on) +{ + int timeout = 2000000; + + if (gdrm->glamo_core->suspending) { + dev_err(&gdrm->glamo_core->pdev->dev, + "IGNORING glamofb_cmd_mode while" + " suspended\n"); + return -EBUSY; + } + + dev_dbg(gdrm->dev, "glamofb_cmd_mode(on=%d)\n", on); + if (on) { + dev_dbg(gdrm->dev, "%s: waiting for cmdq empty: ", + __func__); + while ((!glamo_lcd_cmdq_empty(gdrm)) && (timeout--)) + /* yield() */; + if (timeout < 0) { + printk(KERN_ERR "*************" + " LCD command queue never got empty " + "*************\n"); + return -EIO; + } + dev_dbg(gdrm->dev, "empty!\n"); + + /* display the entire frame then switch to command */ + reg_write_lcd(gdrm, GLAMO_REG_LCD_COMMAND1, + GLAMO_LCD_CMD_TYPE_DISP | + GLAMO_LCD_CMD_DATA_FIRE_VSYNC); + + /* wait until lcd idle */ + dev_dbg(gdrm->dev, "waiting for LCD idle: "); + timeout = 2000000; + while ((!reg_read_lcd(gdrm, GLAMO_REG_LCD_STATUS2) & (1 << 12)) && + (timeout--)) + /* yield() */; + if (timeout < 0) { + printk(KERN_ERR"*************" + " LCD never idle " + "*************\n"); + return -EIO; + } + + mdelay(100); + + dev_dbg(gdrm->dev, "cmd mode entered\n"); + + } else { + /* RGB interface needs vsync/hsync */ + int mode; + mode = reg_read_lcd(gdrm, GLAMO_REG_LCD_MODE3); + if ( mode & GLAMO_LCD_MODE3_RGB) + reg_write_lcd(gdrm, GLAMO_REG_LCD_COMMAND1, + GLAMO_LCD_CMD_TYPE_DISP | + GLAMO_LCD_CMD_DATA_DISP_SYNC); + + reg_write_lcd(gdrm, GLAMO_REG_LCD_COMMAND1, + GLAMO_LCD_CMD_TYPE_DISP | + GLAMO_LCD_CMD_DATA_DISP_FIRE); + } + + return 0; +} + + static struct glamo_script lcd_init_script[] = { { GLAMO_REG_LCD_MODE1, 0x0020 }, /* no display rotation, no hardware cursor, no dither, no gamma, @@ -143,7 +242,7 @@ static int glamo_run_lcd_script(struct glamodrm_handle *gdrm, else if (line->reg == 0xfffe) msleep(line->val); else - reg_write(gdrm, script[i].reg, script[i].val); + reg_write_lcd(gdrm, script[i].reg, script[i].val); } return 0; @@ -216,7 +315,57 @@ static void glamo_crtc_mode_set(struct drm_crtc *crtc, int x, int y, struct drm_framebuffer *old_fb) { + struct glamodrm_handle *gdrm; + struct glamo_crtc *gcrtc; + int retr_end, disp_start, disp_end; + printk(KERN_CRIT "glamo_crtc_mode_set\n"); + + /* Dig out our handle */ + gcrtc = to_glamo_crtc(crtc); + gdrm = gcrtc->gdrm; /* Here it is! */ + + glamo_lcd_cmd_mode(gdrm, 1); + glamo_engine_reclock(gdrm->glamo_core, GLAMO_ENGINE_LCD, mode->clock); + + reg_set_bit_mask_lcd(gdrm, GLAMO_REG_LCD_WIDTH, + GLAMO_LCD_WIDTH_MASK, mode->hdisplay); + reg_set_bit_mask_lcd(gdrm, GLAMO_REG_LCD_HEIGHT, + GLAMO_LCD_HEIGHT_MASK, mode->vdisplay); + reg_set_bit_mask_lcd(gdrm, GLAMO_REG_LCD_PITCH, + GLAMO_LCD_PITCH_MASK, mode->hdisplay*2); + + /* Convert "X modeline timings" into "Glamo timings" */ + retr_end = mode->hsync_end - mode->hsync_start; + disp_start = mode->htotal - mode->hsync_start; + disp_end = mode->hsync_start; + reg_set_bit_mask_lcd(gdrm, GLAMO_REG_LCD_HORIZ_TOTAL, + GLAMO_LCD_HV_TOTAL_MASK, mode->htotal); + reg_set_bit_mask_lcd(gdrm, GLAMO_REG_LCD_HORIZ_RETR_START, + GLAMO_LCD_HV_RETR_START_MASK, 0); + reg_set_bit_mask_lcd(gdrm, GLAMO_REG_LCD_HORIZ_RETR_END, + GLAMO_LCD_HV_RETR_END_MASK, retr_end); + reg_set_bit_mask_lcd(gdrm, GLAMO_REG_LCD_HORIZ_DISP_START, + GLAMO_LCD_HV_RETR_DISP_START_MASK, disp_start); + reg_set_bit_mask_lcd(gdrm, GLAMO_REG_LCD_HORIZ_DISP_END, + GLAMO_LCD_HV_RETR_DISP_END_MASK, disp_end); + + /* The same in the vertical direction */ + retr_end = mode->vsync_end - mode->vsync_start; + disp_start = mode->vtotal - mode->vsync_start; + disp_end = mode->vsync_start; + reg_set_bit_mask_lcd(gdrm, GLAMO_REG_LCD_VERT_TOTAL, + GLAMO_LCD_HV_TOTAL_MASK, mode->vtotal); + reg_set_bit_mask_lcd(gdrm, GLAMO_REG_LCD_VERT_RETR_START, + GLAMO_LCD_HV_RETR_START_MASK, 0); + reg_set_bit_mask_lcd(gdrm, GLAMO_REG_LCD_VERT_RETR_END, + GLAMO_LCD_HV_RETR_END_MASK, retr_end); + reg_set_bit_mask_lcd(gdrm, GLAMO_REG_LCD_VERT_DISP_START, + GLAMO_LCD_HV_RETR_DISP_START_MASK, disp_start); + reg_set_bit_mask_lcd(gdrm, GLAMO_REG_LCD_VERT_DISP_END, + GLAMO_LCD_HV_RETR_DISP_END_MASK, disp_end); + + glamo_lcd_cmd_mode(gdrm, 0); } @@ -224,7 +373,7 @@ static void glamo_crtc_mode_set(struct drm_crtc *crtc, static void glamo_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y, struct drm_framebuffer *old_fb) { - printk(KERN_CRIT "glamo_crtc_mode_set\n"); + printk(KERN_CRIT "glamo_crtc_mode_set_base\n"); } @@ -298,6 +447,13 @@ static void glamo_connector_destroy(struct drm_connector *connector) static int glamo_connector_get_modes(struct drm_connector *connector) { struct drm_display_mode *mode; + struct glamofb_platform_data *mach_info; + struct glamo_output *goutput = to_glamo_output(connector); + struct glamodrm_handle *gdrm = goutput->gdrm; + + /* Dig out the record which will tell us about the hardware */ + mach_info = gdrm->glamo_core->pdev->dev.platform_data; + printk(KERN_CRIT "glamo_connector_get_modes\n"); mode = drm_mode_create(connector->dev); @@ -305,6 +461,32 @@ static int glamo_connector_get_modes(struct drm_connector *connector) return 0; /* Fill in 'mode' here */ mode->type = DRM_MODE_TYPE_DEFAULT | DRM_MODE_TYPE_PREFERRED; + + /* Convert framebuffer timings into KMS timings */ + mode->clock = 1000000 / mach_info->pixclock; /* ps -> Hz */ + mode->hdisplay = mach_info->xres.defval; + mode->hsync_start = mach_info->right_margin + mode->hdisplay; + mode->hsync_end = mode->hsync_start + mach_info->hsync_len; + mode->htotal = mode->hdisplay + mach_info->left_margin + + mach_info->right_margin + mach_info->hsync_len; + + mode->hskew = 0; + mode->vdisplay = mach_info->yres.defval; + mode->vsync_start = mach_info->lower_margin + mode->vdisplay; + mode->vsync_end = mode->vsync_start + mach_info->vsync_len; + mode->vtotal = mode->vdisplay + mach_info->upper_margin + + mach_info->lower_margin + mach_info->vsync_len; + mode->vscan = 0; + + mode->width_mm = mach_info->width; + mode->height_mm = mach_info->height; + + printk(KERN_CRIT "Modeline \"%ix%i\" %i %i %i %i %i %i %i %i %i\n", + mode->hdisplay, mode->vdisplay, mode->clock, + mode->hdisplay, mode->hsync_start, mode->hsync_end, mode->htotal, + mode->vdisplay, mode->vsync_start, mode->vsync_end, mode->vtotal); + + drm_mode_set_name(mode); drm_mode_probed_add(connector, mode); return 1; /* one mode, for now */ @@ -324,13 +506,9 @@ static int glamo_connector_mode_valid(struct drm_connector *connector, struct drm_display_mode *mode) { printk(KERN_CRIT "glamo_connector_mode_valid\n"); - if (mode->flags & DRM_MODE_FLAG_DBLSCAN) { - printk(KERN_CRIT "Doublescan is not allowed\n"); + if (mode->flags & DRM_MODE_FLAG_DBLSCAN) return MODE_NO_DBLESCAN; - } - printk(KERN_CRIT "Ok!\n"); - return MODE_OK; } @@ -605,6 +783,7 @@ int glamo_display_init(struct drm_device *dev) glamo_output = kzalloc(sizeof(struct glamo_output), GFP_KERNEL); if (glamo_output == NULL) return 1; connector = &glamo_output->base; + glamo_output->gdrm = gdrm; /* Initialise the connector */ drm_connector_init(dev, connector, &glamo_connector_funcs, @@ -631,8 +810,6 @@ int glamo_display_init(struct drm_device *dev) if (list_empty(&dev->mode_config.fb_kernel_list)) { int ret; - printk(KERN_CRIT "creating new fb (console size %dx%d, " - "buffer size %dx%d)\n", 480, 640, 480, 640); ret = glamofb_create(dev, 480, 640, 480, 640, &glamo_fb); if (ret) return -EINVAL; } @@ -654,13 +831,13 @@ int glamo_display_init(struct drm_device *dev) if (register_framebuffer(info) < 0) return -EINVAL; - printk(KERN_INFO "fb%d: %s frame buffer device\n", info->node, - info->fix.id); + printk(KERN_INFO "[glamo-drm] fb%d: %s frame buffer device\n", + info->node, info->fix.id); /* Switch back to kernel console on panic */ kernelfb_mode = *modeset; atomic_notifier_chain_register(&panic_notifier_list, &paniced); - printk(KERN_INFO "registered panic notifier\n"); + printk(KERN_INFO "[glamo-drm] registered panic notifier\n"); return 0; } diff --git a/drivers/mfd/glamo/glamo-drm-private.h b/drivers/mfd/glamo/glamo-drm-private.h index ae65d10a19c..ec4b67c084d 100644 --- a/drivers/mfd/glamo/glamo-drm-private.h +++ b/drivers/mfd/glamo/glamo-drm-private.h @@ -88,6 +88,7 @@ struct glamo_framebuffer { struct glamo_output { struct drm_connector base; struct drm_encoder enc; + struct glamodrm_handle *gdrm; }; diff --git a/drivers/mfd/glamo/glamo-kms-fb.c b/drivers/mfd/glamo/glamo-kms-fb.c index 918b5febfee..43adaed1ea9 100644 --- a/drivers/mfd/glamo/glamo-kms-fb.c +++ b/drivers/mfd/glamo/glamo-kms-fb.c @@ -237,6 +237,8 @@ static int glamofb_pan_display(struct fb_var_screeninfo *var, struct glamo_crtc *glamo_crtc; int ret = 0; int i; + + printk(KERN_CRIT "glamofb_pan_display\n"); list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { for (i = 0; i < par->crtc_count; i++) @@ -399,7 +401,7 @@ int glamofb_create(struct drm_device *dev, uint32_t fb_width, size = ALIGN(size, PAGE_SIZE); fbo = glamo_gem_object_alloc(dev, size, 2); if (!fbo) { - printk(KERN_ERR "failed to allocate framebuffer\n"); + printk(KERN_ERR "[glamo-drm] Failed to allocate framebuffer\n"); ret = -ENOMEM; goto out; } @@ -513,8 +515,7 @@ int glamofb_create(struct drm_device *dev, uint32_t fb_width, case 32: default: /* The Smedia Glamo doesn't support anything but 16bit color */ - printk(KERN_ERR - "Glamo driver does not [yet?] support 24/32bpp\n"); + printk(KERN_ERR "[glamo-drm] Only 16bpp is supported.\n"); return -EINVAL; } @@ -524,8 +525,8 @@ int glamofb_create(struct drm_device *dev, uint32_t fb_width, info->var.pixclock = -1; - printk("allocated %dx%d fb: bo %p\n", glamo_fb->base.width, - glamo_fb->base.height, fbo); + printk(KERN_INFO "[glamo-drm] Allocated %dx%d fb: bo %p\n", + glamo_fb->base.width, glamo_fb->base.height, fbo); mutex_unlock(&dev->struct_mutex); return 0; |