diff options
| author | Dave Airlie <airlied@redhat.com> | 2013-02-08 12:14:50 +1000 | 
|---|---|---|
| committer | Dave Airlie <airlied@redhat.com> | 2013-02-08 12:14:50 +1000 | 
| commit | bb0f78dd7ded88082b2430c43c65bc821c4ea360 (patch) | |
| tree | 715cdc73d1cdc145074ba76aa1765a4f7cf9b0c1 /drivers | |
| parent | 62cd2fa82a38cb3d653517822c62a39cdbb5f365 (diff) | |
| parent | 677d23b70bf949f75746c80cbae92c233c6b5e2a (diff) | |
| download | olio-linux-3.10-bb0f78dd7ded88082b2430c43c65bc821c4ea360.tar.xz olio-linux-3.10-bb0f78dd7ded88082b2430c43c65bc821c4ea360.zip  | |
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
Diffstat (limited to 'drivers')
| -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 | 44 | 
4 files changed, 72 insertions, 24 deletions
diff --git a/drivers/gpu/drm/drm_usb.c b/drivers/gpu/drm/drm_usb.c index 3cec3061141..34a156f0c33 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,  	usbdev = interface_to_usbdev(interface);  	dev->usbdev = usbdev; -	dev->dev = &usbdev->dev; +	dev->dev = &interface->dev;  	mutex_lock(&drm_global_mutex); diff --git a/drivers/gpu/drm/udl/udl_drv.h b/drivers/gpu/drm/udl/udl_drv.h index 87aa5f5d3c8..cc6d90f28c7 100644 --- a/drivers/gpu/drm/udl/udl_drv.h +++ b/drivers/gpu/drm/udl/udl_drv.h @@ -75,6 +75,8 @@ struct udl_framebuffer {  	struct drm_framebuffer base;  	struct udl_gem_object *obj;  	bool active_16; /* active on the 16-bit channel */ +	int x1, y1, x2, y2; /* dirty rect */ +	spinlock_t dirty_lock;  };  #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 caa84f1de9c..b9feec9d08d 100644 --- a/drivers/gpu/drm/udl/udl_fb.c +++ b/drivers/gpu/drm/udl/udl_fb.c @@ -22,9 +22,9 @@  #include <drm/drm_fb_helper.h> -#define DL_DEFIO_WRITE_DELAY    5 /* fb_deferred_io.delay in jiffies */ +#define DL_DEFIO_WRITE_DELAY    (HZ/20) /* fb_deferred_io.delay in jiffies */ -static int fb_defio = 1;  /* Optionally enable experimental fb_defio mmap support */ +static int fb_defio = 0;  /* Optionally enable experimental fb_defio mmap support */  static int fb_bpp = 16;  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,  	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;  	} @@ -433,6 +468,7 @@ udl_framebuffer_init(struct drm_device *dev,  {  	int ret; +	spin_lock_init(&ufb->dirty_lock);  	ufb->obj = obj;  	drm_helper_mode_fill_fb_struct(&ufb->base, mode_cmd);  	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 142fee5f983..f343db73e09 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)  }  #endif -static inline u16 pixel32_to_be16p(const uint8_t *pixel) +static inline u16 pixel32_to_be16(const uint32_t pixel)  { -	uint32_t pix = *(uint32_t *)pixel; -	u16 retval; +	return (((pixel >> 3) & 0x001f) | +		((pixel >> 5) & 0x07e0) | +		((pixel >> 8) & 0xf800)); +} -	retval =  (((pix >> 3) & 0x001f) | -		   ((pix >> 5) & 0x07e0) | -		   ((pix >> 8) & 0xf800)); -	return retval; +static bool pixel_repeats(const void *pixel, const uint32_t repeat, int bpp) +{ +	if (bpp == 2) +		return *(const uint16_t *)pixel == repeat; +	else +		return *(const uint32_t *)pixel == repeat;  }  /* @@ -152,29 +156,33 @@ static void udl_compress_hline16(  		prefetch_range((void *) pixel, (cmd_pixel_end - pixel) * bpp);  		while (pixel < cmd_pixel_end) { -			const u8 * const repeating_pixel = pixel; +			const u8 *const start = pixel; +			u32 repeating_pixel; -			if (bpp == 2) -				*(uint16_t *)cmd = cpu_to_be16p((uint16_t *)pixel); -			else if (bpp == 4) -				*(uint16_t *)cmd = cpu_to_be16(pixel32_to_be16p(pixel)); +			if (bpp == 2) { +				repeating_pixel = *(uint16_t *)pixel; +				*(uint16_t *)cmd = cpu_to_be16(repeating_pixel); +			} else { +				repeating_pixel = *(uint32_t *)pixel; +				*(uint16_t *)cmd = cpu_to_be16(pixel32_to_be16(repeating_pixel)); +			}  			cmd += 2;  			pixel += bpp;  			if (unlikely((pixel < cmd_pixel_end) && -				     (!memcmp(pixel, repeating_pixel, bpp)))) { +				     (pixel_repeats(pixel, repeating_pixel, bpp)))) {  				/* go back and fill in raw pixel count */ -				*raw_pixels_count_byte = (((repeating_pixel - +				*raw_pixels_count_byte = (((start -  						raw_pixel_start) / bpp) + 1) & 0xFF; -				while ((pixel < cmd_pixel_end) -				       && (!memcmp(pixel, repeating_pixel, bpp))) { +				while ((pixel < cmd_pixel_end) && +				       (pixel_repeats(pixel, repeating_pixel, bpp))) {  					pixel += bpp;  				}  				/* immediately after raw data is repeat byte */ -				*cmd++ = (((pixel - repeating_pixel) / bpp) - 1) & 0xFF; +				*cmd++ = (((pixel - start) / bpp) - 1) & 0xFF;  				/* Then start another raw pixel span */  				raw_pixel_start = pixel; @@ -223,6 +231,8 @@ int udl_render_hline(struct drm_device *dev, int bpp, struct urb **urb_ptr,  	u8 *cmd = *urb_buf_ptr;  	u8 *cmd_end = (u8 *) urb->transfer_buffer + urb->transfer_buffer_length; +	BUG_ON(!(bpp == 2 || bpp == 4)); +  	line_start = (u8 *) (front + byte_offset);  	next_pixel = line_start;  	line_end = next_pixel + byte_width;  |