From 346d97bb678e995790128dc7889259bb21800e5b Mon Sep 17 00:00:00 2001 From: Andrzej Zaborowski Date: Wed, 19 Nov 2008 17:09:51 +0000 Subject: Subject: [PATCH] glamo: Don't disable hwcursor for blinking and use vsync-wait. --- drivers/mfd/glamo/glamo-fb.c | 109 ++++++++++++++++++++++++++++++------------- 1 file changed, 76 insertions(+), 33 deletions(-) (limited to 'drivers/mfd/glamo/glamo-fb.c') diff --git a/drivers/mfd/glamo/glamo-fb.c b/drivers/mfd/glamo/glamo-fb.c index 30cdb386476..7e800f571ce 100644 --- a/drivers/mfd/glamo/glamo-fb.c +++ b/drivers/mfd/glamo/glamo-fb.c @@ -72,6 +72,7 @@ struct glamofb_handle { char __iomem *base; struct glamofb_platform_data *mach_info; char __iomem *cursor_addr; + int cursor_on; u_int32_t pseudo_pal[16]; spinlock_t lock_cmd; }; @@ -499,18 +500,53 @@ static int glamofb_setcolreg(unsigned regno, } #ifdef CONFIG_MFD_GLAMO_HWACCEL +static inline void glamofb_vsync_wait(struct glamofb_handle *glamo, + int line, int size, int range) +{ + int count[2]; + + do { + count[0] = reg_read(glamo, GLAMO_REG_LCD_STATUS2) & 0x3ff; + count[1] = reg_read(glamo, GLAMO_REG_LCD_STATUS2) & 0x3ff; + } while (count[0] != count[1] || + (line < count[0] + range && + size > count[0] - range) || + count[0] < range * 2); +} + +/* + * Enable/disable the hardware cursor mode altogether + * (for blinking and such, use glamofb_cursor()). + */ +static void glamofb_cursor_onoff(struct glamofb_handle *glamo, int on) +{ + int y, size; + + if (glamo->cursor_on) { + y = reg_read(glamo, GLAMO_REG_LCD_CURSOR_Y_POS); + size = reg_read(glamo, GLAMO_REG_LCD_CURSOR_Y_SIZE); + + glamofb_vsync_wait(glamo, y, size, 30); + } + + reg_set_bit_mask(glamo, GLAMO_REG_LCD_MODE1, + GLAMO_LCD_MODE1_CURSOR_EN, + on ? GLAMO_LCD_MODE1_CURSOR_EN : 0); + glamo->cursor_on = on; + + /* Hide the cursor by default */ + reg_write(glamo, GLAMO_REG_LCD_CURSOR_X_SIZE, 0); +} + static int glamofb_cursor(struct fb_info *info, struct fb_cursor *cursor) { struct glamofb_handle *glamo = info->par; unsigned long flags; - if (cursor->image.depth > 2) - return -EINVAL; - spin_lock_irqsave(&glamo->lock_cmd, flags); - reg_set_bit_mask(glamo, GLAMO_REG_LCD_MODE1, - GLAMO_LCD_MODE1_CURSOR_EN, 0); + reg_write(glamo, GLAMO_REG_LCD_CURSOR_X_SIZE, + cursor->enable ? cursor->image.width : 0); if (cursor->set & FB_CUR_SETPOS) { reg_write(glamo, GLAMO_REG_LCD_CURSOR_X_POS, @@ -520,12 +556,12 @@ static int glamofb_cursor(struct fb_info *info, struct fb_cursor *cursor) } if (cursor->set & FB_CUR_SETCMAP) { - uint16_t fg = cursor->image.fg_color; - uint16_t bg = cursor->image.bg_color; + uint16_t fg = glamo->pseudo_pal[cursor->image.fg_color]; + uint16_t bg = glamo->pseudo_pal[cursor->image.bg_color]; reg_write(glamo, GLAMO_REG_LCD_CURSOR_FG_COLOR, fg); reg_write(glamo, GLAMO_REG_LCD_CURSOR_BG_COLOR, bg); - reg_write(glamo, GLAMO_REG_LCD_CURSOR_DST_COLOR, bg); + reg_write(glamo, GLAMO_REG_LCD_CURSOR_DST_COLOR, fg); } if (cursor->set & FB_CUR_SETHOT) @@ -534,23 +570,27 @@ static int glamofb_cursor(struct fb_info *info, struct fb_cursor *cursor) if ((cursor->set & FB_CUR_SETSIZE) || (cursor->set & (FB_CUR_SETIMAGE | FB_CUR_SETSHAPE))) { - int x, y, pitch; - const unsigned char *pcol = cursor->image.data; - const unsigned char *pmsk = cursor->mask; - void __iomem *dst = glamo->cursor_addr; - unsigned char dcol = 0; - unsigned char dmsk = 0; - unsigned char byte = 0; - - pitch = (cursor->image.width + 3) >> 2; - reg_write(glamo, GLAMO_REG_LCD_CURSOR_X_SIZE, - cursor->image.width); + int x, y, pitch, op; + const uint8_t *pcol = cursor->image.data; + const uint8_t *pmsk = cursor->mask; + uint8_t __iomem *dst = glamo->cursor_addr; + uint8_t dcol = 0; + uint8_t dmsk = 0; + uint8_t byte = 0; + + if (cursor->image.depth > 1) { + spin_unlock_irqrestore(&glamo->lock_cmd, flags); + return -EINVAL; + } + + pitch = ((cursor->image.width + 7) >> 2) & ~1; reg_write(glamo, GLAMO_REG_LCD_CURSOR_PITCH, - pitch); + pitch); reg_write(glamo, GLAMO_REG_LCD_CURSOR_Y_SIZE, - cursor->image.height); + cursor->image.height); for (y = 0; y < cursor->image.height; y++) { + byte = 0; for (x = 0; x < cursor->image.width; x++) { if ((x % 8) == 0) { dcol = *pcol++; @@ -560,28 +600,28 @@ static int glamofb_cursor(struct fb_info *info, struct fb_cursor *cursor) dmsk >>= 1; } - if (dmsk & 1) { - unsigned int op; + if (cursor->rop == ROP_COPY) + op = (dmsk & 1) ? + (dcol & 1) ? 1 : 3 : 0; + else + op = ((dmsk & 1) << 1) | + ((dcol & 1) << 0); + byte |= op << ((x & 3) << 1); - op = (dcol & 1) ? 1 : 3; - byte |= op << ((x % 4) * 2); - } - - if ((x % 4) == 0) { + if (x % 4 == 3) { writeb(byte, dst + x / 4); byte = 0; } } + if (x % 4) { + writeb(byte, dst + x / 4); + byte = 0; + } dst += pitch; } } - if (cursor->enable) - reg_set_bit_mask(glamo, GLAMO_REG_LCD_MODE1, - GLAMO_LCD_MODE1_CURSOR_EN, - GLAMO_LCD_MODE1_CURSOR_EN); - spin_unlock_irqrestore(&glamo->lock_cmd, flags); return 0; @@ -809,6 +849,9 @@ static int __init glamofb_probe(struct platform_device *pdev) printk(KERN_ERR"spin_lock_init\n"); spin_lock_init(&glamofb->lock_cmd); glamofb_init_regs(glamofb); +#ifdef CONFIG_MFD_GLAMO_HWACCEL + glamofb_cursor_onoff(glamofb, 1); +#endif rc = register_framebuffer(fbinfo); if (rc < 0) { -- cgit v1.2.3