Commit bb0f78dd authored by Dave Airlie's avatar Dave Airlie

Merge branch 'udl-fixes' into drm-next

Fixes for usb/udl devices
* udl-fixes:
  drm/udl: disable fb_defio by default
  drm/udl: Inline memcmp() for RLE compression of xfer
  drm/udl: make usage as a console safer
  drm/usb: bind driver to correct device
parents 62cd2fa8 677d23b7
...@@ -18,7 +18,7 @@ int drm_get_usb_dev(struct usb_interface *interface, ...@@ -18,7 +18,7 @@ int drm_get_usb_dev(struct usb_interface *interface,
usbdev = interface_to_usbdev(interface); usbdev = interface_to_usbdev(interface);
dev->usbdev = usbdev; dev->usbdev = usbdev;
dev->dev = &usbdev->dev; dev->dev = &interface->dev;
mutex_lock(&drm_global_mutex); mutex_lock(&drm_global_mutex);
......
...@@ -75,6 +75,8 @@ struct udl_framebuffer { ...@@ -75,6 +75,8 @@ struct udl_framebuffer {
struct drm_framebuffer base; struct drm_framebuffer base;
struct udl_gem_object *obj; struct udl_gem_object *obj;
bool active_16; /* active on the 16-bit channel */ bool active_16; /* active on the 16-bit channel */
int x1, y1, x2, y2; /* dirty rect */
spinlock_t dirty_lock;
}; };
#define to_udl_fb(x) container_of(x, struct udl_framebuffer, base) #define to_udl_fb(x) container_of(x, struct udl_framebuffer, base)
......
...@@ -22,9 +22,9 @@ ...@@ -22,9 +22,9 @@
#include <drm/drm_fb_helper.h> #include <drm/drm_fb_helper.h>
#define DL_DEFIO_WRITE_DELAY 5 /* fb_deferred_io.delay in jiffies */ #define DL_DEFIO_WRITE_DELAY (HZ/20) /* fb_deferred_io.delay in jiffies */
static int fb_defio = 1; /* Optionally enable experimental fb_defio mmap support */ static int fb_defio = 0; /* Optionally enable experimental fb_defio mmap support */
static int fb_bpp = 16; static int fb_bpp = 16;
module_param(fb_bpp, int, S_IWUSR | S_IRUSR | S_IWGRP | S_IRGRP); module_param(fb_bpp, int, S_IWUSR | S_IRUSR | S_IWGRP | S_IRGRP);
...@@ -153,6 +153,9 @@ int udl_handle_damage(struct udl_framebuffer *fb, int x, int y, ...@@ -153,6 +153,9 @@ int udl_handle_damage(struct udl_framebuffer *fb, int x, int y,
struct urb *urb; struct urb *urb;
int aligned_x; int aligned_x;
int bpp = (fb->base.bits_per_pixel / 8); int bpp = (fb->base.bits_per_pixel / 8);
int x2, y2;
bool store_for_later = false;
unsigned long flags;
if (!fb->active_16) if (!fb->active_16)
return 0; return 0;
...@@ -169,8 +172,6 @@ int udl_handle_damage(struct udl_framebuffer *fb, int x, int y, ...@@ -169,8 +172,6 @@ int udl_handle_damage(struct udl_framebuffer *fb, int x, int y,
} }
} }
start_cycles = get_cycles();
aligned_x = DL_ALIGN_DOWN(x, sizeof(unsigned long)); aligned_x = DL_ALIGN_DOWN(x, sizeof(unsigned long));
width = DL_ALIGN_UP(width + (x-aligned_x), sizeof(unsigned long)); width = DL_ALIGN_UP(width + (x-aligned_x), sizeof(unsigned long));
x = aligned_x; x = aligned_x;
...@@ -180,19 +181,53 @@ int udl_handle_damage(struct udl_framebuffer *fb, int x, int y, ...@@ -180,19 +181,53 @@ int udl_handle_damage(struct udl_framebuffer *fb, int x, int y,
(y + height > fb->base.height)) (y + height > fb->base.height))
return -EINVAL; return -EINVAL;
/* if we are in atomic just store the info
can't test inside spin lock */
if (in_atomic())
store_for_later = true;
x2 = x + width - 1;
y2 = y + height - 1;
spin_lock_irqsave(&fb->dirty_lock, flags);
if (fb->y1 < y)
y = fb->y1;
if (fb->y2 > y2)
y2 = fb->y2;
if (fb->x1 < x)
x = fb->x1;
if (fb->x2 > x2)
x2 = fb->x2;
if (store_for_later) {
fb->x1 = x;
fb->x2 = x2;
fb->y1 = y;
fb->y2 = y2;
spin_unlock_irqrestore(&fb->dirty_lock, flags);
return 0;
}
fb->x1 = fb->y1 = INT_MAX;
fb->x2 = fb->y2 = 0;
spin_unlock_irqrestore(&fb->dirty_lock, flags);
start_cycles = get_cycles();
urb = udl_get_urb(dev); urb = udl_get_urb(dev);
if (!urb) if (!urb)
return 0; return 0;
cmd = urb->transfer_buffer; cmd = urb->transfer_buffer;
for (i = y; i < y + height ; i++) { for (i = y; i <= y2 ; i++) {
const int line_offset = fb->base.pitches[0] * i; const int line_offset = fb->base.pitches[0] * i;
const int byte_offset = line_offset + (x * bpp); const int byte_offset = line_offset + (x * bpp);
const int dev_byte_offset = (fb->base.width * bpp * i) + (x * bpp); const int dev_byte_offset = (fb->base.width * bpp * i) + (x * bpp);
if (udl_render_hline(dev, bpp, &urb, if (udl_render_hline(dev, bpp, &urb,
(char *) fb->obj->vmapping, (char *) fb->obj->vmapping,
&cmd, byte_offset, dev_byte_offset, &cmd, byte_offset, dev_byte_offset,
width * bpp, (x2 - x + 1) * bpp,
&bytes_identical, &bytes_sent)) &bytes_identical, &bytes_sent))
goto error; goto error;
} }
...@@ -433,6 +468,7 @@ udl_framebuffer_init(struct drm_device *dev, ...@@ -433,6 +468,7 @@ udl_framebuffer_init(struct drm_device *dev,
{ {
int ret; int ret;
spin_lock_init(&ufb->dirty_lock);
ufb->obj = obj; ufb->obj = obj;
drm_helper_mode_fill_fb_struct(&ufb->base, mode_cmd); drm_helper_mode_fill_fb_struct(&ufb->base, mode_cmd);
ret = drm_framebuffer_init(dev, &ufb->base, &udlfb_funcs); ret = drm_framebuffer_init(dev, &ufb->base, &udlfb_funcs);
......
...@@ -75,15 +75,19 @@ static int udl_trim_hline(const u8 *bback, const u8 **bfront, int *width_bytes) ...@@ -75,15 +75,19 @@ static int udl_trim_hline(const u8 *bback, const u8 **bfront, int *width_bytes)
} }
#endif #endif
static inline u16 pixel32_to_be16p(const uint8_t *pixel) static inline u16 pixel32_to_be16(const uint32_t pixel)
{ {
uint32_t pix = *(uint32_t *)pixel; return (((pixel >> 3) & 0x001f) |
u16 retval; ((pixel >> 5) & 0x07e0) |
((pixel >> 8) & 0xf800));
}
retval = (((pix >> 3) & 0x001f) | static bool pixel_repeats(const void *pixel, const uint32_t repeat, int bpp)
((pix >> 5) & 0x07e0) | {
((pix >> 8) & 0xf800)); if (bpp == 2)
return retval; return *(const uint16_t *)pixel == repeat;
else
return *(const uint32_t *)pixel == repeat;
} }
/* /*
...@@ -152,29 +156,33 @@ static void udl_compress_hline16( ...@@ -152,29 +156,33 @@ static void udl_compress_hline16(
prefetch_range((void *) pixel, (cmd_pixel_end - pixel) * bpp); prefetch_range((void *) pixel, (cmd_pixel_end - pixel) * bpp);
while (pixel < cmd_pixel_end) { while (pixel < cmd_pixel_end) {
const u8 * const repeating_pixel = pixel; const u8 *const start = pixel;
u32 repeating_pixel;
if (bpp == 2)
*(uint16_t *)cmd = cpu_to_be16p((uint16_t *)pixel); if (bpp == 2) {
else if (bpp == 4) repeating_pixel = *(uint16_t *)pixel;
*(uint16_t *)cmd = cpu_to_be16(pixel32_to_be16p(pixel)); *(uint16_t *)cmd = cpu_to_be16(repeating_pixel);
} else {
repeating_pixel = *(uint32_t *)pixel;
*(uint16_t *)cmd = cpu_to_be16(pixel32_to_be16(repeating_pixel));
}
cmd += 2; cmd += 2;
pixel += bpp; pixel += bpp;
if (unlikely((pixel < cmd_pixel_end) && if (unlikely((pixel < cmd_pixel_end) &&
(!memcmp(pixel, repeating_pixel, bpp)))) { (pixel_repeats(pixel, repeating_pixel, bpp)))) {
/* go back and fill in raw pixel count */ /* go back and fill in raw pixel count */
*raw_pixels_count_byte = (((repeating_pixel - *raw_pixels_count_byte = (((start -
raw_pixel_start) / bpp) + 1) & 0xFF; raw_pixel_start) / bpp) + 1) & 0xFF;
while ((pixel < cmd_pixel_end) while ((pixel < cmd_pixel_end) &&
&& (!memcmp(pixel, repeating_pixel, bpp))) { (pixel_repeats(pixel, repeating_pixel, bpp))) {
pixel += bpp; pixel += bpp;
} }
/* immediately after raw data is repeat byte */ /* immediately after raw data is repeat byte */
*cmd++ = (((pixel - repeating_pixel) / bpp) - 1) & 0xFF; *cmd++ = (((pixel - start) / bpp) - 1) & 0xFF;
/* Then start another raw pixel span */ /* Then start another raw pixel span */
raw_pixel_start = pixel; raw_pixel_start = pixel;
...@@ -223,6 +231,8 @@ int udl_render_hline(struct drm_device *dev, int bpp, struct urb **urb_ptr, ...@@ -223,6 +231,8 @@ int udl_render_hline(struct drm_device *dev, int bpp, struct urb **urb_ptr,
u8 *cmd = *urb_buf_ptr; u8 *cmd = *urb_buf_ptr;
u8 *cmd_end = (u8 *) urb->transfer_buffer + urb->transfer_buffer_length; u8 *cmd_end = (u8 *) urb->transfer_buffer + urb->transfer_buffer_length;
BUG_ON(!(bpp == 2 || bpp == 4));
line_start = (u8 *) (front + byte_offset); line_start = (u8 *) (front + byte_offset);
next_pixel = line_start; next_pixel = line_start;
line_end = next_pixel + byte_width; line_end = next_pixel + byte_width;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment