.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
---|
1 | 2 | /* |
---|
2 | 3 | * udlfb.c -- Framebuffer driver for DisplayLink USB controller |
---|
3 | 4 | * |
---|
4 | 5 | * Copyright (C) 2009 Roberto De Ioris <roberto@unbit.it> |
---|
5 | 6 | * Copyright (C) 2009 Jaya Kumar <jayakumar.lkml@gmail.com> |
---|
6 | 7 | * Copyright (C) 2009 Bernie Thompson <bernie@plugable.com> |
---|
7 | | - * |
---|
8 | | - * This file is subject to the terms and conditions of the GNU General Public |
---|
9 | | - * License v2. See the file COPYING in the main directory of this archive for |
---|
10 | | - * more details. |
---|
11 | 8 | * |
---|
12 | 9 | * Layout is based on skeletonfb by James Simmons and Geert Uytterhoeven, |
---|
13 | 10 | * usb-skeleton by GregKH. |
---|
.. | .. |
---|
29 | 26 | #include <asm/unaligned.h> |
---|
30 | 27 | #include <video/udlfb.h> |
---|
31 | 28 | #include "edid.h" |
---|
| 29 | + |
---|
| 30 | +#define OUT_EP_NUM 1 /* The endpoint number we will use */ |
---|
32 | 31 | |
---|
33 | 32 | static const struct fb_fix_screeninfo dlfb_fix = { |
---|
34 | 33 | .id = "udlfb", |
---|
.. | .. |
---|
67 | 66 | MODULE_DEVICE_TABLE(usb, id_table); |
---|
68 | 67 | |
---|
69 | 68 | /* module options */ |
---|
70 | | -static bool console = 1; /* Allow fbcon to open framebuffer */ |
---|
71 | | -static bool fb_defio = 1; /* Detect mmap writes using page faults */ |
---|
72 | | -static bool shadow = 1; /* Optionally disable shadow framebuffer */ |
---|
| 69 | +static bool console = true; /* Allow fbcon to open framebuffer */ |
---|
| 70 | +static bool fb_defio = true; /* Detect mmap writes using page faults */ |
---|
| 71 | +static bool shadow = true; /* Optionally disable shadow framebuffer */ |
---|
73 | 72 | static int pixel_limit; /* Optionally force a pixel resolution limit */ |
---|
74 | 73 | |
---|
75 | 74 | struct dlfb_deferred_free { |
---|
.. | .. |
---|
1041 | 1040 | fb_deferred_io_cleanup(info); |
---|
1042 | 1041 | kfree(info->fbdefio); |
---|
1043 | 1042 | info->fbdefio = NULL; |
---|
1044 | | - info->fbops->fb_mmap = dlfb_ops_mmap; |
---|
1045 | 1043 | } |
---|
1046 | 1044 | |
---|
1047 | 1045 | dev_dbg(info->dev, "release, user=%d count=%d\n", user, dlfb->fb_count); |
---|
.. | .. |
---|
1187 | 1185 | return 0; |
---|
1188 | 1186 | } |
---|
1189 | 1187 | |
---|
1190 | | -static struct fb_ops dlfb_ops = { |
---|
| 1188 | +static const struct fb_ops dlfb_ops = { |
---|
1191 | 1189 | .owner = THIS_MODULE, |
---|
1192 | 1190 | .fb_read = fb_sys_read, |
---|
1193 | 1191 | .fb_write = dlfb_ops_write, |
---|
.. | .. |
---|
1430 | 1428 | struct device_attribute *a, char *buf) { |
---|
1431 | 1429 | struct fb_info *fb_info = dev_get_drvdata(fbdev); |
---|
1432 | 1430 | struct dlfb_data *dlfb = fb_info->par; |
---|
1433 | | - return snprintf(buf, PAGE_SIZE, "%u\n", |
---|
| 1431 | + return sysfs_emit(buf, "%u\n", |
---|
1434 | 1432 | atomic_read(&dlfb->bytes_rendered)); |
---|
1435 | 1433 | } |
---|
1436 | 1434 | |
---|
.. | .. |
---|
1438 | 1436 | struct device_attribute *a, char *buf) { |
---|
1439 | 1437 | struct fb_info *fb_info = dev_get_drvdata(fbdev); |
---|
1440 | 1438 | struct dlfb_data *dlfb = fb_info->par; |
---|
1441 | | - return snprintf(buf, PAGE_SIZE, "%u\n", |
---|
| 1439 | + return sysfs_emit(buf, "%u\n", |
---|
1442 | 1440 | atomic_read(&dlfb->bytes_identical)); |
---|
1443 | 1441 | } |
---|
1444 | 1442 | |
---|
.. | .. |
---|
1446 | 1444 | struct device_attribute *a, char *buf) { |
---|
1447 | 1445 | struct fb_info *fb_info = dev_get_drvdata(fbdev); |
---|
1448 | 1446 | struct dlfb_data *dlfb = fb_info->par; |
---|
1449 | | - return snprintf(buf, PAGE_SIZE, "%u\n", |
---|
| 1447 | + return sysfs_emit(buf, "%u\n", |
---|
1450 | 1448 | atomic_read(&dlfb->bytes_sent)); |
---|
1451 | 1449 | } |
---|
1452 | 1450 | |
---|
.. | .. |
---|
1454 | 1452 | struct device_attribute *a, char *buf) { |
---|
1455 | 1453 | struct fb_info *fb_info = dev_get_drvdata(fbdev); |
---|
1456 | 1454 | struct dlfb_data *dlfb = fb_info->par; |
---|
1457 | | - return snprintf(buf, PAGE_SIZE, "%u\n", |
---|
| 1455 | + return sysfs_emit(buf, "%u\n", |
---|
1458 | 1456 | atomic_read(&dlfb->cpu_kcycles_used)); |
---|
1459 | 1457 | } |
---|
1460 | 1458 | |
---|
.. | .. |
---|
1462 | 1460 | struct file *filp, |
---|
1463 | 1461 | struct kobject *kobj, struct bin_attribute *a, |
---|
1464 | 1462 | char *buf, loff_t off, size_t count) { |
---|
1465 | | - struct device *fbdev = container_of(kobj, struct device, kobj); |
---|
| 1463 | + struct device *fbdev = kobj_to_dev(kobj); |
---|
1466 | 1464 | struct fb_info *fb_info = dev_get_drvdata(fbdev); |
---|
1467 | 1465 | struct dlfb_data *dlfb = fb_info->par; |
---|
1468 | 1466 | |
---|
.. | .. |
---|
1484 | 1482 | struct file *filp, |
---|
1485 | 1483 | struct kobject *kobj, struct bin_attribute *a, |
---|
1486 | 1484 | char *src, loff_t src_off, size_t src_size) { |
---|
1487 | | - struct device *fbdev = container_of(kobj, struct device, kobj); |
---|
| 1485 | + struct device *fbdev = kobj_to_dev(kobj); |
---|
1488 | 1486 | struct fb_info *fb_info = dev_get_drvdata(fbdev); |
---|
1489 | 1487 | struct dlfb_data *dlfb = fb_info->par; |
---|
1490 | 1488 | int ret; |
---|
.. | .. |
---|
1653 | 1651 | const struct device_attribute *attr; |
---|
1654 | 1652 | struct dlfb_data *dlfb; |
---|
1655 | 1653 | struct fb_info *info; |
---|
1656 | | - int retval = -ENOMEM; |
---|
| 1654 | + int retval; |
---|
1657 | 1655 | struct usb_device *usbdev = interface_to_usbdev(intf); |
---|
| 1656 | + static u8 out_ep[] = {OUT_EP_NUM + USB_DIR_OUT, 0}; |
---|
1658 | 1657 | |
---|
1659 | 1658 | /* usb initialization */ |
---|
1660 | 1659 | dlfb = kzalloc(sizeof(*dlfb), GFP_KERNEL); |
---|
.. | .. |
---|
1668 | 1667 | dlfb->udev = usb_get_dev(usbdev); |
---|
1669 | 1668 | usb_set_intfdata(intf, dlfb); |
---|
1670 | 1669 | |
---|
| 1670 | + if (!usb_check_bulk_endpoints(intf, out_ep)) { |
---|
| 1671 | + dev_err(&intf->dev, "Invalid DisplayLink device!\n"); |
---|
| 1672 | + retval = -EINVAL; |
---|
| 1673 | + goto error; |
---|
| 1674 | + } |
---|
| 1675 | + |
---|
1671 | 1676 | dev_dbg(&intf->dev, "console enable=%d\n", console); |
---|
1672 | 1677 | dev_dbg(&intf->dev, "fb_defio enable=%d\n", fb_defio); |
---|
1673 | 1678 | dev_dbg(&intf->dev, "shadow enable=%d\n", shadow); |
---|
.. | .. |
---|
1677 | 1682 | if (!dlfb_parse_vendor_descriptor(dlfb, intf)) { |
---|
1678 | 1683 | dev_err(&intf->dev, |
---|
1679 | 1684 | "firmware not recognized, incompatible device?\n"); |
---|
| 1685 | + retval = -ENODEV; |
---|
1680 | 1686 | goto error; |
---|
1681 | 1687 | } |
---|
1682 | 1688 | |
---|
.. | .. |
---|
1691 | 1697 | /* allocates framebuffer driver structure, not framebuffer memory */ |
---|
1692 | 1698 | info = framebuffer_alloc(0, &dlfb->udev->dev); |
---|
1693 | 1699 | if (!info) { |
---|
1694 | | - dev_err(&dlfb->udev->dev, "framebuffer_alloc failed\n"); |
---|
| 1700 | + retval = -ENOMEM; |
---|
1695 | 1701 | goto error; |
---|
1696 | 1702 | } |
---|
1697 | 1703 | |
---|
.. | .. |
---|
1922 | 1928 | } |
---|
1923 | 1929 | |
---|
1924 | 1930 | /* urb->transfer_buffer_length set to actual before submit */ |
---|
1925 | | - usb_fill_bulk_urb(urb, dlfb->udev, usb_sndbulkpipe(dlfb->udev, 1), |
---|
| 1931 | + usb_fill_bulk_urb(urb, dlfb->udev, |
---|
| 1932 | + usb_sndbulkpipe(dlfb->udev, OUT_EP_NUM), |
---|
1926 | 1933 | buf, size, dlfb_urb_completion, unode); |
---|
1927 | 1934 | urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; |
---|
1928 | 1935 | |
---|