| .. | .. |
|---|
| 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. |
|---|
| .. | .. |
|---|
| 67 | 64 | MODULE_DEVICE_TABLE(usb, id_table); |
|---|
| 68 | 65 | |
|---|
| 69 | 66 | /* 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 */ |
|---|
| 67 | +static bool console = true; /* Allow fbcon to open framebuffer */ |
|---|
| 68 | +static bool fb_defio = true; /* Detect mmap writes using page faults */ |
|---|
| 69 | +static bool shadow = true; /* Optionally disable shadow framebuffer */ |
|---|
| 73 | 70 | static int pixel_limit; /* Optionally force a pixel resolution limit */ |
|---|
| 74 | 71 | |
|---|
| 75 | 72 | struct dlfb_deferred_free { |
|---|
| .. | .. |
|---|
| 1041 | 1038 | fb_deferred_io_cleanup(info); |
|---|
| 1042 | 1039 | kfree(info->fbdefio); |
|---|
| 1043 | 1040 | info->fbdefio = NULL; |
|---|
| 1044 | | - info->fbops->fb_mmap = dlfb_ops_mmap; |
|---|
| 1045 | 1041 | } |
|---|
| 1046 | 1042 | |
|---|
| 1047 | 1043 | dev_dbg(info->dev, "release, user=%d count=%d\n", user, dlfb->fb_count); |
|---|
| .. | .. |
|---|
| 1187 | 1183 | return 0; |
|---|
| 1188 | 1184 | } |
|---|
| 1189 | 1185 | |
|---|
| 1190 | | -static struct fb_ops dlfb_ops = { |
|---|
| 1186 | +static const struct fb_ops dlfb_ops = { |
|---|
| 1191 | 1187 | .owner = THIS_MODULE, |
|---|
| 1192 | 1188 | .fb_read = fb_sys_read, |
|---|
| 1193 | 1189 | .fb_write = dlfb_ops_write, |
|---|
| .. | .. |
|---|
| 1430 | 1426 | struct device_attribute *a, char *buf) { |
|---|
| 1431 | 1427 | struct fb_info *fb_info = dev_get_drvdata(fbdev); |
|---|
| 1432 | 1428 | struct dlfb_data *dlfb = fb_info->par; |
|---|
| 1433 | | - return snprintf(buf, PAGE_SIZE, "%u\n", |
|---|
| 1429 | + return sysfs_emit(buf, "%u\n", |
|---|
| 1434 | 1430 | atomic_read(&dlfb->bytes_rendered)); |
|---|
| 1435 | 1431 | } |
|---|
| 1436 | 1432 | |
|---|
| .. | .. |
|---|
| 1438 | 1434 | struct device_attribute *a, char *buf) { |
|---|
| 1439 | 1435 | struct fb_info *fb_info = dev_get_drvdata(fbdev); |
|---|
| 1440 | 1436 | struct dlfb_data *dlfb = fb_info->par; |
|---|
| 1441 | | - return snprintf(buf, PAGE_SIZE, "%u\n", |
|---|
| 1437 | + return sysfs_emit(buf, "%u\n", |
|---|
| 1442 | 1438 | atomic_read(&dlfb->bytes_identical)); |
|---|
| 1443 | 1439 | } |
|---|
| 1444 | 1440 | |
|---|
| .. | .. |
|---|
| 1446 | 1442 | struct device_attribute *a, char *buf) { |
|---|
| 1447 | 1443 | struct fb_info *fb_info = dev_get_drvdata(fbdev); |
|---|
| 1448 | 1444 | struct dlfb_data *dlfb = fb_info->par; |
|---|
| 1449 | | - return snprintf(buf, PAGE_SIZE, "%u\n", |
|---|
| 1445 | + return sysfs_emit(buf, "%u\n", |
|---|
| 1450 | 1446 | atomic_read(&dlfb->bytes_sent)); |
|---|
| 1451 | 1447 | } |
|---|
| 1452 | 1448 | |
|---|
| .. | .. |
|---|
| 1454 | 1450 | struct device_attribute *a, char *buf) { |
|---|
| 1455 | 1451 | struct fb_info *fb_info = dev_get_drvdata(fbdev); |
|---|
| 1456 | 1452 | struct dlfb_data *dlfb = fb_info->par; |
|---|
| 1457 | | - return snprintf(buf, PAGE_SIZE, "%u\n", |
|---|
| 1453 | + return sysfs_emit(buf, "%u\n", |
|---|
| 1458 | 1454 | atomic_read(&dlfb->cpu_kcycles_used)); |
|---|
| 1459 | 1455 | } |
|---|
| 1460 | 1456 | |
|---|
| .. | .. |
|---|
| 1462 | 1458 | struct file *filp, |
|---|
| 1463 | 1459 | struct kobject *kobj, struct bin_attribute *a, |
|---|
| 1464 | 1460 | char *buf, loff_t off, size_t count) { |
|---|
| 1465 | | - struct device *fbdev = container_of(kobj, struct device, kobj); |
|---|
| 1461 | + struct device *fbdev = kobj_to_dev(kobj); |
|---|
| 1466 | 1462 | struct fb_info *fb_info = dev_get_drvdata(fbdev); |
|---|
| 1467 | 1463 | struct dlfb_data *dlfb = fb_info->par; |
|---|
| 1468 | 1464 | |
|---|
| .. | .. |
|---|
| 1484 | 1480 | struct file *filp, |
|---|
| 1485 | 1481 | struct kobject *kobj, struct bin_attribute *a, |
|---|
| 1486 | 1482 | char *src, loff_t src_off, size_t src_size) { |
|---|
| 1487 | | - struct device *fbdev = container_of(kobj, struct device, kobj); |
|---|
| 1483 | + struct device *fbdev = kobj_to_dev(kobj); |
|---|
| 1488 | 1484 | struct fb_info *fb_info = dev_get_drvdata(fbdev); |
|---|
| 1489 | 1485 | struct dlfb_data *dlfb = fb_info->par; |
|---|
| 1490 | 1486 | int ret; |
|---|
| .. | .. |
|---|
| 1653 | 1649 | const struct device_attribute *attr; |
|---|
| 1654 | 1650 | struct dlfb_data *dlfb; |
|---|
| 1655 | 1651 | struct fb_info *info; |
|---|
| 1656 | | - int retval = -ENOMEM; |
|---|
| 1652 | + int retval; |
|---|
| 1657 | 1653 | struct usb_device *usbdev = interface_to_usbdev(intf); |
|---|
| 1654 | + struct usb_endpoint_descriptor *out; |
|---|
| 1658 | 1655 | |
|---|
| 1659 | 1656 | /* usb initialization */ |
|---|
| 1660 | 1657 | dlfb = kzalloc(sizeof(*dlfb), GFP_KERNEL); |
|---|
| .. | .. |
|---|
| 1668 | 1665 | dlfb->udev = usb_get_dev(usbdev); |
|---|
| 1669 | 1666 | usb_set_intfdata(intf, dlfb); |
|---|
| 1670 | 1667 | |
|---|
| 1668 | + retval = usb_find_common_endpoints(intf->cur_altsetting, NULL, &out, NULL, NULL); |
|---|
| 1669 | + if (retval) { |
|---|
| 1670 | + dev_err(&intf->dev, "Device should have at lease 1 bulk endpoint!\n"); |
|---|
| 1671 | + goto error; |
|---|
| 1672 | + } |
|---|
| 1673 | + |
|---|
| 1671 | 1674 | dev_dbg(&intf->dev, "console enable=%d\n", console); |
|---|
| 1672 | 1675 | dev_dbg(&intf->dev, "fb_defio enable=%d\n", fb_defio); |
|---|
| 1673 | 1676 | dev_dbg(&intf->dev, "shadow enable=%d\n", shadow); |
|---|
| .. | .. |
|---|
| 1677 | 1680 | if (!dlfb_parse_vendor_descriptor(dlfb, intf)) { |
|---|
| 1678 | 1681 | dev_err(&intf->dev, |
|---|
| 1679 | 1682 | "firmware not recognized, incompatible device?\n"); |
|---|
| 1683 | + retval = -ENODEV; |
|---|
| 1680 | 1684 | goto error; |
|---|
| 1681 | 1685 | } |
|---|
| 1682 | 1686 | |
|---|
| .. | .. |
|---|
| 1691 | 1695 | /* allocates framebuffer driver structure, not framebuffer memory */ |
|---|
| 1692 | 1696 | info = framebuffer_alloc(0, &dlfb->udev->dev); |
|---|
| 1693 | 1697 | if (!info) { |
|---|
| 1694 | | - dev_err(&dlfb->udev->dev, "framebuffer_alloc failed\n"); |
|---|
| 1698 | + retval = -ENOMEM; |
|---|
| 1695 | 1699 | goto error; |
|---|
| 1696 | 1700 | } |
|---|
| 1697 | 1701 | |
|---|