1 // SPDX-License-Identifier: GPL-2.0-only 2 3 #include <linux/string.h> 4 5 #include <drm/drm_drv.h> 6 #include <drm/drm_edid.h> 7 8 #include "udl_drv.h" 9 #include "udl_edid.h" 10 11 static int udl_read_edid_block(void *data, u8 *buf, unsigned int block, size_t len) 12 { 13 struct udl_device *udl = data; 14 struct drm_device *dev = &udl->drm; 15 struct usb_device *udev = udl_to_usb_device(udl); 16 u8 *read_buff; 17 int idx, ret; 18 size_t i; 19 20 read_buff = kmalloc(2, GFP_KERNEL); 21 if (!read_buff) 22 return -ENOMEM; 23 24 if (!drm_dev_enter(dev, &idx)) { 25 ret = -ENODEV; 26 goto err_kfree; 27 } 28 29 for (i = 0; i < len; i++) { 30 int bval = (i + block * EDID_LENGTH) << 8; 31 32 ret = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), 33 0x02, (0x80 | (0x02 << 5)), bval, 34 0xA1, read_buff, 2, USB_CTRL_GET_TIMEOUT); 35 if (ret < 0) { 36 drm_err(dev, "Read EDID byte %zu failed err %x\n", i, ret); 37 goto err_drm_dev_exit; 38 } else if (ret < 1) { 39 ret = -EIO; 40 drm_err(dev, "Read EDID byte %zu failed\n", i); 41 goto err_drm_dev_exit; 42 } 43 44 buf[i] = read_buff[1]; 45 } 46 47 drm_dev_exit(idx); 48 kfree(read_buff); 49 50 return 0; 51 52 err_drm_dev_exit: 53 drm_dev_exit(idx); 54 err_kfree: 55 kfree(read_buff); 56 return ret; 57 } 58 59 bool udl_probe_edid(struct udl_device *udl) 60 { 61 u8 hdr[8]; 62 int ret; 63 64 ret = udl_read_edid_block(udl, hdr, 0, sizeof(hdr)); 65 if (ret) 66 return false; 67 68 /* 69 * The adapter sends all-zeros if no monitor has been 70 * connected. We consider anything else a connection. 71 */ 72 return !!memchr_inv(hdr, 0, sizeof(hdr)); 73 } 74 75 const struct drm_edid *udl_edid_read(struct drm_connector *connector) 76 { 77 struct udl_device *udl = to_udl(connector->dev); 78 79 return drm_edid_read_custom(connector, udl_read_edid_block, udl); 80 } 81