1 /*****************************************************************************
3 * Version 0.2 (udlfb) *
4 * (C) 2009 Roberto De Ioris <roberto@unbit.it> *
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 *
10 * 10.06.09 release 0.2.3 (edid ioctl, fallback for unsupported modes) *
11 * 05.06.09 release 0.2.2 (real screen blanking, rle compression, double buffer) *
12 * 31.05.09 release 0.2 *
13 * 22.05.09 First public (ugly) release *
14 *****************************************************************************/
16 #include <linux/module.h>
17 #include <linux/kernel.h>
18 #include <linux/init.h>
19 #include <linux/usb.h>
20 #include <linux/uaccess.h>
23 #include <linux/mutex.h>
27 #define DRIVER_VERSION "DLFB 0.2"
29 /* memory functions taken from vfb */
31 static void *rvmalloc(unsigned long size)
36 size = PAGE_ALIGN(size);
37 mem = vmalloc_32(size);
41 memset(mem, 0, size); /* Clear the ram out, no junk to the user */
42 adr = (unsigned long)mem;
44 SetPageReserved(vmalloc_to_page((void *)adr));
52 static void rvfree(void *mem, unsigned long size)
59 adr = (unsigned long)mem;
60 while ((long)size > 0) {
61 ClearPageReserved(vmalloc_to_page((void *)adr));
68 static int dlfb_mmap(struct fb_info *info, struct vm_area_struct *vma)
70 unsigned long start = vma->vm_start;
71 unsigned long size = vma->vm_end - vma->vm_start;
72 unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;
73 unsigned long page, pos;
75 printk("MMAP: %lu %u\n", offset + size, info->fix.smem_len);
77 if (offset + size > info->fix.smem_len)
80 pos = (unsigned long)info->fix.smem_start + offset;
83 page = vmalloc_to_pfn((void *)pos);
84 if (remap_pfn_range(vma, start, page, PAGE_SIZE, PAGE_SHARED))
95 vma->vm_flags |= VM_RESERVED; /* avoid to swap out this VMA */
100 /* ioctl structure */
108 static struct usb_device_id id_table [] = {
109 { USB_DEVICE(0x17e9, 0x023d) },
114 static struct usb_device_id id_table[] = {
115 {.idVendor = 0x17e9, .match_flags = USB_DEVICE_ID_MATCH_VENDOR,},
118 MODULE_DEVICE_TABLE(usb, id_table);
120 static struct usb_driver dlfb_driver;
122 // thanks to Henrik Bjerregaard Pedersen for this function
123 static char *rle_compress16(uint16_t * src, char *dst, int rem)
128 char *end_if_raw = dst + 6 + 2 * rem;
130 dst += 6; // header will be filled in if RLE is worth it
132 while (rem && dst < end_if_raw) {
133 char *start = (char *)src;
138 while (rem && *src == pix0)
149 Thanks to Henrik Bjerregaard Pedersen for rle implementation and code refactoring.
150 Next step is huffman compression.
154 image_blit(struct dlfb_data *dev_info, int x, int y, int width, int height,
162 int firstdiff, thistime;
166 if (x + width > dev_info->info->var.xres)
169 if (y + height > dev_info->info->var.yres)
172 mutex_lock(&dev_info->bulk_mutex);
175 dev_info->base16 + ((dev_info->info->var.xres * 2 * y) + (x * 2));
177 data += (dev_info->info->var.xres * 2 * y) + (x * 2);
179 /* printk("IMAGE_BLIT\n"); */
181 bufptr = dev_info->buf;
183 for (i = y; i < y + height; i++) {
185 if (dev_info->bufend - bufptr < BUF_HIGH_WATER_MARK) {
186 ret = dlfb_bulk_msg(dev_info, bufptr - dev_info->buf);
187 bufptr = dev_info->buf;
192 /* printk("WRITING LINE %d\n", i); */
196 if (dev_info->bufend - bufptr < BUF_HIGH_WATER_MARK) {
198 dlfb_bulk_msg(dev_info,
199 bufptr - dev_info->buf);
200 bufptr = dev_info->buf;
202 // number of pixels to consider this time
207 // find position of first pixel that has changed
209 for (j = 0; j < thistime * 2; j++) {
210 if (dev_info->backing_buffer
211 [base - dev_info->base16 + j] != data[j]) {
217 if (firstdiff >= 0) {
221 rle_compress16((uint16_t *) (data +
224 thistime - firstdiff);
227 bufptr + 6 + 2 * (thistime - firstdiff)) {
233 firstdiff * 2) >> 16);
235 (char)((base + firstdiff * 2) >> 8);
237 (char)(base + firstdiff * 2);
238 bufptr[5] = thistime - firstdiff;
243 // fallback to raw (or some other encoding?)
249 firstdiff * 2) >> 16);
251 (char)((base + firstdiff * 2) >> 8);
253 (char)(base + firstdiff * 2);
254 *bufptr++ = thistime - firstdiff;
255 // PUT COMPRESSION HERE
256 for (j = firstdiff * 2;
257 j < thistime * 2; j += 2) {
258 *bufptr++ = data[j + 1];
264 base += thistime * 2;
265 data += thistime * 2;
269 memcpy(dev_info->backing_buffer + (base - dev_info->base16) -
270 (width * 2), data - (width * 2), width * 2);
272 base += (dev_info->info->var.xres * 2) - (width * 2);
273 data += (dev_info->info->var.xres * 2) - (width * 2);
277 if (bufptr > dev_info->buf) {
278 ret = dlfb_bulk_msg(dev_info, bufptr - dev_info->buf);
281 mutex_unlock(&dev_info->bulk_mutex);
288 draw_rect(struct dlfb_data *dev_info, int x, int y, int width, int height,
289 unsigned char red, unsigned char green, unsigned char blue)
295 (((((red) & 0xF8) | ((green) >> 5)) & 0xFF) << 8) +
296 (((((green) & 0x1C) << 3) | ((blue) >> 3)) & 0xFF);
301 if (x + width > dev_info->info->var.xres)
304 if (y + height > dev_info->info->var.yres)
307 mutex_lock(&dev_info->bulk_mutex);
309 base = dev_info->base16 + (dev_info->info->var.xres * 2 * y) + (x * 2);
311 bufptr = dev_info->buf;
313 for (i = y; i < y + height; i++) {
315 for (j = 0; j < width * 2; j += 2) {
316 dev_info->backing_buffer[base - dev_info->base16 + j] =
318 dev_info->backing_buffer[base - dev_info->base16 + j +
321 if (dev_info->bufend - bufptr < BUF_HIGH_WATER_MARK) {
322 ret = dlfb_bulk_msg(dev_info, bufptr - dev_info->buf);
323 bufptr = dev_info->buf;
330 if (dev_info->bufend - bufptr < BUF_HIGH_WATER_MARK) {
332 dlfb_bulk_msg(dev_info,
333 bufptr - dev_info->buf);
334 bufptr = dev_info->buf;
340 *bufptr++ = (char)(base >> 16);
341 *bufptr++ = (char)(base >> 8);
342 *bufptr++ = (char)(base);
356 *bufptr++ = (char)(col >> 8);
357 *bufptr++ = (char)(col);
361 base += (dev_info->info->var.xres * 2) - (width * 2);
365 if (bufptr > dev_info->buf)
366 ret = dlfb_bulk_msg(dev_info, bufptr - dev_info->buf);
368 mutex_unlock(&dev_info->bulk_mutex);
373 static void swapfb(struct dlfb_data *dev_info)
379 mutex_lock(&dev_info->bulk_mutex);
381 tmpbase = dev_info->base16;
383 dev_info->base16 = dev_info->base16d;
384 dev_info->base16d = tmpbase;
386 bufptr = dev_info->buf;
388 bufptr = dlfb_set_register(bufptr, 0xFF, 0x00);
392 dlfb_set_register(bufptr, 0x20, (char)(dev_info->base16 >> 16));
393 bufptr = dlfb_set_register(bufptr, 0x21, (char)(dev_info->base16 >> 8));
394 bufptr = dlfb_set_register(bufptr, 0x22, (char)(dev_info->base16));
396 bufptr = dlfb_set_register(bufptr, 0xFF, 0x00);
398 dlfb_bulk_msg(dev_info, bufptr - dev_info->buf);
400 mutex_unlock(&dev_info->bulk_mutex);
403 static int copyfb(struct dlfb_data *dev_info)
412 base = dev_info->base16d;
414 mutex_lock(&dev_info->bulk_mutex);
416 source = dev_info->base16;
418 bufptr = dev_info->buf;
420 for (i = 0; i < dev_info->info->var.yres; i++) {
422 if (dev_info->bufend - bufptr < BUF_HIGH_WATER_MARK) {
423 ret = dlfb_bulk_msg(dev_info, bufptr - dev_info->buf);
424 bufptr = dev_info->buf;
427 rem = dev_info->info->var.xres;
431 if (dev_info->bufend - bufptr < BUF_HIGH_WATER_MARK) {
433 dlfb_bulk_msg(dev_info,
434 bufptr - dev_info->buf);
435 bufptr = dev_info->buf;
442 *bufptr++ = (char)(base >> 16);
443 *bufptr++ = (char)(base >> 8);
444 *bufptr++ = (char)(base);
448 *bufptr++ = (char)(source >> 16);
449 *bufptr++ = (char)(source >> 8);
450 *bufptr++ = (char)(source);
458 *bufptr++ = (char)(source >> 16);
459 *bufptr++ = (char)(source >> 8);
460 *bufptr++ = (char)(source);
469 if (bufptr > dev_info->buf)
470 ret = dlfb_bulk_msg(dev_info, bufptr - dev_info->buf);
472 mutex_unlock(&dev_info->bulk_mutex);
479 copyarea(struct dlfb_data *dev_info, int dx, int dy, int sx, int sy,
480 int width, int height)
489 if (dx + width > dev_info->info->var.xres)
492 if (dy + height > dev_info->info->var.yres)
495 mutex_lock(&dev_info->bulk_mutex);
498 dev_info->base16 + (dev_info->info->var.xres * 2 * dy) + (dx * 2);
499 source = (dev_info->info->var.xres * 2 * sy) + (sx * 2);
501 bufptr = dev_info->buf;
503 for (i = sy; i < sy + height; i++) {
505 memcpy(dev_info->backing_buffer + base - dev_info->base16,
506 dev_info->backing_buffer + source, width * 2);
508 if (dev_info->bufend - bufptr < BUF_HIGH_WATER_MARK) {
509 ret = dlfb_bulk_msg(dev_info, bufptr - dev_info->buf);
510 bufptr = dev_info->buf;
517 if (dev_info->bufend - bufptr < BUF_HIGH_WATER_MARK) {
519 dlfb_bulk_msg(dev_info,
520 bufptr - dev_info->buf);
521 bufptr = dev_info->buf;
527 *bufptr++ = (char)(base >> 16);
528 *bufptr++ = (char)(base >> 8);
529 *bufptr++ = (char)(base);
533 *bufptr++ = (char)(source >> 16);
534 *bufptr++ = (char)(source >> 8);
535 *bufptr++ = (char)(source);
543 *bufptr++ = (char)(source >> 16);
544 *bufptr++ = (char)(source >> 8);
545 *bufptr++ = (char)(source);
553 base += (dev_info->info->var.xres * 2) - (width * 2);
554 source += (dev_info->info->var.xres * 2) - (width * 2);
557 if (bufptr > dev_info->buf)
558 ret = dlfb_bulk_msg(dev_info, bufptr - dev_info->buf);
560 mutex_unlock(&dev_info->bulk_mutex);
565 static void dlfb_copyarea(struct fb_info *info, const struct fb_copyarea *area)
568 struct dlfb_data *dev = info->par;
570 copyarea(dev, area->dx, area->dy, area->sx, area->sy, area->width,
573 /* printk("COPY AREA %d %d %d %d %d %d !!!\n", area->dx, area->dy, area->sx, area->sy, area->width, area->height); */
577 static void dlfb_imageblit(struct fb_info *info, const struct fb_image *image)
581 struct dlfb_data *dev = info->par;
582 /* printk("IMAGE BLIT (1) %d %d %d %d DEPTH %d {%p}!!!\n", image->dx, image->dy, image->width, image->height, image->depth, dev->udev); */
583 cfb_imageblit(info, image);
585 image_blit(dev, image->dx, image->dy, image->width, image->height,
587 /* 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); */
590 static void dlfb_fillrect(struct fb_info *info,
591 const struct fb_fillrect *region)
594 unsigned char red, green, blue;
595 struct dlfb_data *dev = info->par;
597 memcpy(&red, ®ion->color, 1);
598 memcpy(&green, ®ion->color + 1, 1);
599 memcpy(&blue, ®ion->color + 2, 1);
600 draw_rect(dev, region->dx, region->dy, region->width, region->height,
602 /* printk("FILL RECT %d %d !!!\n", region->dx, region->dy); */
606 static int dlfb_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg)
609 struct dlfb_data *dev_info = info->par;
610 struct dloarea *area = NULL;
613 char *edid = (char *)arg;
615 if (copy_to_user(edid, dev_info->edid, 128)) {
621 if (cmd == 0xAA || cmd == 0xAB || cmd == 0xAC) {
623 area = (struct dloarea *)arg;
628 if (area->x > info->var.xres)
629 area->x = info->var.xres;
634 if (area->y > info->var.yres)
635 area->y = info->var.yres;
639 image_blit(dev_info, area->x, area->y, area->w, area->h,
644 image_blit(dev_info, area->x, area->y, area->w, area->h,
647 } else if (cmd == 0xAB) {
656 area->x2, area->y2, area->x, area->y, area->w,
662 /* taken from vesafb */
665 dlfb_setcolreg(unsigned regno, unsigned red, unsigned green,
666 unsigned blue, unsigned transp, struct fb_info *info)
670 if (regno >= info->cmap.len)
674 if (info->var.red.offset == 10) {
676 ((u32 *) (info->pseudo_palette))[regno] =
677 ((red & 0xf800) >> 1) |
678 ((green & 0xf800) >> 6) | ((blue & 0xf800) >> 11);
681 ((u32 *) (info->pseudo_palette))[regno] =
683 ((green & 0xfc00) >> 5) | ((blue & 0xf800) >> 11);
690 static int dlfb_release(struct fb_info *info, int user)
692 struct dlfb_data *dev_info = info->par;
693 image_blit(dev_info, 0, 0, info->var.xres, info->var.yres,
698 static int dlfb_blank(int blank_mode, struct fb_info *info)
700 struct dlfb_data *dev_info = info->par;
701 char *bufptr = dev_info->buf;
703 bufptr = dlfb_set_register(bufptr, 0xFF, 0x00);
704 if (blank_mode != FB_BLANK_UNBLANK) {
705 bufptr = dlfb_set_register(bufptr, 0x1F, 0x01);
707 bufptr = dlfb_set_register(bufptr, 0x1F, 0x00);
709 bufptr = dlfb_set_register(bufptr, 0xFF, 0xFF);
711 dlfb_bulk_msg(dev_info, bufptr - dev_info->buf);
716 static struct fb_ops dlfb_ops = {
717 .fb_setcolreg = dlfb_setcolreg,
718 .fb_fillrect = dlfb_fillrect,
719 .fb_copyarea = dlfb_copyarea,
720 .fb_imageblit = dlfb_imageblit,
721 .fb_mmap = dlfb_mmap,
722 .fb_ioctl = dlfb_ioctl,
723 .fb_release = dlfb_release,
724 .fb_blank = dlfb_blank,
728 dlfb_probe(struct usb_interface *interface, const struct usb_device_id *id)
730 struct dlfb_data *dev_info;
731 struct fb_info *info;
736 dev_info = kzalloc(sizeof(*dev_info), GFP_KERNEL);
737 if (dev_info == NULL) {
738 printk("cannot allocate dev_info structure.\n");
742 mutex_init(&dev_info->bulk_mutex);
744 dev_info->udev = usb_get_dev(interface_to_usbdev(interface));
745 dev_info->interface = interface;
747 printk("DisplayLink device attached\n");
749 /* add framebuffer info to usb interface */
750 usb_set_intfdata(interface, dev_info);
752 dev_info->buf = kmalloc(BUF_SIZE, GFP_KERNEL);
753 /* usb_buffer_alloc(dev_info->udev, BUF_SIZE , GFP_KERNEL, &dev_info->tx_urb->transfer_dma); */
755 if (dev_info->buf == NULL) {
756 printk("unable to allocate memory for dlfb commands\n");
759 dev_info->bufend = dev_info->buf + BUF_SIZE;
761 dev_info->tx_urb = usb_alloc_urb(0, GFP_KERNEL);
762 usb_fill_bulk_urb(dev_info->tx_urb, dev_info->udev,
763 usb_sndbulkpipe(dev_info->udev, 1), dev_info->buf, 0,
764 dlfb_bulk_callback, dev_info);
767 usb_control_msg(dev_info->udev, usb_rcvctrlpipe(dev_info->udev, 0),
768 (0x06), (0x80 | (0x02 << 5)), 0, 0, rbuf, 4, 0);
769 printk("ret control msg 0: %d %x%x%x%x\n", ret, rbuf[0], rbuf[1],
774 info = framebuffer_alloc(sizeof(u32) * 256, &dev_info->udev->dev);
777 printk("non posso allocare il framebuffer displaylink");
781 fb_parse_edid(dev_info->edid, &info->var);
783 printk("EDID XRES %d YRES %d\n", info->var.xres, info->var.yres);
785 if (dlfb_set_video_mode(dev_info, info->var.xres, info->var.yres) != 0) {
786 info->var.xres = 1280;
787 info->var.yres = 1024;
788 if (dlfb_set_video_mode
789 (dev_info, info->var.xres, info->var.yres) != 0) {
794 printk("found valid mode...%d\n", info->var.pixclock);
796 info->pseudo_palette = info->par;
797 info->par = dev_info;
799 dev_info->info = info;
802 FBINFO_DEFAULT | FBINFO_READS_FAST | FBINFO_HWACCEL_IMAGEBLIT |
803 FBINFO_HWACCEL_COPYAREA | FBINFO_HWACCEL_FILLRECT;
804 info->fbops = &dlfb_ops;
805 info->screen_base = rvmalloc(dev_info->screen_size);
807 if (info->screen_base == NULL) {
809 ("cannot allocate framebuffer virtual memory of %d bytes\n",
810 dev_info->screen_size);
814 printk("screen base allocated !!!\n");
816 dev_info->backing_buffer = kzalloc(dev_info->screen_size, GFP_KERNEL);
818 if (!dev_info->backing_buffer)
819 printk("non posso allocare il backing buffer\n");
821 /* info->var = dev_info->si; */
823 info->var.bits_per_pixel = 16;
824 info->var.activate = FB_ACTIVATE_TEST;
825 info->var.vmode = FB_VMODE_NONINTERLACED;
827 info->var.red.offset = 11;
828 info->var.red.length = 5;
829 info->var.red.msb_right = 0;
831 info->var.green.offset = 5;
832 info->var.green.length = 6;
833 info->var.green.msb_right = 0;
835 info->var.blue.offset = 0;
836 info->var.blue.length = 5;
837 info->var.blue.msb_right = 0;
839 /* info->var.pixclock = (10000000 / FB_W * 1000 / FB_H)/2 ; */
841 info->fix.smem_start = (unsigned long)info->screen_base;
842 info->fix.smem_len = PAGE_ALIGN(dev_info->screen_size);
843 if (strlen(dev_info->udev->product) > 15) {
844 memcpy(info->fix.id, dev_info->udev->product, 15);
846 memcpy(info->fix.id, dev_info->udev->product,
847 strlen(dev_info->udev->product));
849 info->fix.type = FB_TYPE_PACKED_PIXELS;
850 info->fix.visual = FB_VISUAL_TRUECOLOR;
851 info->fix.accel = info->flags;
852 info->fix.line_length = dev_info->line_length;
854 if (fb_alloc_cmap(&info->cmap, 256, 0) < 0)
857 printk("colormap allocated\n");
858 if (register_framebuffer(info) < 0)
861 draw_rect(dev_info, 0, 0, dev_info->info->var.xres,
862 dev_info->info->var.yres, 0x30, 0xff, 0x30);
867 fb_dealloc_cmap(&info->cmap);
869 rvfree(info->screen_base, dev_info->screen_size);
871 framebuffer_release(info);
873 usb_set_intfdata(interface, NULL);
874 usb_put_dev(dev_info->udev);
880 static void dlfb_disconnect(struct usb_interface *interface)
882 struct dlfb_data *dev_info = usb_get_intfdata(interface);
884 mutex_unlock(&dev_info->bulk_mutex);
886 usb_kill_urb(dev_info->tx_urb);
887 usb_free_urb(dev_info->tx_urb);
888 usb_set_intfdata(interface, NULL);
889 usb_put_dev(dev_info->udev);
891 if (dev_info->info) {
892 unregister_framebuffer(dev_info->info);
893 fb_dealloc_cmap(&dev_info->info->cmap);
894 rvfree(dev_info->info->screen_base, dev_info->screen_size);
895 kfree(dev_info->backing_buffer);
896 framebuffer_release(dev_info->info);
902 printk("DisplayLink device disconnected\n");
905 static struct usb_driver dlfb_driver = {
908 .disconnect = dlfb_disconnect,
909 .id_table = id_table,
912 static int __init dlfb_init(void)
918 res = usb_register(&dlfb_driver);
920 err("usb_register failed. Error number %d", res);
922 printk("VMODES initialized\n");
927 static void __exit dlfb_exit(void)
929 usb_deregister(&dlfb_driver);
932 module_init(dlfb_init);
933 module_exit(dlfb_exit);
935 MODULE_AUTHOR("Roberto De Ioris <roberto@unbit.it>");
936 MODULE_DESCRIPTION(DRIVER_VERSION);
937 MODULE_LICENSE("GPL");