2 * drivers/video/arm-hdlcd.c
4 * Copyright (C) 2011 ARM Limited
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
10 * ARM HDLCD Controller
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>
19 #include <linux/delay.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>
37 #ifdef CONFIG_SERIAL_AMBA_PCU_UART
38 int get_edid(u8 *msgbuf);
42 #define to_hdlcd_device(info) container_of(info, struct hdlcd_device, fb)
44 static struct of_device_id hdlcd_of_matches[] = {
45 { .compatible = "arm,hdlcd" },
49 /* Framebuffer size. */
50 static unsigned long framebuffer_size;
52 #ifdef HDLCD_COUNT_BUFFERUNDERRUNS
53 static unsigned long buffer_underrun_events;
54 static DEFINE_SPINLOCK(hdlcd_underrun_lock);
56 static void hdlcd_underrun_set(unsigned long val)
58 spin_lock(&hdlcd_underrun_lock);
59 buffer_underrun_events = val;
60 spin_unlock(&hdlcd_underrun_lock);
63 static unsigned long hdlcd_underrun_get(void)
66 spin_lock(&hdlcd_underrun_lock);
67 val = buffer_underrun_events;
68 spin_unlock(&hdlcd_underrun_lock);
73 static int hdlcd_underrun_show(struct seq_file *m, void *v)
75 unsigned char underrun_string[32];
76 snprintf(underrun_string, 32, "%lu\n", hdlcd_underrun_get());
77 seq_puts(m, underrun_string);
81 static int proc_hdlcd_underrun_open(struct inode *inode, struct file *file)
83 return single_open(file, hdlcd_underrun_show, NULL);
86 static const struct file_operations proc_hdlcd_underrun_operations = {
87 .open = proc_hdlcd_underrun_open,
90 .release = single_release,
93 static int hdlcd_underrun_init(void)
95 hdlcd_underrun_set(0);
96 proc_create("hdlcd_underrun", 0, NULL, &proc_hdlcd_underrun_operations);
99 static void hdlcd_underrun_close(void)
101 remove_proc_entry("hdlcd_underrun", NULL);
104 static int hdlcd_underrun_init(void) { return 0; }
105 static void hdlcd_underrun_close(void) { }
109 static char *fb_mode = "1680x1050-32@60\0\0\0\0\0";
111 static struct fb_var_screeninfo cached_var_screeninfo;
113 static struct fb_videomode hdlcd_default_mode = {
124 .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
125 .vmode = FB_VMODE_NONINTERLACED
128 static inline void hdlcd_enable(struct hdlcd_device *hdlcd)
130 dev_dbg(hdlcd->dev, "HDLCD: output enabled\n");
131 writel(1, hdlcd->base + HDLCD_REG_COMMAND);
134 static inline void hdlcd_disable(struct hdlcd_device *hdlcd)
136 dev_dbg(hdlcd->dev, "HDLCD: output disabled\n");
137 writel(0, hdlcd->base + HDLCD_REG_COMMAND);
140 static int hdlcd_set_bitfields(struct hdlcd_device *hdlcd,
141 struct fb_var_screeninfo *var)
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;
151 switch (var->bits_per_pixel) {
155 var->green.length = 8;
156 var->blue.length = 8;
161 var->green.length = 6;
162 var->blue.length = 5;
165 var->transp.length = 8;
168 var->green.length = 8;
169 var->blue.length = 8;
177 if(var->bits_per_pixel != 32)
179 var->green.offset = var->blue.length;
180 var->red.offset = var->green.offset + var->green.length;
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.
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;
201 static int hdlcd_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
203 struct hdlcd_device *hdlcd = to_hdlcd_device(info);
204 int bytes_per_pixel = var->bits_per_pixel / 8;
206 #ifdef HDLCD_NO_VIRTUAL_SCREEN
207 var->yres_virtual = var->yres;
209 var->yres_virtual = 2 * var->yres;
212 if ((var->xres_virtual * bytes_per_pixel * var->yres_virtual) > hdlcd->fb.fix.smem_len)
215 if (var->xres > HDLCD_MAX_XRES || var->yres > HDLCD_MAX_YRES)
218 /* make sure the bitfields are set appropriately */
219 return hdlcd_set_bitfields(hdlcd, var);
223 static int hdlcd_pan_display(struct fb_var_screeninfo *var,
224 struct fb_info *info);
226 #define WRITE_HDLCD_REG(reg, value) writel((value), hdlcd->base + (reg))
227 #define READ_HDLCD_REG(reg) readl(hdlcd->base + (reg))
229 static int hdlcd_set_par(struct fb_info *info)
231 struct hdlcd_device *hdlcd = to_hdlcd_device(info);
232 int bytes_per_pixel = hdlcd->fb.var.bits_per_pixel / 8;
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
245 hdlcd_pan_display(&info->var, info);
251 hdlcd->fb.fix.line_length = hdlcd->fb.var.xres * bytes_per_pixel;
253 if (hdlcd->fb.var.bits_per_pixel >= 16)
254 hdlcd->fb.fix.visual = FB_VISUAL_TRUECOLOR;
256 hdlcd->fb.fix.visual = FB_VISUAL_PSEUDOCOLOR;
258 memcpy(&cached_var_screeninfo, &info->var, sizeof(struct fb_var_screeninfo));
260 polarities = HDLCD_POLARITY_DATAEN |
261 #ifndef CONFIG_ARCH_TUSCAN
262 HDLCD_POLARITY_PIXELCLK |
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;
268 hdlcd_disable(hdlcd);
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);
287 WRITE_HDLCD_REG(HDLCD_REG_RED_SELECT, ((hdlcd->fb.var.red.length & 0xf) << 8) | hdlcd->fb.var.red.offset);
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);
292 clk_set_rate(hdlcd->clk, (1000000000 / hdlcd->fb.var.pixclock) * 1000);
293 clk_enable(hdlcd->clk);
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)
304 u32 *pal = info->pseudo_palette;
306 pal[regno] = ((red >> 8) << info->var.red.offset) |
307 ((green >> 8) << info->var.green.offset) |
308 ((blue >> 8) << info->var.blue.offset);
314 static irqreturn_t hdlcd_irq(int irq, void *data)
316 struct hdlcd_device *hdlcd = data;
317 unsigned long irq_mask, irq_status;
319 irq_mask = READ_HDLCD_REG(HDLCD_REG_INT_MASK);
320 irq_status = READ_HDLCD_REG(HDLCD_REG_INT_STATUS);
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);
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);
334 complete(&hdlcd->vsync_completion);
340 static int hdlcd_wait_for_vsync(struct fb_info *info)
342 struct hdlcd_device *hdlcd = to_hdlcd_device(info);
343 unsigned long irq_mask;
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);
350 err = wait_for_completion_interruptible_timeout(&hdlcd->vsync_completion,
351 msecs_to_jiffies(100));
359 static int hdlcd_blank(int blank_mode, struct fb_info *info)
361 struct hdlcd_device *hdlcd = to_hdlcd_device(info);
363 switch (blank_mode) {
364 case FB_BLANK_POWERDOWN:
365 clk_disable(hdlcd->clk);
366 case FB_BLANK_NORMAL:
367 hdlcd_disable(hdlcd);
369 case FB_BLANK_UNBLANK:
370 clk_enable(hdlcd->clk);
373 case FB_BLANK_VSYNC_SUSPEND:
374 case FB_BLANK_HSYNC_SUSPEND:
382 static void hdlcd_mmap_open(struct vm_area_struct *vma)
386 static void hdlcd_mmap_close(struct vm_area_struct *vma)
390 static struct vm_operations_struct hdlcd_mmap_ops = {
391 .open = hdlcd_mmap_open,
392 .close = hdlcd_mmap_close,
395 static int hdlcd_mmap(struct fb_info *info, struct vm_area_struct *vma)
397 struct hdlcd_device *hdlcd = to_hdlcd_device(info);
400 unsigned long len = hdlcd->fb.fix.smem_len;
402 if (vma->vm_end - vma->vm_start == 0)
404 if (vma->vm_pgoff > (~0UL >> PAGE_SHIFT))
407 off = vma->vm_pgoff << PAGE_SHIFT;
408 if ((off >= len) || (vma->vm_end - vma->vm_start + off) > len)
411 start = hdlcd->fb.fix.smem_start;
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,
426 static int hdlcd_pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
428 struct hdlcd_device *hdlcd = to_hdlcd_device(info);
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));
434 hdlcd_wait_for_vsync(info);
439 static int hdlcd_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg)
444 case FBIO_WAITFORVSYNC:
445 err = hdlcd_wait_for_vsync(info);
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
470 static int hdlcd_setup(struct hdlcd_device *hdlcd)
475 hdlcd->fb.device = hdlcd->dev;
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);
483 err = clk_prepare(hdlcd->clk);
485 goto clk_prepare_err;
487 hdlcd->base = ioremap_nocache(hdlcd->fb.fix.mmio_start, hdlcd->fb.fix.mmio_len);
489 dev_err(hdlcd->dev, "HDLCD: unable to map registers\n");
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");
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);
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);
510 strcpy(hdlcd->fb.fix.id, "hdlcd");
511 hdlcd->fb.fbops = &hdlcd_ops;
512 hdlcd->fb.flags = FBINFO_FLAG_DEFAULT/* | FBINFO_VIRTFB*/;
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;
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;
527 init_completion(&hdlcd->vsync_completion);
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);
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);
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;
556 hdlcd->fb.var.yres_virtual = hdlcd->fb.var.yres * 2;
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");
565 fb_set_cmap(&hdlcd->fb.cmap, &hdlcd->fb);
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);
575 /* Ensure interrupts are disabled */
576 WRITE_HDLCD_REG(HDLCD_REG_INT_MASK, 0);
578 fb_set_var(&hdlcd->fb, &hdlcd->fb.var);
580 if (!register_framebuffer(&hdlcd->fb)) {
584 dev_err(hdlcd->dev, "HDLCD: cannot register framebuffer\n");
586 fb_dealloc_cmap(&hdlcd->fb.cmap);
588 iounmap(hdlcd->base);
590 kfree(hdlcd->fb.pseudo_palette);
592 clk_unprepare(hdlcd->clk);
598 static inline unsigned char atohex(u8 data)
602 /* truncate the upper nibble and add 9 to non-digit values */
603 return (data > 0x39) ? ((data & 0xf) + 9) : (data & 0xf);
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)
615 hdlcd->edid = kzalloc(EDID_LENGTH, GFP_KERNEL);
619 for (i = 0, j = 0; i < data_len; i++) {
620 if (isspace(edid_data[i]))
622 hdlcd->edid[j++] = atohex(edid_data[i]);
623 if (j >= EDID_LENGTH)
627 if (j < EDID_LENGTH) {
636 static int hdlcd_probe(struct platform_device *pdev)
639 struct hdlcd_device *hdlcd;
640 struct resource *mem;
642 struct device_node *of_node;
645 memset(&cached_var_screeninfo, 0, sizeof(struct fb_var_screeninfo));
647 dev_dbg(&pdev->dev, "HDLCD: probing\n");
649 hdlcd = kzalloc(sizeof(*hdlcd), GFP_KERNEL);
654 of_node = pdev->dev.of_node;
658 const __be32 *prop = of_get_property(of_node, "mode", &len);
660 strncpy(fb_mode, (char *)prop, len);
661 prop = of_get_property(of_node, "framebuffer", &len);
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);
673 edid = of_get_property(of_node, "edid", &len);
675 err = parse_edid_data(hdlcd, edid, len);
676 #ifdef CONFIG_SERIAL_AMBA_PCU_UART
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);
683 err = get_edid(hdlcd->edid);
684 #endif /* CONFIG_SERIAL_AMBA_PCU_UART */
687 dev_info(&pdev->dev, "HDLCD: Failed to parse EDID data\n");
689 #endif /* CONFIG_OF */
691 mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
693 dev_err(&pdev->dev, "HDLCD: cannot get platform resources\n");
698 i = platform_get_irq(pdev, 0);
700 dev_err(&pdev->dev, "HDLCD: no irq defined for vsync\n");
704 err = request_irq(i, hdlcd_irq, 0, dev_name(&pdev->dev), hdlcd);
706 dev_err(&pdev->dev, "HDLCD: unable to request irq\n");
712 if (!request_mem_region(mem->start, resource_size(mem), dev_name(&pdev->dev))) {
717 if (!hdlcd->fb.fix.smem_start) {
718 dev_err(&pdev->dev, "platform did not allocate frame buffer memory\n");
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");
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);
734 /* Clear the framebuffer */
735 memset(hdlcd->fb.screen_base, 0, framebuffer_size);
737 hdlcd->dev = &pdev->dev;
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);
742 err = hdlcd_setup(hdlcd);
747 platform_set_drvdata(pdev, hdlcd);
751 iounmap(hdlcd->fb.screen_base);
752 memblock_free(hdlcd->fb.fix.smem_start, hdlcd->fb.fix.smem_start);
755 release_mem_region(mem->start, resource_size(mem));
758 free_irq(hdlcd->irq, hdlcd);
766 static int hdlcd_remove(struct platform_device *pdev)
768 struct hdlcd_device *hdlcd = platform_get_drvdata(pdev);
770 clk_disable(hdlcd->clk);
771 clk_unprepare(hdlcd->clk);
775 iounmap(hdlcd->fb.screen_base);
776 iounmap(hdlcd->base);
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);
784 free_irq(hdlcd->irq, NULL);
791 static int hdlcd_suspend(struct platform_device *pdev, pm_message_t state)
793 /* not implemented yet */
797 static int hdlcd_resume(struct platform_device *pdev)
799 /* not implemented yet */
803 #define hdlcd_suspend NULL
804 #define hdlcd_resume NULL
807 static struct platform_driver hdlcd_driver = {
808 .probe = hdlcd_probe,
809 .remove = hdlcd_remove,
810 .suspend = hdlcd_suspend,
811 .resume = hdlcd_resume,
814 .owner = THIS_MODULE,
815 .of_match_table = hdlcd_of_matches,
819 static int __init hdlcd_init(void)
821 #ifdef HDLCD_COUNT_BUFFERUNDERRUNS
822 int err = platform_driver_register(&hdlcd_driver);
824 hdlcd_underrun_init();
827 return platform_driver_register(&hdlcd_driver);
831 void __exit hdlcd_exit(void)
833 #ifdef HDLCD_COUNT_BUFFERUNDERRUNS
834 hdlcd_underrun_close();
836 platform_driver_unregister(&hdlcd_driver);
839 module_init(hdlcd_init);
840 module_exit(hdlcd_exit);
842 MODULE_AUTHOR("Liviu Dudau");
843 MODULE_DESCRIPTION("ARM HDLCD core driver");
844 MODULE_LICENSE("GPL v2");