Loading drivers/staging/udlfb/udlfb.c +271 −87 Original line number Diff line number Diff line Loading @@ -7,6 +7,8 @@ * Based on the amazing work of Florian Echtler and libdlo 0.1 * * * * * * 10.06.09 release 0.2.3 (edid ioctl, fallback for unsupported modes) * * 05.06.09 release 0.2.2 (real screen blanking, rle compression, double buffer) * * 31.05.09 release 0.2 * * 22.05.09 First public (ugly) release * *****************************************************************************/ Loading Loading @@ -99,6 +101,7 @@ static int dlfb_mmap(struct fb_info *info, struct vm_area_struct *vma) struct dloarea { int x, y; int w, h; int x2, y2; }; /* Loading @@ -116,6 +119,37 @@ MODULE_DEVICE_TABLE(usb, id_table); static struct usb_driver dlfb_driver; // thanks to Henrik Bjerregaard Pedersen for this function static char *rle_compress16(uint16_t * src, char *dst, int rem) { int rl; uint16_t pix0; char *end_if_raw = dst + 6 + 2 * rem; dst += 6; // header will be filled in if RLE is worth it while (rem && dst < end_if_raw) { char *start = (char *)src; pix0 = *src++; rl = 1; rem--; while (rem && *src == pix0) rem--, rl++, src++; *dst++ = rl; *dst++ = start[1]; *dst++ = start[0]; } return dst; } /* Thanks to Henrik Bjerregaard Pedersen for rle implementation and code refactoring. Next step is huffman compression. */ static int image_blit(struct dlfb_data *dev_info, int x, int y, int width, int height, char *data) Loading @@ -125,7 +159,7 @@ image_blit(struct dlfb_data *dev_info, int x, int y, int width, int height, int rem = width; int ret; int diff; int firstdiff, thistime; char *bufptr; Loading @@ -137,7 +171,8 @@ image_blit(struct dlfb_data *dev_info, int x, int y, int width, int height, mutex_lock(&dev_info->bulk_mutex); base = dev_info->base16 + (dev_info->info->var.xres * 2 * y) + (x * 2); base = dev_info->base16 + ((dev_info->info->var.xres * 2 * y) + (x * 2)); data += (dev_info->info->var.xres * 2 * y) + (x * 2); Loading @@ -164,86 +199,84 @@ image_blit(struct dlfb_data *dev_info, int x, int y, int width, int height, bufptr - dev_info->buf); bufptr = dev_info->buf; } if (rem > 255) { diff = 0; for (j = 0; j < 510; j++) { if (dev_info-> backing_buffer[base + j] != data[j]) { diff = 1; // number of pixels to consider this time thistime = rem; if (thistime > 255) thistime = 255; // find position of first pixel that has changed firstdiff = -1; for (j = 0; j < thistime * 2; j++) { if (dev_info->backing_buffer [base - dev_info->base16 + j] != data[j]) { firstdiff = j / 2; break; } } if (diff == 1) { *bufptr++ = 0xAF; *bufptr++ = 0x68; if (firstdiff >= 0) { char *end_of_rle; *bufptr++ = (char)(base >> 16); *bufptr++ = (char)(base >> 8); *bufptr++ = (char)(base); *bufptr++ = 255; /* PUT COMPRESSION HERE */ for (j = 0; j < 510; j += 2) { bufptr[j] = data[j + 1]; bufptr[j + 1] = data[j]; } bufptr += 510; } end_of_rle = rle_compress16((uint16_t *) (data + firstdiff * 2), bufptr, thistime - firstdiff); rem -= 255; base += 510; data += 510; } else { if (end_of_rle < bufptr + 6 + 2 * (thistime - firstdiff)) { bufptr[0] = 0xAF; bufptr[1] = 0x69; diff = 0; bufptr[2] = (char)((base + firstdiff * 2) >> 16); bufptr[3] = (char)((base + firstdiff * 2) >> 8); bufptr[4] = (char)(base + firstdiff * 2); bufptr[5] = thistime - firstdiff; for (j = 0; j < rem * 2; j++) { if (dev_info-> backing_buffer[base + j] != data[j]) { diff = 1; break; } } if (diff == 1) { bufptr = end_of_rle; } else { // fallback to raw (or some other encoding?) *bufptr++ = 0xAF; *bufptr++ = 0x68; *bufptr++ = (char)(base >> 16); *bufptr++ = (char)(base >> 8); *bufptr++ = (char)(base); *bufptr++ = rem; /* PUT COMPRESSION HERE */ for (j = 0; j < rem * 2; j += 2) { bufptr[j] = data[j + 1]; bufptr[j + 1] = data[j]; *bufptr++ = (char)((base + firstdiff * 2) >> 16); *bufptr++ = (char)((base + firstdiff * 2) >> 8); *bufptr++ = (char)(base + firstdiff * 2); *bufptr++ = thistime - firstdiff; // PUT COMPRESSION HERE for (j = firstdiff * 2; j < thistime * 2; j += 2) { *bufptr++ = data[j + 1]; *bufptr++ = data[j]; } bufptr += rem * 2; } base += rem * 2; data += rem * 2; rem = 0; } base += thistime * 2; data += thistime * 2; rem -= thistime; } memcpy(dev_info->backing_buffer + base - (width * 2), data - (width * 2), width * 2); memcpy(dev_info->backing_buffer + (base - dev_info->base16) - (width * 2), data - (width * 2), width * 2); base += (dev_info->info->var.xres * 2) - (width * 2); data += (dev_info->info->var.xres * 2) - (width * 2); } if (bufptr > dev_info->buf) if (bufptr > dev_info->buf) { ret = dlfb_bulk_msg(dev_info, bufptr - dev_info->buf); } mutex_unlock(&dev_info->bulk_mutex); Loading Loading @@ -280,8 +313,10 @@ draw_rect(struct dlfb_data *dev_info, int x, int y, int width, int height, for (i = y; i < y + height; i++) { for (j = 0; j < width * 2; j += 2) { dev_info->backing_buffer[base + j] = (char)(col >> 8); dev_info->backing_buffer[base + j + 1] = (char)(col); dev_info->backing_buffer[base - dev_info->base16 + j] = (char)(col >> 8); dev_info->backing_buffer[base - dev_info->base16 + j + 1] = (char)(col); } if (dev_info->bufend - bufptr < BUF_HIGH_WATER_MARK) { ret = dlfb_bulk_msg(dev_info, bufptr - dev_info->buf); Loading Loading @@ -335,6 +370,111 @@ draw_rect(struct dlfb_data *dev_info, int x, int y, int width, int height, return 1; } static void swapfb(struct dlfb_data *dev_info) { int tmpbase; char *bufptr; mutex_lock(&dev_info->bulk_mutex); tmpbase = dev_info->base16; dev_info->base16 = dev_info->base16d; dev_info->base16d = tmpbase; bufptr = dev_info->buf; bufptr = dlfb_set_register(bufptr, 0xFF, 0x00); // set addresses bufptr = dlfb_set_register(bufptr, 0x20, (char)(dev_info->base16 >> 16)); bufptr = dlfb_set_register(bufptr, 0x21, (char)(dev_info->base16 >> 8)); bufptr = dlfb_set_register(bufptr, 0x22, (char)(dev_info->base16)); bufptr = dlfb_set_register(bufptr, 0xFF, 0x00); dlfb_bulk_msg(dev_info, bufptr - dev_info->buf); mutex_unlock(&dev_info->bulk_mutex); } static int copyfb(struct dlfb_data *dev_info) { int base; int source; int rem; int i, ret; char *bufptr; base = dev_info->base16d; mutex_lock(&dev_info->bulk_mutex); source = dev_info->base16; bufptr = dev_info->buf; for (i = 0; i < dev_info->info->var.yres; i++) { if (dev_info->bufend - bufptr < BUF_HIGH_WATER_MARK) { ret = dlfb_bulk_msg(dev_info, bufptr - dev_info->buf); bufptr = dev_info->buf; } rem = dev_info->info->var.xres; while (rem) { if (dev_info->bufend - bufptr < BUF_HIGH_WATER_MARK) { ret = dlfb_bulk_msg(dev_info, bufptr - dev_info->buf); bufptr = dev_info->buf; } *bufptr++ = 0xAF; *bufptr++ = 0x6A; *bufptr++ = (char)(base >> 16); *bufptr++ = (char)(base >> 8); *bufptr++ = (char)(base); if (rem > 255) { *bufptr++ = 255; *bufptr++ = (char)(source >> 16); *bufptr++ = (char)(source >> 8); *bufptr++ = (char)(source); rem -= 255; base += 255 * 2; source += 255 * 2; } else { *bufptr++ = rem; *bufptr++ = (char)(source >> 16); *bufptr++ = (char)(source >> 8); *bufptr++ = (char)(source); base += rem * 2; source += rem * 2; rem = 0; } } } if (bufptr > dev_info->buf) ret = dlfb_bulk_msg(dev_info, bufptr - dev_info->buf); mutex_unlock(&dev_info->bulk_mutex); return 1; } static int copyarea(struct dlfb_data *dev_info, int dx, int dy, int sx, int sy, int width, int height) Loading Loading @@ -362,7 +502,7 @@ copyarea(struct dlfb_data *dev_info, int dx, int dy, int sx, int sy, for (i = sy; i < sy + height; i++) { memcpy(dev_info->backing_buffer + base, memcpy(dev_info->backing_buffer + base - dev_info->base16, dev_info->backing_buffer + source, width * 2); if (dev_info->bufend - bufptr < BUF_HIGH_WATER_MARK) { Loading Loading @@ -447,7 +587,8 @@ static void dlfb_imageblit(struct fb_info *info, const struct fb_image *image) /* 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); */ } static void dlfb_fillrect(struct fb_info *info, const struct fb_fillrect *region) static void dlfb_fillrect(struct fb_info *info, const struct fb_fillrect *region) { unsigned char red, green, blue; Loading @@ -466,9 +607,18 @@ static int dlfb_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg) { struct dlfb_data *dev_info = info->par; struct dloarea *area; struct dloarea *area = NULL; if (cmd == 0xAA) { if (cmd == 0xAD) { char *edid = (char *)arg; dlfb_edid(dev_info); if (copy_to_user(edid, dev_info->edid, 128)) { return -EFAULT; } return 0; } if (cmd == 0xAA || cmd == 0xAB || cmd == 0xAC) { area = (struct dloarea *)arg; Loading @@ -483,10 +633,29 @@ static int dlfb_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg) if (area->y > info->var.yres) area->y = info->var.yres; } if (cmd == 0xAA) { image_blit(dev_info, area->x, area->y, area->w, area->h, info->screen_base); } if (cmd == 0xAC) { copyfb(dev_info); image_blit(dev_info, area->x, area->y, area->w, area->h, info->screen_base); swapfb(dev_info); } else if (cmd == 0xAB) { if (area->x2 < 0) area->x2 = 0; if (area->y2 < 0) area->y2 = 0; copyarea(dev_info, area->x2, area->y2, area->x, area->y, area->w, area->h); } return 0; } Loading Loading @@ -528,6 +697,19 @@ static int dlfb_release(struct fb_info *info, int user) static int dlfb_blank(int blank_mode, struct fb_info *info) { struct dlfb_data *dev_info = info->par; char *bufptr = dev_info->buf; bufptr = dlfb_set_register(bufptr, 0xFF, 0x00); if (blank_mode != FB_BLANK_UNBLANK) { bufptr = dlfb_set_register(bufptr, 0x1F, 0x01); } else { bufptr = dlfb_set_register(bufptr, 0x1F, 0x00); } bufptr = dlfb_set_register(bufptr, 0xFF, 0xFF); dlfb_bulk_msg(dev_info, bufptr - dev_info->buf); return 0; } Loading @@ -547,7 +729,6 @@ dlfb_probe(struct usb_interface *interface, const struct usb_device_id *id) { struct dlfb_data *dev_info; struct fb_info *info; int i; int ret; char rbuf[4]; Loading Loading @@ -588,15 +769,7 @@ dlfb_probe(struct usb_interface *interface, const struct usb_device_id *id) printk("ret control msg 0: %d %x%x%x%x\n", ret, rbuf[0], rbuf[1], rbuf[2], rbuf[3]); for (i = 0; i < 128; i++) { ret = usb_control_msg(dev_info->udev, usb_rcvctrlpipe(dev_info->udev, 0), (0x02), (0x80 | (0x02 << 5)), i << 8, 0xA1, rbuf, 2, 0); /* printk("ret control msg edid %d: %d [%d]\n",i, ret, rbuf[1]); */ dev_info->edid[i] = rbuf[1]; } dlfb_edid(dev_info); info = framebuffer_alloc(sizeof(u32) * 256, &dev_info->udev->dev); Loading @@ -609,8 +782,14 @@ dlfb_probe(struct usb_interface *interface, const struct usb_device_id *id) printk("EDID XRES %d YRES %d\n", info->var.xres, info->var.yres); if (dlfb_set_video_mode(dev_info, info->var.xres, info->var.yres) != 0) if (dlfb_set_video_mode(dev_info, info->var.xres, info->var.yres) != 0) { info->var.xres = 1280; info->var.yres = 1024; if (dlfb_set_video_mode (dev_info, info->var.xres, info->var.yres) != 0) { goto out; } } printk("found valid mode...%d\n", info->var.pixclock); Loading Loading @@ -661,7 +840,12 @@ dlfb_probe(struct usb_interface *interface, const struct usb_device_id *id) info->fix.smem_start = (unsigned long)info->screen_base; info->fix.smem_len = PAGE_ALIGN(dev_info->screen_size); memcpy(info->fix.id, "DisplayLink FB", 14); if (strlen(dev_info->udev->product) > 15) { memcpy(info->fix.id, dev_info->udev->product, 15); } else { memcpy(info->fix.id, dev_info->udev->product, strlen(dev_info->udev->product)); } info->fix.type = FB_TYPE_PACKED_PIXELS; info->fix.visual = FB_VISUAL_TRUECOLOR; info->fix.accel = info->flags; Loading drivers/staging/udlfb/udlfb.h +28 −1 Original line number Diff line number Diff line Loading @@ -26,7 +26,9 @@ struct dlfb_data { int line_length; struct completion done; int base16; int base16d; int base8; int base8d; }; struct dlfb_video_mode { Loading @@ -48,6 +50,24 @@ static void dlfb_bulk_callback(struct urb *urb) complete(&dev_info->done); } static void dlfb_edid(struct dlfb_data *dev_info) { int i; int ret; char rbuf[2]; for (i = 0; i < 128; i++) { ret = usb_control_msg(dev_info->udev, usb_rcvctrlpipe(dev_info->udev, 0), (0x02), (0x80 | (0x02 << 5)), i << 8, 0xA1, rbuf, 2, 0); /*printk("ret control msg edid %d: %d [%d]\n",i, ret, rbuf[1]); */ dev_info->edid[i] = rbuf[1]; } } static int dlfb_bulk_msg(struct dlfb_data *dev_info, int len) { int ret; Loading Loading @@ -129,8 +149,12 @@ static int dlfb_set_video_mode(struct dlfb_data *dev_info, int width, int height && dlfb_video_modes[i].yres == height) { dev_info->base16 = 0; dev_info->base16d = width * height * (FB_BPP / 8); dev_info->base8 = width * height * (FB_BPP / 8);; //dev_info->base8 = width * height * (FB_BPP / 8); dev_info->base8 = dev_info->base16; dev_info->base8d = dev_info->base16d; /* set encryption key (null) */ memcpy(dev_info->buf, STD_CHANNEL, 16); Loading @@ -144,6 +168,9 @@ static int dlfb_set_video_mode(struct dlfb_data *dev_info, int width, int height /* set registers */ bufptr = dlfb_set_register(bufptr, 0xFF, 0x00); /* set color depth */ bufptr = dlfb_set_register(bufptr, 0x00, 0x00); /* set addresses */ bufptr = dlfb_set_register(bufptr, 0x20, Loading Loading
drivers/staging/udlfb/udlfb.c +271 −87 Original line number Diff line number Diff line Loading @@ -7,6 +7,8 @@ * Based on the amazing work of Florian Echtler and libdlo 0.1 * * * * * * 10.06.09 release 0.2.3 (edid ioctl, fallback for unsupported modes) * * 05.06.09 release 0.2.2 (real screen blanking, rle compression, double buffer) * * 31.05.09 release 0.2 * * 22.05.09 First public (ugly) release * *****************************************************************************/ Loading Loading @@ -99,6 +101,7 @@ static int dlfb_mmap(struct fb_info *info, struct vm_area_struct *vma) struct dloarea { int x, y; int w, h; int x2, y2; }; /* Loading @@ -116,6 +119,37 @@ MODULE_DEVICE_TABLE(usb, id_table); static struct usb_driver dlfb_driver; // thanks to Henrik Bjerregaard Pedersen for this function static char *rle_compress16(uint16_t * src, char *dst, int rem) { int rl; uint16_t pix0; char *end_if_raw = dst + 6 + 2 * rem; dst += 6; // header will be filled in if RLE is worth it while (rem && dst < end_if_raw) { char *start = (char *)src; pix0 = *src++; rl = 1; rem--; while (rem && *src == pix0) rem--, rl++, src++; *dst++ = rl; *dst++ = start[1]; *dst++ = start[0]; } return dst; } /* Thanks to Henrik Bjerregaard Pedersen for rle implementation and code refactoring. Next step is huffman compression. */ static int image_blit(struct dlfb_data *dev_info, int x, int y, int width, int height, char *data) Loading @@ -125,7 +159,7 @@ image_blit(struct dlfb_data *dev_info, int x, int y, int width, int height, int rem = width; int ret; int diff; int firstdiff, thistime; char *bufptr; Loading @@ -137,7 +171,8 @@ image_blit(struct dlfb_data *dev_info, int x, int y, int width, int height, mutex_lock(&dev_info->bulk_mutex); base = dev_info->base16 + (dev_info->info->var.xres * 2 * y) + (x * 2); base = dev_info->base16 + ((dev_info->info->var.xres * 2 * y) + (x * 2)); data += (dev_info->info->var.xres * 2 * y) + (x * 2); Loading @@ -164,86 +199,84 @@ image_blit(struct dlfb_data *dev_info, int x, int y, int width, int height, bufptr - dev_info->buf); bufptr = dev_info->buf; } if (rem > 255) { diff = 0; for (j = 0; j < 510; j++) { if (dev_info-> backing_buffer[base + j] != data[j]) { diff = 1; // number of pixels to consider this time thistime = rem; if (thistime > 255) thistime = 255; // find position of first pixel that has changed firstdiff = -1; for (j = 0; j < thistime * 2; j++) { if (dev_info->backing_buffer [base - dev_info->base16 + j] != data[j]) { firstdiff = j / 2; break; } } if (diff == 1) { *bufptr++ = 0xAF; *bufptr++ = 0x68; if (firstdiff >= 0) { char *end_of_rle; *bufptr++ = (char)(base >> 16); *bufptr++ = (char)(base >> 8); *bufptr++ = (char)(base); *bufptr++ = 255; /* PUT COMPRESSION HERE */ for (j = 0; j < 510; j += 2) { bufptr[j] = data[j + 1]; bufptr[j + 1] = data[j]; } bufptr += 510; } end_of_rle = rle_compress16((uint16_t *) (data + firstdiff * 2), bufptr, thistime - firstdiff); rem -= 255; base += 510; data += 510; } else { if (end_of_rle < bufptr + 6 + 2 * (thistime - firstdiff)) { bufptr[0] = 0xAF; bufptr[1] = 0x69; diff = 0; bufptr[2] = (char)((base + firstdiff * 2) >> 16); bufptr[3] = (char)((base + firstdiff * 2) >> 8); bufptr[4] = (char)(base + firstdiff * 2); bufptr[5] = thistime - firstdiff; for (j = 0; j < rem * 2; j++) { if (dev_info-> backing_buffer[base + j] != data[j]) { diff = 1; break; } } if (diff == 1) { bufptr = end_of_rle; } else { // fallback to raw (or some other encoding?) *bufptr++ = 0xAF; *bufptr++ = 0x68; *bufptr++ = (char)(base >> 16); *bufptr++ = (char)(base >> 8); *bufptr++ = (char)(base); *bufptr++ = rem; /* PUT COMPRESSION HERE */ for (j = 0; j < rem * 2; j += 2) { bufptr[j] = data[j + 1]; bufptr[j + 1] = data[j]; *bufptr++ = (char)((base + firstdiff * 2) >> 16); *bufptr++ = (char)((base + firstdiff * 2) >> 8); *bufptr++ = (char)(base + firstdiff * 2); *bufptr++ = thistime - firstdiff; // PUT COMPRESSION HERE for (j = firstdiff * 2; j < thistime * 2; j += 2) { *bufptr++ = data[j + 1]; *bufptr++ = data[j]; } bufptr += rem * 2; } base += rem * 2; data += rem * 2; rem = 0; } base += thistime * 2; data += thistime * 2; rem -= thistime; } memcpy(dev_info->backing_buffer + base - (width * 2), data - (width * 2), width * 2); memcpy(dev_info->backing_buffer + (base - dev_info->base16) - (width * 2), data - (width * 2), width * 2); base += (dev_info->info->var.xres * 2) - (width * 2); data += (dev_info->info->var.xres * 2) - (width * 2); } if (bufptr > dev_info->buf) if (bufptr > dev_info->buf) { ret = dlfb_bulk_msg(dev_info, bufptr - dev_info->buf); } mutex_unlock(&dev_info->bulk_mutex); Loading Loading @@ -280,8 +313,10 @@ draw_rect(struct dlfb_data *dev_info, int x, int y, int width, int height, for (i = y; i < y + height; i++) { for (j = 0; j < width * 2; j += 2) { dev_info->backing_buffer[base + j] = (char)(col >> 8); dev_info->backing_buffer[base + j + 1] = (char)(col); dev_info->backing_buffer[base - dev_info->base16 + j] = (char)(col >> 8); dev_info->backing_buffer[base - dev_info->base16 + j + 1] = (char)(col); } if (dev_info->bufend - bufptr < BUF_HIGH_WATER_MARK) { ret = dlfb_bulk_msg(dev_info, bufptr - dev_info->buf); Loading Loading @@ -335,6 +370,111 @@ draw_rect(struct dlfb_data *dev_info, int x, int y, int width, int height, return 1; } static void swapfb(struct dlfb_data *dev_info) { int tmpbase; char *bufptr; mutex_lock(&dev_info->bulk_mutex); tmpbase = dev_info->base16; dev_info->base16 = dev_info->base16d; dev_info->base16d = tmpbase; bufptr = dev_info->buf; bufptr = dlfb_set_register(bufptr, 0xFF, 0x00); // set addresses bufptr = dlfb_set_register(bufptr, 0x20, (char)(dev_info->base16 >> 16)); bufptr = dlfb_set_register(bufptr, 0x21, (char)(dev_info->base16 >> 8)); bufptr = dlfb_set_register(bufptr, 0x22, (char)(dev_info->base16)); bufptr = dlfb_set_register(bufptr, 0xFF, 0x00); dlfb_bulk_msg(dev_info, bufptr - dev_info->buf); mutex_unlock(&dev_info->bulk_mutex); } static int copyfb(struct dlfb_data *dev_info) { int base; int source; int rem; int i, ret; char *bufptr; base = dev_info->base16d; mutex_lock(&dev_info->bulk_mutex); source = dev_info->base16; bufptr = dev_info->buf; for (i = 0; i < dev_info->info->var.yres; i++) { if (dev_info->bufend - bufptr < BUF_HIGH_WATER_MARK) { ret = dlfb_bulk_msg(dev_info, bufptr - dev_info->buf); bufptr = dev_info->buf; } rem = dev_info->info->var.xres; while (rem) { if (dev_info->bufend - bufptr < BUF_HIGH_WATER_MARK) { ret = dlfb_bulk_msg(dev_info, bufptr - dev_info->buf); bufptr = dev_info->buf; } *bufptr++ = 0xAF; *bufptr++ = 0x6A; *bufptr++ = (char)(base >> 16); *bufptr++ = (char)(base >> 8); *bufptr++ = (char)(base); if (rem > 255) { *bufptr++ = 255; *bufptr++ = (char)(source >> 16); *bufptr++ = (char)(source >> 8); *bufptr++ = (char)(source); rem -= 255; base += 255 * 2; source += 255 * 2; } else { *bufptr++ = rem; *bufptr++ = (char)(source >> 16); *bufptr++ = (char)(source >> 8); *bufptr++ = (char)(source); base += rem * 2; source += rem * 2; rem = 0; } } } if (bufptr > dev_info->buf) ret = dlfb_bulk_msg(dev_info, bufptr - dev_info->buf); mutex_unlock(&dev_info->bulk_mutex); return 1; } static int copyarea(struct dlfb_data *dev_info, int dx, int dy, int sx, int sy, int width, int height) Loading Loading @@ -362,7 +502,7 @@ copyarea(struct dlfb_data *dev_info, int dx, int dy, int sx, int sy, for (i = sy; i < sy + height; i++) { memcpy(dev_info->backing_buffer + base, memcpy(dev_info->backing_buffer + base - dev_info->base16, dev_info->backing_buffer + source, width * 2); if (dev_info->bufend - bufptr < BUF_HIGH_WATER_MARK) { Loading Loading @@ -447,7 +587,8 @@ static void dlfb_imageblit(struct fb_info *info, const struct fb_image *image) /* 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); */ } static void dlfb_fillrect(struct fb_info *info, const struct fb_fillrect *region) static void dlfb_fillrect(struct fb_info *info, const struct fb_fillrect *region) { unsigned char red, green, blue; Loading @@ -466,9 +607,18 @@ static int dlfb_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg) { struct dlfb_data *dev_info = info->par; struct dloarea *area; struct dloarea *area = NULL; if (cmd == 0xAA) { if (cmd == 0xAD) { char *edid = (char *)arg; dlfb_edid(dev_info); if (copy_to_user(edid, dev_info->edid, 128)) { return -EFAULT; } return 0; } if (cmd == 0xAA || cmd == 0xAB || cmd == 0xAC) { area = (struct dloarea *)arg; Loading @@ -483,10 +633,29 @@ static int dlfb_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg) if (area->y > info->var.yres) area->y = info->var.yres; } if (cmd == 0xAA) { image_blit(dev_info, area->x, area->y, area->w, area->h, info->screen_base); } if (cmd == 0xAC) { copyfb(dev_info); image_blit(dev_info, area->x, area->y, area->w, area->h, info->screen_base); swapfb(dev_info); } else if (cmd == 0xAB) { if (area->x2 < 0) area->x2 = 0; if (area->y2 < 0) area->y2 = 0; copyarea(dev_info, area->x2, area->y2, area->x, area->y, area->w, area->h); } return 0; } Loading Loading @@ -528,6 +697,19 @@ static int dlfb_release(struct fb_info *info, int user) static int dlfb_blank(int blank_mode, struct fb_info *info) { struct dlfb_data *dev_info = info->par; char *bufptr = dev_info->buf; bufptr = dlfb_set_register(bufptr, 0xFF, 0x00); if (blank_mode != FB_BLANK_UNBLANK) { bufptr = dlfb_set_register(bufptr, 0x1F, 0x01); } else { bufptr = dlfb_set_register(bufptr, 0x1F, 0x00); } bufptr = dlfb_set_register(bufptr, 0xFF, 0xFF); dlfb_bulk_msg(dev_info, bufptr - dev_info->buf); return 0; } Loading @@ -547,7 +729,6 @@ dlfb_probe(struct usb_interface *interface, const struct usb_device_id *id) { struct dlfb_data *dev_info; struct fb_info *info; int i; int ret; char rbuf[4]; Loading Loading @@ -588,15 +769,7 @@ dlfb_probe(struct usb_interface *interface, const struct usb_device_id *id) printk("ret control msg 0: %d %x%x%x%x\n", ret, rbuf[0], rbuf[1], rbuf[2], rbuf[3]); for (i = 0; i < 128; i++) { ret = usb_control_msg(dev_info->udev, usb_rcvctrlpipe(dev_info->udev, 0), (0x02), (0x80 | (0x02 << 5)), i << 8, 0xA1, rbuf, 2, 0); /* printk("ret control msg edid %d: %d [%d]\n",i, ret, rbuf[1]); */ dev_info->edid[i] = rbuf[1]; } dlfb_edid(dev_info); info = framebuffer_alloc(sizeof(u32) * 256, &dev_info->udev->dev); Loading @@ -609,8 +782,14 @@ dlfb_probe(struct usb_interface *interface, const struct usb_device_id *id) printk("EDID XRES %d YRES %d\n", info->var.xres, info->var.yres); if (dlfb_set_video_mode(dev_info, info->var.xres, info->var.yres) != 0) if (dlfb_set_video_mode(dev_info, info->var.xres, info->var.yres) != 0) { info->var.xres = 1280; info->var.yres = 1024; if (dlfb_set_video_mode (dev_info, info->var.xres, info->var.yres) != 0) { goto out; } } printk("found valid mode...%d\n", info->var.pixclock); Loading Loading @@ -661,7 +840,12 @@ dlfb_probe(struct usb_interface *interface, const struct usb_device_id *id) info->fix.smem_start = (unsigned long)info->screen_base; info->fix.smem_len = PAGE_ALIGN(dev_info->screen_size); memcpy(info->fix.id, "DisplayLink FB", 14); if (strlen(dev_info->udev->product) > 15) { memcpy(info->fix.id, dev_info->udev->product, 15); } else { memcpy(info->fix.id, dev_info->udev->product, strlen(dev_info->udev->product)); } info->fix.type = FB_TYPE_PACKED_PIXELS; info->fix.visual = FB_VISUAL_TRUECOLOR; info->fix.accel = info->flags; Loading
drivers/staging/udlfb/udlfb.h +28 −1 Original line number Diff line number Diff line Loading @@ -26,7 +26,9 @@ struct dlfb_data { int line_length; struct completion done; int base16; int base16d; int base8; int base8d; }; struct dlfb_video_mode { Loading @@ -48,6 +50,24 @@ static void dlfb_bulk_callback(struct urb *urb) complete(&dev_info->done); } static void dlfb_edid(struct dlfb_data *dev_info) { int i; int ret; char rbuf[2]; for (i = 0; i < 128; i++) { ret = usb_control_msg(dev_info->udev, usb_rcvctrlpipe(dev_info->udev, 0), (0x02), (0x80 | (0x02 << 5)), i << 8, 0xA1, rbuf, 2, 0); /*printk("ret control msg edid %d: %d [%d]\n",i, ret, rbuf[1]); */ dev_info->edid[i] = rbuf[1]; } } static int dlfb_bulk_msg(struct dlfb_data *dev_info, int len) { int ret; Loading Loading @@ -129,8 +149,12 @@ static int dlfb_set_video_mode(struct dlfb_data *dev_info, int width, int height && dlfb_video_modes[i].yres == height) { dev_info->base16 = 0; dev_info->base16d = width * height * (FB_BPP / 8); dev_info->base8 = width * height * (FB_BPP / 8);; //dev_info->base8 = width * height * (FB_BPP / 8); dev_info->base8 = dev_info->base16; dev_info->base8d = dev_info->base16d; /* set encryption key (null) */ memcpy(dev_info->buf, STD_CHANNEL, 16); Loading @@ -144,6 +168,9 @@ static int dlfb_set_video_mode(struct dlfb_data *dev_info, int width, int height /* set registers */ bufptr = dlfb_set_register(bufptr, 0xFF, 0x00); /* set color depth */ bufptr = dlfb_set_register(bufptr, 0x00, 0x00); /* set addresses */ bufptr = dlfb_set_register(bufptr, 0x20, Loading