aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/udl/udl_fb.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/udl/udl_fb.c')
-rw-r--r--drivers/gpu/drm/udl/udl_fb.c48
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
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);