diff options
| author | Dave Airlie <airlied@redhat.com> | 2013-02-07 21:14:50 -0500 |
|---|---|---|
| committer | Dave Airlie <airlied@redhat.com> | 2013-02-07 21:14:50 -0500 |
| commit | bb0f78dd7ded88082b2430c43c65bc821c4ea360 (patch) | |
| tree | 715cdc73d1cdc145074ba76aa1765a4f7cf9b0c1 | |
| parent | 62cd2fa82a38cb3d653517822c62a39cdbb5f365 (diff) | |
| parent | 677d23b70bf949f75746c80cbae92c233c6b5e2a (diff) | |
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
| -rw-r--r-- | drivers/gpu/drm/drm_usb.c | 2 | ||||
| -rw-r--r-- | drivers/gpu/drm/udl/udl_drv.h | 2 | ||||
| -rw-r--r-- | drivers/gpu/drm/udl/udl_fb.c | 48 | ||||
| -rw-r--r-- | drivers/gpu/drm/udl/udl_transfer.c | 46 |
4 files changed, 73 insertions, 25 deletions
diff --git a/drivers/gpu/drm/drm_usb.c b/drivers/gpu/drm/drm_usb.c index 3cec30611417..34a156f0c336 100644 --- a/drivers/gpu/drm/drm_usb.c +++ b/drivers/gpu/drm/drm_usb.c | |||
| @@ -18,7 +18,7 @@ int drm_get_usb_dev(struct usb_interface *interface, | |||
| 18 | 18 | ||
| 19 | usbdev = interface_to_usbdev(interface); | 19 | usbdev = interface_to_usbdev(interface); |
| 20 | dev->usbdev = usbdev; | 20 | dev->usbdev = usbdev; |
| 21 | dev->dev = &usbdev->dev; | 21 | dev->dev = &interface->dev; |
| 22 | 22 | ||
| 23 | mutex_lock(&drm_global_mutex); | 23 | mutex_lock(&drm_global_mutex); |
| 24 | 24 | ||
diff --git a/drivers/gpu/drm/udl/udl_drv.h b/drivers/gpu/drm/udl/udl_drv.h index 87aa5f5d3c88..cc6d90f28c71 100644 --- a/drivers/gpu/drm/udl/udl_drv.h +++ b/drivers/gpu/drm/udl/udl_drv.h | |||
| @@ -75,6 +75,8 @@ struct udl_framebuffer { | |||
| 75 | struct drm_framebuffer base; | 75 | struct drm_framebuffer base; |
| 76 | struct udl_gem_object *obj; | 76 | struct udl_gem_object *obj; |
| 77 | bool active_16; /* active on the 16-bit channel */ | 77 | bool active_16; /* active on the 16-bit channel */ |
| 78 | int x1, y1, x2, y2; /* dirty rect */ | ||
| 79 | spinlock_t dirty_lock; | ||
| 78 | }; | 80 | }; |
| 79 | 81 | ||
| 80 | #define to_udl_fb(x) container_of(x, struct udl_framebuffer, base) | 82 | #define to_udl_fb(x) container_of(x, struct udl_framebuffer, base) |
diff --git a/drivers/gpu/drm/udl/udl_fb.c b/drivers/gpu/drm/udl/udl_fb.c index caa84f1de9c1..b9feec9d08d3 100644 --- a/drivers/gpu/drm/udl/udl_fb.c +++ b/drivers/gpu/drm/udl/udl_fb.c | |||
| @@ -22,9 +22,9 @@ | |||
| 22 | 22 | ||
| 23 | #include <drm/drm_fb_helper.h> | 23 | #include <drm/drm_fb_helper.h> |
| 24 | 24 | ||
| 25 | #define DL_DEFIO_WRITE_DELAY 5 /* fb_deferred_io.delay in jiffies */ | 25 | #define DL_DEFIO_WRITE_DELAY (HZ/20) /* fb_deferred_io.delay in jiffies */ |
| 26 | 26 | ||
| 27 | static int fb_defio = 1; /* Optionally enable experimental fb_defio mmap support */ | 27 | static int fb_defio = 0; /* Optionally enable experimental fb_defio mmap support */ |
| 28 | static int fb_bpp = 16; | 28 | static int fb_bpp = 16; |
| 29 | 29 | ||
| 30 | module_param(fb_bpp, int, S_IWUSR | S_IRUSR | S_IWGRP | S_IRGRP); | 30 | 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 | struct urb *urb; | 153 | struct urb *urb; |
| 154 | int aligned_x; | 154 | int aligned_x; |
| 155 | int bpp = (fb->base.bits_per_pixel / 8); | 155 | int bpp = (fb->base.bits_per_pixel / 8); |
| 156 | int x2, y2; | ||
| 157 | bool store_for_later = false; | ||
| 158 | unsigned long flags; | ||
| 156 | 159 | ||
| 157 | if (!fb->active_16) | 160 | if (!fb->active_16) |
| 158 | return 0; | 161 | return 0; |
| @@ -169,8 +172,6 @@ int udl_handle_damage(struct udl_framebuffer *fb, int x, int y, | |||
| 169 | } | 172 | } |
| 170 | } | 173 | } |
| 171 | 174 | ||
| 172 | start_cycles = get_cycles(); | ||
| 173 | |||
| 174 | aligned_x = DL_ALIGN_DOWN(x, sizeof(unsigned long)); | 175 | aligned_x = DL_ALIGN_DOWN(x, sizeof(unsigned long)); |
| 175 | width = DL_ALIGN_UP(width + (x-aligned_x), sizeof(unsigned long)); | 176 | width = DL_ALIGN_UP(width + (x-aligned_x), sizeof(unsigned long)); |
| 176 | x = aligned_x; | 177 | x = aligned_x; |
| @@ -180,19 +181,53 @@ int udl_handle_damage(struct udl_framebuffer *fb, int x, int y, | |||
| 180 | (y + height > fb->base.height)) | 181 | (y + height > fb->base.height)) |
| 181 | return -EINVAL; | 182 | return -EINVAL; |
| 182 | 183 | ||
| 184 | /* if we are in atomic just store the info | ||
| 185 | can't test inside spin lock */ | ||
| 186 | if (in_atomic()) | ||
| 187 | store_for_later = true; | ||
| 188 | |||
| 189 | x2 = x + width - 1; | ||
| 190 | y2 = y + height - 1; | ||
| 191 | |||
| 192 | spin_lock_irqsave(&fb->dirty_lock, flags); | ||
| 193 | |||
| 194 | if (fb->y1 < y) | ||
| 195 | y = fb->y1; | ||
| 196 | if (fb->y2 > y2) | ||
| 197 | y2 = fb->y2; | ||
| 198 | if (fb->x1 < x) | ||
| 199 | x = fb->x1; | ||
| 200 | if (fb->x2 > x2) | ||
| 201 | x2 = fb->x2; | ||
| 202 | |||
| 203 | if (store_for_later) { | ||
| 204 | fb->x1 = x; | ||
| 205 | fb->x2 = x2; | ||
| 206 | fb->y1 = y; | ||
| 207 | fb->y2 = y2; | ||
| 208 | spin_unlock_irqrestore(&fb->dirty_lock, flags); | ||
| 209 | return 0; | ||
| 210 | } | ||
| 211 | |||
| 212 | fb->x1 = fb->y1 = INT_MAX; | ||
| 213 | fb->x2 = fb->y2 = 0; | ||
| 214 | |||
| 215 | spin_unlock_irqrestore(&fb->dirty_lock, flags); | ||
| 216 | start_cycles = get_cycles(); | ||
| 217 | |||
| 183 | urb = udl_get_urb(dev); | 218 | urb = udl_get_urb(dev); |
| 184 | if (!urb) | 219 | if (!urb) |
| 185 | return 0; | 220 | return 0; |
| 186 | cmd = urb->transfer_buffer; | 221 | cmd = urb->transfer_buffer; |
| 187 | 222 | ||
| 188 | for (i = y; i < y + height ; i++) { | 223 | for (i = y; i <= y2 ; i++) { |
| 189 | const int line_offset = fb->base.pitches[0] * i; | 224 | const int line_offset = fb->base.pitches[0] * i; |
| 190 | const int byte_offset = line_offset + (x * bpp); | 225 | const int byte_offset = line_offset + (x * bpp); |
| 191 | const int dev_byte_offset = (fb->base.width * bpp * i) + (x * bpp); | 226 | const int dev_byte_offset = (fb->base.width * bpp * i) + (x * bpp); |
| 192 | if (udl_render_hline(dev, bpp, &urb, | 227 | if (udl_render_hline(dev, bpp, &urb, |
| 193 | (char *) fb->obj->vmapping, | 228 | (char *) fb->obj->vmapping, |
| 194 | &cmd, byte_offset, dev_byte_offset, | 229 | &cmd, byte_offset, dev_byte_offset, |
| 195 | width * bpp, | 230 | (x2 - x + 1) * bpp, |
| 196 | &bytes_identical, &bytes_sent)) | 231 | &bytes_identical, &bytes_sent)) |
| 197 | goto error; | 232 | goto error; |
| 198 | } | 233 | } |
| @@ -433,6 +468,7 @@ udl_framebuffer_init(struct drm_device *dev, | |||
| 433 | { | 468 | { |
| 434 | int ret; | 469 | int ret; |
| 435 | 470 | ||
| 471 | spin_lock_init(&ufb->dirty_lock); | ||
| 436 | ufb->obj = obj; | 472 | ufb->obj = obj; |
| 437 | drm_helper_mode_fill_fb_struct(&ufb->base, mode_cmd); | 473 | drm_helper_mode_fill_fb_struct(&ufb->base, mode_cmd); |
| 438 | ret = drm_framebuffer_init(dev, &ufb->base, &udlfb_funcs); | 474 | ret = drm_framebuffer_init(dev, &ufb->base, &udlfb_funcs); |
diff --git a/drivers/gpu/drm/udl/udl_transfer.c b/drivers/gpu/drm/udl/udl_transfer.c index 142fee5f983f..f343db73e095 100644 --- a/drivers/gpu/drm/udl/udl_transfer.c +++ b/drivers/gpu/drm/udl/udl_transfer.c | |||
| @@ -75,15 +75,19 @@ static int udl_trim_hline(const u8 *bback, const u8 **bfront, int *width_bytes) | |||
| 75 | } | 75 | } |
| 76 | #endif | 76 | #endif |
| 77 | 77 | ||
| 78 | static inline u16 pixel32_to_be16p(const uint8_t *pixel) | 78 | static inline u16 pixel32_to_be16(const uint32_t pixel) |
| 79 | { | 79 | { |
| 80 | uint32_t pix = *(uint32_t *)pixel; | 80 | return (((pixel >> 3) & 0x001f) | |
| 81 | u16 retval; | 81 | ((pixel >> 5) & 0x07e0) | |
| 82 | ((pixel >> 8) & 0xf800)); | ||
| 83 | } | ||
| 82 | 84 | ||
| 83 | retval = (((pix >> 3) & 0x001f) | | 85 | static bool pixel_repeats(const void *pixel, const uint32_t repeat, int bpp) |
| 84 | ((pix >> 5) & 0x07e0) | | 86 | { |
| 85 | ((pix >> 8) & 0xf800)); | 87 | if (bpp == 2) |
| 86 | return retval; | 88 | return *(const uint16_t *)pixel == repeat; |
| 89 | else | ||
| 90 | return *(const uint32_t *)pixel == repeat; | ||
| 87 | } | 91 | } |
| 88 | 92 | ||
| 89 | /* | 93 | /* |
| @@ -152,29 +156,33 @@ static void udl_compress_hline16( | |||
| 152 | prefetch_range((void *) pixel, (cmd_pixel_end - pixel) * bpp); | 156 | prefetch_range((void *) pixel, (cmd_pixel_end - pixel) * bpp); |
| 153 | 157 | ||
| 154 | while (pixel < cmd_pixel_end) { | 158 | while (pixel < cmd_pixel_end) { |
| 155 | const u8 * const repeating_pixel = pixel; | 159 | const u8 *const start = pixel; |
| 156 | 160 | u32 repeating_pixel; | |
| 157 | if (bpp == 2) | 161 | |
| 158 | *(uint16_t *)cmd = cpu_to_be16p((uint16_t *)pixel); | 162 | if (bpp == 2) { |
| 159 | else if (bpp == 4) | 163 | repeating_pixel = *(uint16_t *)pixel; |
| 160 | *(uint16_t *)cmd = cpu_to_be16(pixel32_to_be16p(pixel)); | 164 | *(uint16_t *)cmd = cpu_to_be16(repeating_pixel); |
