Staging: udlfb: clean up checkpatch warnings in udlfb.c
[linux-2.6/mini2440.git] / drivers / staging / udlfb / udlfb.c
blob45b8ae7882de588dd1ac17d8586b842f2fcfabe5
1 /*****************************************************************************
2 * DLFB Kernel Driver *
3 * Version 0.2 (udlfb) *
4 * (C) 2009 Roberto De Ioris <roberto@unbit.it> *
5 * *
6 * This file is licensed under the GPLv2. See COPYING in the package. *
7 * Based on the amazing work of Florian Echtler and libdlo 0.1 *
8 * *
9 * *
10 * 31.05.09 release 0.2 *
11 * 22.05.09 First public (ugly) release *
12 *****************************************************************************/
14 #include <linux/module.h>
15 #include <linux/kernel.h>
16 #include <linux/init.h>
17 #include <linux/usb.h>
18 #include <linux/uaccess.h>
19 #include <linux/mm.h>
20 #include <linux/fb.h>
21 #include <linux/mutex.h>
23 #include "udlfb.h"
25 #define DRIVER_VERSION "DLFB 0.2"
27 /* memory functions taken from vfb */
29 static void *rvmalloc(unsigned long size)
31 void *mem;
32 unsigned long adr;
34 size = PAGE_ALIGN(size);
35 mem = vmalloc_32(size);
36 if (!mem)
37 return NULL;
39 memset(mem, 0, size); /* Clear the ram out, no junk to the user */
40 adr = (unsigned long)mem;
41 while (size > 0) {
42 SetPageReserved(vmalloc_to_page((void *)adr));
43 adr += PAGE_SIZE;
44 size -= PAGE_SIZE;
47 return mem;
50 static void rvfree(void *mem, unsigned long size)
52 unsigned long adr;
54 if (!mem)
55 return;
57 adr = (unsigned long)mem;
58 while ((long)size > 0) {
59 ClearPageReserved(vmalloc_to_page((void *)adr));
60 adr += PAGE_SIZE;
61 size -= PAGE_SIZE;
63 vfree(mem);
66 static int dlfb_mmap(struct fb_info *info, struct vm_area_struct *vma)
68 unsigned long start = vma->vm_start;
69 unsigned long size = vma->vm_end - vma->vm_start;
70 unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;
71 unsigned long page, pos;
73 printk("MMAP: %lu %u\n", offset + size, info->fix.smem_len);
75 if (offset + size > info->fix.smem_len)
76 return -EINVAL;
78 pos = (unsigned long)info->fix.smem_start + offset;
80 while (size > 0) {
81 page = vmalloc_to_pfn((void *)pos);
82 if (remap_pfn_range(vma, start, page, PAGE_SIZE, PAGE_SHARED))
83 return -EAGAIN;
85 start += PAGE_SIZE;
86 pos += PAGE_SIZE;
87 if (size > PAGE_SIZE)
88 size -= PAGE_SIZE;
89 else
90 size = 0;
93 vma->vm_flags |= VM_RESERVED; /* avoid to swap out this VMA */
94 return 0;
98 /* ioctl structure */
99 struct dloarea {
100 int x, y;
101 int w, h;
105 static struct usb_device_id id_table [] = {
106 { USB_DEVICE(0x17e9, 0x023d) },
111 static struct usb_device_id id_table[] = {
112 {.idVendor = 0x17e9, .match_flags = USB_DEVICE_ID_MATCH_VENDOR,},
115 MODULE_DEVICE_TABLE(usb, id_table);
117 static struct usb_driver dlfb_driver;
119 static int
120 image_blit(struct dlfb_data *dev_info, int x, int y, int width, int height,
121 char *data)
124 int i, j, base;
125 int rem = width;
126 int ret;
128 int diff;
130 char *bufptr;
132 if (x + width > dev_info->info->var.xres)
133 return -EINVAL;
135 if (y + height > dev_info->info->var.yres)
136 return -EINVAL;
138 mutex_lock(&dev_info->bulk_mutex);
140 base = dev_info->base16 + (dev_info->info->var.xres * 2 * y) + (x * 2);
142 data += (dev_info->info->var.xres * 2 * y) + (x * 2);
144 /* printk("IMAGE_BLIT\n"); */
146 bufptr = dev_info->buf;
148 for (i = y; i < y + height; i++) {
150 if (dev_info->bufend - bufptr < BUF_HIGH_WATER_MARK) {
151 ret = dlfb_bulk_msg(dev_info, bufptr - dev_info->buf);
152 bufptr = dev_info->buf;
155 rem = width;
157 /* printk("WRITING LINE %d\n", i); */
159 while (rem) {
161 if (dev_info->bufend - bufptr < BUF_HIGH_WATER_MARK) {
162 ret =
163 dlfb_bulk_msg(dev_info,
164 bufptr - dev_info->buf);
165 bufptr = dev_info->buf;
168 if (rem > 255) {
170 diff = 0;
171 for (j = 0; j < 510; j++) {
172 if (dev_info->
173 backing_buffer[base + j] !=
174 data[j]) {
175 diff = 1;
176 break;
180 if (diff == 1) {
181 *bufptr++ = 0xAF;
182 *bufptr++ = 0x68;
184 *bufptr++ = (char)(base >> 16);
185 *bufptr++ = (char)(base >> 8);
186 *bufptr++ = (char)(base);
187 *bufptr++ = 255;
188 /* PUT COMPRESSION HERE */
189 for (j = 0; j < 510; j += 2) {
190 bufptr[j] = data[j + 1];
191 bufptr[j + 1] = data[j];
193 bufptr += 510;
196 rem -= 255;
197 base += 510;
198 data += 510;
199 } else {
201 diff = 0;
203 for (j = 0; j < rem * 2; j++) {
204 if (dev_info->
205 backing_buffer[base + j] !=
206 data[j]) {
207 diff = 1;
208 break;
212 if (diff == 1) {
214 *bufptr++ = 0xAF;
215 *bufptr++ = 0x68;
217 *bufptr++ = (char)(base >> 16);
218 *bufptr++ = (char)(base >> 8);
219 *bufptr++ = (char)(base);
220 *bufptr++ = rem;
221 /* PUT COMPRESSION HERE */
222 for (j = 0; j < rem * 2; j += 2) {
223 bufptr[j] = data[j + 1];
224 bufptr[j + 1] = data[j];
226 bufptr += rem * 2;
230 base += rem * 2;
231 data += rem * 2;
232 rem = 0;
237 memcpy(dev_info->backing_buffer + base - (width * 2),
238 data - (width * 2), width * 2);
240 base += (dev_info->info->var.xres * 2) - (width * 2);
241 data += (dev_info->info->var.xres * 2) - (width * 2);
245 if (bufptr > dev_info->buf)
246 ret = dlfb_bulk_msg(dev_info, bufptr - dev_info->buf);
248 mutex_unlock(&dev_info->bulk_mutex);
250 return base;
254 static int
255 draw_rect(struct dlfb_data *dev_info, int x, int y, int width, int height,
256 unsigned char red, unsigned char green, unsigned char blue)
259 int i, j, base;
260 int ret;
261 unsigned short col =
262 (((((red) & 0xF8) | ((green) >> 5)) & 0xFF) << 8) +
263 (((((green) & 0x1C) << 3) | ((blue) >> 3)) & 0xFF);
264 int rem = width;
266 char *bufptr;
268 if (x + width > dev_info->info->var.xres)
269 return -EINVAL;
271 if (y + height > dev_info->info->var.yres)
272 return -EINVAL;
274 mutex_lock(&dev_info->bulk_mutex);
276 base = dev_info->base16 + (dev_info->info->var.xres * 2 * y) + (x * 2);
278 bufptr = dev_info->buf;
280 for (i = y; i < y + height; i++) {
282 for (j = 0; j < width * 2; j += 2) {
283 dev_info->backing_buffer[base + j] = (char)(col >> 8);
284 dev_info->backing_buffer[base + j + 1] = (char)(col);
286 if (dev_info->bufend - bufptr < BUF_HIGH_WATER_MARK) {
287 ret = dlfb_bulk_msg(dev_info, bufptr - dev_info->buf);
288 bufptr = dev_info->buf;
291 rem = width;
293 while (rem) {
295 if (dev_info->bufend - bufptr < BUF_HIGH_WATER_MARK) {
296 ret =
297 dlfb_bulk_msg(dev_info,
298 bufptr - dev_info->buf);
299 bufptr = dev_info->buf;
302 *bufptr++ = 0xAF;
303 *bufptr++ = 0x69;
305 *bufptr++ = (char)(base >> 16);
306 *bufptr++ = (char)(base >> 8);
307 *bufptr++ = (char)(base);
309 if (rem > 255) {
310 *bufptr++ = 255;
311 *bufptr++ = 255;
312 rem -= 255;
313 base += 255 * 2;
314 } else {
315 *bufptr++ = rem;
316 *bufptr++ = rem;
317 base += rem * 2;
318 rem = 0;
321 *bufptr++ = (char)(col >> 8);
322 *bufptr++ = (char)(col);
326 base += (dev_info->info->var.xres * 2) - (width * 2);
330 if (bufptr > dev_info->buf)
331 ret = dlfb_bulk_msg(dev_info, bufptr - dev_info->buf);
333 mutex_unlock(&dev_info->bulk_mutex);
335 return 1;
338 static int
339 copyarea(struct dlfb_data *dev_info, int dx, int dy, int sx, int sy,
340 int width, int height)
342 int base;
343 int source;
344 int rem;
345 int i, ret;
347 char *bufptr;
349 if (dx + width > dev_info->info->var.xres)
350 return -EINVAL;
352 if (dy + height > dev_info->info->var.yres)
353 return -EINVAL;
355 mutex_lock(&dev_info->bulk_mutex);
357 base =
358 dev_info->base16 + (dev_info->info->var.xres * 2 * dy) + (dx * 2);
359 source = (dev_info->info->var.xres * 2 * sy) + (sx * 2);
361 bufptr = dev_info->buf;
363 for (i = sy; i < sy + height; i++) {
365 memcpy(dev_info->backing_buffer + base,
366 dev_info->backing_buffer + source, width * 2);
368 if (dev_info->bufend - bufptr < BUF_HIGH_WATER_MARK) {
369 ret = dlfb_bulk_msg(dev_info, bufptr - dev_info->buf);
370 bufptr = dev_info->buf;
373 rem = width;
375 while (rem) {
377 if (dev_info->bufend - bufptr < BUF_HIGH_WATER_MARK) {
378 ret =
379 dlfb_bulk_msg(dev_info,
380 bufptr - dev_info->buf);
381 bufptr = dev_info->buf;
384 *bufptr++ = 0xAF;
385 *bufptr++ = 0x6A;
387 *bufptr++ = (char)(base >> 16);
388 *bufptr++ = (char)(base >> 8);
389 *bufptr++ = (char)(base);
391 if (rem > 255) {
392 *bufptr++ = 255;
393 *bufptr++ = (char)(source >> 16);
394 *bufptr++ = (char)(source >> 8);
395 *bufptr++ = (char)(source);
397 rem -= 255;
398 base += 255 * 2;
399 source += 255 * 2;
401 } else {
402 *bufptr++ = rem;
403 *bufptr++ = (char)(source >> 16);
404 *bufptr++ = (char)(source >> 8);
405 *bufptr++ = (char)(source);
407 base += rem * 2;
408 source += rem * 2;
409 rem = 0;
413 base += (dev_info->info->var.xres * 2) - (width * 2);
414 source += (dev_info->info->var.xres * 2) - (width * 2);
417 if (bufptr > dev_info->buf)
418 ret = dlfb_bulk_msg(dev_info, bufptr - dev_info->buf);
420 mutex_unlock(&dev_info->bulk_mutex);
422 return 1;
425 void dlfb_copyarea(struct fb_info *info, const struct fb_copyarea *area)
428 struct dlfb_data *dev = info->par;
430 copyarea(dev, area->dx, area->dy, area->sx, area->sy, area->width,
431 area->height);
433 /* printk("COPY AREA %d %d %d %d %d %d !!!\n", area->dx, area->dy, area->sx, area->sy, area->width, area->height); */
437 void dlfb_imageblit(struct fb_info *info, const struct fb_image *image)
440 int ret;
441 struct dlfb_data *dev = info->par;
442 /* printk("IMAGE BLIT (1) %d %d %d %d DEPTH %d {%p}!!!\n", image->dx, image->dy, image->width, image->height, image->depth, dev->udev); */
443 cfb_imageblit(info, image);
444 ret =
445 image_blit(dev, image->dx, image->dy, image->width, image->height,
446 info->screen_base);
447 /* printk("IMAGE BLIT (2) %d %d %d %d DEPTH %d {%p} %d!!!\n", image->dx, image->dy, image->width, image->height, image->depth, dev->udev, ret); */
450 void dlfb_fillrect(struct fb_info *info, const struct fb_fillrect *region)
453 unsigned char red, green, blue;
454 struct dlfb_data *dev = info->par;
456 memcpy(&red, &region->color, 1);
457 memcpy(&green, &region->color + 1, 1);
458 memcpy(&blue, &region->color + 2, 1);
459 draw_rect(dev, region->dx, region->dy, region->width, region->height,
460 red, green, blue);
461 /* printk("FILL RECT %d %d !!!\n", region->dx, region->dy); */
465 static int dlfb_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg)
468 struct dlfb_data *dev_info = info->par;
469 struct dloarea *area;
471 if (cmd == 0xAA) {
473 area = (struct dloarea *)arg;
475 if (area->x < 0)
476 area->x = 0;
478 if (area->x > info->var.xres)
479 area->x = info->var.xres;
481 if (area->y < 0)
482 area->y = 0;
484 if (area->y > info->var.yres)
485 area->y = info->var.yres;
487 image_blit(dev_info, area->x, area->y, area->w, area->h,
488 info->screen_base);
490 return 0;
493 /* taken from vesafb */
495 static int
496 dlfb_setcolreg(unsigned regno, unsigned red, unsigned green,
497 unsigned blue, unsigned transp, struct fb_info *info)
499 int err = 0;
501 if (regno >= info->cmap.len)
502 return 1;
504 if (regno < 16) {
505 if (info->var.red.offset == 10) {
506 /* 1:5:5:5 */
507 ((u32 *) (info->pseudo_palette))[regno] =
508 ((red & 0xf800) >> 1) |
509 ((green & 0xf800) >> 6) | ((blue & 0xf800) >> 11);
510 } else {
511 /* 0:5:6:5 */
512 ((u32 *) (info->pseudo_palette))[regno] =
513 ((red & 0xf800)) |
514 ((green & 0xfc00) >> 5) | ((blue & 0xf800) >> 11);
518 return err;
521 static int dlfb_release(struct fb_info *info, int user)
523 struct dlfb_data *dev_info = info->par;
524 image_blit(dev_info, 0, 0, info->var.xres, info->var.yres,
525 info->screen_base);
526 return 0;
529 static int dlfb_blank(int blank_mode, struct fb_info *info)
531 return 0;
534 static struct fb_ops dlfb_ops = {
535 .fb_setcolreg = dlfb_setcolreg,
536 .fb_fillrect = dlfb_fillrect,
537 .fb_copyarea = dlfb_copyarea,
538 .fb_imageblit = dlfb_imageblit,
539 .fb_mmap = dlfb_mmap,
540 .fb_ioctl = dlfb_ioctl,
541 .fb_release = dlfb_release,
542 .fb_blank = dlfb_blank,
545 static int
546 dlfb_probe(struct usb_interface *interface, const struct usb_device_id *id)
548 struct dlfb_data *dev_info;
549 struct fb_info *info;
550 int i;
552 int ret;
553 char rbuf[4];
555 dev_info = kzalloc(sizeof(*dev_info), GFP_KERNEL);
556 if (dev_info == NULL) {
557 printk("cannot allocate dev_info structure.\n");
558 return -ENOMEM;
561 mutex_init(&dev_info->bulk_mutex);
563 dev_info->udev = usb_get_dev(interface_to_usbdev(interface));
564 dev_info->interface = interface;
566 printk("DisplayLink device attached\n");
568 /* add framebuffer info to usb interface */
569 usb_set_intfdata(interface, dev_info);
571 dev_info->buf = kmalloc(BUF_SIZE, GFP_KERNEL);
572 /* usb_buffer_alloc(dev_info->udev, BUF_SIZE , GFP_KERNEL, &dev_info->tx_urb->transfer_dma); */
574 if (dev_info->buf == NULL) {
575 printk("unable to allocate memory for dlfb commands\n");
576 goto out;
578 dev_info->bufend = dev_info->buf + BUF_SIZE;
580 dev_info->tx_urb = usb_alloc_urb(0, GFP_KERNEL);
581 usb_fill_bulk_urb(dev_info->tx_urb, dev_info->udev,
582 usb_sndbulkpipe(dev_info->udev, 1), dev_info->buf, 0,
583 dlfb_bulk_callback, dev_info);
585 ret =
586 usb_control_msg(dev_info->udev, usb_rcvctrlpipe(dev_info->udev, 0),
587 (0x06), (0x80 | (0x02 << 5)), 0, 0, rbuf, 4, 0);
588 printk("ret control msg 0: %d %x%x%x%x\n", ret, rbuf[0], rbuf[1],
589 rbuf[2], rbuf[3]);
591 for (i = 0; i < 128; i++) {
592 ret =
593 usb_control_msg(dev_info->udev,
594 usb_rcvctrlpipe(dev_info->udev, 0), (0x02),
595 (0x80 | (0x02 << 5)), i << 8, 0xA1, rbuf, 2,
597 /* printk("ret control msg edid %d: %d [%d]\n",i, ret, rbuf[1]); */
598 dev_info->edid[i] = rbuf[1];
601 info = framebuffer_alloc(sizeof(u32) * 256, &dev_info->udev->dev);
603 if (!info) {
604 printk("non posso allocare il framebuffer displaylink");
605 goto out;
608 fb_parse_edid(dev_info->edid, &info->var);
610 printk("EDID XRES %d YRES %d\n", info->var.xres, info->var.yres);
612 if (dlfb_set_video_mode(dev_info, info->var.xres, info->var.yres) != 0)
613 goto out;
615 printk("found valid mode...%d\n", info->var.pixclock);
617 info->pseudo_palette = info->par;
618 info->par = dev_info;
620 dev_info->info = info;
622 info->flags =
623 FBINFO_DEFAULT | FBINFO_READS_FAST | FBINFO_HWACCEL_IMAGEBLIT |
624 FBINFO_HWACCEL_COPYAREA | FBINFO_HWACCEL_FILLRECT;
625 info->fbops = &dlfb_ops;
626 info->screen_base = rvmalloc(dev_info->screen_size);
628 if (info->screen_base == NULL) {
629 printk
630 ("cannot allocate framebuffer virtual memory of %d bytes\n",
631 dev_info->screen_size);
632 goto out0;
635 printk("screen base allocated !!!\n");
637 dev_info->backing_buffer = kzalloc(dev_info->screen_size, GFP_KERNEL);
639 if (!dev_info->backing_buffer)
640 printk("non posso allocare il backing buffer\n");
642 /* info->var = dev_info->si; */
644 info->var.bits_per_pixel = 16;
645 info->var.activate = FB_ACTIVATE_TEST;
646 info->var.vmode = FB_VMODE_NONINTERLACED;
648 info->var.red.offset = 11;
649 info->var.red.length = 5;
650 info->var.red.msb_right = 0;
652 info->var.green.offset = 5;
653 info->var.green.length = 6;
654 info->var.green.msb_right = 0;
656 info->var.blue.offset = 0;
657 info->var.blue.length = 5;
658 info->var.blue.msb_right = 0;
660 /* info->var.pixclock = (10000000 / FB_W * 1000 / FB_H)/2 ; */
662 info->fix.smem_start = (unsigned long)info->screen_base;
663 info->fix.smem_len = PAGE_ALIGN(dev_info->screen_size);
664 memcpy(info->fix.id, "DisplayLink FB", 14);
665 info->fix.type = FB_TYPE_PACKED_PIXELS;
666 info->fix.visual = FB_VISUAL_TRUECOLOR;
667 info->fix.accel = info->flags;
668 info->fix.line_length = dev_info->line_length;
670 if (fb_alloc_cmap(&info->cmap, 256, 0) < 0)
671 goto out1;
673 printk("colormap allocated\n");
674 if (register_framebuffer(info) < 0)
675 goto out2;
677 draw_rect(dev_info, 0, 0, dev_info->info->var.xres,
678 dev_info->info->var.yres, 0x30, 0xff, 0x30);
680 return 0;
682 out2:
683 fb_dealloc_cmap(&info->cmap);
684 out1:
685 rvfree(info->screen_base, dev_info->screen_size);
686 out0:
687 framebuffer_release(info);
688 out:
689 usb_set_intfdata(interface, NULL);
690 usb_put_dev(dev_info->udev);
691 kfree(dev_info);
692 return -ENOMEM;
696 static void dlfb_disconnect(struct usb_interface *interface)
698 struct dlfb_data *dev_info = usb_get_intfdata(interface);
700 mutex_unlock(&dev_info->bulk_mutex);
702 usb_kill_urb(dev_info->tx_urb);
703 usb_free_urb(dev_info->tx_urb);
704 usb_set_intfdata(interface, NULL);
705 usb_put_dev(dev_info->udev);
707 if (dev_info->info) {
708 unregister_framebuffer(dev_info->info);
709 fb_dealloc_cmap(&dev_info->info->cmap);
710 rvfree(dev_info->info->screen_base, dev_info->screen_size);
711 kfree(dev_info->backing_buffer);
712 framebuffer_release(dev_info->info);
716 kfree(dev_info);
718 printk("DisplayLink device disconnected\n");
721 static struct usb_driver dlfb_driver = {
722 .name = "udlfb",
723 .probe = dlfb_probe,
724 .disconnect = dlfb_disconnect,
725 .id_table = id_table,
728 static int __init dlfb_init(void)
730 int res;
732 dlfb_init_modes();
734 res = usb_register(&dlfb_driver);
735 if (res)
736 err("usb_register failed. Error number %d", res);
738 printk("VMODES initialized\n");
740 return res;
743 static void __exit dlfb_exit(void)
745 usb_deregister(&dlfb_driver);
748 module_init(dlfb_init);
749 module_exit(dlfb_exit);
751 MODULE_AUTHOR("Roberto De Ioris <roberto@unbit.it>");
752 MODULE_DESCRIPTION(DRIVER_VERSION);
753 MODULE_LICENSE("GPL");