diff options
Diffstat (limited to 'drivers/gpu/drm/udl/udl_connector.c')
-rw-r--r-- | drivers/gpu/drm/udl/udl_connector.c | 31 |
1 files changed, 23 insertions, 8 deletions
diff --git a/drivers/gpu/drm/udl/udl_connector.c b/drivers/gpu/drm/udl/udl_connector.c index b3b2cedf6745..fe5cdbcf2636 100644 --- a/drivers/gpu/drm/udl/udl_connector.c +++ b/drivers/gpu/drm/udl/udl_connector.c | |||
@@ -22,13 +22,17 @@ | |||
22 | static u8 *udl_get_edid(struct udl_device *udl) | 22 | static u8 *udl_get_edid(struct udl_device *udl) |
23 | { | 23 | { |
24 | u8 *block; | 24 | u8 *block; |
25 | char rbuf[3]; | 25 | char *rbuf; |
26 | int ret, i; | 26 | int ret, i; |
27 | 27 | ||
28 | block = kmalloc(EDID_LENGTH, GFP_KERNEL); | 28 | block = kmalloc(EDID_LENGTH, GFP_KERNEL); |
29 | if (block == NULL) | 29 | if (block == NULL) |
30 | return NULL; | 30 | return NULL; |
31 | 31 | ||
32 | rbuf = kmalloc(2, GFP_KERNEL); | ||
33 | if (rbuf == NULL) | ||
34 | goto error; | ||
35 | |||
32 | for (i = 0; i < EDID_LENGTH; i++) { | 36 | for (i = 0; i < EDID_LENGTH; i++) { |
33 | ret = usb_control_msg(udl->ddev->usbdev, | 37 | ret = usb_control_msg(udl->ddev->usbdev, |
34 | usb_rcvctrlpipe(udl->ddev->usbdev, 0), (0x02), | 38 | usb_rcvctrlpipe(udl->ddev->usbdev, 0), (0x02), |
@@ -36,16 +40,17 @@ static u8 *udl_get_edid(struct udl_device *udl) | |||
36 | HZ); | 40 | HZ); |
37 | if (ret < 1) { | 41 | if (ret < 1) { |
38 | DRM_ERROR("Read EDID byte %d failed err %x\n", i, ret); | 42 | DRM_ERROR("Read EDID byte %d failed err %x\n", i, ret); |
39 | i--; | ||
40 | goto error; | 43 | goto error; |
41 | } | 44 | } |
42 | block[i] = rbuf[1]; | 45 | block[i] = rbuf[1]; |
43 | } | 46 | } |
44 | 47 | ||
48 | kfree(rbuf); | ||
45 | return block; | 49 | return block; |
46 | 50 | ||
47 | error: | 51 | error: |
48 | kfree(block); | 52 | kfree(block); |
53 | kfree(rbuf); | ||
49 | return NULL; | 54 | return NULL; |
50 | } | 55 | } |
51 | 56 | ||
@@ -57,6 +62,14 @@ static int udl_get_modes(struct drm_connector *connector) | |||
57 | 62 | ||
58 | edid = (struct edid *)udl_get_edid(udl); | 63 | edid = (struct edid *)udl_get_edid(udl); |
59 | 64 | ||
65 | /* | ||
66 | * We only read the main block, but if the monitor reports extension | ||
67 | * blocks then the drm edid code expects them to be present, so patch | ||
68 | * the extension count to 0. | ||
69 | */ | ||
70 | edid->checksum += edid->extensions; | ||
71 | edid->extensions = 0; | ||
72 | |||
60 | drm_mode_connector_update_edid_property(connector, edid); | 73 | drm_mode_connector_update_edid_property(connector, edid); |
61 | ret = drm_add_edid_modes(connector, edid); | 74 | ret = drm_add_edid_modes(connector, edid); |
62 | kfree(edid); | 75 | kfree(edid); |
@@ -84,7 +97,8 @@ udl_detect(struct drm_connector *connector, bool force) | |||
84 | return connector_status_connected; | 97 | return connector_status_connected; |
85 | } | 98 | } |
86 | 99 | ||
87 | struct drm_encoder *udl_best_single_encoder(struct drm_connector *connector) | 100 | static struct drm_encoder* |
101 | udl_best_single_encoder(struct drm_connector *connector) | ||
88 | { | 102 | { |
89 | int enc_id = connector->encoder_ids[0]; | 103 | int enc_id = connector->encoder_ids[0]; |
90 | struct drm_mode_object *obj; | 104 | struct drm_mode_object *obj; |
@@ -97,8 +111,9 @@ struct drm_encoder *udl_best_single_encoder(struct drm_connector *connector) | |||
97 | return encoder; | 111 | return encoder; |
98 | } | 112 | } |
99 | 113 | ||
100 | int udl_connector_set_property(struct drm_connector *connector, struct drm_property *property, | 114 | static int udl_connector_set_property(struct drm_connector *connector, |
101 | uint64_t val) | 115 | struct drm_property *property, |
116 | uint64_t val) | ||
102 | { | 117 | { |
103 | return 0; | 118 | return 0; |
104 | } | 119 | } |
@@ -110,13 +125,13 @@ static void udl_connector_destroy(struct drm_connector *connector) | |||
110 | kfree(connector); | 125 | kfree(connector); |
111 | } | 126 | } |
112 | 127 | ||
113 | struct drm_connector_helper_funcs udl_connector_helper_funcs = { | 128 | static struct drm_connector_helper_funcs udl_connector_helper_funcs = { |
114 | .get_modes = udl_get_modes, | 129 | .get_modes = udl_get_modes, |
115 | .mode_valid = udl_mode_valid, | 130 | .mode_valid = udl_mode_valid, |
116 | .best_encoder = udl_best_single_encoder, | 131 | .best_encoder = udl_best_single_encoder, |
117 | }; | 132 | }; |
118 | 133 | ||
119 | struct drm_connector_funcs udl_connector_funcs = { | 134 | static struct drm_connector_funcs udl_connector_funcs = { |
120 | .dpms = drm_helper_connector_dpms, | 135 | .dpms = drm_helper_connector_dpms, |
121 | .detect = udl_detect, | 136 | .detect = udl_detect, |
122 | .fill_modes = drm_helper_probe_single_connector_modes, | 137 | .fill_modes = drm_helper_probe_single_connector_modes, |
@@ -138,7 +153,7 @@ int udl_connector_init(struct drm_device *dev, struct drm_encoder *encoder) | |||
138 | drm_sysfs_connector_add(connector); | 153 | drm_sysfs_connector_add(connector); |
139 | drm_mode_connector_attach_encoder(connector, encoder); | 154 | drm_mode_connector_attach_encoder(connector, encoder); |
140 | 155 | ||
141 | drm_connector_attach_property(connector, | 156 | drm_object_attach_property(&connector->base, |
142 | dev->mode_config.dirty_info_property, | 157 | dev->mode_config.dirty_info_property, |
143 | 1); | 158 | 1); |
144 | return 0; | 159 | return 0; |