aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDave Airlie <airlied@redhat.com>2013-02-07 21:14:50 -0500
committerDave Airlie <airlied@redhat.com>2013-02-07 21:14:50 -0500
commitbb0f78dd7ded88082b2430c43c65bc821c4ea360 (patch)
tree715cdc73d1cdc145074ba76aa1765a4f7cf9b0c1
parent62cd2fa82a38cb3d653517822c62a39cdbb5f365 (diff)
parent677d23b70bf949f75746c80cbae92c233c6b5e2a (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.c2
-rw-r--r--drivers/gpu/drm/udl/udl_drv.h2
-rw-r--r--drivers/gpu/drm/udl/udl_fb.c48
-rw-r--r--drivers/gpu/drm/udl/udl_transfer.c46
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
27static int fb_defio = 1; /* Optionally enable experimental fb_defio mmap support */ 27static int fb_defio = 0; /* Optionally enable experimental fb_defio mmap support */
28static int fb_bpp = 16; 28static int fb_bpp = 16;
29 29
30module_param(fb_bpp, int, S_IWUSR | S_IRUSR | S_IWGRP | S_IRGRP); 30module_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
78static inline u16 pixel32_to_be16p(const uint8_t *pixel) 78static 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) | 85static 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;