diff --git a/ms912x.h b/ms912x.h index fe6bf44..efa2223 100644 --- a/ms912x.h +++ b/ms912x.h @@ -26,7 +26,8 @@ struct ms912x_device { struct drm_connector connector; struct drm_simple_display_pipe display_pipe; - + + struct completion urb_completion; struct drm_rect update_rect; void *transfer_buffer; int num_urbs; diff --git a/ms912x_drv.c b/ms912x_drv.c index 2b85fc0..74577e4 100644 --- a/ms912x_drv.c +++ b/ms912x_drv.c @@ -162,7 +162,9 @@ int ms912x_pipe_check(struct drm_simple_display_pipe *pipe, return 0; } -static void ms912x_merge_rects(struct drm_rect* dest, struct drm_rect* r1, struct drm_rect* r2) { +static void ms912x_merge_rects(struct drm_rect *dest, struct drm_rect *r1, + struct drm_rect *r2) +{ dest->x1 = min(r1->x1, r2->x1); dest->y1 = min(r1->y1, r2->y1); dest->x2 = max(r1->x2, r2->x2); @@ -205,7 +207,8 @@ static const uint32_t ms912x_pipe_formats[] = { static int ms912x_usb_probe(struct usb_interface *interface, const struct usb_device_id *id) { - int ret, i; + int ret; + unsigned int i; struct ms912x_device *ms912x; struct drm_device *dev; @@ -243,7 +246,10 @@ static int ms912x_usb_probe(struct usb_interface *interface, ms912x_read_byte(ms912x, i); } - ms912x_init_urb(ms912x, 100 * MS912X_MAX_TRANSFER_LENGTH); + // Enough to send a full frame of 1920x1080 + ms912x_init_urb(ms912x, 64); + + init_completion(&ms912x->urb_completion); ret = ms912x_connector_init(ms912x); if (ret) diff --git a/ms912x_transfer.c b/ms912x_transfer.c index bf5d4ab..d65e6ea 100644 --- a/ms912x_transfer.c +++ b/ms912x_transfer.c @@ -8,7 +8,7 @@ void ms912x_free_urb(struct ms912x_device *ms912x) { - int i, blocks; + unsigned int i, blocks; struct ms912x_urb *urb_entry; struct usb_device *usb_dev = interface_to_usbdev(ms912x->intf); blocks = ms912x->num_urbs; @@ -39,17 +39,17 @@ void ms912x_urb_completion(struct urb *urb) list_add_tail(&urb_entry->entry, &ms912x->urb_available_list); spin_unlock_irqrestore(&ms912x->urb_available_list_lock, flags); up(&ms912x->urb_available_list_sem); + complete(&ms912x->urb_completion); } -int ms912x_init_urb(struct ms912x_device *ms912x, size_t total_size) +int ms912x_init_urb(struct ms912x_device *ms912x, size_t blocks) { - int i, blocks; + unsigned int i; struct ms912x_urb *urb_entry; struct urb *urb; void *urb_buf; struct usb_device *usb_dev = interface_to_usbdev(ms912x->intf); - blocks = DIV_ROUND_UP(total_size, MS912X_MAX_TRANSFER_LENGTH); spin_lock_init(&ms912x->urb_available_list_lock); INIT_LIST_HEAD(&ms912x->urb_available_list); sema_init(&ms912x->urb_available_list_sem, 0); @@ -106,29 +106,32 @@ struct urb *ms912x_get_urb(struct ms912x_device *ms912x) return urb_entry->urb; } -static inline int ms912x_rgb_to_y(int r, int g, int b) +static inline unsigned int ms912x_rgb_to_y(unsigned int r, unsigned int g, + unsigned int b) { - const int luma = (16 << 16) + 16763 * r + 32904 * g + 6391 * b; + const unsigned int luma = (16 << 16) + 16763 * r + 32904 * g + 6391 * b; return luma >> 16; } -static inline int ms912x_rgb_to_u(int r, int g, int b) +static inline unsigned int ms912x_rgb_to_u(unsigned int r, unsigned int g, + unsigned int b) { - const int u = (128 << 16) - 9676 * r - 18996 * g + 28672 * b; + const unsigned int u = (128 << 16) - 9676 * r - 18996 * g + 28672 * b; return u >> 16; } -static inline int ms912x_rgb_to_v(int r, int g, int b) +static inline unsigned int ms912x_rgb_to_v(unsigned int r, unsigned int g, + unsigned int b) { - const int v = (128 << 16) + 28672 * r - 24009 * g - 4663 * b; + const unsigned int v = (128 << 16) + 28672 * r - 24009 * g - 4663 * b; return v >> 16; } static int ms912x_xrgb_to_yuv422_line(u8 *transfer_buffer, u32 *xrgb_buffer, size_t len) { - int i, offset = 0; + unsigned int i, offset = 0; unsigned int pixel1, pixel2; - int r1, g1, b1, r2, g2, b2; - int v, y1, u, y2; + unsigned int r1, g1, b1, r2, g2, b2; + unsigned int v, y1, u, y2; for (i = 0; i < len; i += 2) { pixel1 = xrgb_buffer[i]; pixel2 = xrgb_buffer[i + 1]; @@ -218,6 +221,7 @@ void ms912x_fb_send_rect(struct drm_framebuffer *fb, transfer_blocks = DIV_ROUND_UP(total_length, MS912X_MAX_TRANSFER_LENGTH); + reinit_completion(&ms912x->urb_completion); for (i = 0; i < transfer_blocks; i++) { /* Last block may be shorter */ urb = ms912x_get_urb(ms912x); @@ -238,6 +242,12 @@ void ms912x_fb_send_rect(struct drm_framebuffer *fb, break; } } + for (i = 0; i < transfer_blocks; i++) { + if (!wait_for_completion_timeout(&ms912x->urb_completion, + msecs_to_jiffies(1000))) { + break; + } + } drm_gem_fb_end_cpu_access(fb, DMA_FROM_DEVICE); free_transfer_buffer: