Root/drivers/video/jz4740_slcd_fb.c

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

Archive Download this file



interactive