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 * 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>
21 #include <linux/mutex.h>
25 #define DRIVER_VERSION "DLFB 0.2"
27 /* memory functions taken from vfb */
29 static void *rvmalloc(unsigned long size
)
34 size
= PAGE_ALIGN(size
);
35 mem
= vmalloc_32(size
);
39 memset(mem
, 0, size
); /* Clear the ram out, no junk to the user */
40 adr
= (unsigned long)mem
;
42 SetPageReserved(vmalloc_to_page((void *)adr
));
50 static void rvfree(void *mem
, unsigned long size
)
57 adr
= (unsigned long)mem
;
58 while ((long)size
> 0) {
59 ClearPageReserved(vmalloc_to_page((void *)adr
));
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
)
78 pos
= (unsigned long)info
->fix
.smem_start
+ offset
;
81 page
= vmalloc_to_pfn((void *)pos
);
82 if (remap_pfn_range(vma
, start
, page
, PAGE_SIZE
, PAGE_SHARED
))
93 vma
->vm_flags
|= VM_RESERVED
; /* avoid to swap out this VMA */
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
;
120 image_blit(struct dlfb_data
*dev_info
, int x
, int y
, int width
, int height
,
132 if (x
+ width
> dev_info
->info
->var
.xres
)
135 if (y
+ height
> dev_info
->info
->var
.yres
)
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
;
157 /* printk("WRITING LINE %d\n", i); */
161 if (dev_info
->bufend
- bufptr
< BUF_HIGH_WATER_MARK
) {
163 dlfb_bulk_msg(dev_info
,
164 bufptr
- dev_info
->buf
);
165 bufptr
= dev_info
->buf
;
171 for (j
= 0; j
< 510; j
++) {
173 backing_buffer
[base
+ j
] !=
184 *bufptr
++ = (char)(base
>> 16);
185 *bufptr
++ = (char)(base
>> 8);
186 *bufptr
++ = (char)(base
);
188 /* PUT COMPRESSION HERE */
189 for (j
= 0; j
< 510; j
+= 2) {
190 bufptr
[j
] = data
[j
+ 1];
191 bufptr
[j
+ 1] = data
[j
];
203 for (j
= 0; j
< rem
* 2; j
++) {
205 backing_buffer
[base
+ j
] !=
217 *bufptr
++ = (char)(base
>> 16);
218 *bufptr
++ = (char)(base
>> 8);
219 *bufptr
++ = (char)(base
);
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
];
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
);
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
)
262 (((((red
) & 0xF8) | ((green
) >> 5)) & 0xFF) << 8) +
263 (((((green
) & 0x1C) << 3) | ((blue
) >> 3)) & 0xFF);
268 if (x
+ width
> dev_info
->info
->var
.xres
)
271 if (y
+ height
> dev_info
->info
->var
.yres
)
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
;
295 if (dev_info
->bufend
- bufptr
< BUF_HIGH_WATER_MARK
) {
297 dlfb_bulk_msg(dev_info
,
298 bufptr
- dev_info
->buf
);
299 bufptr
= dev_info
->buf
;
305 *bufptr
++ = (char)(base
>> 16);
306 *bufptr
++ = (char)(base
>> 8);
307 *bufptr
++ = (char)(base
);
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
);
339 copyarea(struct dlfb_data
*dev_info
, int dx
, int dy
, int sx
, int sy
,
340 int width
, int height
)
349 if (dx
+ width
> dev_info
->info
->var
.xres
)
352 if (dy
+ height
> dev_info
->info
->var
.yres
)
355 mutex_lock(&dev_info
->bulk_mutex
);
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
;
377 if (dev_info
->bufend
- bufptr
< BUF_HIGH_WATER_MARK
) {
379 dlfb_bulk_msg(dev_info
,
380 bufptr
- dev_info
->buf
);
381 bufptr
= dev_info
->buf
;
387 *bufptr
++ = (char)(base
>> 16);
388 *bufptr
++ = (char)(base
>> 8);
389 *bufptr
++ = (char)(base
);
393 *bufptr
++ = (char)(source
>> 16);
394 *bufptr
++ = (char)(source
>> 8);
395 *bufptr
++ = (char)(source
);
403 *bufptr
++ = (char)(source
>> 16);
404 *bufptr
++ = (char)(source
>> 8);
405 *bufptr
++ = (char)(source
);
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
);
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
,
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
)
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
);
445 image_blit(dev
, image
->dx
, image
->dy
, image
->width
, image
->height
,
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
, ®ion
->color
, 1);
457 memcpy(&green
, ®ion
->color
+ 1, 1);
458 memcpy(&blue
, ®ion
->color
+ 2, 1);
459 draw_rect(dev
, region
->dx
, region
->dy
, region
->width
, region
->height
,
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
;
473 area
= (struct dloarea
*)arg
;
478 if (area
->x
> info
->var
.xres
)
479 area
->x
= info
->var
.xres
;
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
,
493 /* taken from vesafb */
496 dlfb_setcolreg(unsigned regno
, unsigned red
, unsigned green
,
497 unsigned blue
, unsigned transp
, struct fb_info
*info
)
501 if (regno
>= info
->cmap
.len
)
505 if (info
->var
.red
.offset
== 10) {
507 ((u32
*) (info
->pseudo_palette
))[regno
] =
508 ((red
& 0xf800) >> 1) |
509 ((green
& 0xf800) >> 6) | ((blue
& 0xf800) >> 11);
512 ((u32
*) (info
->pseudo_palette
))[regno
] =
514 ((green
& 0xfc00) >> 5) | ((blue
& 0xf800) >> 11);
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
,
529 static int dlfb_blank(int blank_mode
, struct fb_info
*info
)
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
,
546 dlfb_probe(struct usb_interface
*interface
, const struct usb_device_id
*id
)
548 struct dlfb_data
*dev_info
;
549 struct fb_info
*info
;
555 dev_info
= kzalloc(sizeof(*dev_info
), GFP_KERNEL
);
556 if (dev_info
== NULL
) {
557 printk("cannot allocate dev_info structure.\n");
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");
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
);
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],
591 for (i
= 0; i
< 128; i
++) {
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
);
604 printk("non posso allocare il framebuffer displaylink");
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)
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
;
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
) {
630 ("cannot allocate framebuffer virtual memory of %d bytes\n",
631 dev_info
->screen_size
);
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)
673 printk("colormap allocated\n");
674 if (register_framebuffer(info
) < 0)
677 draw_rect(dev_info
, 0, 0, dev_info
->info
->var
.xres
,
678 dev_info
->info
->var
.yres
, 0x30, 0xff, 0x30);
683 fb_dealloc_cmap(&info
->cmap
);
685 rvfree(info
->screen_base
, dev_info
->screen_size
);
687 framebuffer_release(info
);
689 usb_set_intfdata(interface
, NULL
);
690 usb_put_dev(dev_info
->udev
);
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
);
718 printk("DisplayLink device disconnected\n");
721 static struct usb_driver dlfb_driver
= {
724 .disconnect
= dlfb_disconnect
,
725 .id_table
= id_table
,
728 static int __init
dlfb_init(void)
734 res
= usb_register(&dlfb_driver
);
736 err("usb_register failed. Error number %d", res
);
738 printk("VMODES initialized\n");
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");