diff options
Diffstat (limited to 'drivers/gpu/drm/udl/udl_fb.c')
-rw-r--r-- | drivers/gpu/drm/udl/udl_fb.c | 48 |
1 files changed, 42 insertions, 6 deletions
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); |