Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v5.3-rc3 156 lines 4.1 kB view raw
1// SPDX-License-Identifier: GPL-2.0-only 2/* 3 * Copyright (C) 2012 Red Hat 4 * based in parts on udlfb.c: 5 * Copyright (C) 2009 Roberto De Ioris <roberto@unbit.it> 6 * Copyright (C) 2009 Jaya Kumar <jayakumar.lkml@gmail.com> 7 * Copyright (C) 2009 Bernie Thompson <bernie@plugable.com> 8 */ 9 10#include <drm/drmP.h> 11#include <drm/drm_crtc.h> 12#include <drm/drm_edid.h> 13#include <drm/drm_crtc_helper.h> 14#include <drm/drm_probe_helper.h> 15#include "udl_connector.h" 16#include "udl_drv.h" 17 18static int udl_get_edid_block(void *data, u8 *buf, unsigned int block, 19 size_t len) 20{ 21 int ret, i; 22 u8 *read_buff; 23 struct udl_device *udl = data; 24 25 read_buff = kmalloc(2, GFP_KERNEL); 26 if (!read_buff) 27 return -1; 28 29 for (i = 0; i < len; i++) { 30 int bval = (i + block * EDID_LENGTH) << 8; 31 ret = usb_control_msg(udl->udev, 32 usb_rcvctrlpipe(udl->udev, 0), 33 (0x02), (0x80 | (0x02 << 5)), bval, 34 0xA1, read_buff, 2, HZ); 35 if (ret < 1) { 36 DRM_ERROR("Read EDID byte %d failed err %x\n", i, ret); 37 kfree(read_buff); 38 return -1; 39 } 40 buf[i] = read_buff[1]; 41 } 42 43 kfree(read_buff); 44 return 0; 45} 46 47static int udl_get_modes(struct drm_connector *connector) 48{ 49 struct udl_drm_connector *udl_connector = 50 container_of(connector, 51 struct udl_drm_connector, 52 connector); 53 54 drm_connector_update_edid_property(connector, udl_connector->edid); 55 if (udl_connector->edid) 56 return drm_add_edid_modes(connector, udl_connector->edid); 57 return 0; 58} 59 60static enum drm_mode_status udl_mode_valid(struct drm_connector *connector, 61 struct drm_display_mode *mode) 62{ 63 struct udl_device *udl = connector->dev->dev_private; 64 if (!udl->sku_pixel_limit) 65 return 0; 66 67 if (mode->vdisplay * mode->hdisplay > udl->sku_pixel_limit) 68 return MODE_VIRTUAL_Y; 69 70 return 0; 71} 72 73static enum drm_connector_status 74udl_detect(struct drm_connector *connector, bool force) 75{ 76 struct udl_device *udl = connector->dev->dev_private; 77 struct udl_drm_connector *udl_connector = 78 container_of(connector, 79 struct udl_drm_connector, 80 connector); 81 82 /* cleanup previous edid */ 83 if (udl_connector->edid != NULL) { 84 kfree(udl_connector->edid); 85 udl_connector->edid = NULL; 86 } 87 88 udl_connector->edid = drm_do_get_edid(connector, udl_get_edid_block, udl); 89 if (!udl_connector->edid) 90 return connector_status_disconnected; 91 92 return connector_status_connected; 93} 94 95static struct drm_encoder* 96udl_best_single_encoder(struct drm_connector *connector) 97{ 98 int enc_id = connector->encoder_ids[0]; 99 return drm_encoder_find(connector->dev, NULL, enc_id); 100} 101 102static int udl_connector_set_property(struct drm_connector *connector, 103 struct drm_property *property, 104 uint64_t val) 105{ 106 return 0; 107} 108 109static void udl_connector_destroy(struct drm_connector *connector) 110{ 111 struct udl_drm_connector *udl_connector = 112 container_of(connector, 113 struct udl_drm_connector, 114 connector); 115 116 drm_connector_unregister(connector); 117 drm_connector_cleanup(connector); 118 kfree(udl_connector->edid); 119 kfree(connector); 120} 121 122static const struct drm_connector_helper_funcs udl_connector_helper_funcs = { 123 .get_modes = udl_get_modes, 124 .mode_valid = udl_mode_valid, 125 .best_encoder = udl_best_single_encoder, 126}; 127 128static const struct drm_connector_funcs udl_connector_funcs = { 129 .dpms = drm_helper_connector_dpms, 130 .detect = udl_detect, 131 .fill_modes = drm_helper_probe_single_connector_modes, 132 .destroy = udl_connector_destroy, 133 .set_property = udl_connector_set_property, 134}; 135 136int udl_connector_init(struct drm_device *dev, struct drm_encoder *encoder) 137{ 138 struct udl_drm_connector *udl_connector; 139 struct drm_connector *connector; 140 141 udl_connector = kzalloc(sizeof(struct udl_drm_connector), GFP_KERNEL); 142 if (!udl_connector) 143 return -ENOMEM; 144 145 connector = &udl_connector->connector; 146 drm_connector_init(dev, connector, &udl_connector_funcs, 147 DRM_MODE_CONNECTOR_DVII); 148 drm_connector_helper_add(connector, &udl_connector_helper_funcs); 149 150 drm_connector_register(connector); 151 drm_connector_attach_encoder(connector, encoder); 152 connector->polled = DRM_CONNECTOR_POLL_HPD | 153 DRM_CONNECTOR_POLL_CONNECT | DRM_CONNECTOR_POLL_DISCONNECT; 154 155 return 0; 156}