source: trunk/target/linux/xburst/files-2.6.32/drivers/video/jz4740_fb.c @ 19982

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

[xburst] jz4740_fb: Add support for parallel displays, improve power consumption
and some minor bugfixes

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