Root/drivers/video/jz4740_slcd_fb.c

Source at commit e7de309271c0d5199e6c27808c9784f2ffe4f4ef created 8 years 7 months ago.
By Maarten ter Huurne, MIPS: JZ4740: SLCD: TV-out related cleanups.
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_PAL 2
595#define FB_A320TV_LAST 2
596
597static int jzfb_tv_out(struct jzfb *jzfb, unsigned int mode)
598{
599    int blank = jzfb->is_enabled ? FB_BLANK_UNBLANK : FB_BLANK_POWERDOWN;
600    struct fb_event event = {
601        .info = jzfb->fb,
602        .data = &blank,
603    };
604
605    printk("A320 TV out: %d\n", mode);
606    if (mode > FB_A320TV_LAST)
607        return -EINVAL;
608
609    if (mode != FB_A320TV_OFF) {
610        cancel_delayed_work(&jzfb->refresh_work);
611        /* Abort any DMA transfer that might be in progress and
612           allow direct writes to the panel. */
613        jzfb_disable_dma(jzfb);
614        jzfb->panel->disable(jzfb);
615
616        /* set up LCD controller for TV output */
617
618        writel(JZ_LCD_CFG_HSYNC_ACTIVE_LOW |
619               JZ_LCD_CFG_VSYNC_ACTIVE_LOW,
620               jzfb->base + JZ_REG_LCD_CFG);
621
622        /* V-Sync pulse end position */
623        writel(10, jzfb->base + JZ_REG_LCD_VSYNC);
624
625        if (mode == FB_A320TV_PAL) {
626            /* PAL */
627            /* H-Sync pulse start position */
628            writel(0x0000007D, jzfb->base + JZ_REG_LCD_HSYNC);
629            /* virtual area size */
630            writel(0x036c0112, jzfb->base + JZ_REG_LCD_VAT);
631            /* horizontal start/end point */
632            writel(0x02240364, jzfb->base + JZ_REG_LCD_DAH);
633            /* vertical start/end point */
634            writel(0x001b010b, jzfb->base + JZ_REG_LCD_DAV);
635        } else {
636            /* NTSC */
637            writel(0x0000003c, jzfb->base + JZ_REG_LCD_HSYNC);
638            writel(0x02e00110, jzfb->base + JZ_REG_LCD_VAT);
639            writel(0x019902d9, jzfb->base + JZ_REG_LCD_DAH);
640            writel(0x001d010d, jzfb->base + JZ_REG_LCD_DAV);
641        }
642        writel(0, jzfb->base + JZ_REG_LCD_PS);
643        writel(0, jzfb->base + JZ_REG_LCD_CLS);
644        writel(0, jzfb->base + JZ_REG_LCD_SPL);
645        writel(0, jzfb->base + JZ_REG_LCD_REV);
646        /* reset status register */
647        writel(0, jzfb->base + JZ_REG_LCD_STATE);
648
649        /* tell LCDC about the frame descriptor address */
650        writel(jzfb->framedesc_phys, jzfb->base + JZ_REG_LCD_DA0);
651
652        writel(JZ_LCD_CTRL_BURST_16 | JZ_LCD_CTRL_ENABLE |
653               JZ_LCD_CTRL_BPP_15_16,
654               jzfb->base + JZ_REG_LCD_CTRL);
655    } else {
656        /* disable LCD controller and re-enable SLCD */
657        writel(JZ_LCD_CFG_SLCD, jzfb->base + JZ_REG_LCD_CFG);
658        jzfb->panel->enable(jzfb);
659        schedule_delayed_work(&jzfb->refresh_work, 0);
660    }
661
662    /* reaffirm the current blanking state, to trigger a backlight update */
663    fb_notifier_call_chain(FB_EVENT_BLANK, &event);
664    return 0;
665}
666
667static int jzfb_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg)
668{
669    struct jzfb *jzfb = info->par;
670    switch (cmd) {
671        case FBIOA320TVOUT:
672            /* No TV-out mode while sleeping. */
673            if (!jzfb->is_enabled)
674                return -EBUSY;
675
676            return jzfb_tv_out(jzfb, arg);
677        default:
678            return -EINVAL;
679    }
680    return 0;
681}
682
683static ssize_t jzfb_panel_show(struct device *dev, struct device_attribute *attr,
684            char *buf)
685{
686    struct jzfb *jzfb = dev_get_drvdata(dev);
687    return sprintf(buf, "%s\n", jzfb->panel->name);
688}
689
690static ssize_t jzfb_panel_store(struct device *dev, struct device_attribute *attr,
691            const char *buf, size_t n)
692{
693    struct jzfb *jzfb = dev_get_drvdata(dev);
694    const struct jz_slcd_panel *panel = jz_slcd_panel_from_name(buf);
695
696    if (!panel) {
697        dev_err(dev, "Unknown SLCD panel: %s\n", buf);
698        return -EINVAL;
699    }
700
701    if (panel != jzfb->panel) {
702        jzfb->panel->disable(jzfb);
703        jzfb->panel->exit(jzfb);
704        jzfb->panel = panel;
705        panel->init(jzfb);
706        panel->enable(jzfb);
707    }
708    return n;
709}
710
711static DEVICE_ATTR(panel, 0644, jzfb_panel_show, jzfb_panel_store);
712
713static struct fb_ops jzfb_ops = {
714    .owner = THIS_MODULE,
715    .fb_check_var = jzfb_check_var,
716    .fb_set_par = jzfb_set_par,
717    .fb_setcolreg = jzfb_setcolreg,
718    .fb_blank = jzfb_blank,
719    .fb_pan_display = jzfb_pan_display,
720    .fb_fillrect = sys_fillrect,
721    .fb_copyarea = sys_copyarea,
722    .fb_imageblit = sys_imageblit,
723    .fb_ioctl = jzfb_ioctl,
724    .fb_mmap = jzfb_mmap,
725};
726
727static int __devinit jzfb_probe(struct platform_device *pdev)
728{
729    int ret;
730    struct jzfb *jzfb;
731    struct fb_info *fb;
732    struct jz4740_fb_platform_data *pdata = pdev->dev.platform_data;
733    struct resource *mem;
734
735    if (!pdata) {
736        dev_err(&pdev->dev, "Missing platform data\n");
737        return -ENOENT;
738    }
739
740    mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
741
742    if (!mem) {
743        dev_err(&pdev->dev, "Failed to get register memory resource\n");
744        return -ENOENT;
745    }
746
747    mem = request_mem_region(mem->start, resource_size(mem), pdev->name);
748
749    if (!mem) {
750        dev_err(&pdev->dev, "Failed to request register memory region\n");
751        return -EBUSY;
752    }
753
754    fb = framebuffer_alloc(sizeof(struct jzfb), &pdev->dev);
755
756    if (!fb) {
757        dev_err(&pdev->dev, "Failed to allocate framebuffer device\n");
758        ret = -ENOMEM;
759        goto err_release_mem_region;
760    }
761
762    fb->fbops = &jzfb_ops;
763    fb->flags = FBINFO_DEFAULT;
764
765    jzfb = fb->par;
766    jzfb->pdev = pdev;
767    jzfb->pdata = pdata;
768    jzfb->mem = mem;
769
770    jzfb->dma = jz4740_dma_request(&pdev->dev, dev_name(&pdev->dev), 0);
771    if (!jzfb->dma) {
772        dev_err(&pdev->dev, "Failed to get DMA channel\n");
773        ret = -EBUSY;
774        goto err_framebuffer_release;
775    }
776    jz4740_dma_configure(jzfb->dma, &jzfb_slcd_dma_config);
777    jz4740_dma_set_complete_cb(jzfb->dma, &jzfb_refresh_work_complete);
778
779    jzfb->ldclk = clk_get(&pdev->dev, "lcd");
780    if (IS_ERR(jzfb->ldclk)) {
781        ret = PTR_ERR(jzfb->ldclk);
782        dev_err(&pdev->dev, "Failed to get lcd clock: %d\n", ret);
783        goto err_free_dma;
784    }
785
786    jzfb->lpclk = clk_get(&pdev->dev, "lcd_pclk");
787    if (IS_ERR(jzfb->lpclk)) {
788        ret = PTR_ERR(jzfb->lpclk);
789        dev_err(&pdev->dev, "Failed to get lcd pixel clock: %d\n", ret);
790        goto err_put_ldclk;
791    }
792
793    jzfb->base = ioremap(mem->start, resource_size(mem));
794
795    if (!jzfb->base) {
796        dev_err(&pdev->dev, "Failed to ioremap register memory region\n");
797        ret = -EBUSY;
798        goto err_put_lpclk;
799    }
800
801    platform_set_drvdata(pdev, jzfb);
802
803    fb_videomode_to_modelist(pdata->modes, pdata->num_modes,
804                 &fb->modelist);
805    fb->mode = pdata->modes;
806
807    fb_videomode_to_var(&fb->var, fb->mode);
808    fb->var.bits_per_pixel = pdata->bpp;
809    jzfb_check_var(&fb->var, fb);
810
811    ret = jzfb_alloc_devmem(jzfb);
812    if (ret) {
813        dev_err(&pdev->dev, "Failed to allocate video memory\n");
814        goto err_iounmap;
815    }
816
817    fb->fix = jzfb_fix;
818    fb->fix.line_length = fb->var.bits_per_pixel * fb->var.xres / 8;
819    fb->fix.mmio_start = mem->start;
820    fb->fix.mmio_len = resource_size(mem);
821    fb->fix.smem_start = jzfb->vidmem_phys;
822    fb->fix.smem_len = fb->fix.line_length * fb->var.yres_virtual;
823    fb->screen_base = jzfb->vidmem;
824    fb->pseudo_palette = jzfb->pseudo_palette;
825
826    fb_alloc_cmap(&fb->cmap, 256, 0);
827
828    mutex_init(&jzfb->lock);
829
830    clk_enable(jzfb->ldclk);
831    jzfb->is_enabled = 1;
832
833    writel(JZ_LCD_CFG_SLCD, jzfb->base + JZ_REG_LCD_CFG);
834    writeb(0, jzfb->base + JZ_REG_SLCD_CTRL);
835
836    jzfb_set_par(fb);
837
838    jz_gpio_bulk_request(jz_slcd_ctrl_pins, jzfb_num_ctrl_pins(jzfb));
839    if (jzfb->pdata->lcd_type & (1 << 6)) {
840        /* serial */
841        jz_gpio_bulk_request(&jz_slcd_data_pins[15], 1);
842    } else {
843        /* parallel */
844        jz_gpio_bulk_request(jz_slcd_data_pins,
845                     jzfb_num_data_pins(jzfb));
846    }
847
848    jzfb->panel = jz_slcd_panels_probe(jzfb);
849    if (!jzfb->panel) {
850        dev_err(&pdev->dev, "Failed to find panel driver\n");
851        ret = -ENOENT;
852        goto err_free_devmem;
853    }
854    jzfb_disable_dma(jzfb);
855    jzfb->panel->init(jzfb);
856    jzfb->panel->enable(jzfb);
857
858    ret = register_framebuffer(fb);
859    if (ret) {
860        dev_err(&pdev->dev, "Failed to register framebuffer: %d\n", ret);
861        goto err_free_panel;
862    }
863
864    jzfb->fb = fb;
865    fb_prepare_logo(jzfb->fb, 0);
866    fb_show_logo(jzfb->fb, 0);
867
868    INIT_DELAYED_WORK(&jzfb->refresh_work, jzfb_refresh_work);
869    schedule_delayed_work(&jzfb->refresh_work, 0);
870
871    ret = device_create_file(&pdev->dev, &dev_attr_panel);
872    if (!ret)
873        return 0;
874
875    cancel_delayed_work_sync(&jzfb->refresh_work);
876err_free_panel:
877    jzfb->panel->exit(jzfb);
878err_free_devmem:
879    jzfb_free_gpio_pins(jzfb);
880
881    fb_dealloc_cmap(&fb->cmap);
882    jzfb_free_devmem(jzfb);
883err_iounmap:
884    iounmap(jzfb->base);
885err_put_lpclk:
886    clk_put(jzfb->lpclk);
887err_put_ldclk:
888    clk_put(jzfb->ldclk);
889err_free_dma:
890    jz4740_dma_free(jzfb->dma);
891err_framebuffer_release:
892    framebuffer_release(fb);
893err_release_mem_region:
894    release_mem_region(mem->start, resource_size(mem));
895    return ret;
896}
897
898static int __devexit jzfb_remove(struct platform_device *pdev)
899{
900    struct jzfb *jzfb = platform_get_drvdata(pdev);
901
902    device_remove_file(&pdev->dev, &dev_attr_panel);
903    jzfb_blank(FB_BLANK_POWERDOWN, jzfb->fb);
904
905    /* Blanking will prevent future refreshes from behind scheduled.
906       Now wait for a possible refresh in progress to finish. */
907    cancel_delayed_work_sync(&jzfb->refresh_work);
908
909    jzfb->panel->exit(jzfb);
910
911    jzfb_free_gpio_pins(jzfb);
912
913    jz4740_dma_free(jzfb->dma);
914
915    iounmap(jzfb->base);
916    release_mem_region(jzfb->mem->start, resource_size(jzfb->mem));
917
918    fb_dealloc_cmap(&jzfb->fb->cmap);
919    jzfb_free_devmem(jzfb);
920
921    platform_set_drvdata(pdev, NULL);
922
923    clk_put(jzfb->lpclk);
924    clk_put(jzfb->ldclk);
925
926    framebuffer_release(jzfb->fb);
927
928    return 0;
929}
930
931#ifdef CONFIG_PM
932
933static int jzfb_suspend(struct device *dev)
934{
935    struct jzfb *jzfb = dev_get_drvdata(dev);
936
937    console_lock();
938    fb_set_suspend(jzfb->fb, 1);
939    console_unlock();
940
941    mutex_lock(&jzfb->lock);
942    if (jzfb->is_enabled)
943        jzfb_disable(jzfb);
944    mutex_unlock(&jzfb->lock);
945
946    return 0;
947}
948
949static int jzfb_resume(struct device *dev)
950{
951    struct jzfb *jzfb = dev_get_drvdata(dev);
952    clk_enable(jzfb->ldclk);
953
954    mutex_lock(&jzfb->lock);
955    if (jzfb->is_enabled)
956        jzfb_enable(jzfb);
957    mutex_unlock(&jzfb->lock);
958
959    console_lock();
960    fb_set_suspend(jzfb->fb, 0);
961    console_unlock();
962
963    return 0;
964}
965
966static const struct dev_pm_ops jzfb_pm_ops = {
967    .suspend = jzfb_suspend,
968    .resume = jzfb_resume,
969    .poweroff = jzfb_suspend,
970    .restore = jzfb_resume,
971};
972
973#define JZFB_PM_OPS (&jzfb_pm_ops)
974
975#else
976#define JZFB_PM_OPS NULL
977#endif
978
979static struct platform_driver jzfb_driver = {
980    .probe = jzfb_probe,
981    .remove = __devexit_p(jzfb_remove),
982    .driver = {
983        .name = "jz4740-fb",
984        .pm = JZFB_PM_OPS,
985    },
986};
987
988static int __init jzfb_init(void)
989{
990    return platform_driver_register(&jzfb_driver);
991}
992module_init(jzfb_init);
993
994static void __exit jzfb_exit(void)
995{
996    platform_driver_unregister(&jzfb_driver);
997}
998module_exit(jzfb_exit);
999
1000MODULE_LICENSE("GPL");
1001MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>, Maarten ter Huurne <maarten@treewalker.org>");
1002MODULE_DESCRIPTION("JZ4740 SoC SLCD framebuffer driver");
1003MODULE_ALIAS("platform:jz4740-fb");
1004

Archive Download this file



interactive