aboutsummaryrefslogtreecommitdiffstats
path: root/target/linux/xburst/files-2.6.32/drivers/video
diff options
context:
space:
mode:
authorLars-Peter Clausen <lars@metafoo.de>2010-08-04 13:33:55 +0000
committerLars-Peter Clausen <lars@metafoo.de>2010-08-04 13:33:55 +0000
commit1980190a5a96fba4d36be8f8037ba9925c263b57 (patch)
tree5be4947af9799c165de22a46b0db260d2d6d3d91 /target/linux/xburst/files-2.6.32/drivers/video
parentf312e1580b6053bc87c931dbd588197d77c9f691 (diff)
downloadupstream-1980190a5a96fba4d36be8f8037ba9925c263b57.tar.gz
upstream-1980190a5a96fba4d36be8f8037ba9925c263b57.tar.bz2
upstream-1980190a5a96fba4d36be8f8037ba9925c263b57.zip
Drop 2.6.32 patches
SVN-Revision: 22485
Diffstat (limited to 'target/linux/xburst/files-2.6.32/drivers/video')
-rw-r--r--target/linux/xburst/files-2.6.32/drivers/video/backlight/gpm940b0.c255
-rw-r--r--target/linux/xburst/files-2.6.32/drivers/video/jz4740_fb.c790
-rw-r--r--target/linux/xburst/files-2.6.32/drivers/video/metronomefb.c1341
3 files changed, 0 insertions, 2386 deletions
diff --git a/target/linux/xburst/files-2.6.32/drivers/video/backlight/gpm940b0.c b/target/linux/xburst/files-2.6.32/drivers/video/backlight/gpm940b0.c
deleted file mode 100644
index 5cfb12f0e8..0000000000
--- a/target/linux/xburst/files-2.6.32/drivers/video/backlight/gpm940b0.c
+++ /dev/null
@@ -1,255 +0,0 @@
-/*
- * Copyright (C) 2009, Lars-Peter Clausen <lars@metafoo.de>
- * JZ4720/JZ4740 SoC LCD framebuffer driver
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- */
-
-#include <linux/module.h>
-#include <linux/spi/spi.h>
-#include <linux/lcd.h>
-#include <linux/backlight.h>
-#include <linux/delay.h>
-
-struct gpm940b0 {
- struct spi_device *spi;
- struct lcd_device *lcd;
- struct backlight_device *bl;
- unsigned enabled:1;
-};
-
-static int gpm940b0_write_reg(struct spi_device *spi, uint8_t reg,
- uint8_t data)
-{
- uint8_t buf[2];
- buf[0] = ((reg & 0x40) << 1) | (reg & 0x3f);
- buf[1] = data;
-
- return spi_write(spi, buf, sizeof(buf));
-}
-
-static void gpm940b0_power_disable(struct gpm940b0 *gpm940b0)
-{
- int ret = gpm940b0_write_reg(gpm940b0->spi, 0x5, 0xc6) ;
- if (ret < 0)
- printk("Failed to disable power: %d\n", ret);
-}
-
-static void gpm940b0_power_enable(struct gpm940b0 *gpm940b0)
-{
- gpm940b0_write_reg(gpm940b0->spi, 0x5, 0xc7);
-}
-
-
-static int gpm940b0_set_power(struct lcd_device *lcd, int power)
-{
- struct gpm940b0 *gpm940b0 = lcd_get_data(lcd);
-
- switch (power) {
- case FB_BLANK_UNBLANK:
- mdelay(20);
- gpm940b0->enabled = 1;
- gpm940b0_power_enable(gpm940b0);
- break;
- default:
- gpm940b0->enabled = 0;
- gpm940b0_power_disable(gpm940b0);
- mdelay(20);
- break;
- }
- return 0;
-}
-
-static int gpm940b0_set_contrast(struct lcd_device *lcd, int contrast)
-{
- struct gpm940b0 *gpm940b0 = lcd_get_data(lcd);
- gpm940b0_write_reg(gpm940b0->spi, 0x0d, contrast);
- return 0;
-}
-
-static int gpm940b0_set_mode(struct lcd_device *lcd, struct fb_videomode *mode)
-{
- if (mode->xres != 320 && mode->yres != 240)
- return -EINVAL;
-
- return 0;
-}
-
-/*
-int gpm940b0_bl_update_status(struct backlight_device *bl)
-{
- struct gpm940b0 *gpm940b0 = bl_get_data(bl);
-
- gpm940b0->reg5 &= ~0x38;
- gpm940b0->reg5 |= ((bl->props.brightness << 3) & 0x38);
-
- gpm940b0_write_reg(gpm940b0->spi, 0x5, gpm940b0->reg5);
-
- return 0;
-}*/
-
-static ssize_t reg_write(struct device *dev, struct device_attribute *attr,
- const char *buf, size_t count)
-{
- char *buf2;
- uint32_t reg = simple_strtoul(buf, &buf2, 10);
- uint32_t val = simple_strtoul(buf2 + 1, NULL, 10);
- struct gpm940b0 *gpm940b0 = dev_get_drvdata(dev);
-
- if (reg < 0 || val < 0)
- return -EINVAL;
-
- gpm940b0_write_reg(gpm940b0->spi, reg, val);
- return count;
-}
-
-static DEVICE_ATTR(reg, 0644, NULL, reg_write);
-
-static struct lcd_ops gpm940b0_lcd_ops = {
- .set_power = gpm940b0_set_power,
- .set_contrast = gpm940b0_set_contrast,
- .set_mode = gpm940b0_set_mode,
-};
-
-#if 0
-static struct backlight_ops gpm940b0_bl_ops = {
-/* .get_brightness = gpm940b0_bl_get_brightness,*/
- .update_status = gpm940b0_bl_update_status,
-};
-#endif
-
-static int __devinit gpm940b0_probe(struct spi_device *spi)
-{
- int ret;
- struct gpm940b0 *gpm940b0;
-
- gpm940b0 = kmalloc(sizeof(*gpm940b0), GFP_KERNEL);
-
- spi->bits_per_word = 8;
-
- ret = spi_setup(spi);
- if (ret) {
- dev_err(&spi->dev, "Failed to setup spi\n");
- goto err_free_gpm940b0;
- }
-
- gpm940b0->spi = spi;
-
- gpm940b0->lcd = lcd_device_register("gpm940b0-lcd", &spi->dev, gpm940b0,
- &gpm940b0_lcd_ops);
-
- if (IS_ERR(gpm940b0->lcd)) {
- ret = PTR_ERR(gpm940b0->lcd);
- dev_err(&spi->dev, "Failed to register lcd device: %d\n", ret);
- goto err_free_gpm940b0;
- }
-
- gpm940b0->lcd->props.max_contrast = 255;
-
-#if 0
- gpm940b0->bl = backlight_device_register("gpm940b0-bl", &spi->dev, gpm940b0,
- &gpm940b0_bl_ops);
-
- if (IS_ERR(gpm940b0->bl)) {
- ret = PTR_ERR(gpm940b0->bl);
- dev_err(&spi->dev, "Failed to register backlight device: %d\n", ret);
- gpm940b0->bl = NULL;
- } else {
- gpm940b0->bl->props.max_brightness = 8;
- gpm940b0->bl->props.brightness = 0;
- gpm940b0->bl->props.power = FB_BLANK_UNBLANK;
- }
-#endif
-
- ret = device_create_file(&spi->dev, &dev_attr_reg);
- if (ret)
- goto err_unregister_lcd;
-
- gpm940b0->enabled = 1;
- dev_set_drvdata(&spi->dev, gpm940b0);
-
- gpm940b0_write_reg(spi, 0x13, 0x01);
- gpm940b0_write_reg(spi, 0x5, 0xc7);
- return 0;
-err_unregister_lcd:
- lcd_device_unregister(gpm940b0->lcd);
-err_free_gpm940b0:
- kfree(gpm940b0);
- return ret;
-}
-
-static int __devexit gpm940b0_remove(struct spi_device *spi)
-{
- struct gpm940b0 *gpm940b0 = spi_get_drvdata(spi);
-#if 0
- if (gpm940b0->bl)
- backlight_device_unregister(gpm940b0->bl);
-#endif
-
- lcd_device_unregister(gpm940b0->lcd);
-
- spi_set_drvdata(spi, NULL);
- kfree(gpm940b0);
- return 0;
-}
-
-#ifdef CONFIG_PM
-
-static int gpm940b0_suspend(struct spi_device *spi, pm_message_t state)
-{
- struct gpm940b0 *gpm940b0 = spi_get_drvdata(spi);
- if (gpm940b0->enabled) {
- gpm940b0_power_disable(gpm940b0);
- mdelay(10);
- }
- return 0;
-}
-
-static int gpm940b0_resume(struct spi_device *spi)
-{
- struct gpm940b0 *gpm940b0 = spi_get_drvdata(spi);
- if (gpm940b0->enabled)
- gpm940b0_power_enable(gpm940b0);
- return 0;
-}
-
-#else
-#define gpm940b0_suspend NULL
-#define gpm940b0_resume NULL
-#endif
-
-static struct spi_driver gpm940b0_driver = {
- .driver = {
- .name = "gpm940b0",
- .owner = THIS_MODULE,
- },
- .probe = gpm940b0_probe,
- .remove = __devexit_p(gpm940b0_remove),
- .suspend = gpm940b0_suspend,
- .resume = gpm940b0_resume,
-};
-
-static int __init gpm940b0_init(void)
-{
- return spi_register_driver(&gpm940b0_driver);
-}
-module_init(gpm940b0_init);
-
-static void __exit gpm940b0_exit(void)
-{
- return spi_unregister_driver(&gpm940b0_driver);
-}
-module_exit(gpm940b0_exit)
-
-MODULE_AUTHOR("Lars-Peter Clausen");
-MODULE_LICENSE("GPL v2");
-MODULE_DESCRIPTION("LCD and backlight controll for Giantplus GPM940B0");
-MODULE_ALIAS("spi:gpm940b0");
diff --git a/target/linux/xburst/files-2.6.32/drivers/video/jz4740_fb.c b/target/linux/xburst/files-2.6.32/drivers/video/jz4740_fb.c
deleted file mode 100644
index eeb702a6f3..0000000000
--- a/target/linux/xburst/files-2.6.32/drivers/video/jz4740_fb.c
+++ /dev/null
@@ -1,790 +0,0 @@
-/*
- * Copyright (C) 2009, Lars-Peter Clausen <lars@metafoo.de>
- * JZ4720/JZ4740 SoC LCD framebuffer driver
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- */
-
-#include <linux/types.h>
-#include <linux/platform_device.h>
-#include <linux/console.h>
-#include <linux/fb.h>
-#include <linux/module.h>
-#include <linux/dma-mapping.h>
-#include <linux/mutex.h>
-#include <linux/delay.h>
-#include <linux/clk.h>
-
-#include <linux/jz4740_fb.h>
-#include <asm/mach-jz4740/gpio.h>
-
-#define JZ_REG_LCD_CFG 0x00
-#define JZ_REG_LCD_VSYNC 0x04
-#define JZ_REG_LCD_HSYNC 0x08
-#define JZ_REG_LCD_VAT 0x0C
-#define JZ_REG_LCD_DAH 0x10
-#define JZ_REG_LCD_DAV 0x14
-#define JZ_REG_LCD_PS 0x18
-#define JZ_REG_LCD_CLS 0x1C
-#define JZ_REG_LCD_SPL 0x20
-#define JZ_REG_LCD_REV 0x24
-#define JZ_REG_LCD_CTRL 0x30
-#define JZ_REG_LCD_STATE 0x34
-#define JZ_REG_LCD_IID 0x38
-#define JZ_REG_LCD_DA0 0x40
-#define JZ_REG_LCD_SA0 0x44
-#define JZ_REG_LCD_FID0 0x48
-#define JZ_REG_LCD_CMD0 0x4C
-#define JZ_REG_LCD_DA1 0x50
-#define JZ_REG_LCD_SA1 0x54
-#define JZ_REG_LCD_FID1 0x58
-#define JZ_REG_LCD_CMD1 0x5C
-
-#define JZ_LCD_CFG_SLCD BIT(31)
-#define JZ_LCD_CFG_PS_DISABLE BIT(23)
-#define JZ_LCD_CFG_CLS_DISABLE BIT(22)
-#define JZ_LCD_CFG_SPL_DISABLE BIT(21)
-#define JZ_LCD_CFG_REV_DISABLE BIT(20)
-#define JZ_LCD_CFG_HSYNCM BIT(19)
-#define JZ_LCD_CFG_PCLKM BIT(18)
-#define JZ_LCD_CFG_INV BIT(17)
-#define JZ_LCD_CFG_SYNC_DIR BIT(16)
-#define JZ_LCD_CFG_PS_POLARITY BIT(15)
-#define JZ_LCD_CFG_CLS_POLARITY BIT(14)
-#define JZ_LCD_CFG_SPL_POLARITY BIT(13)
-#define JZ_LCD_CFG_REV_POLARITY BIT(12)
-#define JZ_LCD_CFG_HSYNC_ACTIVE_LOW BIT(11)
-#define JZ_LCD_CFG_PCLK_FALLING_EDGE BIT(10)
-#define JZ_LCD_CFG_DE_ACTIVE_LOW BIT(9)
-#define JZ_LCD_CFG_VSYNC_ACTIVE_LOW BIT(8)
-#define JZ_LCD_CFG_18_BIT BIT(7)
-#define JZ_LCD_CFG_PDW BIT(5) | BIT(4)
-#define JZ_LCD_CFG_MODE_MASK 0xf
-
-#define JZ_LCD_CTRL_BURST_4 (0x0 << 28)
-#define JZ_LCD_CTRL_BURST_8 (0x1 << 28)
-#define JZ_LCD_CTRL_BURST_16 (0x2 << 28)
-#define JZ_LCD_CTRL_RGB555 BIT(27)
-#define JZ_LCD_CTRL_OFUP BIT(26)
-#define JZ_LCD_CTRL_FRC_GRAYSCALE_16 (0x0 << 24)
-#define JZ_LCD_CTRL_FRC_GRAYSCALE_4 (0x1 << 24)
-#define JZ_LCD_CTRL_FRC_GRAYSCALE_2 (0x2 << 24)
-#define JZ_LCD_CTRL_PDD_MASK (0xff << 16)
-#define JZ_LCD_CTRL_EOF_IRQ BIT(13)
-#define JZ_LCD_CTRL_SOF_IRQ BIT(12)
-#define JZ_LCD_CTRL_OFU_IRQ BIT(11)
-#define JZ_LCD_CTRL_IFU0_IRQ BIT(10)
-#define JZ_LCD_CTRL_IFU1_IRQ BIT(9)
-#define JZ_LCD_CTRL_DD_IRQ BIT(8)
-#define JZ_LCD_CTRL_QDD_IRQ BIT(7)
-#define JZ_LCD_CTRL_REVERSE_ENDIAN BIT(6)
-#define JZ_LCD_CTRL_LSB_FISRT BIT(5)
-#define JZ_LCD_CTRL_DISABLE BIT(4)
-#define JZ_LCD_CTRL_ENABLE BIT(3)
-#define JZ_LCD_CTRL_BPP_1 0x0
-#define JZ_LCD_CTRL_BPP_2 0x1
-#define JZ_LCD_CTRL_BPP_4 0x2
-#define JZ_LCD_CTRL_BPP_8 0x3
-#define JZ_LCD_CTRL_BPP_15_16 0x4
-#define JZ_LCD_CTRL_BPP_18_24 0x5
-
-#define JZ_LCD_CMD_SOF_IRQ BIT(15)
-#define JZ_LCD_CMD_EOF_IRQ BIT(16)
-#define JZ_LCD_CMD_ENABLE_PAL BIT(12)
-
-#define JZ_LCD_SYNC_MASK 0x3ff
-
-#define JZ_LCD_STATE_DISABLED BIT(0)
-
-struct jzfb_framedesc {
- uint32_t next;
- uint32_t addr;
- uint32_t id;
- uint32_t cmd;
-} __attribute__((packed));
-
-struct jzfb {
- struct fb_info *fb;
- struct platform_device *pdev;
- void __iomem *base;
- struct resource *mem;
- struct jz4740_fb_platform_data *pdata;
-
- size_t vidmem_size;
- void *vidmem;
- dma_addr_t vidmem_phys;
- struct jzfb_framedesc *framedesc;
- dma_addr_t framedesc_phys;
-
- struct clk *ldclk;
- struct clk *lpclk;
-
- unsigned is_enabled:1;
- struct mutex lock; /* Protecting against running enable/disable in paralell */
-
- uint32_t pseudo_palette[256];
-};
-
-static struct fb_fix_screeninfo jzfb_fix __devinitdata = {
- .id = "JZ4740 FB",
- .type = FB_TYPE_PACKED_PIXELS,
- .visual = FB_VISUAL_TRUECOLOR,
- .xpanstep = 0,
- .ypanstep = 0,
- .ywrapstep = 0,
- .accel = FB_ACCEL_NONE,
-};
-
-const static struct jz_gpio_bulk_request jz_lcd_ctrl_pins[] = {
- JZ_GPIO_BULK_PIN(LCD_PCLK),
- JZ_GPIO_BULK_PIN(LCD_HSYNC),
- JZ_GPIO_BULK_PIN(LCD_VSYNC),
- JZ_GPIO_BULK_PIN(LCD_DE),
- JZ_GPIO_BULK_PIN(LCD_PS),
- JZ_GPIO_BULK_PIN(LCD_REV),
-};
-
-const static struct jz_gpio_bulk_request jz_lcd_data_pins[] = {
- JZ_GPIO_BULK_PIN(LCD_DATA0),
- JZ_GPIO_BULK_PIN(LCD_DATA1),
- JZ_GPIO_BULK_PIN(LCD_DATA2),
- JZ_GPIO_BULK_PIN(LCD_DATA3),
- JZ_GPIO_BULK_PIN(LCD_DATA4),
- JZ_GPIO_BULK_PIN(LCD_DATA5),
- JZ_GPIO_BULK_PIN(LCD_DATA6),
- JZ_GPIO_BULK_PIN(LCD_DATA7),
- JZ_GPIO_BULK_PIN(LCD_DATA8),
- JZ_GPIO_BULK_PIN(LCD_DATA9),
- JZ_GPIO_BULK_PIN(LCD_DATA10),
- JZ_GPIO_BULK_PIN(LCD_DATA11),
- JZ_GPIO_BULK_PIN(LCD_DATA12),
- JZ_GPIO_BULK_PIN(LCD_DATA13),
- JZ_GPIO_BULK_PIN(LCD_DATA14),
- JZ_GPIO_BULK_PIN(LCD_DATA15),
- JZ_GPIO_BULK_PIN(LCD_DATA16),
- JZ_GPIO_BULK_PIN(LCD_DATA17),
-};
-
-static unsigned int jzfb_num_ctrl_pins(struct jzfb *jzfb)
-{
- unsigned int num;
-
- switch (jzfb->pdata->lcd_type) {
- case JZ_LCD_TYPE_GENERIC_16_BIT:
- num = 4;
- break;
- case JZ_LCD_TYPE_GENERIC_18_BIT:
- num = 4;
- break;
- case JZ_LCD_TYPE_8BIT_SERIAL:
- num = 3;
- break;
- default:
- num = 0;
- break;
- }
- return num;
-}
-
-static unsigned int jzfb_num_data_pins(struct jzfb *jzfb)
-{
- unsigned int num;
-
- switch (jzfb->pdata->lcd_type) {
- case JZ_LCD_TYPE_GENERIC_16_BIT:
- num = 16;
- break;
- case JZ_LCD_TYPE_GENERIC_18_BIT:
- num = 19;
- break;
- case JZ_LCD_TYPE_8BIT_SERIAL:
- num = 8;
- break;
- default:
- num = 0;
- break;
- }
- return num;
-}
-
-static int jzfb_setcolreg(unsigned regno, unsigned red, unsigned green, unsigned blue,
- unsigned transp, struct fb_info *fb)
-{
- if (regno >= fb->cmap.len)
- return -EINVAL;
-
- ((uint32_t*)fb->pseudo_palette)[regno] = red << 16 | green << 8 | blue;
-
- return 0;
-}
-
-static int jzfb_get_controller_bpp(struct jzfb *jzfb)
-{
- switch(jzfb->pdata->bpp) {
- case 18:
- case 24:
- return 32;
- case 15:
- return 16;
- default:
- return jzfb->pdata->bpp;
- }
-}
-
-static struct fb_videomode *jzfb_get_mode(struct jzfb* jzfb, struct fb_var_screeninfo *var)
-{
- size_t i;
- struct fb_videomode *mode = jzfb->pdata->modes;
-
- for (i = 0; i < jzfb->pdata->num_modes; ++i, ++mode) {
- if (mode->xres == var->xres && mode->yres == var->yres)
- return mode;
- }
-
- return NULL;
-}
-
-static int jzfb_check_var(struct fb_var_screeninfo *var, struct fb_info *fb)
-{
- struct jzfb* jzfb = fb->par;
- struct fb_videomode *mode;
-
- if (var->bits_per_pixel != jzfb_get_controller_bpp(jzfb) &&
- var->bits_per_pixel != jzfb->pdata->bpp)
- return -EINVAL;
-
- mode = jzfb_get_mode(jzfb, var);
- if (mode == NULL)
- return -EINVAL;
-
- fb_videomode_to_var(var, mode);
-
- switch (jzfb->pdata->bpp) {
- case 8:
- break;
- case 15:
- var->red.offset = 10;
- var->red.length = 5;
- var->green.offset = 6;
- var->green.length = 5;
- var->blue.offset = 0;
- var->blue.length = 5;
- break;
- case 16:
- var->red.offset = 11;
- var->red.length = 5;
- var->green.offset = 6;
- var->green.length = 6;
- var->blue.offset = 0;
- var->blue.length = 5;
- break;
- case 18:
- var->red.offset = 16;
- var->red.length = 6;
- var->green.offset = 8;
- var->green.length = 6;
- var->blue.offset = 0;
- var->blue.length = 6;
- var->bits_per_pixel = 32;
- break;
- case 32:
- case 24:
- var->transp.offset = 24;
- var->transp.length = 8;
- var->red.offset = 16;
- var->red.length = 8;
- var->green.offset = 8;
- var->green.length = 8;
- var->blue.offset = 0;
- var->blue.length = 8;
- var->bits_per_pixel = 32;
- break;
- default:
- break;
- }
-
- return 0;
-}
-
-static int jzfb_set_par(struct fb_info *info)
-{
- struct jzfb* jzfb = info->par;
- struct fb_var_screeninfo *var = &info->var;
- struct fb_videomode *mode;
- uint16_t hds, vds;
- uint16_t hde, vde;
- uint16_t ht, vt;
- uint32_t ctrl;
- uint32_t cfg;
- unsigned long rate;
-
- mode = jzfb_get_mode(jzfb, var);
- if (mode == NULL)
- return -EINVAL;
-
- info->mode = mode;
-
- hds = mode->hsync_len + mode->left_margin;
- hde = hds + mode->xres;
- ht = hde + mode->right_margin;
-
- vds = mode->vsync_len + mode->upper_margin;
- vde = vds + mode->yres;
- vt = vde + mode->lower_margin;
-
- ctrl = JZ_LCD_CTRL_OFUP | JZ_LCD_CTRL_BURST_16;
-
- switch (jzfb->pdata->bpp) {
- case 1:
- ctrl |= JZ_LCD_CTRL_BPP_1;
- break;
- case 2:
- ctrl |= JZ_LCD_CTRL_BPP_2;
- break;
- case 4:
- ctrl |= JZ_LCD_CTRL_BPP_4;
- break;
- case 8:
- ctrl |= JZ_LCD_CTRL_BPP_8;
- break;
- case 15:
- ctrl |= JZ_LCD_CTRL_RGB555; /* Falltrough */
- case 16:
- ctrl |= JZ_LCD_CTRL_BPP_15_16;
- break;
- case 18:
- case 24:
- case 32:
- ctrl |= JZ_LCD_CTRL_BPP_18_24;
- break;
- default:
- break;
- }
-
- cfg = 0;
- cfg |= JZ_LCD_CFG_PS_DISABLE;
- cfg |= JZ_LCD_CFG_CLS_DISABLE;
- cfg |= JZ_LCD_CFG_SPL_DISABLE;
- cfg |= JZ_LCD_CFG_REV_DISABLE;
-
- if (!(mode->sync & FB_SYNC_HOR_HIGH_ACT))
- cfg |= JZ_LCD_CFG_HSYNC_ACTIVE_LOW;
-
- if (!(mode->sync & FB_SYNC_VERT_HIGH_ACT))
- cfg |= JZ_LCD_CFG_VSYNC_ACTIVE_LOW;
-
- if (jzfb->pdata->pixclk_falling_edge)
- cfg |= JZ_LCD_CFG_PCLK_FALLING_EDGE;
-
- if (jzfb->pdata->date_enable_active_low)
- cfg |= JZ_LCD_CFG_DE_ACTIVE_LOW;
-
- if (jzfb->pdata->lcd_type == JZ_LCD_TYPE_GENERIC_18_BIT)
- cfg |= JZ_LCD_CFG_18_BIT;
-
- cfg |= jzfb->pdata->lcd_type & 0xf;
-
- if (mode->pixclock) {
- rate = PICOS2KHZ(mode->pixclock) * 1000;
- mode->refresh = rate / vt / ht;
- } else {
- if (jzfb->pdata->lcd_type == JZ_LCD_TYPE_8BIT_SERIAL)
- rate = mode->refresh * (vt + 2 * mode->xres) * ht;
- else
- rate = mode->refresh * vt * ht;
-
- mode->pixclock = KHZ2PICOS(rate / 1000);
- }
-
- mutex_lock(&jzfb->lock);
- if (!jzfb->is_enabled)
- clk_enable(jzfb->ldclk);
- else
- ctrl |= JZ_LCD_CTRL_ENABLE;
-
- writel(mode->hsync_len, jzfb->base + JZ_REG_LCD_HSYNC);
- writel(mode->vsync_len, jzfb->base + JZ_REG_LCD_VSYNC);
-
- writel((ht << 16) | vt, jzfb->base + JZ_REG_LCD_VAT);
-
- writel((hds << 16) | hde, jzfb->base + JZ_REG_LCD_DAH);
- writel((vds << 16) | vde, jzfb->base + JZ_REG_LCD_DAV);
-
- writel(cfg, jzfb->base + JZ_REG_LCD_CFG);
-
- writel(ctrl, jzfb->base + JZ_REG_LCD_CTRL);
-
- if (!jzfb->is_enabled)
- clk_disable(jzfb->ldclk);
- mutex_unlock(&jzfb->lock);
-
- clk_set_rate(jzfb->lpclk, rate);
- clk_set_rate(jzfb->ldclk, rate * 3);
-
- return 0;
-}
-
-static void jzfb_enable(struct jzfb *jzfb)
-{
- uint32_t ctrl;
-
- clk_enable(jzfb->ldclk);
-
- jz_gpio_bulk_resume(jz_lcd_ctrl_pins, jzfb_num_ctrl_pins(jzfb));
- jz_gpio_bulk_resume(jz_lcd_data_pins, jzfb_num_data_pins(jzfb));
-
- writel(0, jzfb->base + JZ_REG_LCD_STATE);
-
- writel(jzfb->framedesc->next, jzfb->base + JZ_REG_LCD_DA0);
-
- ctrl = readl(jzfb->base + JZ_REG_LCD_CTRL);
- ctrl |= JZ_LCD_CTRL_ENABLE;
- ctrl &= ~JZ_LCD_CTRL_DISABLE;
- writel(ctrl, jzfb->base + JZ_REG_LCD_CTRL);
-}
-
-static void jzfb_disable(struct jzfb *jzfb)
-{
- uint32_t ctrl;
-
- ctrl = readl(jzfb->base + JZ_REG_LCD_CTRL);
- ctrl |= JZ_LCD_CTRL_DISABLE;
- writel(ctrl, jzfb->base + JZ_REG_LCD_CTRL);
- do {
- ctrl = readl(jzfb->base + JZ_REG_LCD_STATE);
- } while (!(ctrl & JZ_LCD_STATE_DISABLED));
-
- jz_gpio_bulk_suspend(jz_lcd_ctrl_pins, jzfb_num_ctrl_pins(jzfb));
- jz_gpio_bulk_suspend(jz_lcd_data_pins, jzfb_num_data_pins(jzfb));
-
- clk_disable(jzfb->ldclk);
-}
-
-static int jzfb_blank(int blank_mode, struct fb_info *info)
-{
- struct jzfb* jzfb = info->par;
-
- switch (blank_mode) {
- case FB_BLANK_UNBLANK:
- mutex_lock(&jzfb->lock);
- if (jzfb->is_enabled) {
- mutex_unlock(&jzfb->lock);
- return 0;
- }
-
- jzfb_enable(jzfb);
- jzfb->is_enabled = 1;
-
- mutex_unlock(&jzfb->lock);
-
- break;
- default:
- mutex_lock(&jzfb->lock);
- if (!jzfb->is_enabled) {
- mutex_unlock(&jzfb->lock);
- return 0;
- }
-
- jzfb_disable(jzfb);
-
- jzfb->is_enabled = 0;
- mutex_unlock(&jzfb->lock);
- break;
- }
-
- return 0;
-}
-
-static int jzfb_alloc_devmem(struct jzfb *jzfb)
-{
- int max_videosize = 0;
- struct fb_videomode *mode = jzfb->pdata->modes;
- void *page;
- int i;
-
- for (i = 0; i < jzfb->pdata->num_modes; ++mode, ++i) {
- if (max_videosize < mode->xres * mode->yres)
- max_videosize = mode->xres * mode->yres;
- }
-
- max_videosize *= jzfb_get_controller_bpp(jzfb) >> 3;
-
- jzfb->framedesc = dma_alloc_coherent(&jzfb->pdev->dev,
- sizeof(*jzfb->framedesc),
- &jzfb->framedesc_phys, GFP_KERNEL);
-
- if (!jzfb->framedesc)
- return -ENOMEM;
-
- jzfb->vidmem_size = PAGE_ALIGN(max_videosize);
- jzfb->vidmem = dma_alloc_coherent(&jzfb->pdev->dev,
- jzfb->vidmem_size,
- &jzfb->vidmem_phys, GFP_KERNEL);
-
- if (!jzfb->vidmem) {
- goto err_free_framedesc;
- }
-
- for (page = jzfb->vidmem;
- page < jzfb->vidmem + PAGE_ALIGN(jzfb->vidmem_size);
- page += PAGE_SIZE) {
- SetPageReserved(virt_to_page(page));
- }
-
-
- jzfb->framedesc->next = jzfb->framedesc_phys;
- jzfb->framedesc->addr = jzfb->vidmem_phys;
- jzfb->framedesc->id = 0xdeafbead;
- jzfb->framedesc->cmd = 0;
- jzfb->framedesc->cmd |= max_videosize / 4;
-
- return 0;
-
-err_free_framedesc:
- dma_free_coherent(&jzfb->pdev->dev, sizeof(*jzfb->framedesc),
- jzfb->framedesc, jzfb->framedesc_phys);
- return -ENOMEM;
-}
-
-static void jzfb_free_devmem(struct jzfb *jzfb)
-{
- dma_free_coherent(&jzfb->pdev->dev, jzfb->vidmem_size,
- jzfb->vidmem, jzfb->vidmem_phys);
- dma_free_coherent(&jzfb->pdev->dev, sizeof(*jzfb->framedesc),
- jzfb->framedesc, jzfb->framedesc_phys);
-}
-
-static struct fb_ops jzfb_ops = {
- .owner = THIS_MODULE,
- .fb_check_var = jzfb_check_var,
- .fb_set_par = jzfb_set_par,
- .fb_blank = jzfb_blank,
- .fb_fillrect = sys_fillrect,
- .fb_copyarea = sys_copyarea,
- .fb_imageblit = sys_imageblit,
- .fb_setcolreg = jzfb_setcolreg,
-};
-
-static int __devinit jzfb_probe(struct platform_device *pdev)
-{
- int ret;
- struct jzfb *jzfb;
- struct fb_info *fb;
- struct jz4740_fb_platform_data *pdata = pdev->dev.platform_data;
- struct resource *mem;
-
- if (!pdata) {
- dev_err(&pdev->dev, "Missing platform data\n");
- return -ENOENT;
- }
-
- mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-
- if (!mem) {
- dev_err(&pdev->dev, "Failed to get register memory resource\n");
- return -ENOENT;
- }
-
- mem = request_mem_region(mem->start, resource_size(mem), pdev->name);
-
- if (!mem) {
- dev_err(&pdev->dev, "Failed to request register memory region\n");
- return -EBUSY;
- }
-
-
- fb = framebuffer_alloc(sizeof(struct jzfb), &pdev->dev);
-
- if (!fb) {
- dev_err(&pdev->dev, "Failed to allocate framebuffer device\n");
- ret = -ENOMEM;
- goto err_release_mem_region;
- }
-
- fb->fbops = &jzfb_ops;
- fb->flags = FBINFO_DEFAULT;
-
- jzfb = fb->par;
- jzfb->pdev = pdev;
- jzfb->pdata = pdata;
- jzfb->mem = mem;
-
- jzfb->ldclk = clk_get(&pdev->dev, "lcd");
- jzfb->lpclk = clk_get(&pdev->dev, "lcd_pclk");
-
- if (IS_ERR(jzfb->ldclk)) {
- ret = PTR_ERR(jzfb->ldclk);
- dev_err(&pdev->dev, "Faild to get device clock: %d\n", ret);
- goto err_framebuffer_release;
- }
-
- if (IS_ERR(jzfb->lpclk)) {
- ret = PTR_ERR(jzfb->ldclk);
- dev_err(&pdev->dev, "Faild to get pixel clock: %d\n", ret);
- goto err_framebuffer_release;
- }
-
-
- jzfb->base = ioremap(mem->start, resource_size(mem));
-
- if (!jzfb->base) {
- dev_err(&pdev->dev, "Failed to ioremap register memory region\n");
- ret = -EBUSY;
- goto err_framebuffer_release;
- }
-
- platform_set_drvdata(pdev, jzfb);
-
- fb_videomode_to_modelist(pdata->modes, pdata->num_modes,
- &fb->modelist);
- fb->mode = pdata->modes;
-
- fb_videomode_to_var(&fb->var, fb->mode);
- fb->var.bits_per_pixel = pdata->bpp;
- jzfb_check_var(&fb->var, fb);
-
- ret = jzfb_alloc_devmem(jzfb);
- if (ret) {
- dev_err(&pdev->dev, "Failed to allocate video memory\n");
- goto err_iounmap;
- }
-
- fb->fix = jzfb_fix;
- fb->fix.line_length = fb->var.bits_per_pixel * fb->var.xres / 8;
- fb->fix.mmio_start = mem->start;
- fb->fix.mmio_len = resource_size(mem);
- fb->fix.smem_start = jzfb->vidmem_phys;
- fb->fix.smem_len = fb->fix.line_length * fb->var.yres;
- fb->screen_base = jzfb->vidmem;
- fb->pseudo_palette = jzfb->pseudo_palette;
-
- fb_alloc_cmap(&fb->cmap, 256, 0);
-
- mutex_init(&jzfb->lock);
-
- clk_enable(jzfb->ldclk);
- jzfb->is_enabled = 1;
-
- writel(jzfb->framedesc->next, jzfb->base + JZ_REG_LCD_DA0);
- jzfb_set_par(fb);
-
- jz_gpio_bulk_request(jz_lcd_ctrl_pins, jzfb_num_ctrl_pins(jzfb));
- jz_gpio_bulk_request(jz_lcd_data_pins, jzfb_num_data_pins(jzfb));
-
- ret = register_framebuffer(fb);
- if (ret) {
- dev_err(&pdev->dev, "Failed to register framebuffer: %d\n", ret);
- goto err_free_devmem;
- }
-
- jzfb->fb = fb;
-
- return 0;
-err_free_devmem:
- jzfb_free_devmem(jzfb);
-err_iounmap:
- iounmap(jzfb->base);
-err_framebuffer_release:
- framebuffer_release(fb);
-err_release_mem_region:
- release_mem_region(mem->start, resource_size(mem));
- return ret;
-}
-
-static int __devexit jzfb_remove(struct platform_device *pdev)
-{
- struct jzfb *jzfb = platform_get_drvdata(pdev);
-
- jz_gpio_bulk_free(jz_lcd_ctrl_pins, jzfb_num_ctrl_pins(jzfb));
- jz_gpio_bulk_free(jz_lcd_data_pins, jzfb_num_data_pins(jzfb));
- iounmap(jzfb->base);
- release_mem_region(jzfb->mem->start, resource_size(jzfb->mem));
- jzfb_free_devmem(jzfb);
- platform_set_drvdata(pdev, NULL);
- framebuffer_release(jzfb->fb);
- return 0;
-}
-
-#ifdef CONFIG_PM
-
-static int jzfb_suspend(struct device *dev)
-{
- struct jzfb *jzfb = dev_get_drvdata(dev);
-
- acquire_console_sem();
- fb_set_suspend(jzfb->fb, 1);
- release_console_sem();
-
- mutex_lock(&jzfb->lock);
- if (jzfb->is_enabled)
- jzfb_disable(jzfb);
- mutex_unlock(&jzfb->lock);
-
- return 0;
-}
-
-static int jzfb_resume(struct device *dev)
-{
- struct jzfb *jzfb = dev_get_drvdata(dev);
- clk_enable(jzfb->ldclk);
-
- mutex_lock(&jzfb->lock);
- if (jzfb->is_enabled)
- jzfb_enable(jzfb);
- mutex_unlock(&jzfb->lock);
-
- acquire_console_sem();
- fb_set_suspend(jzfb->fb, 0);
- release_console_sem();
-
- return 0;
-}
-
-static const struct dev_pm_ops jzfb_pm_ops = {
- .suspend = jzfb_suspend,
- .resume = jzfb_resume,
- .poweroff = jzfb_suspend,
- .restore = jzfb_resume,
-};
-
-#define JZFB_PM_OPS (&jzfb_pm_ops)
-
-#else
-#define JZFB_PM_OPS NULL
-#endif
-
-static struct platform_driver jzfb_driver = {
- .probe = jzfb_probe,
- .remove = __devexit_p(jzfb_remove),
-
- .driver = {
- .name = "jz4740-fb",
- .pm = JZFB_PM_OPS,
- },
-};
-
-int __init jzfb_init(void)
-{
- return platform_driver_register(&jzfb_driver);
-}
-module_init(jzfb_init);
-
-void __exit jzfb_exit(void)
-{
- platform_driver_unregister(&jzfb_driver);
-}
-module_exit(jzfb_exit);
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
-MODULE_DESCRIPTION("JZ4720/JZ4740 SoC LCD framebuffer driver");
-MODULE_ALIAS("platform:jz4740-fb");
-MODULE_ALIAS("platform:jz4720-fb");
diff --git a/target/linux/xburst/files-2.6.32/drivers/video/metronomefb.c b/target/linux/xburst/files-2.6.32/drivers/video/metronomefb.c
deleted file mode 100644
index 390d26e0d5..0000000000
--- a/target/linux/xburst/files-2.6.32/drivers/video/metronomefb.c
+++ /dev/null
@@ -1,1341 +0,0 @@
-/*
- * linux/drivers/video/metronomefb.c -- FB driver for Metronome controller
- *
- * Copyright (C) 2008, Jaya Kumar
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file COPYING in the main directory of this archive for
- * more details.
- *
- * Layout is based on skeletonfb.c by James Simmons and Geert Uytterhoeven.
- *
- * This work was made possible by help and equipment support from E-Ink
- * Corporation. http://support.eink.com/community
- *
- * This driver is written to be used with the Metronome display controller.
- * It is intended to be architecture independent. A board specific driver
- * must be used to perform all the physical IO interactions. An example
- * is provided as am200epd.c
- *
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/slab.h>
-#include <linux/vmalloc.h>
-#include <linux/delay.h>
-#include <linux/interrupt.h>
-#include <linux/fb.h>
-#include <linux/init.h>
-#include <linux/platform_device.h>
-#include <linux/list.h>
-#include <linux/firmware.h>
-#include <linux/dma-mapping.h>
-#include <linux/uaccess.h>
-#include <linux/irq.h>
-#include <linux/ctype.h>
-
-#include <video/metronomefb.h>
-
-#include <asm/unaligned.h>
-
-#define WF_MODE_INIT 0 /* Initialization */
-#define WF_MODE_MU 1 /* Monochrome update */
-#define WF_MODE_GU 2 /* Grayscale update */
-#define WF_MODE_GC 3 /* Grayscale clearing */
-
-static int temp = 25;
-
-/* frame differs from image. frame includes non-visible pixels */
-struct epd_frame {
- int fw; /* frame width */
- int fh; /* frame height */
- u16 config[4];
- int wfm_size;
-};
-
-static const struct epd_frame epd_frame_table[] = {
- {
- .fw = 832,
- .fh = 622,
- .config = {
- 15 /* sdlew */
- | 2 << 8 /* sdosz */
- | 0 << 11 /* sdor */
- | 0 << 12 /* sdces */
- | 0 << 15, /* sdcer */
- 42 /* gdspl */
- | 1 << 8 /* gdr1 */
- | 1 << 9 /* sdshr */
- | 0 << 15, /* gdspp */
- 18 /* gdspw */
- | 0 << 15, /* dispc */
- 599 /* vdlc */
- | 0 << 11 /* dsi */
- | 0 << 12, /* dsic */
- },
- .wfm_size = 47001,
- },
- {
- .fw = 1088,
- .fh = 791,
- .config = {
- 0x0104,
- 0x031f,
- 0x0088,
- 0x02ff,
- },
- .wfm_size = 46770,
- },
- {
- .fw = 1200,
- .fh = 842,
- .config = {
- 0x0101,
- 0x030e,
- 0x0012,
- 0x0280,
- },
- .wfm_size = 46770,
- },
- {
- .fw = 800,
- .fh = 600,
- .config = {
- 15 /* sdlew */
- | 2 << 8 /* sdosz */
- | 0 << 11 /* sdor */
- | 0 << 12 /* sdces */
- | 0 << 15, /* sdcer */
- 42 /* gdspl */
- | 1 << 8 /* gdr1 */
- | 1 << 9 /* sdshr */
- | 0 << 15, /* gdspp */
- 18 /* gdspw */
- | 0 << 15, /* dispc */
- 599 /* vdlc */
- | 0 << 11 /* dsi */
- | 0 << 12, /* dsic */
- },
- .wfm_size = 46901,
- },
-};
-
-static const struct fb_fix_screeninfo metronomefb_fix __devinitconst = {
- .id = "metronomefb",
- .type = FB_TYPE_PACKED_PIXELS,
- .visual = FB_VISUAL_STATIC_PSEUDOCOLOR,
- .xpanstep = 0,
- .ypanstep = 0,
- .ywrapstep = 0,
- .accel = FB_ACCEL_NONE,
-};
-
-static const struct fb_var_screeninfo metronomefb_var __devinitconst = {
- .bits_per_pixel = 8,
- .grayscale = 1,
- .nonstd = 1,
- .red = { 4, 3, 0 },
- .green = { 0, 0, 0 },
- .blue = { 0, 0, 0 },
- .transp = { 0, 0, 0 },
-};
-
-/* the waveform structure that is coming from userspace firmware */
-struct waveform_hdr {
- u8 stuff[32];
-
- u8 wmta[3];
- u8 fvsn;
-
- u8 luts;
- u8 mc;
- u8 trc;
- u8 stuff3;
-
- u8 endb;
- u8 swtb;
- u8 stuff2a[2];
-
- u8 stuff2b[3];
- u8 wfm_cs;
-} __attribute__ ((packed));
-
-/* main metronomefb functions */
-static u8 calc_cksum(int start, int end, u8 *mem)
-{
- u8 tmp = 0;
- int i;
-
- for (i = start; i < end; i++)
- tmp += mem[i];
-
- return tmp;
-}
-
-static u16 calc_img_cksum(u16 *start, int length)
-{
- u16 tmp = 0;
-
- while (length--)
- tmp += *start++;
-
- return tmp;
-}
-
-/* here we decode the incoming waveform file and populate metromem */
-static int load_waveform(u8 *mem, size_t size, int m, int t,
- struct metronomefb_par *par)
-{
- int tta;
- int wmta;
- int trn = 0;
- int i;
- unsigned char v;
- u8 cksum;
- int cksum_idx;
- int wfm_idx, owfm_idx;
- int mem_idx = 0;
- struct waveform_hdr *wfm_hdr;
- u8 *metromem = par->metromem_wfm;
- struct device *dev = &par->pdev->dev;
- u8 mc, trc;
- u16 *p;
- u16 img_cksum;
-
- dev_dbg(dev, "Loading waveforms, mode %d, temperature %d\n", m, t);
-
- wfm_hdr = (struct waveform_hdr *) mem;
-
- if (wfm_hdr->fvsn != 1) {
- dev_err(dev, "Error: bad fvsn %x\n", wfm_hdr->fvsn);
- return -EINVAL;
- }
- if (wfm_hdr->luts != 0) {
- dev_err(dev, "Error: bad luts %x\n", wfm_hdr->luts);
- return -EINVAL;
- }
- cksum = calc_cksum(32, 47, mem);
- if (cksum != wfm_hdr->wfm_cs) {
- dev_err(dev, "Error: bad cksum %x != %x\n", cksum,
- wfm_hdr->wfm_cs);
- return -EINVAL;
- }
- mc = wfm_hdr->mc + 1;
- trc = wfm_hdr->trc + 1;
-
- for (i = 0; i < 5; i++) {
- if (*(wfm_hdr->stuff2a + i) != 0) {
- dev_err(dev, "Error: unexpected value in padding\n");
- return -EINVAL;
- }
- }
-
- /* calculating trn. trn is something used to index into
- the waveform. presumably selecting the right one for the
- desired temperature. it works out the offset of the first
- v that exceeds the specified temperature */
- if ((sizeof(*wfm_hdr) + trc) > size)
- return -EINVAL;
-
- for (i = sizeof(*wfm_hdr); i <= sizeof(*wfm_hdr) + trc; i++) {
- if (mem[i] > t) {
- trn = i - sizeof(*wfm_hdr) - 1;
- break;
- }
- }
-
- /* check temperature range table checksum */
- cksum_idx = sizeof(*wfm_hdr) + trc + 1;
- if (cksum_idx > size)
- return -EINVAL;
- cksum = calc_cksum(sizeof(*wfm_hdr), cksum_idx, mem);
- if (cksum != mem[cksum_idx]) {
- dev_err(dev, "Error: bad temperature range table cksum"
- " %x != %x\n", cksum, mem[cksum_idx]);
- return -EINVAL;
- }
-
- /* check waveform mode table address checksum */
- wmta = get_unaligned_le32(wfm_hdr->wmta) & 0x00FFFFFF;
- cksum_idx = wmta + m*4 + 3;
- if (cksum_idx > size)
- return -EINVAL;
- cksum = calc_cksum(cksum_idx - 3, cksum_idx, mem);
- if (cksum != mem[cksum_idx]) {
- dev_err(dev, "Error: bad mode table address cksum"
- " %x != %x\n", cksum, mem[cksum_idx]);
- return -EINVAL;
- }
-
- /* check waveform temperature table address checksum */
- tta = get_unaligned_le32(mem + wmta + m * 4) & 0x00FFFFFF;
- cksum_idx = tta + trn*4 + 3;
- if (cksum_idx > size)
- return -EINVAL;
- cksum = calc_cksum(cksum_idx - 3, cksum_idx, mem);
- if (cksum != mem[cksum_idx]) {
- dev_err(dev, "Error: bad temperature table address cksum"
- " %x != %x\n", cksum, mem[cksum_idx]);
- return -EINVAL;
- }
-
- /* here we do the real work of putting the waveform into the
- metromem buffer. this does runlength decoding of the waveform */
- wfm_idx = get_unaligned_le32(mem + tta + trn * 4) & 0x00FFFFFF;
- owfm_idx = wfm_idx;
- if (wfm_idx > size)
- return -EINVAL;
- while (wfm_idx < size) {
- unsigned char rl;
- v = mem[wfm_idx++];
- if (v == wfm_hdr->swtb) {
- while (((v = mem[wfm_idx++]) != wfm_hdr->swtb) &&
- wfm_idx < size)
- metromem[mem_idx++] = v;
-
- continue;
- }
-
- if (v == wfm_hdr->endb)
- break;
-
- rl = mem[wfm_idx++];
- for (i = 0; i <= rl; i++)
- metromem[mem_idx++] = v;
- }
-
- cksum_idx = wfm_idx;
- if (cksum_idx > size)
- return -EINVAL;
- dev_dbg(dev, "mem_idx = %u\n", mem_idx);
- cksum = calc_cksum(owfm_idx, cksum_idx, mem);
- if (cksum != mem[cksum_idx]) {
- dev_err(dev, "Error: bad waveform data cksum"
- " %x != %x\n", cksum, mem[cksum_idx]);
- return -EINVAL;
- }
- par->frame_count = (mem_idx/64);
-
- p = (u16 *)par->metromem_wfm;
- img_cksum = calc_img_cksum(p, 16384 / 2);
- p[16384 / 2] = __cpu_to_le16(img_cksum);
-
- par->current_wf_mode = m;
- par->current_wf_temp = t;
-
- return 0;
-}
-
-static int check_err(struct metronomefb_par *par)
-{
- int res;
-
- res = par->board->get_err(par);
- dev_dbg(&par->pdev->dev, "ERR = %d\n", res);
- return res;
-}
-
-static inline int wait_for_rdy(struct metronomefb_par *par)
-{
- int res = 0;
-
- if (!par->board->get_rdy(par))
- res = par->board->met_wait_event_intr(par);
-
- return res;
-}
-
-static int metronome_display_cmd(struct metronomefb_par *par)
-{
- int i;
- u16 cs;
- u16 opcode;
- int res;
-
- res = wait_for_rdy(par);
- if (res)
- return res;
-
- dev_dbg(&par->pdev->dev, "%s: ENTER\n", __func__);
- /* setup display command
- we can't immediately set the opcode since the controller
- will try parse the command before we've set it all up
- so we just set cs here and set the opcode at the end */
-
- if (par->metromem_cmd->opcode == 0xCC40)
- opcode = cs = 0xCC41;
- else
- opcode = cs = 0xCC40;
-
- /* set the args ( 2 bytes ) for display */
- i = 0;
- par->metromem_cmd->args[i] = 0 << 3 /* border update */
- | (3 << 4)
-// | ((borderval++ % 4) & 0x0F) << 4
- | (par->frame_count - 1) << 8;
- cs += par->metromem_cmd->args[i++];
-
- /* the rest are 0 */
- memset((u8 *) (par->metromem_cmd->args + i), 0, (32-i)*2);
-
- par->metromem_cmd->csum = cs;
- par->metromem_cmd->opcode = opcode; /* display cmd */
-
- return 0;
-
-}
-
-static int __devinit metronome_powerup_cmd(struct metronomefb_par *par)
-{
- int i;
- u16 cs;
- int res;
-
- dev_dbg(&par->pdev->dev, "%s: ENTER\n", __func__);
- /* setup power up command */
- par->metromem_cmd->opcode = 0x1234; /* pwr up pseudo cmd */
- cs = par->metromem_cmd->opcode;
-
- /* set pwr1,2,3 to 1024 */
- for (i = 0; i < 3; i++) {
-// par->metromem_cmd->args[i] = 1024;
- par->metromem_cmd->args[i] = 100;
- cs += par->metromem_cmd->args[i];
- }
-
- /* the rest are 0 */
- memset((u8 *) (par->metromem_cmd->args + i), 0, (32-i)*2);
-
- par->metromem_cmd->csum = cs;
-
- msleep(1);
- par->board->set_rst(par, 1);
-
- msleep(1);
- par->board->set_stdby(par, 1);
-
- res = par->board->met_wait_event(par);
- dev_dbg(&par->pdev->dev, "%s: EXIT: %d\n", __func__, res);
- return res;
-}
-
-static int __devinit metronome_config_cmd(struct metronomefb_par *par)
-{
- /* setup config command
- we can't immediately set the opcode since the controller
- will try parse the command before we've set it all up */
-
- dev_dbg(&par->pdev->dev, "%s: ENTER\n", __func__);
- memcpy(par->metromem_cmd->args, par->epd_frame->config,
- sizeof(par->epd_frame->config));
- /* the rest are 0 */
- memset((u8 *) (par->metromem_cmd->args + 4), 0, (32-4)*2);
-
- par->metromem_cmd->csum = 0xCC10;
- par->metromem_cmd->csum += calc_img_cksum(par->metromem_cmd->args, 4);
- par->metromem_cmd->opcode = 0xCC10; /* config cmd */
-
- return par->board->met_wait_event(par);
-}
-
-static int __devinit metronome_init_cmd(struct metronomefb_par *par)
-{
- int i;
- u16 cs;
-
- /* setup init command
- we can't immediately set the opcode since the controller
- will try parse the command before we've set it all up
- so we just set cs here and set the opcode at the end */
-
- dev_dbg(&par->pdev->dev, "%s: ENTER\n", __func__);
- cs = 0xCC20;
-
- /* set the args ( 2 bytes ) for init */
- i = 0;
- par->metromem_cmd->args[i] = 0x0007;
- cs += par->metromem_cmd->args[i++];
-
- /* the rest are 0 */
- memset((u8 *) (par->metromem_cmd->args + i), 0, (32-i)*2);
-
- par->metromem_cmd->csum = cs;
- par->metromem_cmd->opcode = 0xCC20; /* init cmd */
-
- return par->board->met_wait_event(par);
-}
-
-static int metronome_bootup(struct metronomefb_par *par)
-{
- int res;
-
- res = metronome_powerup_cmd(par);
- if (res) {
- dev_err(&par->pdev->dev, "metronomefb: POWERUP cmd failed\n");
- goto finish;
- }
-
- check_err(par);
- res = metronome_config_cmd(par);
- if (res) {
- dev_err(&par->pdev->dev, "metronomefb: CONFIG cmd failed\n");
- goto finish;
- }
- check_err(par);
-
- res = metronome_init_cmd(par);
- if (res)
- dev_err(&par->pdev->dev, "metronomefb: INIT cmd failed\n");
- check_err(par);
-
-finish:
- return res;
-}
-
-static int __devinit metronome_init_regs(struct metronomefb_par *par)
-{
- int res;
-
- if (par->board->power_ctl)
- par->board->power_ctl(par, METRONOME_POWER_ON);
-
- res = metronome_bootup(par);
-
- return res;
-}
-
-static uint16_t metronomefb_update_img_buffer_rotated(struct metronomefb_par *par)
-{
- int x, y;
- int xstep, ystep;
- int i, j;
- uint16_t cksum = 0;
- uint8_t *buf = par->info->screen_base;
- uint32_t *img = (uint32_t *)(par->metromem_img);
- int fw = par->epd_frame->fw;
- int fh = par->epd_frame->fh;
- int fw_buf = fw / 4;
- uint32_t *fxbuckets = par->fxbuckets;
- uint32_t *fybuckets = par->fybuckets;
- uint32_t diff;
- uint32_t tmp;
-
- switch (par->info->var.rotate) {
- case FB_ROTATE_CW:
- xstep = -fh;
- ystep = fw * fh + 1;
- j = (fw - 1) * fh;
- break;
- case FB_ROTATE_UD:
- xstep = -1;
- ystep = 0;
- j = fw * fh - 1;
- break;
- case FB_ROTATE_CCW:
- xstep = fh;
- ystep = -fw * fh - 1;
- j = fh - 1;
- break;
- default:
- BUG();
- break;
- }
-
- memset(fxbuckets, 0, fw_buf * sizeof(*fxbuckets));
- memset(fybuckets, 0, fh * sizeof(*fybuckets));
-
- i = 0;
- for (y = 0; y < fh; y++) {
- for(x = 0; x < fw_buf; x++, i++) {
- if (j < 0 || j >= fw * fh) {
- printk("moo: %d %d %d %d %d\n", j, x, y, fw_buf, fh);
- return 0;
- }
- tmp = (buf[j] << 5);
- j += xstep;
- tmp |= (buf[j] << 13);
- j += xstep;
- tmp |= (buf[j] << 21);
- j += xstep;
- tmp |= (buf[j] << 29);
- j += xstep;
- tmp &= 0xe0e0e0e0;
-
- img[i] &= 0xf0f0f0f0;
- diff = img[i] ^ tmp;
-
- fxbuckets[x] |= diff;
- fybuckets[y] |= diff;
-
- img[i] = (img[i] >> 4) | tmp;
- cksum += img[i] & 0x0000ffff;
- cksum += (img[i] >> 16);
-
- }
- j += ystep;
- }
-
- return cksum;
-}
-
-static uint16_t metronomefb_update_img_buffer_normal(struct metronomefb_par *par)
-{
- int x, y, i;
- uint16_t cksum = 0;
- uint32_t *buf = (uint32_t __force *)par->info->screen_base;
- uint32_t *img = (uint32_t *)(par->metromem_img);
- uint32_t diff;
- uint32_t tmp;
- int fw = par->epd_frame->fw;
- int fh = par->epd_frame->fh;
- int fw_buf = fw / sizeof(*buf);
- uint32_t *fxbuckets = par->fxbuckets;
- uint32_t *fybuckets = par->fybuckets;
-
- memset(fxbuckets, 0, fw_buf * sizeof(*fxbuckets));
- memset(fybuckets, 0, fh * sizeof(*fybuckets));
-
- i = 0;
- for (y = 0; y < fh; y++) {
- for(x = 0; x < fw_buf; x++, i++) {
- tmp = (buf[i] << 5) & 0xe0e0e0e0;
- img[i] &= 0xf0f0f0f0;
- diff = img[i] ^ tmp;
-
- fxbuckets[x] |= diff;
- fybuckets[y] |= diff;
-
- img[i] = (img[i] >> 4) | tmp;
- cksum += img[i] & 0x0000ffff;
- cksum += (img[i] >> 16);
- }
- }
-
- return cksum;
-}
-
-static unsigned int metronomefb_get_change_count(struct metronomefb_par *par)
-{
- int min_x;
- int max_x;
- int min_y;
- int max_y;
- int fw = par->epd_frame->fw / 4;
- int fh = par->epd_frame->fh;
- unsigned int change_count;
- uint32_t *fxbuckets = par->fxbuckets;
- uint32_t *fybuckets = par->fybuckets;
-
- for (min_x = 0; min_x < fw; ++min_x) {
- if(fxbuckets[min_x])
- break;
- }
-
- for (max_x = fw - 1; max_x >= 0; --max_x) {
- if(fxbuckets[max_x])
- break;
- }
-
- for (min_y = 0; min_y < fh; min_y++) {
- if(fybuckets[min_y])
- break;
- }
-
- for (max_y = fh - 1; max_y >= 0; --max_y) {
- if(fybuckets[max_y])
- break;
- }
-
- if ((min_x > max_x) || (min_y > max_y))
- change_count = 0;
- else
- change_count = (max_x - min_x + 1) * (max_y - min_y + 1) * 4;
-
- dev_dbg(&par->pdev->dev, "min_x = %d, max_x = %d, min_y = %d, max_y = %d\n",
- min_x, max_x, min_y, max_y);
-
- return change_count;
-}
-
-static void metronomefb_dpy_update(struct metronomefb_par *par, int clear_all)
-{
- unsigned int fbsize = par->info->fix.smem_len;
- uint16_t cksum;
- int m;
-
- wait_for_rdy(par);
-
- if (par->info->var.rotate == 0)
- cksum = metronomefb_update_img_buffer_normal(par);
- else
- cksum = metronomefb_update_img_buffer_rotated(par);
-
- *par->metromem_img_csum = __cpu_to_le16(cksum);
-
- if (clear_all || par->is_first_update ||
- (par->partial_updates_count == par->partial_autorefresh_interval)) {
- m = WF_MODE_GC;
- par->partial_updates_count = 0;
- } else {
- int change_count = metronomefb_get_change_count(par);
- if (change_count < fbsize / 100 * par->manual_refresh_threshold)
- m = WF_MODE_GU;
- else
- m = WF_MODE_GC;
-
- dev_dbg(&par->pdev->dev, "change_count = %u, treshold = %u%% (%u pixels)\n",
- change_count, par->manual_refresh_threshold,
- fbsize / 100 * par->manual_refresh_threshold);
- ++par->partial_updates_count;
- }
-
- if (m != par->current_wf_mode)
- load_waveform((u8 *) par->firmware->data, par->firmware->size,
- m, par->current_wf_temp, par);
-
-again:
- metronome_display_cmd(par);
- wait_for_rdy(par);
- if (unlikely(check_err(par))) {
- par->board->set_stdby(par, 0);
- printk("Resetting Metronome\n");
- par->board->set_rst(par, 0);
- mdelay(1);
- if (par->board->power_ctl)
- par->board->power_ctl(par, METRONOME_POWER_OFF);
-
- mdelay(1);
- load_waveform((u8 *) par->firmware->data, par->firmware->size,
- WF_MODE_GC, par->current_wf_temp, par);
-
- if (par->board->power_ctl)
- par->board->power_ctl(par, METRONOME_POWER_ON);
- metronome_bootup(par);
-
- goto again;
- }
-
- par->is_first_update = 0;
-}
-
-/* this is called back from the deferred io workqueue */
-static void metronomefb_dpy_deferred_io(struct fb_info *info,
- struct list_head *pagelist)
-{
- struct metronomefb_par *par = info->par;
-
- /* We will update entire display because we need to change
- * 'previous image' field in pixels which was changed at
- * previous refresh
- */
- mutex_lock(&par->lock);
- metronomefb_dpy_update(par, 0);
- mutex_unlock(&par->lock);
-}
-
-static void metronomefb_fillrect(struct fb_info *info,
- const struct fb_fillrect *rect)
-{
- struct metronomefb_par *par = info->par;
-
- mutex_lock(&par->lock);
- sys_fillrect(info, rect);
- metronomefb_dpy_update(par, 0);
- mutex_unlock(&par->lock);
-}
-
-static void metronomefb_copyarea(struct fb_info *info,
- const struct fb_copyarea *area)
-{
- struct metronomefb_par *par = info->par;
-
- mutex_lock(&par->lock);
- sys_copyarea(info, area);
- metronomefb_dpy_update(par, 0);
- mutex_unlock(&par->lock);
-}
-
-static void metronomefb_imageblit(struct fb_info *info,
- const struct fb_image *image)
-{
- struct metronomefb_par *par = info->par;
-
- mutex_lock(&par->lock);
- sys_imageblit(info, image);
- metronomefb_dpy_update(par, 0);
- mutex_unlock(&par->lock);
-}
-
-/*
- * this is the slow path from userspace. they can seek and write to
- * the fb. it is based on fb_sys_write
- */
-static ssize_t metronomefb_write(struct fb_info *info, const char __user *buf,
- size_t count, loff_t *ppos)
-{
- struct metronomefb_par *par = info->par;
- unsigned long p = *ppos;
- void *dst;
- int err = 0;
- unsigned long total_size;
-
- if (info->state != FBINFO_STATE_RUNNING)
- return -EPERM;
-
- total_size = info->fix.smem_len;
-
- if (p > total_size)
- return -EFBIG;
-
- if (count > total_size) {
- err = -EFBIG;
- count = total_size;
- }
-
- if (count + p > total_size) {
- if (!err)
- err = -ENOSPC;
-
- count = total_size - p;
- }
-
- dst = (void __force *)(info->screen_base + p);
-
- mutex_lock(&par->lock);
-
- if (copy_from_user(dst, buf, count))
- err = -EFAULT;
-
- if (!err)
- *ppos += count;
-
- metronomefb_dpy_update(par, 0);
- mutex_unlock(&par->lock);
-
- return (err) ? err : count;
-}
-
-static int metronome_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
-{
- struct metronomefb_par *par = info->par;
-
- if (par->epd_frame->fw == var->xres && par->epd_frame->fh == var->yres)
- return 0;
-
- return -EINVAL;
-}
-
-static int metronomefb_set_par(struct fb_info *info)
-{
- struct metronomefb_par *par = info->par;
-
- switch (info->var.rotate) {
- case FB_ROTATE_CW:
- case FB_ROTATE_CCW:
- info->fix.line_length = info->var.yres;
- break;
- case FB_ROTATE_UD:
- default:
- info->fix.line_length = info->var.xres;
- break;
- }
-
- mutex_lock(&par->lock);
- metronomefb_dpy_update(info->par, 1);
- mutex_unlock(&par->lock);
-
- return 0;
-}
-
-static struct fb_ops metronomefb_ops = {
- .owner = THIS_MODULE,
- .fb_write = metronomefb_write,
- .fb_fillrect = metronomefb_fillrect,
- .fb_copyarea = metronomefb_copyarea,
- .fb_imageblit = metronomefb_imageblit,
- .fb_check_var = metronome_check_var,
- .fb_set_par = metronomefb_set_par,
-};
-
-static struct fb_deferred_io metronomefb_defio = {
- .delay = HZ / 4,
- .deferred_io = metronomefb_dpy_deferred_io,
-};
-
-static ssize_t metronomefb_defio_delay_show(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- struct fb_info *info = dev_get_drvdata(dev);
-
- sprintf(buf, "%lu\n", info->fbdefio->delay * 1000 / HZ);
- return strlen(buf) + 1;
-}
-
-static ssize_t metronomefb_defio_delay_store(struct device *dev,
- struct device_attribute *attr, const char *buf, size_t size)
-{
- struct fb_info *info = dev_get_drvdata(dev);
- char *after;
- unsigned long state = simple_strtoul(buf, &after, 10);
- size_t count = after - buf;
- ssize_t ret = -EINVAL;
-
- if (*after && isspace(*after))
- count++;
-
- state = state * HZ / 1000;
-
- if (!state)
- state = 1;
-
- if (count == size) {
- ret = count;
- info->fbdefio->delay = state;
- }
-
- return ret;
-}
-
-static ssize_t metronomefb_manual_refresh_thr_show(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- struct fb_info *info = dev_get_drvdata(dev);
- struct metronomefb_par *par = info->par;
-
- return sprintf(buf, "%u\n", par->manual_refresh_threshold);
-}
-
-static ssize_t metronomefb_manual_refresh_thr_store(struct device *dev,
- struct device_attribute *attr, const char *buf, size_t size)
-{
- struct fb_info *info = dev_get_drvdata(dev);
- struct metronomefb_par *par = info->par;
- char *after;
- unsigned long val = simple_strtoul(buf, &after, 10);
- size_t count = after - buf;
- ssize_t ret = -EINVAL;
-
- if (*after && isspace(*after))
- count++;
-
- if (val > 100)
- return -EINVAL;
-
-
- if (count == size) {
- ret = count;
- par->manual_refresh_threshold = val;
- }
-
- return ret;
-}
-
-static ssize_t metronomefb_autorefresh_interval_show(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- struct fb_info *info = dev_get_drvdata(dev);
- struct metronomefb_par *par = info->par;
-
- return sprintf(buf, "%u\n", par->partial_autorefresh_interval);
-}
-
-static ssize_t metronomefb_autorefresh_interval_store(struct device *dev,
- struct device_attribute *attr, const char *buf, size_t size)
-{
- struct fb_info *info = dev_get_drvdata(dev);
- struct metronomefb_par *par = info->par;
- char *after;
- unsigned long val = simple_strtoul(buf, &after, 10);
- size_t count = after - buf;
- ssize_t ret = -EINVAL;
-
- if (*after && isspace(*after))
- count++;
-
- if (val > 100)
- return -EINVAL;
-
-
- if (count == size) {
- ret = count;
- par->partial_autorefresh_interval = val;
- }
-
- return ret;
-}
-
-static ssize_t metronomefb_temp_show(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- struct fb_info *info = dev_get_drvdata(dev);
- struct metronomefb_par *par = info->par;
-
- return sprintf(buf, "%u\n", par->current_wf_temp);
-}
-
-static ssize_t metronomefb_temp_store(struct device *dev,
- struct device_attribute *attr, const char *buf, size_t size)
-{
- struct fb_info *info = dev_get_drvdata(dev);
- struct metronomefb_par *par = info->par;
- char *after;
- unsigned long val = simple_strtoul(buf, &after, 10);
- size_t count = after - buf;
- ssize_t ret = -EINVAL;
-
- if (*after && isspace(*after))
- count++;
-
- if (val > 100)
- return -EINVAL;
-
-
- if (count == size) {
- ret = count;
- if (val != par->current_wf_temp)
- load_waveform((u8 *) par->firmware->data, par->firmware->size,
- par->current_wf_mode, val, par);
- }
-
- return ret;
-}
-
-DEVICE_ATTR(defio_delay, 0644,
- metronomefb_defio_delay_show, metronomefb_defio_delay_store);
-DEVICE_ATTR(manual_refresh_threshold, 0644,
- metronomefb_manual_refresh_thr_show, metronomefb_manual_refresh_thr_store);
-DEVICE_ATTR(temp, 0644,
- metronomefb_temp_show, metronomefb_temp_store);
-DEVICE_ATTR(autorefresh_interval, 0644,
- metronomefb_autorefresh_interval_show, metronomefb_autorefresh_interval_store);
-
-
-static int __devinit metronomefb_probe(struct platform_device *dev)
-{
- struct fb_info *info;
- struct metronome_board *board;
- int retval = -ENOMEM;
- int videomemorysize;
- unsigned char *videomemory;
- struct metronomefb_par *par;
- const struct firmware *fw_entry;
- int i;
- int panel_type;
- int fw, fh;
- int epd_dt_index;
-
- /* pick up board specific routines */
- board = dev->dev.platform_data;
- if (!board)
- return -EINVAL;
-
- /* try to count device specific driver, if can't, platform recalls */
- if (!try_module_get(board->owner))
- return -ENODEV;
-
- info = framebuffer_alloc(sizeof(struct metronomefb_par), &dev->dev);
- if (!info)
- goto err;
-
- /* we have two blocks of memory.
- info->screen_base which is vm, and is the fb used by apps.
- par->metromem which is physically contiguous memory and
- contains the display controller commands, waveform,
- processed image data and padding. this is the data pulled
- by the device's LCD controller and pushed to Metronome.
- the metromem memory is allocated by the board driver and
- is provided to us */
-
- panel_type = board->get_panel_type();
- switch (panel_type) {
- case 5:
- epd_dt_index = 3;
- break;
- case 6:
- epd_dt_index = 0;
- break;
- case 8:
- epd_dt_index = 1;
- break;
- case 97:
- epd_dt_index = 2;
- break;
- default:
- dev_err(&dev->dev, "Unexpected panel type. Defaulting to 6\n");
- epd_dt_index = 0;
- break;
- }
-
- fw = epd_frame_table[epd_dt_index].fw;
- fh = epd_frame_table[epd_dt_index].fh;
-
- /* we need to add a spare page because our csum caching scheme walks
- * to the end of the page */
- videomemorysize = PAGE_SIZE + (fw * fh);
- videomemory = vmalloc(videomemorysize);
- if (!videomemory)
- goto err_fb_rel;
-
- memset(videomemory, 0xff, videomemorysize);
-
- info->screen_base = (char __force __iomem *)videomemory;
- info->fbops = &metronomefb_ops;
-
- info->var = metronomefb_var;
- info->var.xres = fw;
- info->var.yres = fh;
- info->var.xres_virtual = fw;
- info->var.yres_virtual = fh;
- info->fix = metronomefb_fix;
- info->fix.line_length = fw;
- info->fix.smem_len = fw * fh; /* Real size of image area */
- par = info->par;
- par->info = info;
- par->board = board;
- par->epd_frame = &epd_frame_table[epd_dt_index];
- par->pdev = dev;
-
- par->fxbuckets = kmalloc((fw / 4 + 1) * sizeof(*par->fxbuckets), GFP_KERNEL);
- if (!par->fxbuckets)
- goto err_vfree;
-
- par->fybuckets = kmalloc(fh * sizeof(*par->fybuckets), GFP_KERNEL);
- if (!par->fybuckets)
- goto err_fxbuckets;
-
- init_waitqueue_head(&par->waitq);
- par->manual_refresh_threshold = 60;
- par->partial_autorefresh_interval = 256;
- par->partial_updates_count = 0;
- par->is_first_update = 1;
- mutex_init(&par->lock);
-
- /* this table caches per page csum values. */
- par->csum_table = vmalloc(videomemorysize/PAGE_SIZE);
- if (!par->csum_table)
- goto err_fybuckets;
-
- /* the physical framebuffer that we use is setup by
- * the platform device driver. It will provide us
- * with cmd, wfm and image memory in a contiguous area. */
- retval = board->setup_fb(par);
- if (retval) {
- dev_err(&dev->dev, "Failed to setup fb\n");
- goto err_csum_table;
- }
-
- /* after this point we should have a framebuffer */
- if ((!par->metromem_wfm) || (!par->metromem_img) ||
- (!par->metromem_dma)) {
- dev_err(&dev->dev, "fb access failure\n");
- retval = -EINVAL;
- goto err_csum_table;
- }
-
- info->fix.smem_start = par->metromem_dma;
-
- /* load the waveform in. assume mode 3, temp 31 for now
- a) request the waveform file from userspace
- b) process waveform and decode into metromem */
- retval = request_firmware(&fw_entry, "metronome.wbf", &dev->dev);
- if (retval < 0) {
- dev_err(&dev->dev, "Failed to get waveform\n");
- goto err_csum_table;
- }
-
- retval = load_waveform((u8 *) fw_entry->data, fw_entry->size, WF_MODE_GC, temp,
- par);
- if (retval < 0) {
- dev_err(&dev->dev, "Failed processing waveform\n");
- goto err_csum_table;
- }
- par->firmware = fw_entry;
-
- retval = board->setup_io(par);
- if (retval) {
- dev_err(&dev->dev, "metronomefb: setup_io() failed\n");
- goto err_csum_table;
- }
-
- if (board->setup_irq(info))
- goto err_csum_table;
-
- retval = metronome_init_regs(par);
- if (retval < 0)
- goto err_free_irq;
-
- info->flags = FBINFO_FLAG_DEFAULT;
-
- info->fbdefio = &metronomefb_defio;
- fb_deferred_io_init(info);
-
- retval = fb_alloc_cmap(&info->cmap, 8, 0);
- if (retval < 0) {
- dev_err(&dev->dev, "Failed to allocate colormap\n");
- goto err_free_irq;
- }
-
- /* set cmap */
- for (i = 0; i < 8; i++)
- info->cmap.red[i] = ((2 * i + 1)*(0xFFFF))/16;
- memcpy(info->cmap.green, info->cmap.red, sizeof(u16)*8);
- memcpy(info->cmap.blue, info->cmap.red, sizeof(u16)*8);
-
- retval = register_framebuffer(info);
- if (retval < 0)
- goto err_cmap;
-
- platform_set_drvdata(dev, info);
-
- retval = device_create_file(info->dev, &dev_attr_defio_delay);
- if (retval)
- goto err_devattr_defio_delay;
-
- retval = device_create_file(info->dev, &dev_attr_manual_refresh_threshold);
- if (retval)
- goto err_devattr_manual_refresh_thr;
-
- retval = device_create_file(info->dev, &dev_attr_temp);
- if (retval)
- goto err_devattr_temp;
-
- retval = device_create_file(info->dev, &dev_attr_autorefresh_interval);
- if (retval)
- goto err_devattr_autorefresh;
-
- dev_info(&dev->dev,
- "fb%d: Metronome frame buffer device, using %dK of video"
- " memory\n", info->node, videomemorysize >> 10);
-
- return 0;
-
- device_remove_file(info->dev, &dev_attr_autorefresh_interval);
-err_devattr_autorefresh:
- device_remove_file(info->dev, &dev_attr_temp);
-err_devattr_temp:
- device_remove_file(info->dev, &dev_attr_manual_refresh_threshold);
-err_devattr_manual_refresh_thr:
- device_remove_file(info->dev, &dev_attr_defio_delay);
-err_devattr_defio_delay:
- unregister_framebuffer(info);
-err_cmap:
- fb_dealloc_cmap(&info->cmap);
-err_free_irq:
- board->cleanup(par);
-err_csum_table:
- vfree(par->csum_table);
-err_fybuckets:
- kfree(par->fybuckets);
-err_fxbuckets:
- kfree(par->fxbuckets);
-err_vfree:
- vfree(videomemory);
-err_fb_rel:
- framebuffer_release(info);
-err:
- module_put(board->owner);
- return retval;
-}
-
-static int __devexit metronomefb_remove(struct platform_device *dev)
-{
- struct fb_info *info = platform_get_drvdata(dev);
-
- if (info) {
- struct metronomefb_par *par = info->par;
-
- par->board->set_stdby(par, 0);
- mdelay(1);
- if (par->board->power_ctl)
- par->board->power_ctl(par, METRONOME_POWER_OFF);
-
- device_remove_file(info->dev, &dev_attr_autorefresh_interval);
- device_remove_file(info->dev, &dev_attr_temp);
- device_remove_file(info->dev, &dev_attr_manual_refresh_threshold);
- device_remove_file(info->dev, &dev_attr_defio_delay);
- unregister_framebuffer(info);
- fb_deferred_io_cleanup(info);
- fb_dealloc_cmap(&info->cmap);
- par->board->cleanup(par);
- vfree(par->csum_table);
- kfree(par->fybuckets);
- kfree(par->fxbuckets);
- vfree((void __force *)info->screen_base);
- module_put(par->board->owner);
- release_firmware(par->firmware);
- dev_dbg(&dev->dev, "calling release\n");
- framebuffer_release(info);
- }
- return 0;
-}
-
-#ifdef CONFIG_PM
-static int metronomefb_suspend(struct platform_device *pdev, pm_message_t message)
-{
- struct fb_info *info = platform_get_drvdata(pdev);
- struct metronomefb_par *par = info->par;
-
- par->board->set_stdby(par, 0);
- par->board->set_rst(par, 0);
- if (par->board->power_ctl)
- par->board->power_ctl(par, METRONOME_POWER_OFF);
-
-
- return 0;
-}
-
-static int metronomefb_resume(struct platform_device *pdev)
-{
- struct fb_info *info = platform_get_drvdata(pdev);
- struct metronomefb_par *par = info->par;
-
- if (par->board->power_ctl)
- par->board->power_ctl(par, METRONOME_POWER_ON);
-
- mutex_lock(&par->lock);
- metronome_bootup(par);
- mutex_unlock(&par->lock);
-
- return 0;
-}
-
-#else
-#define metronomefb_suspend NULL
-#define metronomefb_resume NULL
-#endif
-
-
-static struct platform_driver metronomefb_driver = {
- .driver = {
- .owner = THIS_MODULE,
- .name = "metronomefb",
- },
- .probe = metronomefb_probe,
- .remove = __devexit_p(metronomefb_remove),
- .suspend = metronomefb_suspend,
- .resume = metronomefb_resume,
-};
-
-static int __init metronomefb_init(void)
-{
- return platform_driver_register(&metronomefb_driver);
-}
-
-static void __exit metronomefb_exit(void)
-{
- platform_driver_unregister(&metronomefb_driver);
-}
-
-module_param(temp, int, 0);
-MODULE_PARM_DESC(temp, "Set current temperature");
-
-module_init(metronomefb_init);
-module_exit(metronomefb_exit);
-
-MODULE_DESCRIPTION("fbdev driver for Metronome controller");
-MODULE_AUTHOR("Jaya Kumar");
-MODULE_LICENSE("GPL");