Merge remote-tracking branch 'lsk/v3.10/topic/gator' into linux-linaro-lsk
[firefly-linux-kernel-4.4.55.git] / drivers / video / arm-hdlcd.c
1 /*
2  * drivers/video/arm-hdlcd.c
3  *
4  * Copyright (C) 2011 ARM Limited
5  *
6  * This file is subject to the terms and conditions of the GNU General Public
7  * License.  See the file COPYING in the main directory of this archive
8  * for more details.
9  *
10  *  ARM HDLCD Controller
11  */
12
13 #include <linux/module.h>
14 #include <linux/kernel.h>
15 #include <linux/errno.h>
16 #include <linux/string.h>
17 #include <linux/ctype.h>
18 #include <linux/mm.h>
19 #include <linux/delay.h>
20 #include <linux/of.h>
21 #include <linux/fb.h>
22 #include <linux/clk.h>
23 #include <linux/init.h>
24 #include <linux/interrupt.h>
25 #include <linux/ioport.h>
26 #include <linux/dma-mapping.h>
27 #include <linux/platform_device.h>
28 #include <linux/memblock.h>
29 #include <linux/arm-hdlcd.h>
30 #ifdef HDLCD_COUNT_BUFFERUNDERRUNS
31 #include <linux/proc_fs.h>
32 #include <linux/seq_file.h>
33 #endif
34
35 #include "edid.h"
36
37 #ifdef CONFIG_SERIAL_AMBA_PCU_UART
38 int get_edid(u8 *msgbuf);
39 #else
40 #endif
41
42 #define to_hdlcd_device(info)   container_of(info, struct hdlcd_device, fb)
43
44 static struct of_device_id  hdlcd_of_matches[] = {
45         { .compatible   = "arm,hdlcd" },
46         {},
47 };
48
49 /* Framebuffer size.  */
50 static unsigned long framebuffer_size;
51
52 #ifdef HDLCD_COUNT_BUFFERUNDERRUNS
53 static unsigned long buffer_underrun_events;
54 static DEFINE_SPINLOCK(hdlcd_underrun_lock);
55
56 static void hdlcd_underrun_set(unsigned long val)
57 {
58         spin_lock(&hdlcd_underrun_lock);
59         buffer_underrun_events = val;
60         spin_unlock(&hdlcd_underrun_lock);
61 }
62
63 static unsigned long hdlcd_underrun_get(void)
64 {
65         unsigned long val;
66         spin_lock(&hdlcd_underrun_lock);
67         val = buffer_underrun_events;
68         spin_unlock(&hdlcd_underrun_lock);
69         return val;
70 }
71
72 #ifdef CONFIG_PROC_FS
73 static int hdlcd_underrun_show(struct seq_file *m, void *v)
74 {
75         unsigned char underrun_string[32];
76         snprintf(underrun_string, 32, "%lu\n", hdlcd_underrun_get());
77         seq_puts(m, underrun_string);
78         return 0;
79 }
80
81 static int proc_hdlcd_underrun_open(struct inode *inode, struct file *file)
82 {
83         return single_open(file, hdlcd_underrun_show, NULL);
84 }
85
86 static const struct file_operations proc_hdlcd_underrun_operations = {
87         .open           = proc_hdlcd_underrun_open,
88         .read           = seq_read,
89         .llseek         = seq_lseek,
90         .release        = single_release,
91 };
92
93 static int hdlcd_underrun_init(void)
94 {
95         hdlcd_underrun_set(0);
96         proc_create("hdlcd_underrun", 0, NULL, &proc_hdlcd_underrun_operations);
97         return 0;
98 }
99 static void hdlcd_underrun_close(void)
100 {
101         remove_proc_entry("hdlcd_underrun", NULL);
102 }
103 #else
104 static int hdlcd_underrun_init(void) { return 0; }
105 static void hdlcd_underrun_close(void) { }
106 #endif
107 #endif
108
109 static char *fb_mode = "1680x1050-32@60\0\0\0\0\0";
110
111 static struct fb_var_screeninfo cached_var_screeninfo;
112
113 static struct fb_videomode hdlcd_default_mode = {
114         .refresh        = 60,
115         .xres           = 1680,
116         .yres           = 1050,
117         .pixclock       = 8403,
118         .left_margin    = 80,
119         .right_margin   = 48,
120         .upper_margin   = 21,
121         .lower_margin   = 3,
122         .hsync_len      = 32,
123         .vsync_len      = 6,
124         .sync           = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
125         .vmode          = FB_VMODE_NONINTERLACED
126 };
127
128 static inline void hdlcd_enable(struct hdlcd_device *hdlcd)
129 {
130         dev_dbg(hdlcd->dev, "HDLCD: output enabled\n");
131         writel(1, hdlcd->base + HDLCD_REG_COMMAND);
132 }
133
134 static inline void hdlcd_disable(struct hdlcd_device *hdlcd)
135 {
136         dev_dbg(hdlcd->dev, "HDLCD: output disabled\n");
137         writel(0, hdlcd->base + HDLCD_REG_COMMAND);
138 }
139
140 static int hdlcd_set_bitfields(struct hdlcd_device *hdlcd,
141                                 struct fb_var_screeninfo *var)
142 {
143         int ret = 0;
144
145         memset(&var->transp, 0, sizeof(var->transp));
146         var->red.msb_right = 0;
147         var->green.msb_right = 0;
148         var->blue.msb_right = 0;
149         var->blue.offset = 0;
150
151         switch (var->bits_per_pixel) {
152         case 8:
153                 /* pseudocolor */
154                 var->red.length = 8;
155                 var->green.length = 8;
156                 var->blue.length = 8;
157                 break;
158         case 16:
159                 /* 565 format */
160                 var->red.length = 5;
161                 var->green.length = 6;
162                 var->blue.length = 5;
163                 break;
164         case 32:
165                 var->transp.length = 8;
166         case 24:
167                 var->red.length = 8;
168                 var->green.length = 8;
169                 var->blue.length = 8;
170                 break;
171         default:
172                 ret = -EINVAL;
173                 break;
174         }
175
176         if (!ret) {
177                 if(var->bits_per_pixel != 32)
178                 {
179                         var->green.offset = var->blue.length;
180                         var->red.offset = var->green.offset + var->green.length;
181                 }
182                 else
183                 {
184                         /* Previously, the byte ordering for 32-bit color was
185                          * (msb)<alpha><red><green><blue>(lsb)
186                          * but this does not match what android expects and
187                          * the colors are odd. Instead, use
188                          * <alpha><blue><green><red>
189                          * Since we tell fb what we are doing, console
190                          * , X and directfb access should work fine.
191                          */
192                         var->green.offset = var->red.length;
193                         var->blue.offset = var->green.offset + var->green.length;
194                         var->transp.offset = var->blue.offset + var->blue.length;
195                 }
196         }
197
198         return ret;
199 }
200
201 static int hdlcd_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
202 {
203         struct hdlcd_device *hdlcd = to_hdlcd_device(info);
204         int bytes_per_pixel = var->bits_per_pixel / 8;
205
206 #ifdef HDLCD_NO_VIRTUAL_SCREEN
207         var->yres_virtual = var->yres;
208 #else
209         var->yres_virtual = 2 * var->yres;
210 #endif
211
212         if ((var->xres_virtual * bytes_per_pixel * var->yres_virtual) > hdlcd->fb.fix.smem_len)
213                 return -ENOMEM;
214
215         if (var->xres > HDLCD_MAX_XRES || var->yres > HDLCD_MAX_YRES)
216                 return -EINVAL;
217
218         /* make sure the bitfields are set appropriately */
219         return hdlcd_set_bitfields(hdlcd, var);
220 }
221
222 /* prototype */
223 static int hdlcd_pan_display(struct fb_var_screeninfo *var,
224         struct fb_info *info);
225
226 #define WRITE_HDLCD_REG(reg, value)     writel((value), hdlcd->base + (reg))
227 #define READ_HDLCD_REG(reg)             readl(hdlcd->base + (reg))
228
229 static int hdlcd_set_par(struct fb_info *info)
230 {
231         struct hdlcd_device *hdlcd = to_hdlcd_device(info);
232         int bytes_per_pixel = hdlcd->fb.var.bits_per_pixel / 8;
233         int polarities;
234         int old_yoffset;
235
236         /* check for shortcuts */
237         old_yoffset = cached_var_screeninfo.yoffset;
238         cached_var_screeninfo.yoffset = info->var.yoffset;
239         if (!memcmp(&info->var, &cached_var_screeninfo,
240                                 sizeof(struct fb_var_screeninfo))) {
241                 if(old_yoffset != info->var.yoffset) {
242                         /* we only changed yoffset, and we already
243                          * already recorded it a couple lines up
244                          */
245                         hdlcd_pan_display(&info->var, info);
246                 }
247                 /* or no change */
248                 return 0;
249         }
250
251         hdlcd->fb.fix.line_length = hdlcd->fb.var.xres * bytes_per_pixel;
252
253         if (hdlcd->fb.var.bits_per_pixel >= 16)
254                 hdlcd->fb.fix.visual = FB_VISUAL_TRUECOLOR;
255         else
256                 hdlcd->fb.fix.visual = FB_VISUAL_PSEUDOCOLOR;
257
258         memcpy(&cached_var_screeninfo, &info->var, sizeof(struct fb_var_screeninfo));
259
260         polarities = HDLCD_POLARITY_DATAEN |
261 #ifndef CONFIG_ARCH_TUSCAN
262                 HDLCD_POLARITY_PIXELCLK |
263 #endif
264                 HDLCD_POLARITY_DATA;
265         polarities |= (hdlcd->fb.var.sync & FB_SYNC_HOR_HIGH_ACT) ? HDLCD_POLARITY_HSYNC : 0;
266         polarities |= (hdlcd->fb.var.sync & FB_SYNC_VERT_HIGH_ACT) ? HDLCD_POLARITY_VSYNC : 0;
267
268         hdlcd_disable(hdlcd);
269
270         WRITE_HDLCD_REG(HDLCD_REG_FB_LINE_LENGTH, hdlcd->fb.var.xres * bytes_per_pixel);
271         WRITE_HDLCD_REG(HDLCD_REG_FB_LINE_PITCH, hdlcd->fb.var.xres * bytes_per_pixel);
272         WRITE_HDLCD_REG(HDLCD_REG_FB_LINE_COUNT, hdlcd->fb.var.yres - 1);
273         WRITE_HDLCD_REG(HDLCD_REG_V_SYNC, hdlcd->fb.var.vsync_len - 1);
274         WRITE_HDLCD_REG(HDLCD_REG_V_BACK_PORCH, hdlcd->fb.var.upper_margin - 1);
275         WRITE_HDLCD_REG(HDLCD_REG_V_DATA, hdlcd->fb.var.yres - 1);
276         WRITE_HDLCD_REG(HDLCD_REG_V_FRONT_PORCH, hdlcd->fb.var.lower_margin - 1);
277         WRITE_HDLCD_REG(HDLCD_REG_H_SYNC, hdlcd->fb.var.hsync_len - 1);
278         WRITE_HDLCD_REG(HDLCD_REG_H_BACK_PORCH, hdlcd->fb.var.left_margin - 1);
279         WRITE_HDLCD_REG(HDLCD_REG_H_DATA, hdlcd->fb.var.xres - 1);
280         WRITE_HDLCD_REG(HDLCD_REG_H_FRONT_PORCH, hdlcd->fb.var.right_margin - 1);
281         WRITE_HDLCD_REG(HDLCD_REG_POLARITIES, polarities);
282         WRITE_HDLCD_REG(HDLCD_REG_PIXEL_FORMAT, (bytes_per_pixel - 1) << 3);
283 #ifdef HDLCD_RED_DEFAULT_COLOUR
284         WRITE_HDLCD_REG(HDLCD_REG_RED_SELECT, (0x00ff0000 | (hdlcd->fb.var.red.length & 0xf) << 8) \
285                                                                                                           | hdlcd->fb.var.red.offset);
286 #else
287         WRITE_HDLCD_REG(HDLCD_REG_RED_SELECT, ((hdlcd->fb.var.red.length & 0xf) << 8) | hdlcd->fb.var.red.offset);
288 #endif
289         WRITE_HDLCD_REG(HDLCD_REG_GREEN_SELECT, ((hdlcd->fb.var.green.length & 0xf) << 8) | hdlcd->fb.var.green.offset);
290         WRITE_HDLCD_REG(HDLCD_REG_BLUE_SELECT, ((hdlcd->fb.var.blue.length & 0xf) << 8) | hdlcd->fb.var.blue.offset);
291
292         clk_set_rate(hdlcd->clk, (1000000000 / hdlcd->fb.var.pixclock) * 1000);
293         clk_enable(hdlcd->clk);
294
295         hdlcd_enable(hdlcd);
296
297         return 0;
298 }
299
300 static int hdlcd_setcolreg(unsigned int regno, unsigned int red, unsigned int green,
301                 unsigned int blue, unsigned int transp, struct fb_info *info)
302 {
303         if (regno < 16) {
304                 u32 *pal = info->pseudo_palette;
305
306                 pal[regno] = ((red >> 8) << info->var.red.offset) |
307                         ((green >> 8) << info->var.green.offset) |
308                         ((blue >> 8) << info->var.blue.offset);
309         }
310
311         return 0;
312 }
313
314 static irqreturn_t hdlcd_irq(int irq, void *data)
315 {
316         struct hdlcd_device *hdlcd = data;
317         unsigned long irq_mask, irq_status;
318
319         irq_mask = READ_HDLCD_REG(HDLCD_REG_INT_MASK);
320         irq_status = READ_HDLCD_REG(HDLCD_REG_INT_STATUS);
321
322         /* acknowledge interrupt(s) */
323         WRITE_HDLCD_REG(HDLCD_REG_INT_CLEAR, irq_status);
324 #ifdef HDLCD_COUNT_BUFFERUNDERRUNS
325         if (irq_status & HDLCD_INTERRUPT_UNDERRUN) {
326                 /* increment the count */
327                 hdlcd_underrun_set(hdlcd_underrun_get() + 1);
328         }
329 #endif
330         if (irq_status & HDLCD_INTERRUPT_VSYNC) {
331                 /* disable future VSYNC interrupts */
332                 WRITE_HDLCD_REG(HDLCD_REG_INT_MASK, irq_mask & ~HDLCD_INTERRUPT_VSYNC);
333
334                 complete(&hdlcd->vsync_completion);
335         }
336
337         return IRQ_HANDLED;
338 }
339
340 static int hdlcd_wait_for_vsync(struct fb_info *info)
341 {
342         struct hdlcd_device *hdlcd = to_hdlcd_device(info);
343         unsigned long irq_mask;
344         int err;
345
346         /* enable VSYNC interrupt */
347         irq_mask = READ_HDLCD_REG(HDLCD_REG_INT_MASK);
348         WRITE_HDLCD_REG(HDLCD_REG_INT_MASK, irq_mask | HDLCD_INTERRUPT_VSYNC);
349
350         err = wait_for_completion_interruptible_timeout(&hdlcd->vsync_completion,
351                                                         msecs_to_jiffies(100));
352
353         if (!err)
354                 return -ETIMEDOUT;
355
356         return 0;
357 }
358
359 static int hdlcd_blank(int blank_mode, struct fb_info *info)
360 {
361         struct hdlcd_device *hdlcd = to_hdlcd_device(info);
362
363         switch (blank_mode) {
364         case FB_BLANK_POWERDOWN:
365                 clk_disable(hdlcd->clk);
366         case FB_BLANK_NORMAL:
367                 hdlcd_disable(hdlcd);
368                 break;
369         case FB_BLANK_UNBLANK:
370                 clk_enable(hdlcd->clk);
371                 hdlcd_enable(hdlcd);
372                 break;
373         case FB_BLANK_VSYNC_SUSPEND:
374         case FB_BLANK_HSYNC_SUSPEND:
375         default:
376                 return 1;
377         }
378
379         return 0;
380 }
381
382 static void hdlcd_mmap_open(struct vm_area_struct *vma)
383 {
384 }
385
386 static void hdlcd_mmap_close(struct vm_area_struct *vma)
387 {
388 }
389
390 static struct vm_operations_struct hdlcd_mmap_ops = {
391         .open   = hdlcd_mmap_open,
392         .close  = hdlcd_mmap_close,
393 };
394
395 static int hdlcd_mmap(struct fb_info *info, struct vm_area_struct *vma)
396 {
397         struct hdlcd_device *hdlcd = to_hdlcd_device(info);
398         unsigned long off;
399         unsigned long start;
400         unsigned long len = hdlcd->fb.fix.smem_len;
401
402         if (vma->vm_end - vma->vm_start == 0)
403                 return 0;
404         if (vma->vm_pgoff > (~0UL >> PAGE_SHIFT))
405                 return -EINVAL;
406
407         off = vma->vm_pgoff << PAGE_SHIFT;
408         if ((off >= len) || (vma->vm_end - vma->vm_start + off) > len)
409                 return -EINVAL;
410
411         start = hdlcd->fb.fix.smem_start;
412         off += start;
413
414         vma->vm_pgoff = off >> PAGE_SHIFT;
415         vma->vm_flags |= VM_IO;
416         vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
417         vma->vm_ops = &hdlcd_mmap_ops;
418         if (io_remap_pfn_range(vma, vma->vm_start, off >> PAGE_SHIFT,
419                                 vma->vm_end - vma->vm_start,
420                                 vma->vm_page_prot))
421                 return -EAGAIN;
422
423         return 0;
424 }
425
426 static int hdlcd_pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
427 {
428         struct hdlcd_device *hdlcd = to_hdlcd_device(info);
429
430         hdlcd->fb.var.yoffset = var->yoffset;
431         WRITE_HDLCD_REG(HDLCD_REG_FB_BASE, hdlcd->fb.fix.smem_start +
432                         (var->yoffset * hdlcd->fb.fix.line_length));
433
434         hdlcd_wait_for_vsync(info);
435
436         return 0;
437 }
438
439 static int hdlcd_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg)
440 {
441         int err;
442
443         switch (cmd) {
444         case FBIO_WAITFORVSYNC:
445                 err = hdlcd_wait_for_vsync(info);
446                 break;
447         default:
448                 err = -ENOIOCTLCMD;
449                 break;
450         }
451
452         return err;
453 }
454
455 static struct fb_ops hdlcd_ops = {
456         .owner                  = THIS_MODULE,
457         .fb_check_var           = hdlcd_check_var,
458         .fb_set_par             = hdlcd_set_par,
459         .fb_setcolreg           = hdlcd_setcolreg,
460         .fb_blank               = hdlcd_blank,
461         .fb_fillrect            = cfb_fillrect,
462         .fb_copyarea            = cfb_copyarea,
463         .fb_imageblit           = cfb_imageblit,
464         .fb_mmap                = hdlcd_mmap,
465         .fb_pan_display         = hdlcd_pan_display,
466         .fb_ioctl               = hdlcd_ioctl,
467         .fb_compat_ioctl        = hdlcd_ioctl
468 };
469
470 static int hdlcd_setup(struct hdlcd_device *hdlcd)
471 {
472         u32 version;
473         int err = -EFAULT;
474
475         hdlcd->fb.device = hdlcd->dev;
476
477         hdlcd->clk = clk_get(hdlcd->dev, NULL);
478         if (IS_ERR(hdlcd->clk)) {
479                 dev_err(hdlcd->dev, "HDLCD: unable to find clock data\n");
480                 return PTR_ERR(hdlcd->clk);
481         }
482
483         err = clk_prepare(hdlcd->clk);
484         if (err)
485                 goto clk_prepare_err;
486
487         hdlcd->base = ioremap_nocache(hdlcd->fb.fix.mmio_start, hdlcd->fb.fix.mmio_len);
488         if (!hdlcd->base) {
489                 dev_err(hdlcd->dev, "HDLCD: unable to map registers\n");
490                 goto remap_err;
491         }
492
493         hdlcd->fb.pseudo_palette = kmalloc(sizeof(u32) * 16, GFP_KERNEL);
494         if (!hdlcd->fb.pseudo_palette) {
495                 dev_err(hdlcd->dev, "HDLCD: unable to allocate pseudo_palette memory\n");
496                 err = -ENOMEM;
497                 goto kmalloc_err;
498         }
499
500         version = readl(hdlcd->base + HDLCD_REG_VERSION);
501         if ((version & HDLCD_PRODUCT_MASK) != HDLCD_PRODUCT_ID) {
502                 dev_err(hdlcd->dev, "HDLCD: unknown product id: 0x%x\n", version);
503                 err = -EINVAL;
504                 goto kmalloc_err;
505         }
506         dev_info(hdlcd->dev, "HDLCD: found ARM HDLCD version r%dp%d\n",
507                 (version & HDLCD_VERSION_MAJOR_MASK) >> 8,
508                 version & HDLCD_VERSION_MINOR_MASK);
509
510         strcpy(hdlcd->fb.fix.id, "hdlcd");
511         hdlcd->fb.fbops                 = &hdlcd_ops;
512         hdlcd->fb.flags                 = FBINFO_FLAG_DEFAULT/* | FBINFO_VIRTFB*/;
513
514         hdlcd->fb.fix.type              = FB_TYPE_PACKED_PIXELS;
515         hdlcd->fb.fix.type_aux          = 0;
516         hdlcd->fb.fix.xpanstep          = 0;
517         hdlcd->fb.fix.ypanstep          = 1;
518         hdlcd->fb.fix.ywrapstep         = 0;
519         hdlcd->fb.fix.accel             = FB_ACCEL_NONE;
520
521         hdlcd->fb.var.nonstd            = 0;
522         hdlcd->fb.var.activate          = FB_ACTIVATE_NOW;
523         hdlcd->fb.var.height            = -1;
524         hdlcd->fb.var.width             = -1;
525         hdlcd->fb.var.accel_flags       = 0;
526
527         init_completion(&hdlcd->vsync_completion);
528
529         if (hdlcd->edid) {
530                 /* build modedb from EDID */
531                 fb_edid_to_monspecs(hdlcd->edid, &hdlcd->fb.monspecs);
532                 fb_videomode_to_modelist(hdlcd->fb.monspecs.modedb,
533                                         hdlcd->fb.monspecs.modedb_len,
534                                         &hdlcd->fb.modelist);
535                 fb_find_mode(&hdlcd->fb.var, &hdlcd->fb, fb_mode,
536                         hdlcd->fb.monspecs.modedb,
537                         hdlcd->fb.monspecs.modedb_len,
538                         &hdlcd_default_mode, 32);
539         } else {
540                 hdlcd->fb.monspecs.hfmin        = 0;
541                 hdlcd->fb.monspecs.hfmax        = 100000;
542                 hdlcd->fb.monspecs.vfmin        = 0;
543                 hdlcd->fb.monspecs.vfmax        = 400;
544                 hdlcd->fb.monspecs.dclkmin      = 1000000;
545                 hdlcd->fb.monspecs.dclkmax      = 100000000;
546                 fb_find_mode(&hdlcd->fb.var, &hdlcd->fb, fb_mode, NULL, 0, &hdlcd_default_mode, 32);
547         }
548
549         dev_info(hdlcd->dev, "using %dx%d-%d@%d mode\n", hdlcd->fb.var.xres,
550                 hdlcd->fb.var.yres, hdlcd->fb.var.bits_per_pixel,
551                 hdlcd->fb.mode ? hdlcd->fb.mode->refresh : 60);
552         hdlcd->fb.var.xres_virtual      = hdlcd->fb.var.xres;
553 #ifdef HDLCD_NO_VIRTUAL_SCREEN
554         hdlcd->fb.var.yres_virtual      = hdlcd->fb.var.yres;
555 #else
556         hdlcd->fb.var.yres_virtual      = hdlcd->fb.var.yres * 2;
557 #endif
558
559         /* initialise and set the palette */
560         if (fb_alloc_cmap(&hdlcd->fb.cmap, NR_PALETTE, 0)) {
561                 dev_err(hdlcd->dev, "failed to allocate cmap memory\n");
562                 err = -ENOMEM;
563                 goto setup_err;
564         }
565         fb_set_cmap(&hdlcd->fb.cmap, &hdlcd->fb);
566
567         /* Allow max number of outstanding requests with the largest beat burst */
568         WRITE_HDLCD_REG(HDLCD_REG_BUS_OPTIONS, HDLCD_BUS_MAX_OUTSTAND | HDLCD_BUS_BURST_16);
569         /* Set the framebuffer base to start of allocated memory */
570         WRITE_HDLCD_REG(HDLCD_REG_FB_BASE, hdlcd->fb.fix.smem_start);
571 #ifdef HDLCD_COUNT_BUFFERUNDERRUNS
572         /* turn on underrun interrupt for counting */
573         WRITE_HDLCD_REG(HDLCD_REG_INT_MASK, HDLCD_INTERRUPT_UNDERRUN);
574 #else
575         /* Ensure interrupts are disabled */
576         WRITE_HDLCD_REG(HDLCD_REG_INT_MASK, 0);
577 #endif  
578         fb_set_var(&hdlcd->fb, &hdlcd->fb.var);
579
580         if (!register_framebuffer(&hdlcd->fb)) {
581                 return 0;
582         }
583
584         dev_err(hdlcd->dev, "HDLCD: cannot register framebuffer\n");
585
586         fb_dealloc_cmap(&hdlcd->fb.cmap);
587 setup_err:
588         iounmap(hdlcd->base);
589 kmalloc_err:
590         kfree(hdlcd->fb.pseudo_palette);
591 remap_err:
592         clk_unprepare(hdlcd->clk);
593 clk_prepare_err:
594         clk_put(hdlcd->clk);
595         return err;
596 }
597
598 static inline unsigned char atohex(u8 data)
599 {
600         if (!isxdigit(data))
601                 return 0;
602         /* truncate the upper nibble and add 9 to non-digit values */
603         return (data > 0x39) ? ((data & 0xf) + 9) : (data & 0xf);
604 }
605
606 /* EDID data is passed from devicetree in a literal string that can contain spaces and
607    the hexadecimal dump of the data */
608 static int parse_edid_data(struct hdlcd_device *hdlcd, const u8 *edid_data, int data_len)
609 {
610         int i, j;
611
612         if (!edid_data)
613                 return -EINVAL;
614
615         hdlcd->edid = kzalloc(EDID_LENGTH, GFP_KERNEL);
616         if (!hdlcd->edid)
617                 return -ENOMEM;
618
619         for (i = 0, j = 0; i < data_len; i++) {
620                 if (isspace(edid_data[i]))
621                         continue;
622                 hdlcd->edid[j++] = atohex(edid_data[i]);
623                 if (j >= EDID_LENGTH)
624                         break;
625         }
626
627         if (j < EDID_LENGTH) {
628                 kfree(hdlcd->edid);
629                 hdlcd->edid = NULL;
630                 return -EINVAL;
631         }
632
633         return 0;
634 }
635
636 static int hdlcd_probe(struct platform_device *pdev)
637 {
638         int err = 0, i;
639         struct hdlcd_device *hdlcd;
640         struct resource *mem;
641 #ifdef CONFIG_OF
642         struct device_node *of_node;
643 #endif
644
645         memset(&cached_var_screeninfo, 0, sizeof(struct fb_var_screeninfo));
646
647         dev_dbg(&pdev->dev, "HDLCD: probing\n");
648
649         hdlcd = kzalloc(sizeof(*hdlcd), GFP_KERNEL);
650         if (!hdlcd)
651                 return -ENOMEM;
652
653 #ifdef CONFIG_OF
654         of_node = pdev->dev.of_node;
655         if (of_node) {
656                 int len;
657                 const u8 *edid;
658                 const __be32 *prop = of_get_property(of_node, "mode", &len);
659                 if (prop)
660                         strncpy(fb_mode, (char *)prop, len);
661                 prop = of_get_property(of_node, "framebuffer", &len);
662                 if (prop) {
663                         hdlcd->fb.fix.smem_start = of_read_ulong(prop,
664                                         of_n_addr_cells(of_node));
665                         prop += of_n_addr_cells(of_node);
666                         framebuffer_size = of_read_ulong(prop,
667                                         of_n_size_cells(of_node));
668                         if (framebuffer_size > HDLCD_MAX_FRAMEBUFFER_SIZE)
669                                 framebuffer_size = HDLCD_MAX_FRAMEBUFFER_SIZE;
670                         dev_dbg(&pdev->dev, "HDLCD: phys_addr = 0x%lx, size = 0x%lx\n",
671                                 hdlcd->fb.fix.smem_start, framebuffer_size);
672                 }
673                 edid = of_get_property(of_node, "edid", &len);
674                 if (edid) {
675                         err = parse_edid_data(hdlcd, edid, len);
676 #ifdef CONFIG_SERIAL_AMBA_PCU_UART
677                 } else {
678                         /* ask the firmware to fetch the EDID */
679                         dev_dbg(&pdev->dev, "HDLCD: Requesting EDID data\n");
680                         hdlcd->edid = kzalloc(EDID_LENGTH, GFP_KERNEL);
681                         if (!hdlcd->edid)
682                                 return -ENOMEM;
683                         err = get_edid(hdlcd->edid);
684 #endif /* CONFIG_SERIAL_AMBA_PCU_UART */
685                 }
686                 if (err)
687                         dev_info(&pdev->dev, "HDLCD: Failed to parse EDID data\n");
688         }
689 #endif /* CONFIG_OF */
690
691         mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
692         if (!mem) {
693                 dev_err(&pdev->dev, "HDLCD: cannot get platform resources\n");
694                 err = -EINVAL;
695                 goto resource_err;
696         }
697
698         i = platform_get_irq(pdev, 0);
699         if (i < 0) {
700                 dev_err(&pdev->dev, "HDLCD: no irq defined for vsync\n");
701                 err = -ENOENT;
702                 goto resource_err;
703         } else {
704                 err = request_irq(i, hdlcd_irq, 0, dev_name(&pdev->dev), hdlcd);
705                 if (err) {
706                         dev_err(&pdev->dev, "HDLCD: unable to request irq\n");
707                         goto resource_err;
708                 }
709                 hdlcd->irq = i;
710         }
711
712         if (!request_mem_region(mem->start, resource_size(mem), dev_name(&pdev->dev))) {
713                 err = -ENXIO;
714                 goto request_err;
715         }
716
717         if (!hdlcd->fb.fix.smem_start) {
718                 dev_err(&pdev->dev, "platform did not allocate frame buffer memory\n");
719                 err = -ENOMEM;
720                 goto memalloc_err;
721         }
722         hdlcd->fb.screen_base = ioremap_wc(hdlcd->fb.fix.smem_start, framebuffer_size);
723         if (!hdlcd->fb.screen_base) {
724                 dev_err(&pdev->dev, "unable to ioremap framebuffer\n");
725                 err = -ENOMEM;
726                 goto probe_err;
727         }
728
729         hdlcd->fb.screen_size = framebuffer_size;
730         hdlcd->fb.fix.smem_len = framebuffer_size;
731         hdlcd->fb.fix.mmio_start = mem->start;
732         hdlcd->fb.fix.mmio_len = resource_size(mem);
733
734         /* Clear the framebuffer */
735         memset(hdlcd->fb.screen_base, 0, framebuffer_size);
736
737         hdlcd->dev = &pdev->dev;
738
739         dev_dbg(&pdev->dev, "HDLCD: framebuffer virt base %p, phys base 0x%lX\n",
740                 hdlcd->fb.screen_base, (unsigned long)hdlcd->fb.fix.smem_start);
741
742         err = hdlcd_setup(hdlcd);
743
744         if (err)
745                 goto probe_err;
746
747         platform_set_drvdata(pdev, hdlcd);
748         return 0;
749
750 probe_err:
751         iounmap(hdlcd->fb.screen_base);
752         memblock_free(hdlcd->fb.fix.smem_start, hdlcd->fb.fix.smem_start);
753
754 memalloc_err:
755         release_mem_region(mem->start, resource_size(mem));
756
757 request_err:
758         free_irq(hdlcd->irq, hdlcd);
759
760 resource_err:
761         kfree(hdlcd);
762
763         return err;
764 }
765
766 static int hdlcd_remove(struct platform_device *pdev)
767 {
768         struct hdlcd_device *hdlcd = platform_get_drvdata(pdev);
769
770         clk_disable(hdlcd->clk);
771         clk_unprepare(hdlcd->clk);
772         clk_put(hdlcd->clk);
773
774         /* unmap memory */
775         iounmap(hdlcd->fb.screen_base);
776         iounmap(hdlcd->base);
777
778         /* deallocate fb memory */
779         fb_dealloc_cmap(&hdlcd->fb.cmap);
780         kfree(hdlcd->fb.pseudo_palette);
781         memblock_free(hdlcd->fb.fix.smem_start, hdlcd->fb.fix.smem_start);
782         release_mem_region(hdlcd->fb.fix.mmio_start, hdlcd->fb.fix.mmio_len);
783
784         free_irq(hdlcd->irq, NULL);
785         kfree(hdlcd);
786
787         return 0;
788 }
789
790 #ifdef CONFIG_PM
791 static int hdlcd_suspend(struct platform_device *pdev, pm_message_t state)
792 {
793         /* not implemented yet */
794         return 0;
795 }
796
797 static int hdlcd_resume(struct platform_device *pdev)
798 {
799         /* not implemented yet */
800         return 0;
801 }
802 #else
803 #define hdlcd_suspend   NULL
804 #define hdlcd_resume    NULL
805 #endif
806
807 static struct platform_driver hdlcd_driver = {
808         .probe          = hdlcd_probe,
809         .remove         = hdlcd_remove,
810         .suspend        = hdlcd_suspend,
811         .resume         = hdlcd_resume,
812         .driver = {
813                 .name           = "hdlcd",
814                 .owner          = THIS_MODULE,
815                 .of_match_table = hdlcd_of_matches,
816         },
817 };
818
819 static int __init hdlcd_init(void)
820 {
821 #ifdef HDLCD_COUNT_BUFFERUNDERRUNS
822         int err = platform_driver_register(&hdlcd_driver);
823         if (!err)
824                 hdlcd_underrun_init();
825         return err;
826 #else
827         return platform_driver_register(&hdlcd_driver);
828 #endif
829 }
830
831 void __exit hdlcd_exit(void)
832 {
833 #ifdef HDLCD_COUNT_BUFFERUNDERRUNS
834         hdlcd_underrun_close();
835 #endif
836         platform_driver_unregister(&hdlcd_driver);
837 }
838
839 module_init(hdlcd_init);
840 module_exit(hdlcd_exit);
841
842 MODULE_AUTHOR("Liviu Dudau");
843 MODULE_DESCRIPTION("ARM HDLCD core driver");
844 MODULE_LICENSE("GPL v2");