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); |
165 | } else { | ||
166 | repeating_pixel = *(uint32_t *)pixel; | ||
167 | *(uint16_t *)cmd = cpu_to_be16(pixel32_to_be16(repeating_pixel)); | ||
168 | } | ||
161 | 169 | ||
162 | cmd += 2; | 170 | cmd += 2; |
163 | pixel += bpp; | 171 | pixel += bpp; |
164 | 172 | ||
165 | if (unlikely((pixel < cmd_pixel_end) && | 173 | if (unlikely((pixel < cmd_pixel_end) && |
166 | (!memcmp(pixel, repeating_pixel, bpp)))) { | 174 | (pixel_repeats(pixel, repeating_pixel, bpp)))) { |
167 | /* go back and fill in raw pixel count */ | 175 | /* go back and fill in raw pixel count */ |
168 | *raw_pixels_count_byte = (((repeating_pixel - | 176 | *raw_pixels_count_byte = (((start - |
169 | raw_pixel_start) / bpp) + 1) & 0xFF; | 177 | raw_pixel_start) / bpp) + 1) & 0xFF; |
170 | 178 | ||
171 | while ((pixel < cmd_pixel_end) | 179 | while ((pixel < cmd_pixel_end) && |
172 | && (!memcmp(pixel, repeating_pixel, bpp))) { | 180 | (pixel_repeats(pixel, repeating_pixel, bpp))) { |
173 | pixel += bpp; | 181 | pixel += bpp; |
174 | } | 182 | } |
175 | 183 | ||
176 | /* immediately after raw data is repeat byte */ | 184 | /* immediately after raw data is repeat byte */ |
177 | *cmd++ = (((pixel - repeating_pixel) / bpp) - 1) & 0xFF; | 185 | *cmd++ = (((pixel - start) / bpp) - 1) & 0xFF; |
178 | 186 | ||
179 | /* Then start another raw pixel span */ | 187 | /* Then start another raw pixel span */ |
180 | raw_pixel_start = pixel; | 188 | raw_pixel_start = pixel; |
@@ -223,6 +231,8 @@ int udl_render_hline(struct drm_device *dev, int bpp, struct urb **urb_ptr, | |||
223 | u8 *cmd = *urb_buf_ptr; | 231 | u8 *cmd = *urb_buf_ptr; |
224 | u8 *cmd_end = (u8 *) urb->transfer_buffer + urb->transfer_buffer_length; | 232 | u8 *cmd_end = (u8 *) urb->transfer_buffer + urb->transfer_buffer_length; |
225 | 233 | ||
234 | BUG_ON(!(bpp == 2 || bpp == 4)); | ||
235 | |||
226 | line_start = (u8 *) (front + byte_offset); | 236 | line_start = (u8 *) (front + byte_offset); |
227 | next_pixel = line_start; | 237 | next_pixel = line_start; |
228 | line_end = next_pixel + byte_width; | 238 | line_end = next_pixel + byte_width; |