Root/drivers/video/jz4740_slcd_fb.c

Source at commit 8212949701cfddb6e3dbe361ce883d4090096904 created 8 years 6 months ago.
By Maarten ter Huurne, MIPS: JZ4740: SLCD: Add PAL-M mode for TV-out.
1/*
2 * Copyright (C) 2009-2010, Lars-Peter Clausen <lars@metafoo.de>
3 * Copyright (C) 2010, Maarten ter Huurne <maarten@treewalker.org>
4 * JZ4720/JZ4740 SoC LCD framebuffer driver
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2 of the License, or (at your
9 * option) any later version.
10 *
11 * You should have received a copy of the GNU General Public License along
12 * with this program; if not, write to the Free Software Foundation, Inc.,
13 * 675 Mass Ave, Cambridge, MA 02139, USA.
14 *
15 */
16
17#include <linux/kernel.h>
18#include <linux/module.h>
19#include <linux/mutex.h>
20#include <linux/platform_device.h>
21
22#include <linux/clk.h>
23#include <linux/delay.h>
24
25#include <linux/console.h>
26#include <linux/fb.h>
27
28#include <linux/dma-mapping.h>
29
30#include <asm/mach-jz4740/dma.h>
31#include <asm/mach-jz4740/gpio.h>
32#include <asm/mach-jz4740/jz4740_fb.h>
33
34#include "jz4740_lcd.h"
35#include "jz4740_slcd.h"
36
37struct jzfb_framedesc {
38    uint32_t next;
39    uint32_t addr;
40    uint32_t id;
41    uint32_t cmd;
42} __attribute__((packed));
43
44static struct fb_fix_screeninfo jzfb_fix __devinitdata = {
45    .id = "JZ4740 SLCD FB",
46    .type = FB_TYPE_PACKED_PIXELS,
47    .visual = FB_VISUAL_TRUECOLOR,
48    .xpanstep = 0,
49    .ypanstep = 1,
50    .ywrapstep = 0,
51    .accel = FB_ACCEL_NONE,
52};
53
54const static struct jz_gpio_bulk_request jz_slcd_ctrl_pins[] = {
55    JZ_GPIO_BULK_PIN(LCD_PCLK),
56    JZ_GPIO_BULK_PIN(SLCD_RS),
57    JZ_GPIO_BULK_PIN(SLCD_CS),
58};
59
60const static struct jz_gpio_bulk_request jz_slcd_data_pins[] = {
61    JZ_GPIO_BULK_PIN(LCD_DATA0),
62    JZ_GPIO_BULK_PIN(LCD_DATA1),
63    JZ_GPIO_BULK_PIN(LCD_DATA2),
64    JZ_GPIO_BULK_PIN(LCD_DATA3),
65    JZ_GPIO_BULK_PIN(LCD_DATA4),
66    JZ_GPIO_BULK_PIN(LCD_DATA5),
67    JZ_GPIO_BULK_PIN(LCD_DATA6),
68    JZ_GPIO_BULK_PIN(LCD_DATA7),
69    JZ_GPIO_BULK_PIN(LCD_DATA8),
70    JZ_GPIO_BULK_PIN(LCD_DATA9),
71    JZ_GPIO_BULK_PIN(LCD_DATA10),
72    JZ_GPIO_BULK_PIN(LCD_DATA11),
73    JZ_GPIO_BULK_PIN(LCD_DATA12),
74    JZ_GPIO_BULK_PIN(LCD_DATA13),
75    JZ_GPIO_BULK_PIN(LCD_DATA14),
76    JZ_GPIO_BULK_PIN(LCD_DATA15),
77    JZ_GPIO_BULK_PIN(LCD_DATA16),
78    JZ_GPIO_BULK_PIN(LCD_DATA17),
79};
80
81static unsigned int jzfb_num_ctrl_pins(struct jzfb *jzfb)
82{
83    return ARRAY_SIZE(jz_slcd_ctrl_pins);
84}
85
86static unsigned int jzfb_num_data_pins(struct jzfb *jzfb)
87{
88    switch (jzfb->pdata->lcd_type) {
89    case JZ_LCD_TYPE_SMART_PARALLEL_8_BIT:
90        return 8;
91    case JZ_LCD_TYPE_SMART_PARALLEL_16_BIT:
92        return 16;
93    case JZ_LCD_TYPE_SMART_PARALLEL_18_BIT:
94        return 18;
95    default:
96        return 0;
97    }
98}
99
100static void jzfb_free_gpio_pins(struct jzfb *jzfb)
101{
102    jz_gpio_bulk_free(jz_slcd_ctrl_pins, jzfb_num_ctrl_pins(jzfb));
103    if (jzfb->pdata->lcd_type & (1 << 6)) {
104        /* serial */
105        jz_gpio_bulk_free(&jz_slcd_data_pins[15], 1);
106    } else {
107        /* parallel */
108        jz_gpio_bulk_free(jz_slcd_data_pins,
109                  jzfb_num_data_pins(jzfb));
110    }
111}
112
113static int jzfb_setcolreg(unsigned regno, unsigned red, unsigned green,
114            unsigned blue, unsigned transp, struct fb_info *fb)
115{
116    if (regno >= 16)
117        return -EINVAL;
118
119    red = (red * ((1 << fb->var.red.length ) - 1)) / ((1 << 16) - 1);
120    green = (green * ((1 << fb->var.green.length) - 1)) / ((1 << 16) - 1);
121    blue = (blue * ((1 << fb->var.blue.length ) - 1)) / ((1 << 16) - 1);
122
123    ((uint32_t *)fb->pseudo_palette)[regno] =
124        (red << fb->var.red.offset ) |
125        (green << fb->var.green.offset) |
126        (blue << fb->var.blue.offset );
127
128    return 0;
129}
130
131static int jzfb_get_controller_bpp(struct jzfb *jzfb)
132{
133    switch (jzfb->pdata->bpp) {
134    case 18:
135    case 24:
136        return 32;
137    case 15:
138        return 16;
139    default:
140        return jzfb->pdata->bpp;
141    }
142}
143
144static struct fb_videomode *jzfb_get_mode(struct jzfb *jzfb, struct fb_var_screeninfo *var)
145{
146    size_t i;
147    struct fb_videomode *mode = jzfb->pdata->modes;
148
149    for (i = 0; i < jzfb->pdata->num_modes; ++i, ++mode) {
150        if (mode->xres == var->xres && mode->yres == var->yres)
151            return mode;
152    }
153
154    return NULL;
155}
156
157static int jzfb_check_var(struct fb_var_screeninfo *var, struct fb_info *fb)
158{
159    struct jzfb *jzfb = fb->par;
160    struct fb_videomode *mode;
161
162    if (var->bits_per_pixel != jzfb_get_controller_bpp(jzfb) &&
163        var->bits_per_pixel != jzfb->pdata->bpp)
164        return -EINVAL;
165
166    mode = jzfb_get_mode(jzfb, var);
167    if (mode == NULL)
168        return -EINVAL;
169
170    fb_videomode_to_var(var, mode);
171
172    /* Reserve space for double buffering. */
173    var->yres_virtual = var->yres * 2;
174
175    switch (jzfb->pdata->bpp) {
176    case 8:
177        break;
178    case 15:
179        var->red.offset = 10;
180        var->red.length = 5;
181        var->green.offset = 5;
182        var->green.length = 5;
183        var->blue.offset = 0;
184        var->blue.length = 5;
185        break;
186    case 16:
187        var->red.offset = 11;
188        var->red.length = 5;
189        var->green.offset = 5;
190        var->green.length = 6;
191        var->blue.offset = 0;
192        var->blue.length = 5;
193        break;
194    case 18:
195        var->red.offset = 16;
196        var->red.length = 6;
197        var->green.offset = 8;
198        var->green.length = 6;
199        var->blue.offset = 0;
200        var->blue.length = 6;
201        var->bits_per_pixel = 32;
202        break;
203    case 32:
204    case 24:
205        var->transp.offset = 24;
206        var->transp.length = 8;
207        var->red.offset = 16;
208        var->red.length = 8;
209        var->green.offset = 8;
210        var->green.length = 8;
211        var->blue.offset = 0;
212        var->blue.length = 8;
213        var->bits_per_pixel = 32;
214        break;
215    default:
216        break;
217    }
218
219    return 0;
220}
221
222static void jzfb_disable_dma(struct jzfb *jzfb)
223{
224    jz4740_dma_disable(jzfb->dma);
225    while (readb(jzfb->base + JZ_REG_SLCD_STATE) & SLCD_STATE_BUSY);
226    writeb(readb(jzfb->base + JZ_REG_SLCD_CTRL) & ~SLCD_CTRL_DMA_EN,
227        jzfb->base + JZ_REG_SLCD_CTRL);
228}
229
230static struct jz4740_dma_config jzfb_slcd_dma_config = {
231    .src_width = JZ4740_DMA_WIDTH_32BIT,
232    .dst_width = JZ4740_DMA_WIDTH_16BIT,
233    .transfer_size = JZ4740_DMA_TRANSFER_SIZE_16BYTE,
234    .request_type = JZ4740_DMA_TYPE_SLCD,
235    .flags = JZ4740_DMA_SRC_AUTOINC,
236    .mode = JZ4740_DMA_MODE_BLOCK,
237};
238
239static void jzfb_upload_frame_dma(struct jzfb *jzfb)
240{
241    struct fb_info *fb = jzfb->fb;
242    struct fb_videomode *mode = fb->mode;
243    __u32 offset = fb->fix.line_length * fb->var.yoffset;
244    __u32 size = fb->fix.line_length * mode->yres;
245
246    /* Ensure that the data to be uploaded is in memory. */
247    dma_cache_sync(fb->device, jzfb->vidmem + offset, size,
248               DMA_TO_DEVICE);
249
250    jz4740_dma_set_src_addr(jzfb->dma, jzfb->vidmem_phys + offset);
251    jz4740_dma_set_dst_addr(jzfb->dma,
252                CPHYSADDR(jzfb->base + JZ_REG_SLCD_FIFO));
253    jz4740_dma_set_transfer_count(jzfb->dma, size);
254
255    while (readb(jzfb->base + JZ_REG_SLCD_STATE) & SLCD_STATE_BUSY);
256    writeb(readb(jzfb->base + JZ_REG_SLCD_CTRL) | SLCD_CTRL_DMA_EN,
257        jzfb->base + JZ_REG_SLCD_CTRL);
258    jz4740_dma_enable(jzfb->dma);
259}
260
261static void jzfb_upload_frame_cpu(struct jzfb *jzfb)
262{
263    const int num_pixels = jzfb->fb->mode->xres * jzfb->fb->mode->yres;
264    uint16_t *p = jzfb->vidmem;
265    int i;
266
267    jzfb_disable_dma(jzfb);
268    for (i = 0; i < num_pixels; i++) {
269        uint16_t rgb = *p++;
270        while (readb(jzfb->base + JZ_REG_SLCD_STATE) & SLCD_STATE_BUSY);
271        writel(SLCD_DATA_RS_DATA | rgb, jzfb->base + JZ_REG_SLCD_DATA);
272    }
273}
274
275static void jzfb_refresh_work(struct work_struct *work)
276{
277    struct jzfb *jzfb = container_of(work, struct jzfb, refresh_work.work);
278
279    mutex_lock(&jzfb->lock);
280    if (jzfb->is_enabled) {
281        if (1) {
282            jzfb_upload_frame_dma(jzfb);
283            /* The DMA complete callback will reschedule. */
284        } else {
285            jzfb_upload_frame_cpu(jzfb);
286            schedule_delayed_work(&jzfb->refresh_work, HZ / 10);
287        }
288    }
289    mutex_unlock(&jzfb->lock);
290}
291
292static void jzfb_refresh_work_complete(
293        struct jz4740_dma_chan *dma, int res, void *dev)
294{
295    struct jzfb *jzfb = dev_get_drvdata(dev);
296    // TODO: Stick to refresh rate in mode description.
297    int interval = HZ / 60;
298
299    schedule_delayed_work(&jzfb->refresh_work, interval);
300}
301
302static int jzfb_set_par(struct fb_info *info)
303{
304    struct jzfb *jzfb = info->par;
305    struct fb_var_screeninfo *var = &info->var;
306    struct fb_videomode *mode;
307    uint16_t slcd_cfg;
308
309    mode = jzfb_get_mode(jzfb, var);
310    if (mode == NULL)
311        return -EINVAL;
312
313    info->mode = mode;
314
315    slcd_cfg = SLCD_CFG_BURST_8_WORD;
316    /* command size */
317    slcd_cfg |= (jzfb->pdata->lcd_type & 3) << SLCD_CFG_CWIDTH_BIT;
318    /* data size */
319    if (jzfb->pdata->lcd_type & (1 << 6)) {
320        /* serial */
321        unsigned int num_bits;
322        switch (jzfb->pdata->lcd_type) {
323        case JZ_LCD_TYPE_SMART_SERIAL_8_BIT:
324            slcd_cfg |= SLCD_CFG_DWIDTH_8_x1;
325            num_bits = 8;
326            break;
327        case JZ_LCD_TYPE_SMART_SERIAL_16_BIT:
328            slcd_cfg |= SLCD_CFG_DWIDTH_16;
329            num_bits = 16;
330            break;
331        case JZ_LCD_TYPE_SMART_SERIAL_18_BIT:
332            slcd_cfg |= SLCD_CFG_DWIDTH_18;
333            num_bits = 18;
334            break;
335        default:
336            num_bits = 0;
337            break;
338        }
339        if (num_bits != jzfb->pdata->bpp) {
340            dev_err(&jzfb->pdev->dev,
341                "Data size (%d) does not match bpp (%d)\n",
342                num_bits, jzfb->pdata->bpp);
343        }
344        slcd_cfg |= SLCD_CFG_TYPE_SERIAL;
345    } else {
346        /* parallel */
347        switch (jzfb->pdata->bpp) {
348        case 8:
349            slcd_cfg |= SLCD_CFG_DWIDTH_8_x1;
350            break;
351        case 15:
352        case 16:
353            switch (jzfb->pdata->lcd_type) {
354            case JZ_LCD_TYPE_SMART_PARALLEL_8_BIT:
355                slcd_cfg |= SLCD_CFG_DWIDTH_8_x2;
356                break;
357            default:
358                slcd_cfg |= SLCD_CFG_DWIDTH_16;
359                break;
360            }
361            break;
362        case 18:
363            switch (jzfb->pdata->lcd_type) {
364            case JZ_LCD_TYPE_SMART_PARALLEL_8_BIT:
365                slcd_cfg |= SLCD_CFG_DWIDTH_8_x3;
366                break;
367            case JZ_LCD_TYPE_SMART_PARALLEL_16_BIT:
368                slcd_cfg |= SLCD_CFG_DWIDTH_9_x2;
369                break;
370            case JZ_LCD_TYPE_SMART_PARALLEL_18_BIT:
371                slcd_cfg |= SLCD_CFG_DWIDTH_18;
372                break;
373            default:
374                break;
375            }
376            break;
377        case 24:
378            slcd_cfg |= SLCD_CFG_DWIDTH_8_x3;
379            break;
380        default:
381            dev_err(&jzfb->pdev->dev,
382                "Unsupported value for bpp: %d\n",
383                jzfb->pdata->bpp);
384        }
385        slcd_cfg |= SLCD_CFG_TYPE_PARALLEL;
386    }
387    if (!jzfb->pdata->chip_select_active_low)
388        slcd_cfg |= SLCD_CFG_CS_ACTIVE_HIGH;
389    if (!jzfb->pdata->register_select_active_low)
390        slcd_cfg |= SLCD_CFG_RS_CMD_HIGH;
391    if (!jzfb->pdata->pixclk_falling_edge)
392        slcd_cfg |= SLCD_CFG_CLK_ACTIVE_RISING;
393
394#if 0
395    // TODO(MtH): Compute rate from refresh or vice versa.
396    if (mode->pixclock) {
397        rate = PICOS2KHZ(mode->pixclock) * 1000;
398        mode->refresh = rate / vt / ht;
399    } else {
400        if (jzfb->pdata->lcd_type == JZ_LCD_TYPE_8BIT_SERIAL)
401            rate = mode->refresh * (vt + 2 * mode->xres) * ht;
402        else
403            rate = mode->refresh * vt * ht;
404
405        mode->pixclock = KHZ2PICOS(rate / 1000);
406    }
407#endif
408
409    mutex_lock(&jzfb->lock);
410    if (!jzfb->is_enabled)
411        clk_enable(jzfb->ldclk);
412
413    // TODO(MtH): We should not change config while DMA might be running.
414    writew(slcd_cfg, jzfb->base + JZ_REG_SLCD_CFG);
415
416    if (!jzfb->is_enabled)
417        clk_disable(jzfb->ldclk);
418    mutex_unlock(&jzfb->lock);
419
420    // TODO(MtH): Use maximum transfer speed that panel can handle.
421    // ILI9325 can do 10 MHz.
422    clk_set_rate(jzfb->lpclk, 12000000);
423    clk_set_rate(jzfb->ldclk, 42000000);
424
425    return 0;
426}
427
428static void jzfb_enable(struct jzfb *jzfb)
429{
430    uint32_t ctrl;
431
432    clk_enable(jzfb->ldclk);
433
434    jz_gpio_bulk_resume(jz_slcd_ctrl_pins, jzfb_num_ctrl_pins(jzfb));
435    if (jzfb->pdata->lcd_type & (1 << 6)) {
436        /* serial */
437        jz_gpio_bulk_resume(&jz_slcd_data_pins[15], 1);
438    } else {
439        /* parallel */
440        jz_gpio_bulk_resume(jz_slcd_data_pins,
441                    jzfb_num_data_pins(jzfb));
442    }
443    jzfb_disable_dma(jzfb);
444    jzfb->panel->enable(jzfb);
445
446    ctrl = readl(jzfb->base + JZ_REG_LCD_CTRL);
447    ctrl |= JZ_LCD_CTRL_ENABLE;
448    ctrl &= ~JZ_LCD_CTRL_DISABLE;
449    writel(ctrl, jzfb->base + JZ_REG_LCD_CTRL);
450
451    schedule_delayed_work(&jzfb->refresh_work, 0);
452}
453
454static void jzfb_disable(struct jzfb *jzfb)
455{
456    /* It is safe but wasteful to call refresh_work() while disabled. */
457    cancel_delayed_work(&jzfb->refresh_work);
458
459    /* Abort any DMA transfer that might be in progress and allow direct
460       writes to the panel. */
461    jzfb_disable_dma(jzfb);
462
463    jzfb->panel->disable(jzfb);
464    jz_gpio_bulk_suspend(jz_slcd_ctrl_pins, jzfb_num_ctrl_pins(jzfb));
465    if (jzfb->pdata->lcd_type & (1 << 6)) {
466        /* serial */
467        jz_gpio_bulk_suspend(&jz_slcd_data_pins[15], 1);
468    } else {
469        /* parallel */
470        jz_gpio_bulk_suspend(jz_slcd_data_pins,
471                     jzfb_num_data_pins(jzfb));
472    }
473
474    clk_disable(jzfb->ldclk);
475}
476
477static int jzfb_blank(int blank_mode, struct fb_info *info)
478{
479    struct jzfb *jzfb = info->par;
480    int ret = 0;
481    int new_enabled = (blank_mode == FB_BLANK_UNBLANK);
482
483    mutex_lock(&jzfb->lock);
484    if (new_enabled) {
485        if (!jzfb->is_enabled)
486            jzfb_enable(jzfb);
487    } else {
488        if (jzfb->is_enabled) {
489            /* No sleep in TV-out mode. */
490            if (readl(jzfb->base + JZ_REG_LCD_CFG) & JZ_LCD_CFG_SLCD)
491                jzfb_disable(jzfb);
492            else
493                ret = -EBUSY;
494        }
495    }
496    if (!ret)
497        jzfb->is_enabled = new_enabled;
498    mutex_unlock(&jzfb->lock);
499
500    return ret;
501}
502
503static int jzfb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
504{
505    struct jzfb *jzfb = info->par;
506
507    info->var.yoffset = var->yoffset;
508    /* update frame start address for TV-out mode */
509    jzfb->framedesc->addr = jzfb->vidmem_phys
510                          + info->fix.line_length * var->yoffset;
511
512    return 0;
513}
514
515static int jzfb_mmap(struct fb_info *info, struct vm_area_struct *vma)
516{
517    const unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;
518    const unsigned long size = vma->vm_end - vma->vm_start;
519
520    if (offset + size > info->fix.smem_len)
521        return -EINVAL;
522
523    if (remap_pfn_range(vma, vma->vm_start,
524                (info->fix.smem_start + offset) >> PAGE_SHIFT,
525                size, vma->vm_page_prot))
526        return -EAGAIN;
527
528    return 0;
529}
530
531static int jzfb_alloc_devmem(struct jzfb *jzfb)
532{
533    int max_framesize = 0;
534    struct fb_videomode *mode = jzfb->pdata->modes;
535    void *page;
536    int i;
537
538    for (i = 0; i < jzfb->pdata->num_modes; ++mode, ++i) {
539        if (max_framesize < mode->xres * mode->yres)
540            max_framesize = mode->xres * mode->yres;
541    }
542
543    max_framesize *= jzfb_get_controller_bpp(jzfb) >> 3;
544
545    jzfb->framedesc = dma_alloc_coherent(&jzfb->pdev->dev,
546                    sizeof(*jzfb->framedesc),
547                    &jzfb->framedesc_phys, GFP_KERNEL);
548
549    if (!jzfb->framedesc)
550        return -ENOMEM;
551
552    /* reserve memory for two frames to allow double buffering */
553    jzfb->vidmem_size = PAGE_ALIGN(max_framesize * 2);
554    jzfb->vidmem = dma_alloc_coherent(&jzfb->pdev->dev,
555                        jzfb->vidmem_size,
556                        &jzfb->vidmem_phys, GFP_KERNEL);
557
558    if (!jzfb->vidmem)
559        goto err_free_framedesc;
560
561    for (page = jzfb->vidmem;
562         page < jzfb->vidmem + PAGE_ALIGN(jzfb->vidmem_size);
563         page += PAGE_SIZE) {
564        SetPageReserved(virt_to_page(page));
565    }
566
567    jzfb->framedesc->next = jzfb->framedesc_phys;
568    jzfb->framedesc->addr = jzfb->vidmem_phys;
569    jzfb->framedesc->id = 0xdeafbead;
570    jzfb->framedesc->cmd = 0;
571    jzfb->framedesc->cmd |= max_framesize / 4;
572
573    return 0;
574
575err_free_framedesc:
576    dma_free_coherent(&jzfb->pdev->dev, sizeof(*jzfb->framedesc),
577                jzfb->framedesc, jzfb->framedesc_phys);
578    return -ENOMEM;
579}
580
581static void jzfb_free_devmem(struct jzfb *jzfb)
582{
583    dma_free_coherent(&jzfb->pdev->dev, jzfb->vidmem_size,
584                jzfb->vidmem, jzfb->vidmem_phys);
585    dma_free_coherent(&jzfb->pdev->dev, sizeof(*jzfb->framedesc),
586                jzfb->framedesc, jzfb->framedesc_phys);
587}
588
589#include "jz4740_lcd.h"
590
591#define FBIOA320TVOUT 0x46F0
592#define FB_A320TV_OFF 0
593#define FB_A320TV_NTSC 1
594#define FB_A320TV_PAL50 2
595#define FB_A320TV_PAL60 3
596#define FB_A320TV_PAL_M 4
597#define FB_A320TV_LAST 4
598
599static int jzfb_tv_out(struct jzfb *jzfb, unsigned int mode)
600{
601    int blank = jzfb->is_enabled ? FB_BLANK_UNBLANK : FB_BLANK_POWERDOWN;
602    struct fb_event event = {
603        .info = jzfb->fb,
604        .data = &blank,
605    };
606
607    printk("A320 TV out: %d\n", mode);
608    if (mode > FB_A320TV_LAST)
609        return -EINVAL;
610
611    if (mode != FB_A320TV_OFF) {
612        cancel_delayed_work(&jzfb->refresh_work);
613        /* Abort any DMA transfer that might be in progress and
614           allow direct writes to the panel. */
615        jzfb_disable_dma(jzfb);
616        jzfb->panel->disable(jzfb);
617
618        /* set up LCD controller for TV output */
619
620        writel(JZ_LCD_CFG_HSYNC_ACTIVE_LOW |
621               JZ_LCD_CFG_VSYNC_ACTIVE_LOW,
622               jzfb->base + JZ_REG_LCD_CFG);
623
624        /* V-Sync pulse end position */
625        writel(10, jzfb->base + JZ_REG_LCD_VSYNC);
626
627        if (mode == FB_A320TV_PAL50) {
628            /* PAL 50 Hz */
629            /* H-Sync pulse start position */
630            writel(0x0000007d, jzfb->base + JZ_REG_LCD_HSYNC);
631            /* virtual area size */
632            writel(0x036c0112, jzfb->base + JZ_REG_LCD_VAT);
633            /* horizontal start/end point */
634            writel(0x02240364, jzfb->base + JZ_REG_LCD_DAH);
635            /* vertical start/end point */
636            writel(0x001b010b, jzfb->base + JZ_REG_LCD_DAV);
637        } else {
638            /* NTSC and PAL 60 Hz */
639            writel(0x0000003c, jzfb->base + JZ_REG_LCD_HSYNC);
640            writel(0x02e00110, jzfb->base + JZ_REG_LCD_VAT);
641            writel(0x019902d9, jzfb->base + JZ_REG_LCD_DAH);
642            writel(0x001d010d, jzfb->base + JZ_REG_LCD_DAV);
643        }
644        writel(0, jzfb->base + JZ_REG_LCD_PS);
645        writel(0, jzfb->base + JZ_REG_LCD_CLS);
646        writel(0, jzfb->base + JZ_REG_LCD_SPL);
647        writel(0, jzfb->base + JZ_REG_LCD_REV);
648        /* reset status register */
649        writel(0, jzfb->base + JZ_REG_LCD_STATE);
650
651        /* tell LCDC about the frame descriptor address */
652        writel(jzfb->framedesc_phys, jzfb->base + JZ_REG_LCD_DA0);
653
654        writel(JZ_LCD_CTRL_BURST_16 | JZ_LCD_CTRL_ENABLE |
655               JZ_LCD_CTRL_BPP_15_16,
656               jzfb->base + JZ_REG_LCD_CTRL);
657    } else {
658        /* disable LCD controller and re-enable SLCD */
659        writel(JZ_LCD_CFG_SLCD, jzfb->base + JZ_REG_LCD_CFG);
660        jzfb->panel->enable(jzfb);
661        schedule_delayed_work(&jzfb->refresh_work, 0);
662    }
663
664    /* reaffirm the current blanking state, to trigger a backlight update */
665    fb_notifier_call_chain(FB_EVENT_BLANK, &event);
666    return 0;
667}
668
669static int jzfb_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg)
670{
671    struct jzfb *jzfb = info->par;
672    switch (cmd) {
673        case FBIOA320TVOUT:
674            /* No TV-out mode while sleeping. */
675            if (!jzfb->is_enabled)
676                return -EBUSY;
677
678            return jzfb_tv_out(jzfb, arg);
679        default:
680            return -EINVAL;
681    }
682    return 0;
683}
684
685static ssize_t jzfb_panel_show(struct device *dev, struct device_attribute *attr,
686            char *buf)
687{
688    struct jzfb *jzfb = dev_get_drvdata(dev);
689    return sprintf(buf, "%s\n", jzfb->panel->name);
690}
691
692static ssize_t jzfb_panel_store(struct device *dev, struct device_attribute *attr,
693            const char *buf, size_t n)
694{
695    struct jzfb *jzfb = dev_get_drvdata(dev);
696    const struct jz_slcd_panel *panel = jz_slcd_panel_from_name(buf);
697
698    if (!panel) {
699        dev_err(dev, "Unknown SLCD panel: %s\n", buf);
700        return -EINVAL;
701    }
702
703    if (panel != jzfb->panel) {
704        jzfb->panel->disable(jzfb);
705        jzfb->panel->exit(jzfb);
706        jzfb->panel = panel;
707        panel->init(jzfb);
708        panel->enable(jzfb);
709    }
710    return n;
711}
712
713static DEVICE_ATTR(panel, 0644, jzfb_panel_show, jzfb_panel_store);
714
715static struct fb_ops jzfb_ops = {
716    .owner = THIS_MODULE,
717    .fb_check_var = jzfb_check_var,
718    .fb_set_par = jzfb_set_par,
719    .fb_setcolreg = jzfb_setcolreg,
720    .fb_blank = jzfb_blank,
721    .fb_pan_display = jzfb_pan_display,
722    .fb_fillrect = sys_fillrect,
723    .fb_copyarea = sys_copyarea,
724    .fb_imageblit = sys_imageblit,
725    .fb_ioctl = jzfb_ioctl,
726    .fb_mmap = jzfb_mmap,
727};
728
729static int __devinit jzfb_probe(struct platform_device *pdev)
730{
731    int ret;
732    struct jzfb *jzfb;
733    struct fb_info *fb;
734    struct jz4740_fb_platform_data *pdata = pdev->dev.platform_data;
735    struct resource *mem;
736
737    if (!pdata) {
738        dev_err(&pdev->dev, "Missing platform data\n");
739        return -ENOENT;
740    }
741
742    mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
743
744    if (!mem) {
745        dev_err(&pdev->dev, "Failed to get register memory resource\n");
746        return -ENOENT;
747    }
748
749    mem = request_mem_region(mem->start, resource_size(mem), pdev->name);
750
751    if (!mem) {
752        dev_err(&pdev->dev, "Failed to request register memory region\n");
753        return -EBUSY;
754    }
755
756    fb = framebuffer_alloc(sizeof(struct jzfb), &pdev->dev);
757
758    if (!fb) {
759        dev_err(&pdev->dev, "Failed to allocate framebuffer device\n");
760        ret = -ENOMEM;
761        goto err_release_mem_region;
762    }
763
764    fb->fbops = &jzfb_ops;
765    fb->flags = FBINFO_DEFAULT;
766
767    jzfb = fb->par;
768    jzfb->pdev = pdev;
769    jzfb->pdata = pdata;
770    jzfb->mem = mem;
771
772    jzfb->dma = jz4740_dma_request(&pdev->dev, dev_name(&pdev->dev), 0);
773    if (!jzfb->dma) {
774        dev_err(&pdev->dev, "Failed to get DMA channel\n");
775        ret = -EBUSY;
776        goto err_framebuffer_release;
777    }
778    jz4740_dma_configure(jzfb->dma, &jzfb_slcd_dma_config);
779    jz4740_dma_set_complete_cb(jzfb->dma, &jzfb_refresh_work_complete);
780
781    jzfb->ldclk = clk_get(&pdev->dev, "lcd");
782    if (IS_ERR(jzfb->ldclk)) {
783        ret = PTR_ERR(jzfb->ldclk);
784        dev_err(&pdev->dev, "Failed to get lcd clock: %d\n", ret);
785        goto err_free_dma;
786    }
787
788    jzfb->lpclk = clk_get(&pdev->dev, "lcd_pclk");
789    if (IS_ERR(jzfb->lpclk)) {
790        ret = PTR_ERR(jzfb->lpclk);
791        dev_err(&pdev->dev, "Failed to get lcd pixel clock: %d\n", ret);
792        goto err_put_ldclk;
793    }
794
795    jzfb->base = ioremap(mem->start, resource_size(mem));
796
797    if (!jzfb->base) {
798        dev_err(&pdev->dev, "Failed to ioremap register memory region\n");
799        ret = -EBUSY;
800        goto err_put_lpclk;
801    }
802
803    platform_set_drvdata(pdev, jzfb);
804
805    fb_videomode_to_modelist(pdata->modes, pdata->num_modes,
806                 &fb->modelist);
807    fb->mode = pdata->modes;
808
809    fb_videomode_to_var(&fb->var, fb->mode);
810    fb->var.bits_per_pixel = pdata->bpp;
811    jzfb_check_var(&fb->var, fb);
812
813    ret = jzfb_alloc_devmem(jzfb);
814    if (ret) {
815        dev_err(&pdev->dev, "Failed to allocate video memory\n");
816        goto err_iounmap;
817    }
818
819    fb->fix = jzfb_fix;
820    fb->fix.line_length = fb->var.bits_per_pixel * fb->var.xres / 8;
821    fb->fix.mmio_start = mem->start;
822    fb->fix.mmio_len = resource_size(mem);
823    fb->fix.smem_start = jzfb->vidmem_phys;
824    fb->fix.smem_len = fb->fix.line_length * fb->var.yres_virtual;
825    fb->screen_base = jzfb->vidmem;
826    fb->pseudo_palette = jzfb->pseudo_palette;
827
828    fb_alloc_cmap(&fb->cmap, 256, 0);
829
830    mutex_init(&jzfb->lock);
831
832    clk_enable(jzfb->ldclk);
833    jzfb->is_enabled = 1;
834
835    writel(JZ_LCD_CFG_SLCD, jzfb->base + JZ_REG_LCD_CFG);
836    writeb(0, jzfb->base + JZ_REG_SLCD_CTRL);
837
838    jzfb_set_par(fb);
839
840    jz_gpio_bulk_request(jz_slcd_ctrl_pins, jzfb_num_ctrl_pins(jzfb));
841    if (jzfb->pdata->lcd_type & (1 << 6)) {
842        /* serial */
843        jz_gpio_bulk_request(&jz_slcd_data_pins[15], 1);
844    } else {
845        /* parallel */
846        jz_gpio_bulk_request(jz_slcd_data_pins,
847                     jzfb_num_data_pins(jzfb));
848    }
849
850    jzfb->panel = jz_slcd_panels_probe(jzfb);
851    if (!jzfb->panel) {
852        dev_err(&pdev->dev, "Failed to find panel driver\n");
853        ret = -ENOENT;
854        goto err_free_devmem;
855    }
856    jzfb_disable_dma(jzfb);
857    jzfb->panel->init(jzfb);
858    jzfb->panel->enable(jzfb);
859
860    ret = register_framebuffer(fb);
861    if (ret) {
862        dev_err(&pdev->dev, "Failed to register framebuffer: %d\n", ret);
863        goto err_free_panel;
864    }
865
866    jzfb->fb = fb;
867    fb_prepare_logo(jzfb->fb, 0);
868    fb_show_logo(jzfb->fb, 0);
869
870    INIT_DELAYED_WORK(&jzfb->refresh_work, jzfb_refresh_work);
871    schedule_delayed_work(&jzfb->refresh_work, 0);
872
873    ret = device_create_file(&pdev->dev, &dev_attr_panel);
874    if (!ret)
875        return 0;
876
877    cancel_delayed_work_sync(&jzfb->refresh_work);
878err_free_panel:
879    jzfb->panel->exit(jzfb);
880err_free_devmem:
881    jzfb_free_gpio_pins(jzfb);
882
883    fb_dealloc_cmap(&fb->cmap);
884    jzfb_free_devmem(jzfb);
885err_iounmap:
886    iounmap(jzfb->base);
887err_put_lpclk:
888    clk_put(jzfb->lpclk);
889err_put_ldclk:
890    clk_put(jzfb->ldclk);
891err_free_dma:
892    jz4740_dma_free(jzfb->dma);
893err_framebuffer_release:
894    framebuffer_release(fb);
895err_release_mem_region:
896    release_mem_region(mem->start, resource_size(mem));
897    return ret;
898}
899
900static int __devexit jzfb_remove(struct platform_device *pdev)
901{
902    struct jzfb *jzfb = platform_get_drvdata(pdev);
903
904    device_remove_file(&pdev->dev, &dev_attr_panel);
905    jzfb_blank(FB_BLANK_POWERDOWN, jzfb->fb);
906
907    /* Blanking will prevent future refreshes from behind scheduled.
908       Now wait for a possible refresh in progress to finish. */
909    cancel_delayed_work_sync(&jzfb->refresh_work);
910
911    jzfb->panel->exit(jzfb);
912
913    jzfb_free_gpio_pins(jzfb);
914
915    jz4740_dma_free(jzfb->dma);
916
917    iounmap(jzfb->base);
918    release_mem_region(jzfb->mem->start, resource_size(jzfb->mem));
919
920    fb_dealloc_cmap(&jzfb->fb->cmap);
921    jzfb_free_devmem(jzfb);
922
923    platform_set_drvdata(pdev, NULL);
924
925    clk_put(jzfb->lpclk);
926    clk_put(jzfb->ldclk);
927
928    framebuffer_release(jzfb->fb);
929
930    return 0;
931}
932
933#ifdef CONFIG_PM
934
935static int jzfb_suspend(struct device *dev)
936{
937    struct jzfb *jzfb = dev_get_drvdata(dev);
938
939    console_lock();
940    fb_set_suspend(jzfb->fb, 1);
941    console_unlock();
942
943    mutex_lock(&jzfb->lock);
944    if (jzfb->is_enabled)
945        jzfb_disable(jzfb);
946    mutex_unlock(&jzfb->lock);
947
948    return 0;
949}
950
951static int jzfb_resume(struct device *dev)
952{
953    struct jzfb *jzfb = dev_get_drvdata(dev);
954    clk_enable(jzfb->ldclk);
955
956    mutex_lock(&jzfb->lock);
957    if (jzfb->is_enabled)
958        jzfb_enable(jzfb);
959    mutex_unlock(&jzfb->lock);
960
961    console_lock();
962    fb_set_suspend(jzfb->fb, 0);
963    console_unlock();
964
965    return 0;
966}
967
968static const struct dev_pm_ops jzfb_pm_ops = {
969    .suspend = jzfb_suspend,
970    .resume = jzfb_resume,
971    .poweroff = jzfb_suspend,
972    .restore = jzfb_resume,
973};
974
975#define JZFB_PM_OPS (&jzfb_pm_ops)
976
977#else
978#define JZFB_PM_OPS NULL
979#endif
980
981static struct platform_driver jzfb_driver = {
982    .probe = jzfb_probe,
983    .remove = __devexit_p(jzfb_remove),
984    .driver = {
985        .name = "jz4740-fb",
986        .pm = JZFB_PM_OPS,
987    },
988};
989
990static int __init jzfb_init(void)
991{
992    return platform_driver_register(&jzfb_driver);
993}
994module_init(jzfb_init);
995
996static void __exit jzfb_exit(void)
997{
998    platform_driver_unregister(&jzfb_driver);
999}
1000module_exit(jzfb_exit);
1001
1002MODULE_LICENSE("GPL");
1003MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>, Maarten ter Huurne <maarten@treewalker.org>");
1004MODULE_DESCRIPTION("JZ4740 SoC SLCD framebuffer driver");
1005MODULE_ALIAS("platform:jz4740-fb");
1006

Archive Download this file



interactive