|
@@ -153,6 +153,9 @@ int udl_handle_damage(struct udl_framebuffer *fb, int x, int y,
|
|
|
struct urb *urb;
|
|
|
int aligned_x;
|
|
|
int bpp = (fb->base.bits_per_pixel / 8);
|
|
|
+ int x2, y2;
|
|
|
+ bool store_for_later = false;
|
|
|
+ unsigned long flags;
|
|
|
|
|
|
if (!fb->active_16)
|
|
|
return 0;
|
|
@@ -169,8 +172,6 @@ int udl_handle_damage(struct udl_framebuffer *fb, int x, int y,
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- start_cycles = get_cycles();
|
|
|
-
|
|
|
aligned_x = DL_ALIGN_DOWN(x, sizeof(unsigned long));
|
|
|
width = DL_ALIGN_UP(width + (x-aligned_x), sizeof(unsigned long));
|
|
|
x = aligned_x;
|
|
@@ -180,19 +181,53 @@ int udl_handle_damage(struct udl_framebuffer *fb, int x, int y,
|
|
|
(y + height > fb->base.height))
|
|
|
return -EINVAL;
|
|
|
|
|
|
+ /* if we are in atomic just store the info
|
|
|
+ can't test inside spin lock */
|
|
|
+ if (in_atomic())
|
|
|
+ store_for_later = true;
|
|
|
+
|
|
|
+ x2 = x + width - 1;
|
|
|
+ y2 = y + height - 1;
|
|
|
+
|
|
|
+ spin_lock_irqsave(&fb->dirty_lock, flags);
|
|
|
+
|
|
|
+ if (fb->y1 < y)
|
|
|
+ y = fb->y1;
|
|
|
+ if (fb->y2 > y2)
|
|
|
+ y2 = fb->y2;
|
|
|
+ if (fb->x1 < x)
|
|
|
+ x = fb->x1;
|
|
|
+ if (fb->x2 > x2)
|
|
|
+ x2 = fb->x2;
|
|
|
+
|
|
|
+ if (store_for_later) {
|
|
|
+ fb->x1 = x;
|
|
|
+ fb->x2 = x2;
|
|
|
+ fb->y1 = y;
|
|
|
+ fb->y2 = y2;
|
|
|
+ spin_unlock_irqrestore(&fb->dirty_lock, flags);
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ fb->x1 = fb->y1 = INT_MAX;
|
|
|
+ fb->x2 = fb->y2 = 0;
|
|
|
+
|
|
|
+ spin_unlock_irqrestore(&fb->dirty_lock, flags);
|
|
|
+ start_cycles = get_cycles();
|
|
|
+
|
|
|
urb = udl_get_urb(dev);
|
|
|
if (!urb)
|
|
|
return 0;
|
|
|
cmd = urb->transfer_buffer;
|
|
|
|
|
|
- for (i = y; i < y + height ; i++) {
|
|
|
+ for (i = y; i <= y2 ; i++) {
|
|
|
const int line_offset = fb->base.pitches[0] * i;
|
|
|
const int byte_offset = line_offset + (x * bpp);
|
|
|
const int dev_byte_offset = (fb->base.width * bpp * i) + (x * bpp);
|
|
|
if (udl_render_hline(dev, bpp, &urb,
|
|
|
(char *) fb->obj->vmapping,
|
|
|
&cmd, byte_offset, dev_byte_offset,
|
|
|
- width * bpp,
|
|
|
+ (x2 - x + 1) * bpp,
|
|
|
&bytes_identical, &bytes_sent))
|
|
|
goto error;
|
|
|
}
|
|
@@ -434,6 +469,7 @@ udl_framebuffer_init(struct drm_device *dev,
|
|
|
{
|
|
|
int ret;
|
|
|
|
|
|
+ spin_lock_init(&ufb->dirty_lock);
|
|
|
ufb->obj = obj;
|
|
|
ret = drm_framebuffer_init(dev, &ufb->base, &udlfb_funcs);
|
|
|
drm_helper_mode_fill_fb_struct(&ufb->base, mode_cmd);
|