source: trunk/target/linux/xburst/patches-2.6.34/051-fb.patch @ 21438

Last change on this file since 21438 was 21438, checked in by lars, 7 years ago

[xburst] Add 2.6.34 patches

File size: 22.6 KB
  • drivers/video/Kconfig

    From 4b85f4f65855e49dec6271cf35efdcee26534210 Mon Sep 17 00:00:00 2001
    From: Lars-Peter Clausen <lars@metafoo.de>
    Date: Sat, 24 Apr 2010 12:13:58 +0200
    Subject: [PATCH] Add jz4740 framebuffer driver
    
    ---
     drivers/video/Kconfig     |    9 +
     drivers/video/Makefile    |    1 +
     drivers/video/jz4740_fb.c |  810 +++++++++++++++++++++++++++++++++++++++++++++
     include/linux/jz4740_fb.h |   58 ++++
     4 files changed, 878 insertions(+), 0 deletions(-)
     create mode 100644 drivers/video/jz4740_fb.c
     create mode 100644 include/linux/jz4740_fb.h
    
    diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
    index 6e16244..14647f0 100644
    a b config FB_BROADSHEET 
    22142214          and could also have been called by other names when coupled with 
    22152215          a bridge adapter. 
    22162216 
     2217config FB_JZ4740 
     2218        tristate "JZ47420/JZ4740 LCD framebuffer support" 
     2219        depends on FB 
     2220        select FB_SYS_FILLRECT 
     2221        select FB_SYS_COPYAREA 
     2222        select FB_SYS_IMAGEBLIT 
     2223        help 
     2224          Framebuffer support for the JZ4720 and JZ4740 SoC. 
     2225 
    22172226source "drivers/video/omap/Kconfig" 
    22182227source "drivers/video/omap2/Kconfig" 
    22192228 
  • drivers/video/Makefile

    diff --git a/drivers/video/Makefile b/drivers/video/Makefile
    index ddc2af2..f56a9ca 100644
    a b obj-$(CONFIG_FB_CARMINE) += carminefb.o 
    131131obj-$(CONFIG_FB_MB862XX)          += mb862xx/ 
    132132obj-$(CONFIG_FB_MSM)              += msm/ 
    133133obj-$(CONFIG_FB_NUC900)           += nuc900fb.o 
     134obj-$(CONFIG_FB_JZ4740)           += jz4740_fb.o 
    134135 
    135136# Platform or fallback drivers go here 
    136137obj-$(CONFIG_FB_UVESA)            += uvesafb.o 
  • new file drivers/video/jz4740_fb.c

    diff --git a/drivers/video/jz4740_fb.c b/drivers/video/jz4740_fb.c
    new file mode 100644
    index 0000000..53f3adb
    - +  
     1/* 
     2 *  Copyright (C) 2009-2010, Lars-Peter Clausen <lars@metafoo.de> 
     3 *              JZ4720/JZ4740 SoC LCD framebuffer driver 
     4 * 
     5 *  This program is free software; you can redistribute  it and/or modify it 
     6 *  under  the terms of  the GNU General  Public License as published by the 
     7 *  Free Software Foundation;  either version 2 of the  License, or (at your 
     8 *  option) any later version. 
     9 * 
     10 *  You should have received a copy of the  GNU General Public License along 
     11 *  with this program; if not, write  to the Free Software Foundation, Inc., 
     12 *  675 Mass Ave, Cambridge, MA 02139, USA. 
     13 * 
     14 */ 
     15 
     16#include <linux/kernel.h> 
     17#include <linux/module.h> 
     18#include <linux/mutex.h> 
     19#include <linux/platform_device.h> 
     20 
     21#include <linux/clk.h> 
     22#include <linux/delay.h> 
     23 
     24#include <linux/console.h> 
     25#include <linux/fb.h> 
     26 
     27#include <linux/dma-mapping.h> 
     28 
     29#include <linux/jz4740_fb.h> 
     30#include <asm/mach-jz4740/gpio.h> 
     31 
     32#define JZ_REG_LCD_CFG          0x00 
     33#define JZ_REG_LCD_VSYNC        0x04 
     34#define JZ_REG_LCD_HSYNC        0x08 
     35#define JZ_REG_LCD_VAT          0x0C 
     36#define JZ_REG_LCD_DAH          0x10 
     37#define JZ_REG_LCD_DAV          0x14 
     38#define JZ_REG_LCD_PS           0x18 
     39#define JZ_REG_LCD_CLS          0x1C 
     40#define JZ_REG_LCD_SPL          0x20 
     41#define JZ_REG_LCD_REV          0x24 
     42#define JZ_REG_LCD_CTRL         0x30 
     43#define JZ_REG_LCD_STATE        0x34 
     44#define JZ_REG_LCD_IID          0x38 
     45#define JZ_REG_LCD_DA0          0x40 
     46#define JZ_REG_LCD_SA0          0x44 
     47#define JZ_REG_LCD_FID0         0x48 
     48#define JZ_REG_LCD_CMD0         0x4C 
     49#define JZ_REG_LCD_DA1          0x50 
     50#define JZ_REG_LCD_SA1          0x54 
     51#define JZ_REG_LCD_FID1         0x58 
     52#define JZ_REG_LCD_CMD1         0x5C 
     53 
     54#define JZ_LCD_CFG_SLCD                 BIT(31) 
     55#define JZ_LCD_CFG_PS_DISABLE           BIT(23) 
     56#define JZ_LCD_CFG_CLS_DISABLE          BIT(22) 
     57#define JZ_LCD_CFG_SPL_DISABLE          BIT(21) 
     58#define JZ_LCD_CFG_REV_DISABLE          BIT(20) 
     59#define JZ_LCD_CFG_HSYNCM               BIT(19) 
     60#define JZ_LCD_CFG_PCLKM                BIT(18) 
     61#define JZ_LCD_CFG_INV                  BIT(17) 
     62#define JZ_LCD_CFG_SYNC_DIR             BIT(16) 
     63#define JZ_LCD_CFG_PS_POLARITY          BIT(15) 
     64#define JZ_LCD_CFG_CLS_POLARITY         BIT(14) 
     65#define JZ_LCD_CFG_SPL_POLARITY         BIT(13) 
     66#define JZ_LCD_CFG_REV_POLARITY         BIT(12) 
     67#define JZ_LCD_CFG_HSYNC_ACTIVE_LOW     BIT(11) 
     68#define JZ_LCD_CFG_PCLK_FALLING_EDGE    BIT(10) 
     69#define JZ_LCD_CFG_DE_ACTIVE_LOW        BIT(9) 
     70#define JZ_LCD_CFG_VSYNC_ACTIVE_LOW     BIT(8) 
     71#define JZ_LCD_CFG_18_BIT               BIT(7) 
     72#define JZ_LCD_CFG_PDW                  (BIT(5) | BIT(4)) 
     73#define JZ_LCD_CFG_MODE_MASK 0xf 
     74 
     75#define JZ_LCD_CTRL_BURST_4             (0x0 << 28) 
     76#define JZ_LCD_CTRL_BURST_8             (0x1 << 28) 
     77#define JZ_LCD_CTRL_BURST_16            (0x2 << 28) 
     78#define JZ_LCD_CTRL_RGB555              BIT(27) 
     79#define JZ_LCD_CTRL_OFUP                BIT(26) 
     80#define JZ_LCD_CTRL_FRC_GRAYSCALE_16    (0x0 << 24) 
     81#define JZ_LCD_CTRL_FRC_GRAYSCALE_4     (0x1 << 24) 
     82#define JZ_LCD_CTRL_FRC_GRAYSCALE_2     (0x2 << 24) 
     83#define JZ_LCD_CTRL_PDD_MASK            (0xff << 16) 
     84#define JZ_LCD_CTRL_EOF_IRQ             BIT(13) 
     85#define JZ_LCD_CTRL_SOF_IRQ             BIT(12) 
     86#define JZ_LCD_CTRL_OFU_IRQ             BIT(11) 
     87#define JZ_LCD_CTRL_IFU0_IRQ            BIT(10) 
     88#define JZ_LCD_CTRL_IFU1_IRQ            BIT(9) 
     89#define JZ_LCD_CTRL_DD_IRQ              BIT(8) 
     90#define JZ_LCD_CTRL_QDD_IRQ             BIT(7) 
     91#define JZ_LCD_CTRL_REVERSE_ENDIAN      BIT(6) 
     92#define JZ_LCD_CTRL_LSB_FISRT           BIT(5) 
     93#define JZ_LCD_CTRL_DISABLE             BIT(4) 
     94#define JZ_LCD_CTRL_ENABLE              BIT(3) 
     95#define JZ_LCD_CTRL_BPP_1               0x0 
     96#define JZ_LCD_CTRL_BPP_2               0x1 
     97#define JZ_LCD_CTRL_BPP_4               0x2 
     98#define JZ_LCD_CTRL_BPP_8               0x3 
     99#define JZ_LCD_CTRL_BPP_15_16           0x4 
     100#define JZ_LCD_CTRL_BPP_18_24           0x5 
     101 
     102#define JZ_LCD_CMD_SOF_IRQ BIT(15) 
     103#define JZ_LCD_CMD_EOF_IRQ BIT(16) 
     104#define JZ_LCD_CMD_ENABLE_PAL BIT(12) 
     105 
     106#define JZ_LCD_SYNC_MASK 0x3ff 
     107 
     108#define JZ_LCD_STATE_DISABLED BIT(0) 
     109 
     110struct jzfb_framedesc { 
     111        uint32_t next; 
     112        uint32_t addr; 
     113        uint32_t id; 
     114        uint32_t cmd; 
     115} __attribute__((packed)); 
     116 
     117struct jzfb { 
     118        struct fb_info *fb; 
     119        struct platform_device *pdev; 
     120        void __iomem *base; 
     121        struct resource *mem; 
     122        struct jz4740_fb_platform_data *pdata; 
     123 
     124        size_t vidmem_size; 
     125        void *vidmem; 
     126        dma_addr_t vidmem_phys; 
     127        struct jzfb_framedesc *framedesc; 
     128        dma_addr_t framedesc_phys; 
     129 
     130        struct clk *ldclk; 
     131        struct clk *lpclk; 
     132 
     133        unsigned is_enabled:1; 
     134        struct mutex lock; 
     135 
     136        uint32_t pseudo_palette[256]; 
     137}; 
     138 
     139static struct fb_fix_screeninfo jzfb_fix __devinitdata = { 
     140        .id =           "JZ4740 FB", 
     141        .type =         FB_TYPE_PACKED_PIXELS, 
     142        .visual =       FB_VISUAL_TRUECOLOR, 
     143        .xpanstep =     0, 
     144        .ypanstep =     0, 
     145        .ywrapstep =    0, 
     146        .accel =        FB_ACCEL_NONE, 
     147}; 
     148 
     149const static struct jz_gpio_bulk_request jz_lcd_ctrl_pins[] = { 
     150        JZ_GPIO_BULK_PIN(LCD_PCLK), 
     151        JZ_GPIO_BULK_PIN(LCD_HSYNC), 
     152        JZ_GPIO_BULK_PIN(LCD_VSYNC), 
     153        JZ_GPIO_BULK_PIN(LCD_DE), 
     154        JZ_GPIO_BULK_PIN(LCD_PS), 
     155        JZ_GPIO_BULK_PIN(LCD_REV), 
     156}; 
     157 
     158const static struct jz_gpio_bulk_request jz_lcd_data_pins[] = { 
     159        JZ_GPIO_BULK_PIN(LCD_DATA0), 
     160        JZ_GPIO_BULK_PIN(LCD_DATA1), 
     161        JZ_GPIO_BULK_PIN(LCD_DATA2), 
     162        JZ_GPIO_BULK_PIN(LCD_DATA3), 
     163        JZ_GPIO_BULK_PIN(LCD_DATA4), 
     164        JZ_GPIO_BULK_PIN(LCD_DATA5), 
     165        JZ_GPIO_BULK_PIN(LCD_DATA6), 
     166        JZ_GPIO_BULK_PIN(LCD_DATA7), 
     167        JZ_GPIO_BULK_PIN(LCD_DATA8), 
     168        JZ_GPIO_BULK_PIN(LCD_DATA9), 
     169        JZ_GPIO_BULK_PIN(LCD_DATA10), 
     170        JZ_GPIO_BULK_PIN(LCD_DATA11), 
     171        JZ_GPIO_BULK_PIN(LCD_DATA12), 
     172        JZ_GPIO_BULK_PIN(LCD_DATA13), 
     173        JZ_GPIO_BULK_PIN(LCD_DATA14), 
     174        JZ_GPIO_BULK_PIN(LCD_DATA15), 
     175        JZ_GPIO_BULK_PIN(LCD_DATA16), 
     176        JZ_GPIO_BULK_PIN(LCD_DATA17), 
     177}; 
     178 
     179static unsigned int jzfb_num_ctrl_pins(struct jzfb *jzfb) 
     180{ 
     181        unsigned int num; 
     182 
     183        switch (jzfb->pdata->lcd_type) { 
     184        case JZ_LCD_TYPE_GENERIC_16_BIT: 
     185                num = 4; 
     186                break; 
     187        case JZ_LCD_TYPE_GENERIC_18_BIT: 
     188                num = 4; 
     189                break; 
     190        case JZ_LCD_TYPE_8BIT_SERIAL: 
     191                num = 3; 
     192                break; 
     193        default: 
     194                num = 0; 
     195                break; 
     196        } 
     197        return num; 
     198} 
     199 
     200static unsigned int jzfb_num_data_pins(struct jzfb *jzfb) 
     201{ 
     202        unsigned int num; 
     203 
     204        switch (jzfb->pdata->lcd_type) { 
     205        case JZ_LCD_TYPE_GENERIC_16_BIT: 
     206                num = 16; 
     207                break; 
     208        case JZ_LCD_TYPE_GENERIC_18_BIT: 
     209                num = 19; 
     210                break; 
     211        case JZ_LCD_TYPE_8BIT_SERIAL: 
     212                num = 8; 
     213                break; 
     214        default: 
     215                num = 0; 
     216                break; 
     217        } 
     218        return num; 
     219} 
     220 
     221static int jzfb_setcolreg(unsigned regno, unsigned red, unsigned green, 
     222                        unsigned blue, unsigned transp, struct fb_info *fb) 
     223{ 
     224        if (regno >= fb->cmap.len) 
     225                return -EINVAL; 
     226 
     227        ((uint32_t *)fb->pseudo_palette)[regno] = red << 16 | green << 8 | blue; 
     228 
     229        return 0; 
     230} 
     231 
     232static int jzfb_get_controller_bpp(struct jzfb *jzfb) 
     233{ 
     234        switch (jzfb->pdata->bpp) { 
     235        case 18: 
     236        case 24: 
     237                return 32; 
     238        case 15: 
     239                return 16; 
     240        default: 
     241                return jzfb->pdata->bpp; 
     242        } 
     243} 
     244 
     245static struct fb_videomode *jzfb_get_mode(struct jzfb *jzfb, struct fb_var_screeninfo *var) 
     246{ 
     247        size_t i; 
     248        struct fb_videomode *mode = jzfb->pdata->modes; 
     249 
     250        for (i = 0; i < jzfb->pdata->num_modes; ++i, ++mode) { 
     251                if (mode->xres == var->xres && mode->yres == var->yres) 
     252                        return mode; 
     253        } 
     254 
     255        return NULL; 
     256} 
     257 
     258static int jzfb_check_var(struct fb_var_screeninfo *var, struct fb_info *fb) 
     259{ 
     260        struct jzfb *jzfb = fb->par; 
     261        struct fb_videomode *mode; 
     262 
     263        if (var->bits_per_pixel != jzfb_get_controller_bpp(jzfb) && 
     264                var->bits_per_pixel != jzfb->pdata->bpp) 
     265                return -EINVAL; 
     266 
     267        mode = jzfb_get_mode(jzfb, var); 
     268        if (mode == NULL) 
     269                return -EINVAL; 
     270 
     271        fb_videomode_to_var(var, mode); 
     272 
     273        switch (jzfb->pdata->bpp) { 
     274        case 8: 
     275                break; 
     276        case 15: 
     277                var->red.offset = 10; 
     278                var->red.length = 5; 
     279                var->green.offset = 6; 
     280                var->green.length = 5; 
     281                var->blue.offset = 0; 
     282                var->blue.length = 5; 
     283                break; 
     284        case 16: 
     285                var->red.offset = 11; 
     286                var->red.length = 5; 
     287                var->green.offset = 6; 
     288                var->green.length = 6; 
     289                var->blue.offset = 0; 
     290                var->blue.length = 5; 
     291                break; 
     292        case 18: 
     293                var->red.offset = 16; 
     294                var->red.length = 6; 
     295                var->green.offset = 8; 
     296                var->green.length = 6; 
     297                var->blue.offset = 0; 
     298                var->blue.length = 6; 
     299                var->bits_per_pixel = 32; 
     300                break; 
     301        case 32: 
     302        case 24: 
     303                var->transp.offset = 24; 
     304                var->transp.length = 8; 
     305                var->red.offset = 16; 
     306                var->red.length = 8; 
     307                var->green.offset = 8; 
     308                var->green.length = 8; 
     309                var->blue.offset = 0; 
     310                var->blue.length = 8; 
     311                var->bits_per_pixel = 32; 
     312                break; 
     313        default: 
     314                break; 
     315        } 
     316 
     317        return 0; 
     318} 
     319 
     320static int jzfb_set_par(struct fb_info *info) 
     321{ 
     322        struct jzfb *jzfb = info->par; 
     323        struct fb_var_screeninfo *var = &info->var; 
     324        struct fb_videomode *mode; 
     325        uint16_t hds, vds; 
     326        uint16_t hde, vde; 
     327        uint16_t ht, vt; 
     328        uint32_t ctrl; 
     329        uint32_t cfg; 
     330        unsigned long rate; 
     331 
     332        mode = jzfb_get_mode(jzfb, var); 
     333        if (mode == NULL) 
     334                return -EINVAL; 
     335 
     336        info->mode = mode; 
     337 
     338        hds = mode->hsync_len + mode->left_margin; 
     339        hde = hds + mode->xres; 
     340        ht = hde + mode->right_margin; 
     341 
     342        vds = mode->vsync_len + mode->upper_margin; 
     343        vde = vds + mode->yres; 
     344        vt = vde + mode->lower_margin; 
     345 
     346        ctrl = JZ_LCD_CTRL_OFUP | JZ_LCD_CTRL_BURST_16; 
     347 
     348        switch (jzfb->pdata->bpp) { 
     349        case 1: 
     350                ctrl |= JZ_LCD_CTRL_BPP_1; 
     351                break; 
     352        case 2: 
     353                ctrl |= JZ_LCD_CTRL_BPP_2; 
     354                break; 
     355        case 4: 
     356                ctrl |= JZ_LCD_CTRL_BPP_4; 
     357                break; 
     358        case 8: 
     359                ctrl |= JZ_LCD_CTRL_BPP_8; 
     360        break; 
     361        case 15: 
     362                ctrl |= JZ_LCD_CTRL_RGB555; /* Falltrough */ 
     363        case 16: 
     364                ctrl |= JZ_LCD_CTRL_BPP_15_16; 
     365                break; 
     366        case 18: 
     367        case 24: 
     368        case 32: 
     369                ctrl |= JZ_LCD_CTRL_BPP_18_24; 
     370                break; 
     371        default: 
     372                break; 
     373        } 
     374 
     375        cfg = 0; 
     376        cfg |= JZ_LCD_CFG_PS_DISABLE; 
     377        cfg |= JZ_LCD_CFG_CLS_DISABLE; 
     378        cfg |= JZ_LCD_CFG_SPL_DISABLE; 
     379        cfg |= JZ_LCD_CFG_REV_DISABLE; 
     380 
     381        if (!(mode->sync & FB_SYNC_HOR_HIGH_ACT)) 
     382                cfg |= JZ_LCD_CFG_HSYNC_ACTIVE_LOW; 
     383 
     384        if (!(mode->sync & FB_SYNC_VERT_HIGH_ACT)) 
     385                cfg |= JZ_LCD_CFG_VSYNC_ACTIVE_LOW; 
     386 
     387        if (jzfb->pdata->pixclk_falling_edge) 
     388                cfg |= JZ_LCD_CFG_PCLK_FALLING_EDGE; 
     389 
     390        if (jzfb->pdata->date_enable_active_low) 
     391                cfg |= JZ_LCD_CFG_DE_ACTIVE_LOW; 
     392 
     393        if (jzfb->pdata->lcd_type == JZ_LCD_TYPE_GENERIC_18_BIT) 
     394                cfg |= JZ_LCD_CFG_18_BIT; 
     395 
     396        cfg |= jzfb->pdata->lcd_type & 0xf; 
     397 
     398        if (mode->pixclock) { 
     399                rate = PICOS2KHZ(mode->pixclock) * 1000; 
     400                mode->refresh = rate / vt / ht; 
     401        } else { 
     402                if (jzfb->pdata->lcd_type == JZ_LCD_TYPE_8BIT_SERIAL) 
     403                        rate = mode->refresh * (vt + 2 * mode->xres) * ht; 
     404                else 
     405                        rate = mode->refresh * vt * ht; 
     406 
     407                mode->pixclock = KHZ2PICOS(rate / 1000); 
     408        } 
     409 
     410        mutex_lock(&jzfb->lock); 
     411        if (!jzfb->is_enabled) 
     412                clk_enable(jzfb->ldclk); 
     413        else 
     414                ctrl |= JZ_LCD_CTRL_ENABLE; 
     415 
     416        writel(mode->hsync_len, jzfb->base + JZ_REG_LCD_HSYNC); 
     417        writel(mode->vsync_len, jzfb->base + JZ_REG_LCD_VSYNC); 
     418 
     419        writel((ht << 16) | vt, jzfb->base + JZ_REG_LCD_VAT); 
     420 
     421        writel((hds << 16) | hde, jzfb->base + JZ_REG_LCD_DAH); 
     422        writel((vds << 16) | vde, jzfb->base + JZ_REG_LCD_DAV); 
     423 
     424        writel(cfg, jzfb->base + JZ_REG_LCD_CFG); 
     425 
     426        writel(ctrl, jzfb->base + JZ_REG_LCD_CTRL); 
     427 
     428        if (!jzfb->is_enabled) 
     429                clk_disable(jzfb->ldclk); 
     430        mutex_unlock(&jzfb->lock); 
     431 
     432        clk_set_rate(jzfb->lpclk, rate); 
     433        clk_set_rate(jzfb->ldclk, rate * 3); 
     434 
     435        return 0; 
     436} 
     437 
     438static void jzfb_enable(struct jzfb *jzfb) 
     439{ 
     440        uint32_t ctrl; 
     441 
     442        clk_enable(jzfb->ldclk); 
     443 
     444        jz_gpio_bulk_resume(jz_lcd_ctrl_pins, jzfb_num_ctrl_pins(jzfb)); 
     445        jz_gpio_bulk_resume(jz_lcd_data_pins, jzfb_num_data_pins(jzfb)); 
     446 
     447        writel(0, jzfb->base + JZ_REG_LCD_STATE); 
     448 
     449        writel(jzfb->framedesc->next, jzfb->base + JZ_REG_LCD_DA0); 
     450 
     451        ctrl = readl(jzfb->base + JZ_REG_LCD_CTRL); 
     452        ctrl |= JZ_LCD_CTRL_ENABLE; 
     453        ctrl &= ~JZ_LCD_CTRL_DISABLE; 
     454        writel(ctrl, jzfb->base + JZ_REG_LCD_CTRL); 
     455} 
     456 
     457static void jzfb_disable(struct jzfb *jzfb) 
     458{ 
     459        uint32_t ctrl; 
     460 
     461        ctrl = readl(jzfb->base + JZ_REG_LCD_CTRL); 
     462        ctrl |= JZ_LCD_CTRL_DISABLE; 
     463        writel(ctrl, jzfb->base + JZ_REG_LCD_CTRL); 
     464        do { 
     465                ctrl = readl(jzfb->base + JZ_REG_LCD_STATE); 
     466        } while (!(ctrl & JZ_LCD_STATE_DISABLED)); 
     467 
     468        jz_gpio_bulk_suspend(jz_lcd_ctrl_pins, jzfb_num_ctrl_pins(jzfb)); 
     469        jz_gpio_bulk_suspend(jz_lcd_data_pins, jzfb_num_data_pins(jzfb)); 
     470 
     471        clk_disable(jzfb->ldclk); 
     472} 
     473 
     474static int jzfb_blank(int blank_mode, struct fb_info *info) 
     475{ 
     476        struct jzfb *jzfb = info->par; 
     477 
     478        switch (blank_mode) { 
     479        case FB_BLANK_UNBLANK: 
     480                mutex_lock(&jzfb->lock); 
     481                if (jzfb->is_enabled) { 
     482                        mutex_unlock(&jzfb->lock); 
     483                        return 0; 
     484                } 
     485 
     486                jzfb_enable(jzfb); 
     487                jzfb->is_enabled = 1; 
     488 
     489                mutex_unlock(&jzfb->lock); 
     490 
     491                break; 
     492        default: 
     493                mutex_lock(&jzfb->lock); 
     494                if (!jzfb->is_enabled) { 
     495                        mutex_unlock(&jzfb->lock); 
     496                        return 0; 
     497                } 
     498 
     499                jzfb_disable(jzfb); 
     500 
     501                jzfb->is_enabled = 0; 
     502                mutex_unlock(&jzfb->lock); 
     503                break; 
     504        } 
     505 
     506        return 0; 
     507} 
     508 
     509static int jzfb_alloc_devmem(struct jzfb *jzfb) 
     510{ 
     511        int max_videosize = 0; 
     512        struct fb_videomode *mode = jzfb->pdata->modes; 
     513        void *page; 
     514        int i; 
     515 
     516        for (i = 0; i < jzfb->pdata->num_modes; ++mode, ++i) { 
     517                if (max_videosize < mode->xres * mode->yres) 
     518                        max_videosize = mode->xres * mode->yres; 
     519        } 
     520 
     521        max_videosize *= jzfb_get_controller_bpp(jzfb) >> 3; 
     522 
     523        jzfb->framedesc = dma_alloc_coherent(&jzfb->pdev->dev, 
     524                                    sizeof(*jzfb->framedesc), 
     525                                    &jzfb->framedesc_phys, GFP_KERNEL); 
     526 
     527        if (!jzfb->framedesc) 
     528                return -ENOMEM; 
     529 
     530        jzfb->vidmem_size = PAGE_ALIGN(max_videosize); 
     531        jzfb->vidmem = dma_alloc_coherent(&jzfb->pdev->dev, 
     532                                                jzfb->vidmem_size, 
     533                                                &jzfb->vidmem_phys, GFP_KERNEL); 
     534 
     535        if (!jzfb->vidmem) 
     536                goto err_free_framedesc; 
     537 
     538        for (page = jzfb->vidmem; 
     539                 page < jzfb->vidmem + PAGE_ALIGN(jzfb->vidmem_size); 
     540                 page += PAGE_SIZE) { 
     541                SetPageReserved(virt_to_page(page)); 
     542        } 
     543 
     544 
     545        jzfb->framedesc->next = jzfb->framedesc_phys; 
     546        jzfb->framedesc->addr = jzfb->vidmem_phys; 
     547        jzfb->framedesc->id = 0xdeafbead; 
     548        jzfb->framedesc->cmd = 0; 
     549        jzfb->framedesc->cmd |= max_videosize / 4; 
     550 
     551        return 0; 
     552 
     553err_free_framedesc: 
     554        dma_free_coherent(&jzfb->pdev->dev, sizeof(*jzfb->framedesc), 
     555                                jzfb->framedesc, jzfb->framedesc_phys); 
     556        return -ENOMEM; 
     557} 
     558 
     559static void jzfb_free_devmem(struct jzfb *jzfb) 
     560{ 
     561        dma_free_coherent(&jzfb->pdev->dev, jzfb->vidmem_size, 
     562                                jzfb->vidmem, jzfb->vidmem_phys); 
     563        dma_free_coherent(&jzfb->pdev->dev, sizeof(*jzfb->framedesc), 
     564                                jzfb->framedesc, jzfb->framedesc_phys); 
     565} 
     566 
     567static struct  fb_ops jzfb_ops = { 
     568        .owner = THIS_MODULE, 
     569        .fb_check_var = jzfb_check_var, 
     570        .fb_set_par = jzfb_set_par, 
     571        .fb_blank = jzfb_blank, 
     572        .fb_fillrect    = sys_fillrect, 
     573        .fb_copyarea    = sys_copyarea, 
     574        .fb_imageblit   = sys_imageblit, 
     575        .fb_setcolreg = jzfb_setcolreg, 
     576}; 
     577 
     578static int __devinit jzfb_probe(struct platform_device *pdev) 
     579{ 
     580        int ret; 
     581        struct jzfb *jzfb; 
     582        struct fb_info *fb; 
     583        struct jz4740_fb_platform_data *pdata = pdev->dev.platform_data; 
     584        struct resource *mem; 
     585 
     586        if (!pdata) { 
     587                dev_err(&pdev->dev, "Missing platform data\n"); 
     588                return -ENOENT; 
     589        } 
     590 
     591        mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); 
     592 
     593        if (!mem) { 
     594                dev_err(&pdev->dev, "Failed to get register memory resource\n"); 
     595                return -ENOENT; 
     596        } 
     597 
     598        mem = request_mem_region(mem->start, resource_size(mem), pdev->name); 
     599 
     600        if (!mem) { 
     601                dev_err(&pdev->dev, "Failed to request register memory region\n"); 
     602                return -EBUSY; 
     603        } 
     604 
     605 
     606        fb = framebuffer_alloc(sizeof(struct jzfb), &pdev->dev); 
     607 
     608        if (!fb) { 
     609                dev_err(&pdev->dev, "Failed to allocate framebuffer device\n"); 
     610                ret = -ENOMEM; 
     611                goto err_release_mem_region; 
     612        } 
     613 
     614        fb->fbops = &jzfb_ops; 
     615        fb->flags = FBINFO_DEFAULT; 
     616 
     617        jzfb = fb->par; 
     618        jzfb->pdev = pdev; 
     619        jzfb->pdata = pdata; 
     620        jzfb->mem = mem; 
     621 
     622        jzfb->ldclk = clk_get(&pdev->dev, "lcd"); 
     623        if (IS_ERR(jzfb->ldclk)) { 
     624                ret = PTR_ERR(jzfb->ldclk); 
     625                dev_err(&pdev->dev, "Failed to get lcd clock: %d\n", ret); 
     626                goto err_framebuffer_release; 
     627        } 
     628 
     629        jzfb->lpclk = clk_get(&pdev->dev, "lcd_pclk"); 
     630        if (IS_ERR(jzfb->lpclk)) { 
     631                ret = PTR_ERR(jzfb->lpclk); 
     632                dev_err(&pdev->dev, "Failed to get lcd pixel clock: %d\n", ret); 
     633                goto err_put_ldclk; 
     634        } 
     635 
     636        jzfb->base = ioremap(mem->start, resource_size(mem)); 
     637 
     638        if (!jzfb->base) { 
     639                dev_err(&pdev->dev, "Failed to ioremap register memory region\n"); 
     640                ret = -EBUSY; 
     641                goto err_put_lpclk; 
     642        } 
     643 
     644        platform_set_drvdata(pdev, jzfb); 
     645 
     646        fb_videomode_to_modelist(pdata->modes, pdata->num_modes, 
     647                                 &fb->modelist); 
     648        fb->mode = pdata->modes; 
     649 
     650        fb_videomode_to_var(&fb->var, fb->mode); 
     651        fb->var.bits_per_pixel = pdata->bpp; 
     652        jzfb_check_var(&fb->var, fb); 
     653 
     654        ret = jzfb_alloc_devmem(jzfb); 
     655        if (ret) { 
     656                dev_err(&pdev->dev, "Failed to allocate video memory\n"); 
     657                goto err_iounmap; 
     658        } 
     659 
     660        fb->fix = jzfb_fix; 
     661        fb->fix.line_length = fb->var.bits_per_pixel * fb->var.xres / 8; 
     662        fb->fix.mmio_start = mem->start; 
     663        fb->fix.mmio_len = resource_size(mem); 
     664        fb->fix.smem_start = jzfb->vidmem_phys; 
     665        fb->fix.smem_len =  fb->fix.line_length * fb->var.yres; 
     666        fb->screen_base = jzfb->vidmem; 
     667        fb->pseudo_palette = jzfb->pseudo_palette; 
     668 
     669        fb_alloc_cmap(&fb->cmap, 256, 0); 
     670 
     671        mutex_init(&jzfb->lock); 
     672 
     673        clk_enable(jzfb->ldclk); 
     674        jzfb->is_enabled = 1; 
     675 
     676        writel(jzfb->framedesc->next, jzfb->base + JZ_REG_LCD_DA0); 
     677        jzfb_set_par(fb); 
     678 
     679        jz_gpio_bulk_request(jz_lcd_ctrl_pins, jzfb_num_ctrl_pins(jzfb)); 
     680        jz_gpio_bulk_request(jz_lcd_data_pins, jzfb_num_data_pins(jzfb)); 
     681 
     682        ret = register_framebuffer(fb); 
     683        if (ret) { 
     684                dev_err(&pdev->dev, "Failed to register framebuffer: %d\n", ret); 
     685                goto err_free_devmem; 
     686        } 
     687 
     688        jzfb->fb = fb; 
     689 
     690        return 0; 
     691 
     692err_free_devmem: 
     693        jz_gpio_bulk_free(jz_lcd_ctrl_pins, jzfb_num_ctrl_pins(jzfb)); 
     694        jz_gpio_bulk_free(jz_lcd_data_pins, jzfb_num_data_pins(jzfb)); 
     695 
     696        fb_dealloc_cmap(&fb->cmap); 
     697        jzfb_free_devmem(jzfb); 
     698err_iounmap: 
     699        iounmap(jzfb->base); 
     700err_put_lpclk: 
     701        clk_put(jzfb->lpclk); 
     702err_put_ldclk: 
     703        clk_put(jzfb->ldclk); 
     704err_framebuffer_release: 
     705        framebuffer_release(fb); 
     706err_release_mem_region: 
     707        release_mem_region(mem->start, resource_size(mem)); 
     708        return ret; 
     709} 
     710 
     711static int __devexit jzfb_remove(struct platform_device *pdev) 
     712{ 
     713        struct jzfb *jzfb = platform_get_drvdata(pdev); 
     714 
     715        jzfb_blank(FB_BLANK_POWERDOWN, jzfb->fb); 
     716 
     717        jz_gpio_bulk_free(jz_lcd_ctrl_pins, jzfb_num_ctrl_pins(jzfb)); 
     718        jz_gpio_bulk_free(jz_lcd_data_pins, jzfb_num_data_pins(jzfb)); 
     719 
     720        iounmap(jzfb->base); 
     721        release_mem_region(jzfb->mem->start, resource_size(jzfb->mem)); 
     722 
     723        fb_dealloc_cmap(&jzfb->fb->cmap); 
     724        jzfb_free_devmem(jzfb); 
     725 
     726        platform_set_drvdata(pdev, NULL); 
     727 
     728        clk_put(jzfb->lpclk); 
     729        clk_put(jzfb->ldclk); 
     730 
     731        framebuffer_release(jzfb->fb); 
     732 
     733        return 0; 
     734} 
     735 
     736#ifdef CONFIG_PM 
     737 
     738static int jzfb_suspend(struct device *dev) 
     739{ 
     740        struct jzfb *jzfb = dev_get_drvdata(dev); 
     741 
     742        acquire_console_sem(); 
     743        fb_set_suspend(jzfb->fb, 1); 
     744        release_console_sem(); 
     745 
     746        mutex_lock(&jzfb->lock); 
     747        if (jzfb->is_enabled) 
     748                jzfb_disable(jzfb); 
     749        mutex_unlock(&jzfb->lock); 
     750 
     751        return 0; 
     752} 
     753 
     754static int jzfb_resume(struct device *dev) 
     755{ 
     756        struct jzfb *jzfb = dev_get_drvdata(dev); 
     757        clk_enable(jzfb->ldclk); 
     758 
     759        mutex_lock(&jzfb->lock); 
     760        if (jzfb->is_enabled) 
     761                jzfb_enable(jzfb); 
     762        mutex_unlock(&jzfb->lock); 
     763 
     764        acquire_console_sem(); 
     765        fb_set_suspend(jzfb->fb, 0); 
     766        release_console_sem(); 
     767 
     768        return 0; 
     769} 
     770 
     771static const struct dev_pm_ops jzfb_pm_ops = { 
     772        .suspend        = jzfb_suspend, 
     773        .resume         = jzfb_resume, 
     774        .poweroff       = jzfb_suspend, 
     775        .restore        = jzfb_resume, 
     776}; 
     777 
     778#define JZFB_PM_OPS (&jzfb_pm_ops) 
     779 
     780#else 
     781#define JZFB_PM_OPS NULL 
     782#endif 
     783 
     784static struct platform_driver jzfb_driver = { 
     785        .probe = jzfb_probe, 
     786        .remove = __devexit_p(jzfb_remove), 
     787 
     788        .driver = { 
     789                .name = "jz4740-fb", 
     790                .pm = JZFB_PM_OPS, 
     791        }, 
     792}; 
     793 
     794static int __init jzfb_init(void) 
     795{ 
     796        return platform_driver_register(&jzfb_driver); 
     797} 
     798module_init(jzfb_init); 
     799 
     800static void __exit jzfb_exit(void) 
     801{ 
     802        platform_driver_unregister(&jzfb_driver); 
     803} 
     804module_exit(jzfb_exit); 
     805 
     806MODULE_LICENSE("GPL"); 
     807MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>"); 
     808MODULE_DESCRIPTION("JZ4720/JZ4740 SoC LCD framebuffer driver"); 
     809MODULE_ALIAS("platform:jz4740-fb"); 
     810MODULE_ALIAS("platform:jz4720-fb"); 
  • new file include/linux/jz4740_fb.h

    diff --git a/include/linux/jz4740_fb.h b/include/linux/jz4740_fb.h
    new file mode 100644
    index 0000000..ab4c963
    - +  
     1/* 
     2 *  Copyright (C) 2009, Lars-Peter Clausen <lars@metafoo.de> 
     3 * 
     4 *  This program is free software; you can redistribute  it and/or modify it 
     5 *  under  the terms of  the GNU General  Public License as published by the 
     6 *  Free Software Foundation;  either version 2 of the  License, or (at your 
     7 *  option) any later version. 
     8 * 
     9 *  You should have received a copy of the  GNU General Public License along 
     10 *  with this program; if not, write  to the Free Software Foundation, Inc., 
     11 *  675 Mass Ave, Cambridge, MA 02139, USA. 
     12 * 
     13 */ 
     14 
     15#ifndef __LINUX_JZ4740_FB_H 
     16#define __LINUX_JZ4740_FB_H 
     17 
     18#include <linux/fb.h> 
     19 
     20enum jz4740_fb_lcd_type { 
     21        JZ_LCD_TYPE_GENERIC_16_BIT = 0, 
     22        JZ_LCD_TYPE_GENERIC_18_BIT = 0 | (1 << 4), 
     23        JZ_LCD_TYPE_SPECIAL_TFT_1 = 1, 
     24        JZ_LCD_TYPE_SPECIAL_TFT_2 = 2, 
     25        JZ_LCD_TYPE_SPECIAL_TFT_3 = 3, 
     26        JZ_LCD_TYPE_NON_INTERLACED_CCIR656 = 5, 
     27        JZ_LCD_TYPE_INTERLACED_CCIR656 = 7, 
     28        JZ_LCD_TYPE_SINGLE_COLOR_STN = 8, 
     29        JZ_LCD_TYPE_SINGLE_MONOCHROME_STN = 9, 
     30        JZ_LCD_TYPE_DUAL_COLOR_STN = 10, 
     31        JZ_LCD_TYPE_DUAL_MONOCHROME_STN = 11, 
     32        JZ_LCD_TYPE_8BIT_SERIAL = 12, 
     33}; 
     34 
     35/* 
     36* width: width of the lcd display in mm 
     37* height: height of the lcd display in mm 
     38* num_modes: size of modes 
     39* modes: list of valid video modes 
     40* bpp: bits per pixel for the lcd 
     41* lcd_type: lcd type 
     42*/ 
     43 
     44struct jz4740_fb_platform_data { 
     45        unsigned int width; 
     46        unsigned int height; 
     47 
     48        size_t num_modes; 
     49        struct fb_videomode *modes; 
     50 
     51        unsigned int bpp; 
     52        enum jz4740_fb_lcd_type lcd_type; 
     53 
     54        unsigned pixclk_falling_edge:1; 
     55        unsigned date_enable_active_low:1; 
     56}; 
     57 
     58#endif 
Note: See TracBrowser for help on using the repository browser.