Lines Matching +full:interface +full:- +full:pix +full:- +full:fmt
1 // SPDX-License-Identifier: GPL-2.0-only
3 * smscufx.c -- Framebuffer driver for SMSC UFX USB controller
13 * Works well with Bernie Thompson's X DAMAGE patch to xf86-video-fbdev
17 * usb-skeleton by GregKH.
20 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt argument
34 #define check_warn(status, fmt, args...) \ argument
35 ({ if (status < 0) pr_warn(fmt, ##args); })
37 #define check_warn_return(status, fmt, args...) \ argument
38 ({ if (status < 0) { pr_warn(fmt, ##args); return status; } })
40 #define check_warn_goto_error(status, fmt, args...) \ argument
41 ({ if (status < 0) { pr_warn(fmt, ##args); goto error; } })
52 * DisplayLink X server as yet - need both to be modified in tandem
58 /* -BULK_SIZE as per usb-skeleton. Can we get full page and avoid overhead? */
60 #define MAX_TRANSFER (PAGE_SIZE*16 - BULK_SIZE)
94 struct device *gdev; /* &udev->dev */
150 return -ENOMEM; in ufx_reg_read()
152 ret = usb_control_msg(dev->udev, usb_rcvctrlpipe(dev->udev, 0), in ufx_reg_read()
176 return -ENOMEM; in ufx_reg_write()
181 ret = usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, 0), in ufx_reg_write()
234 return (value == 0) ? 0 : -EIO; in ufx_lite_reset()
271 return -EIO; in ufx_blank()
308 return -EIO; in ufx_unblank()
345 return -EIO; in ufx_disable()
382 return -EIO; in ufx_enable()
492 return -ETIMEDOUT; in ufx_config_ddr2()
579 int error = abs(pllout_freq1 - clk_pixel_pll); in ufx_calc_pll_values()
590 /* final returned value is equal to calculated value - 1 in ufx_calc_pll_values()
592 asic_pll->div_r0 = div_r0 - 1; in ufx_calc_pll_values()
593 asic_pll->div_f0 = div_f0 - 1; in ufx_calc_pll_values()
594 asic_pll->div_q0 = div_q0; in ufx_calc_pll_values()
595 asic_pll->div_r1 = div_r1 - 1; in ufx_calc_pll_values()
596 asic_pll->div_f1 = div_f1 - 1; in ufx_calc_pll_values()
597 asic_pll->div_q1 = div_q1; in ufx_calc_pll_values()
599 asic_pll->range0 = ufx_calc_range(ref_freq0); in ufx_calc_pll_values()
600 asic_pll->range1 = ufx_calc_range(ref_freq1); in ufx_calc_pll_values()
678 status = ufx_config_pix_clk(dev, var->pixclock); in ufx_set_vid_mode()
685 h_total = var->xres + var->right_margin + var->hsync_len + var->left_margin; in ufx_set_vid_mode()
686 h_active = var->xres; in ufx_set_vid_mode()
687 h_blank_start = var->xres + var->right_margin; in ufx_set_vid_mode()
688 h_blank_end = var->xres + var->right_margin + var->hsync_len; in ufx_set_vid_mode()
689 h_sync_start = var->xres + var->right_margin; in ufx_set_vid_mode()
690 h_sync_end = var->xres + var->right_margin + var->hsync_len; in ufx_set_vid_mode()
692 temp = ((h_total - 1) << 16) | (h_active - 1); in ufx_set_vid_mode()
696 temp = ((h_blank_start - 1) << 16) | (h_blank_end - 1); in ufx_set_vid_mode()
700 temp = ((h_sync_start - 1) << 16) | (h_sync_end - 1); in ufx_set_vid_mode()
705 v_total = var->upper_margin + var->yres + var->lower_margin + var->vsync_len; in ufx_set_vid_mode()
706 v_active = var->yres; in ufx_set_vid_mode()
707 v_blank_start = var->yres + var->lower_margin; in ufx_set_vid_mode()
708 v_blank_end = var->yres + var->lower_margin + var->vsync_len; in ufx_set_vid_mode()
709 v_sync_start = var->yres + var->lower_margin; in ufx_set_vid_mode()
710 v_sync_end = var->yres + var->lower_margin + var->vsync_len; in ufx_set_vid_mode()
712 temp = ((v_total - 1) << 16) | (v_active - 1); in ufx_set_vid_mode()
716 temp = ((v_blank_start - 1) << 16) | (v_blank_end - 1); in ufx_set_vid_mode()
720 temp = ((v_sync_start - 1) << 16) | (v_sync_end - 1); in ufx_set_vid_mode()
730 /* Set the frame length register (#pix * 2 bytes/pixel) */ in ufx_set_vid_mode()
731 temp = var->xres * var->yres * 2; in ufx_set_vid_mode()
736 /* enable desired output interface & disable others */ in ufx_set_vid_mode()
748 if (var->sync & FB_SYNC_HOR_HIGH_ACT) in ufx_set_vid_mode()
751 if (var->sync & FB_SYNC_VERT_HIGH_ACT) in ufx_set_vid_mode()
778 unsigned long start = vma->vm_start; in ufx_ops_mmap()
779 unsigned long size = vma->vm_end - vma->vm_start; in ufx_ops_mmap()
780 unsigned long offset = vma->vm_pgoff << PAGE_SHIFT; in ufx_ops_mmap()
783 if (info->fbdefio) in ufx_ops_mmap()
786 vma->vm_page_prot = pgprot_decrypted(vma->vm_page_prot); in ufx_ops_mmap()
788 if (vma->vm_pgoff > (~0UL >> PAGE_SHIFT)) in ufx_ops_mmap()
789 return -EINVAL; in ufx_ops_mmap()
790 if (size > info->fix.smem_len) in ufx_ops_mmap()
791 return -EINVAL; in ufx_ops_mmap()
792 if (offset > info->fix.smem_len - size) in ufx_ops_mmap()
793 return -EINVAL; in ufx_ops_mmap()
795 pos = (unsigned long)info->fix.smem_start + offset; in ufx_ops_mmap()
803 return -EAGAIN; in ufx_ops_mmap()
808 size -= PAGE_SIZE; in ufx_ops_mmap()
824 BUG_ON(!dev->info); in ufx_raw_rect()
841 cmd[10] = cpu_to_le16(0x4000 | dev->info->var.xres); in ufx_raw_rect()
844 cmd[11] = cpu_to_le16(dev->info->var.yres); in ufx_raw_rect()
848 const int line_offset = dev->info->fix.line_length * (y + line); in ufx_raw_rect()
851 (char *)dev->info->fix.smem_start + byte_offset, width * BPP); in ufx_raw_rect()
862 (x + width > dev->info->var.xres) || in ufx_handle_damage()
863 (y + height > dev->info->var.yres)) in ufx_handle_damage()
864 return -EINVAL; in ufx_handle_damage()
866 if (!atomic_read(&dev->usb_active)) in ufx_handle_damage()
877 BUG_ON(urb->transfer_buffer_length < (24 + (width * 2))); in ufx_handle_damage()
880 urb_lines = (urb->transfer_buffer_length - 24) / packed_line_len; in ufx_handle_damage()
883 urb_lines = min(urb_lines, (height - start_line)); in ufx_handle_damage()
885 memset(urb->transfer_buffer, 0, urb->transfer_buffer_length); in ufx_handle_damage()
887 ufx_raw_rect(dev, urb->transfer_buffer, x, (y + start_line), width, urb_lines); in ufx_handle_damage()
899 /* NOTE: fb_defio.c is holding info->fbdefio.mutex
905 struct ufx_data *dev = info->par; in ufx_dpy_deferred_io()
911 if (!atomic_read(&dev->usb_active)) in ufx_dpy_deferred_io()
919 const int width = dev->info->var.xres; in ufx_dpy_deferred_io()
920 const int y = pageref->offset / (width * 2); in ufx_dpy_deferred_io()
922 height = min(height, (int)(dev->info->var.yres - y)); in ufx_dpy_deferred_io()
924 BUG_ON(y >= dev->info->var.yres); in ufx_dpy_deferred_io()
925 BUG_ON((y + height) > dev->info->var.yres); in ufx_dpy_deferred_io()
934 struct ufx_data *dev = info->par; in ufx_ops_ioctl()
937 if (!atomic_read(&dev->usb_active)) in ufx_ops_ioctl()
943 if (copy_to_user(edid, dev->edid, dev->edid_size)) in ufx_ops_ioctl()
944 return -EFAULT; in ufx_ops_ioctl()
950 /* If we have a damage-aware client, turn fb_defio "off" in ufx_ops_ioctl()
956 if (info->fbdefio) in ufx_ops_ioctl()
957 info->fbdefio->delay = UFX_DEFIO_WRITE_DISABLE; in ufx_ops_ioctl()
961 if (area->x < 0) in ufx_ops_ioctl()
962 area->x = 0; in ufx_ops_ioctl()
964 if (area->x > info->var.xres) in ufx_ops_ioctl()
965 area->x = info->var.xres; in ufx_ops_ioctl()
967 if (area->y < 0) in ufx_ops_ioctl()
968 area->y = 0; in ufx_ops_ioctl()
970 if (area->y > info->var.yres) in ufx_ops_ioctl()
971 area->y = info->var.yres; in ufx_ops_ioctl()
973 ufx_handle_damage(dev, area->x, area->y, area->w, area->h); in ufx_ops_ioctl()
986 if (regno >= info->cmap.len) in ufx_ops_setcolreg()
990 if (info->var.red.offset == 10) { in ufx_ops_setcolreg()
992 ((u32 *) (info->pseudo_palette))[regno] = in ufx_ops_setcolreg()
997 ((u32 *) (info->pseudo_palette))[regno] = in ufx_ops_setcolreg()
1008 * Assumes caller is holding info->lock (for open and release at least) */
1011 struct ufx_data *dev = info->par; in ufx_ops_open()
1017 return -EBUSY; in ufx_ops_open()
1022 if (dev->virtualized) { in ufx_ops_open()
1024 return -ENODEV; in ufx_ops_open()
1027 dev->fb_count++; in ufx_ops_open()
1029 kref_get(&dev->kref); in ufx_ops_open()
1031 if (fb_defio && (info->fbdefio == NULL)) { in ufx_ops_open()
1038 fbdefio->delay = UFX_DEFIO_WRITE_DELAY; in ufx_ops_open()
1039 fbdefio->deferred_io = ufx_dpy_deferred_io; in ufx_ops_open()
1042 info->fbdefio = fbdefio; in ufx_ops_open()
1047 info->node, user, info, dev->fb_count); in ufx_ops_open()
1068 struct ufx_data *dev = info->par; in ufx_ops_destory()
1069 int node = info->node; in ufx_ops_destory()
1077 kref_put(&dev->kref, ufx_free); in ufx_ops_destory()
1086 up(&unode->dev->urbs.limit_sem); in ufx_release_urb_work()
1091 struct fb_info *info = dev->info; in ufx_free_framebuffer()
1093 if (info->cmap.len != 0) in ufx_free_framebuffer()
1094 fb_dealloc_cmap(&info->cmap); in ufx_free_framebuffer()
1095 if (info->monspecs.modedb) in ufx_free_framebuffer()
1096 fb_destroy_modedb(info->monspecs.modedb); in ufx_free_framebuffer()
1097 vfree(info->screen_buffer); in ufx_free_framebuffer()
1099 fb_destroy_modelist(&info->modelist); in ufx_free_framebuffer()
1101 dev->info = NULL; in ufx_free_framebuffer()
1104 kref_put(&dev->kref, ufx_free); in ufx_free_framebuffer()
1108 * Assumes caller is holding info->lock mutex (for open and release at least)
1112 struct ufx_data *dev = info->par; in ufx_ops_release()
1116 dev->fb_count--; in ufx_ops_release()
1118 /* We can't free fb_info here - fbmem will touch it when we return */ in ufx_ops_release()
1119 if (dev->virtualized && (dev->fb_count == 0)) in ufx_ops_release()
1122 if ((dev->fb_count == 0) && (info->fbdefio)) { in ufx_ops_release()
1124 kfree(info->fbdefio); in ufx_ops_release()
1125 info->fbdefio = NULL; in ufx_ops_release()
1129 info->node, user, dev->fb_count); in ufx_ops_release()
1131 kref_put(&dev->kref, ufx_free); in ufx_ops_release()
1143 if ((mode->xres * mode->yres) > (2048 * 1152)) { in ufx_is_valid_mode()
1145 mode->xres, mode->yres); in ufx_is_valid_mode()
1149 if (mode->pixclock < 5000) { in ufx_is_valid_mode()
1151 mode->xres, mode->yres, mode->pixclock); in ufx_is_valid_mode()
1155 pr_debug("%dx%d (pixclk %dps %dMHz) valid mode", mode->xres, mode->yres, in ufx_is_valid_mode()
1156 mode->pixclock, (1000000 / mode->pixclock)); in ufx_is_valid_mode()
1166 var->bits_per_pixel = 16; in ufx_var_color_format()
1167 var->red = red; in ufx_var_color_format()
1168 var->green = green; in ufx_var_color_format()
1169 var->blue = blue; in ufx_var_color_format()
1178 if ((var->xres * var->yres * 2) > info->fix.smem_len) in ufx_ops_check_var()
1179 return -EINVAL; in ufx_ops_check_var()
1181 /* set device-specific elements of var unrelated to mode */ in ufx_ops_check_var()
1187 return -EINVAL; in ufx_ops_check_var()
1194 struct ufx_data *dev = info->par; in ufx_ops_set_par()
1199 pr_debug("set_par mode %dx%d", info->var.xres, info->var.yres); in ufx_ops_set_par()
1200 result = ufx_set_vid_mode(dev, &info->var); in ufx_ops_set_par()
1202 if ((result == 0) && (dev->fb_count == 0)) { in ufx_ops_set_par()
1204 pix_framebuffer = (u16 *)info->screen_buffer; in ufx_ops_set_par()
1205 for (i = 0; i < info->fix.smem_len / 2; i++) in ufx_ops_set_par()
1208 ufx_handle_damage(dev, 0, 0, info->var.xres, info->var.yres); in ufx_ops_set_par()
1211 /* re-enable defio if previously disabled by damage tracking */ in ufx_ops_set_par()
1212 if (info->fbdefio) in ufx_ops_set_par()
1213 info->fbdefio->delay = UFX_DEFIO_WRITE_DELAY; in ufx_ops_set_par()
1221 struct ufx_data *dev = info->par; in ufx_ops_blank()
1222 ufx_set_vid_mode(dev, &info->var); in ufx_ops_blank()
1228 struct ufx_data *dev = info->par; in ufx_ops_damage_range()
1229 int start = max((int)(off / info->fix.line_length), 0); in ufx_ops_damage_range()
1230 int lines = min((u32)((len / info->fix.line_length) + 1), (u32)info->var.yres); in ufx_ops_damage_range()
1232 ufx_handle_damage(dev, 0, start, info->var.xres, lines); in ufx_ops_damage_range()
1237 struct ufx_data *dev = info->par; in ufx_ops_damage_area()
1261 /* Assumes &info->lock held by caller
1265 int old_len = info->fix.smem_len; in ufx_realloc_framebuffer()
1267 unsigned char *old_fb = info->screen_buffer; in ufx_realloc_framebuffer()
1272 new_len = info->fix.line_length * info->var.yres; in ufx_realloc_framebuffer()
1280 return -ENOMEM; in ufx_realloc_framebuffer()
1282 if (info->screen_buffer) { in ufx_realloc_framebuffer()
1284 vfree(info->screen_buffer); in ufx_realloc_framebuffer()
1287 info->screen_buffer = new_fb; in ufx_realloc_framebuffer()
1288 info->fix.smem_len = PAGE_ALIGN(new_len); in ufx_realloc_framebuffer()
1289 info->fix.smem_start = (unsigned long) new_fb; in ufx_realloc_framebuffer()
1290 info->flags = smscufx_info_flags; in ufx_realloc_framebuffer()
1295 /* sets up DDC channel for 100 Kbps, std. speed, 7-bit addr, controller mode,
1321 /* 7-bit (not 10-bit) addressing */ in ufx_i2c_init()
1375 return -EIO; in ufx_i2c_wait_busy()
1390 return -ETIMEDOUT; in ufx_i2c_wait_busy()
1393 /* reads a 128-byte EDID block from the currently selected port and TAR */
1409 /* Read the 128-byte EDID as 2 bursts of 64 bytes */ in ufx_read_edid()
1438 return -ETIMEDOUT; in ufx_read_edid()
1460 if (refcount_read(&info->count)) /* only use mutex if info has been registered */ in ufx_setup_modes()
1461 mutex_lock(&info->lock); in ufx_setup_modes()
1465 result = -ENOMEM; in ufx_setup_modes()
1469 fb_destroy_modelist(&info->modelist); in ufx_setup_modes()
1470 memset(&info->monspecs, 0, sizeof(info->monspecs)); in ufx_setup_modes()
1475 while (tries--) { in ufx_setup_modes()
1479 fb_edid_to_monspecs(edid, &info->monspecs); in ufx_setup_modes()
1481 if (info->monspecs.modedb_len > 0) { in ufx_setup_modes()
1482 dev->edid = edid; in ufx_setup_modes()
1483 dev->edid_size = i; in ufx_setup_modes()
1489 if (info->monspecs.modedb_len == 0) { in ufx_setup_modes()
1492 if (dev->edid) { in ufx_setup_modes()
1493 fb_edid_to_monspecs(dev->edid, &info->monspecs); in ufx_setup_modes()
1494 if (info->monspecs.modedb_len > 0) in ufx_setup_modes()
1500 if (info->monspecs.modedb_len == 0) { in ufx_setup_modes()
1502 fb_edid_to_monspecs(default_edid, &info->monspecs); in ufx_setup_modes()
1503 if (info->monspecs.modedb_len > 0) { in ufx_setup_modes()
1505 dev->edid = edid; in ufx_setup_modes()
1506 dev->edid_size = default_edid_size; in ufx_setup_modes()
1513 if (info->monspecs.modedb_len > 0) { in ufx_setup_modes()
1515 for (i = 0; i < info->monspecs.modedb_len; i++) { in ufx_setup_modes()
1516 if (ufx_is_valid_mode(&info->monspecs.modedb[i], info)) in ufx_setup_modes()
1517 fb_add_videomode(&info->monspecs.modedb[i], in ufx_setup_modes()
1518 &info->modelist); in ufx_setup_modes()
1520 info->monspecs.misc &= ~FB_MISC_1ST_DETAIL; in ufx_setup_modes()
1523 default_vmode = fb_find_best_display(&info->monspecs, in ufx_setup_modes()
1524 &info->modelist); in ufx_setup_modes()
1541 &info->modelist); in ufx_setup_modes()
1551 &info->modelist); in ufx_setup_modes()
1555 if ((default_vmode != NULL) && (dev->fb_count == 0)) { in ufx_setup_modes()
1557 fb_videomode_to_var(&info->var, default_vmode); in ufx_setup_modes()
1558 ufx_var_color_format(&info->var); in ufx_setup_modes()
1561 memcpy(&info->fix, &ufx_fix, sizeof(ufx_fix)); in ufx_setup_modes()
1562 info->fix.line_length = info->var.xres * in ufx_setup_modes()
1563 (info->var.bits_per_pixel / 8); in ufx_setup_modes()
1568 result = -EINVAL; in ufx_setup_modes()
1571 if (edid && (dev->edid != edid)) in ufx_setup_modes()
1574 if (refcount_read(&info->count)) in ufx_setup_modes()
1575 mutex_unlock(&info->lock); in ufx_setup_modes()
1580 static int ufx_usb_probe(struct usb_interface *interface, in ufx_usb_probe() argument
1586 int retval = -ENOMEM; in ufx_usb_probe()
1590 usbdev = interface_to_usbdev(interface); in ufx_usb_probe()
1595 dev_err(&usbdev->dev, "ufx_usb_probe: failed alloc of dev struct\n"); in ufx_usb_probe()
1596 return -ENOMEM; in ufx_usb_probe()
1600 kref_init(&dev->kref); /* matching kref_put in usb .disconnect fn */ in ufx_usb_probe()
1601 kref_get(&dev->kref); /* matching kref_put in free_framebuffer_work */ in ufx_usb_probe()
1603 dev->udev = usbdev; in ufx_usb_probe()
1604 dev->gdev = &usbdev->dev; /* our generic struct device * */ in ufx_usb_probe()
1605 usb_set_intfdata(interface, dev); in ufx_usb_probe()
1607 dev_dbg(dev->gdev, "%s %s - serial #%s\n", in ufx_usb_probe()
1608 usbdev->manufacturer, usbdev->product, usbdev->serial); in ufx_usb_probe()
1609 dev_dbg(dev->gdev, "vid_%04x&pid_%04x&rev_%04x driver's ufx_data struct at %p\n", in ufx_usb_probe()
1610 le16_to_cpu(usbdev->descriptor.idVendor), in ufx_usb_probe()
1611 le16_to_cpu(usbdev->descriptor.idProduct), in ufx_usb_probe()
1612 le16_to_cpu(usbdev->descriptor.bcdDevice), dev); in ufx_usb_probe()
1613 dev_dbg(dev->gdev, "console enable=%d\n", console); in ufx_usb_probe()
1614 dev_dbg(dev->gdev, "fb_defio enable=%d\n", fb_defio); in ufx_usb_probe()
1617 dev_err(dev->gdev, "ufx_alloc_urb_list failed\n"); in ufx_usb_probe()
1621 /* We don't register a new USB class. Our client interface is fbdev */ in ufx_usb_probe()
1624 info = framebuffer_alloc(0, &usbdev->dev); in ufx_usb_probe()
1626 dev_err(dev->gdev, "framebuffer_alloc failed\n"); in ufx_usb_probe()
1630 dev->info = info; in ufx_usb_probe()
1631 info->par = dev; in ufx_usb_probe()
1632 info->pseudo_palette = dev->pseudo_palette; in ufx_usb_probe()
1633 info->fbops = &ufx_ops; in ufx_usb_probe()
1634 INIT_LIST_HEAD(&info->modelist); in ufx_usb_probe()
1636 retval = fb_alloc_cmap(&info->cmap, 256, 0); in ufx_usb_probe()
1638 dev_err(dev->gdev, "fb_alloc_cmap failed %x\n", retval); in ufx_usb_probe()
1644 dev_dbg(dev->gdev, "ID_REV register value 0x%08x", id_rev); in ufx_usb_probe()
1648 dev_dbg(dev->gdev, "FPGA_REV register value 0x%08x", fpga_rev); in ufx_usb_probe()
1650 dev_dbg(dev->gdev, "resetting device"); in ufx_usb_probe()
1654 dev_dbg(dev->gdev, "configuring system clock"); in ufx_usb_probe()
1658 dev_dbg(dev->gdev, "configuring DDR2 controller"); in ufx_usb_probe()
1662 dev_dbg(dev->gdev, "configuring I2C controller"); in ufx_usb_probe()
1666 dev_dbg(dev->gdev, "selecting display mode"); in ufx_usb_probe()
1672 dev_err(dev->gdev, "error %d enabling graphics engine", retval); in ufx_usb_probe()
1677 atomic_set(&dev->usb_active, 1); in ufx_usb_probe()
1679 dev_dbg(dev->gdev, "checking var"); in ufx_usb_probe()
1680 retval = ufx_ops_check_var(&info->var, info); in ufx_usb_probe()
1682 dev_err(dev->gdev, "error %d ufx_ops_check_var", retval); in ufx_usb_probe()
1686 dev_dbg(dev->gdev, "setting par"); in ufx_usb_probe()
1689 dev_err(dev->gdev, "error %d ufx_ops_set_par", retval); in ufx_usb_probe()
1693 dev_dbg(dev->gdev, "registering framebuffer"); in ufx_usb_probe()
1696 dev_err(dev->gdev, "error %d register_framebuffer", retval); in ufx_usb_probe()
1700 dev_info(dev->gdev, "SMSC UDX USB device /dev/fb%d attached. %dx%d resolution." in ufx_usb_probe()
1701 " Using %dK framebuffer memory\n", info->node, in ufx_usb_probe()
1702 info->var.xres, info->var.yres, info->fix.smem_len >> 10); in ufx_usb_probe()
1707 atomic_set(&dev->usb_active, 0); in ufx_usb_probe()
1709 fb_destroy_modedb(info->monspecs.modedb); in ufx_usb_probe()
1710 vfree(info->screen_buffer); in ufx_usb_probe()
1711 fb_destroy_modelist(&info->modelist); in ufx_usb_probe()
1713 fb_dealloc_cmap(&info->cmap); in ufx_usb_probe()
1717 if (dev->urbs.count > 0) in ufx_usb_probe()
1720 kref_put(&dev->kref, ufx_free); /* ref for framebuffer */ in ufx_usb_probe()
1721 kref_put(&dev->kref, ufx_free); /* last ref from kref_init */ in ufx_usb_probe()
1725 static void ufx_usb_disconnect(struct usb_interface *interface) in ufx_usb_disconnect() argument
1732 dev = usb_get_intfdata(interface); in ufx_usb_disconnect()
1733 info = dev->info; in ufx_usb_disconnect()
1738 dev->virtualized = true; in ufx_usb_disconnect()
1740 /* When non-active we'll update virtual framebuffer, but no new urbs */ in ufx_usb_disconnect()
1741 atomic_set(&dev->usb_active, 0); in ufx_usb_disconnect()
1743 usb_set_intfdata(interface, NULL); in ufx_usb_disconnect()
1746 if (dev->fb_count == 0) in ufx_usb_disconnect()
1749 /* this function will wait for all in-flight urbs to complete */ in ufx_usb_disconnect()
1750 if (dev->urbs.count > 0) in ufx_usb_disconnect()
1771 struct urb_node *unode = urb->context; in ufx_urb_completion()
1772 struct ufx_data *dev = unode->dev; in ufx_urb_completion()
1776 if (urb->status) { in ufx_urb_completion()
1777 if (!(urb->status == -ENOENT || in ufx_urb_completion()
1778 urb->status == -ECONNRESET || in ufx_urb_completion()
1779 urb->status == -ESHUTDOWN)) { in ufx_urb_completion()
1780 pr_err("%s - nonzero write bulk status received: %d\n", in ufx_urb_completion()
1781 __func__, urb->status); in ufx_urb_completion()
1782 atomic_set(&dev->lost_pixels, 1); in ufx_urb_completion()
1786 urb->transfer_buffer_length = dev->urbs.size; /* reset to actual */ in ufx_urb_completion()
1788 spin_lock_irqsave(&dev->urbs.lock, flags); in ufx_urb_completion()
1789 list_add_tail(&unode->entry, &dev->urbs.list); in ufx_urb_completion()
1790 dev->urbs.available++; in ufx_urb_completion()
1791 spin_unlock_irqrestore(&dev->urbs.lock, flags); in ufx_urb_completion()
1796 schedule_delayed_work(&unode->release_urb_work, 0); in ufx_urb_completion()
1798 up(&dev->urbs.limit_sem); in ufx_urb_completion()
1803 int count = dev->urbs.count; in ufx_free_urb_list()
1813 while (count--) { in ufx_free_urb_list()
1815 ret = down_interruptible(&dev->urbs.limit_sem); in ufx_free_urb_list()
1819 spin_lock_irqsave(&dev->urbs.lock, flags); in ufx_free_urb_list()
1821 node = dev->urbs.list.next; /* have reserved one with sem */ in ufx_free_urb_list()
1824 spin_unlock_irqrestore(&dev->urbs.lock, flags); in ufx_free_urb_list()
1827 urb = unode->urb; in ufx_free_urb_list()
1830 usb_free_coherent(urb->dev, dev->urbs.size, in ufx_free_urb_list()
1831 urb->transfer_buffer, urb->transfer_dma); in ufx_free_urb_list()
1844 spin_lock_init(&dev->urbs.lock); in ufx_alloc_urb_list()
1846 dev->urbs.size = size; in ufx_alloc_urb_list()
1847 INIT_LIST_HEAD(&dev->urbs.list); in ufx_alloc_urb_list()
1853 unode->dev = dev; in ufx_alloc_urb_list()
1855 INIT_DELAYED_WORK(&unode->release_urb_work, in ufx_alloc_urb_list()
1863 unode->urb = urb; in ufx_alloc_urb_list()
1865 buf = usb_alloc_coherent(dev->udev, size, GFP_KERNEL, in ufx_alloc_urb_list()
1866 &urb->transfer_dma); in ufx_alloc_urb_list()
1873 /* urb->transfer_buffer_length set to actual before submit */ in ufx_alloc_urb_list()
1874 usb_fill_bulk_urb(urb, dev->udev, usb_sndbulkpipe(dev->udev, 1), in ufx_alloc_urb_list()
1876 urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; in ufx_alloc_urb_list()
1878 list_add_tail(&unode->entry, &dev->urbs.list); in ufx_alloc_urb_list()
1883 sema_init(&dev->urbs.limit_sem, i); in ufx_alloc_urb_list()
1884 dev->urbs.count = i; in ufx_alloc_urb_list()
1885 dev->urbs.available = i; in ufx_alloc_urb_list()
1900 /* Wait for an in-flight buffer to complete and get re-queued */ in ufx_get_urb()
1901 ret = down_timeout(&dev->urbs.limit_sem, GET_URB_TIMEOUT); in ufx_get_urb()
1903 atomic_set(&dev->lost_pixels, 1); in ufx_get_urb()
1905 ret, dev->urbs.available); in ufx_get_urb()
1909 spin_lock_irqsave(&dev->urbs.lock, flags); in ufx_get_urb()
1911 BUG_ON(list_empty(&dev->urbs.list)); /* reserved one with limit_sem */ in ufx_get_urb()
1912 entry = dev->urbs.list.next; in ufx_get_urb()
1914 dev->urbs.available--; in ufx_get_urb()
1916 spin_unlock_irqrestore(&dev->urbs.lock, flags); in ufx_get_urb()
1919 urb = unode->urb; in ufx_get_urb()
1929 BUG_ON(len > dev->urbs.size); in ufx_submit_urb()
1931 urb->transfer_buffer_length = len; /* set to actual payload len */ in ufx_submit_urb()
1935 atomic_set(&dev->lost_pixels, 1); in ufx_submit_urb()