Root/drivers/video/jz4740_slcd_fb.c

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

Archive Download this file



interactive