2 * Copyright (C) 2012 Red Hat
3 * based in parts on udlfb.c:
4 * Copyright (C) 2009 Roberto De Ioris <roberto@unbit.it>
5 * Copyright (C) 2009 Jaya Kumar <jayakumar.lkml@gmail.com>
6 * Copyright (C) 2009 Bernie Thompson <bernie@plugable.com>
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
14 #include <drm/drm_crtc.h>
15 #include <drm/drm_edid.h>
16 #include <drm/drm_crtc_helper.h>
17 #include "udl_connector.h"
20 static bool udl_get_edid_block(struct udl_device
*udl
, int block_idx
,
26 read_buff
= kmalloc(2, GFP_KERNEL
);
30 for (i
= 0; i
< EDID_LENGTH
; i
++) {
31 int bval
= (i
+ block_idx
* EDID_LENGTH
) << 8;
32 ret
= usb_control_msg(udl
->udev
,
33 usb_rcvctrlpipe(udl
->udev
, 0),
34 (0x02), (0x80 | (0x02 << 5)), bval
,
35 0xA1, read_buff
, 2, HZ
);
37 DRM_ERROR("Read EDID byte %d failed err %x\n", i
, ret
);
41 buff
[i
] = read_buff
[1];
48 static bool udl_get_edid(struct udl_device
*udl
, u8
**result_buff
,
49 int *result_buff_size
)
52 u8
*block_buff
= NULL
, *buff_ptr
;
54 block_buff
= kmalloc(EDID_LENGTH
, GFP_KERNEL
);
55 if (block_buff
== NULL
)
58 if (udl_get_edid_block(udl
, 0, block_buff
) &&
59 memchr_inv(block_buff
, 0, EDID_LENGTH
)) {
60 extensions
= ((struct edid
*)block_buff
)->extensions
;
62 /* we have to read all extensions one by one */
63 *result_buff_size
= EDID_LENGTH
* (extensions
+ 1);
64 *result_buff
= kmalloc(*result_buff_size
, GFP_KERNEL
);
65 buff_ptr
= *result_buff
;
66 if (buff_ptr
== NULL
) {
70 memcpy(buff_ptr
, block_buff
, EDID_LENGTH
);
72 buff_ptr
+= EDID_LENGTH
;
73 for (i
= 1; i
< extensions
; ++i
) {
74 if (udl_get_edid_block(udl
, i
, buff_ptr
)) {
75 buff_ptr
+= EDID_LENGTH
;
84 /* we have only base edid block */
85 *result_buff
= block_buff
;
86 *result_buff_size
= EDID_LENGTH
;
95 static int udl_get_modes(struct drm_connector
*connector
)
97 struct udl_drm_connector
*udl_connector
=
98 container_of(connector
,
99 struct udl_drm_connector
,
102 drm_mode_connector_update_edid_property(connector
, udl_connector
->edid
);
103 if (udl_connector
->edid
)
104 return drm_add_edid_modes(connector
, udl_connector
->edid
);
108 static int udl_mode_valid(struct drm_connector
*connector
,
109 struct drm_display_mode
*mode
)
111 struct udl_device
*udl
= connector
->dev
->dev_private
;
112 if (!udl
->sku_pixel_limit
)
115 if (mode
->vdisplay
* mode
->hdisplay
> udl
->sku_pixel_limit
)
116 return MODE_VIRTUAL_Y
;
121 static enum drm_connector_status
122 udl_detect(struct drm_connector
*connector
, bool force
)
124 u8
*edid_buff
= NULL
;
125 int edid_buff_size
= 0;
126 struct udl_device
*udl
= connector
->dev
->dev_private
;
127 struct udl_drm_connector
*udl_connector
=
128 container_of(connector
,
129 struct udl_drm_connector
,
132 /* cleanup previous edid */
133 if (udl_connector
->edid
!= NULL
) {
134 kfree(udl_connector
->edid
);
135 udl_connector
->edid
= NULL
;
139 if (!udl_get_edid(udl
, &edid_buff
, &edid_buff_size
))
140 return connector_status_disconnected
;
142 udl_connector
->edid
= (struct edid
*)edid_buff
;
144 return connector_status_connected
;
147 static struct drm_encoder
*
148 udl_best_single_encoder(struct drm_connector
*connector
)
150 int enc_id
= connector
->encoder_ids
[0];
151 return drm_encoder_find(connector
->dev
, NULL
, enc_id
);
154 static int udl_connector_set_property(struct drm_connector
*connector
,
155 struct drm_property
*property
,
161 static void udl_connector_destroy(struct drm_connector
*connector
)
163 struct udl_drm_connector
*udl_connector
=
164 container_of(connector
,
165 struct udl_drm_connector
,
168 drm_connector_unregister(connector
);
169 drm_connector_cleanup(connector
);
170 kfree(udl_connector
->edid
);
174 static const struct drm_connector_helper_funcs udl_connector_helper_funcs
= {
175 .get_modes
= udl_get_modes
,
176 .mode_valid
= udl_mode_valid
,
177 .best_encoder
= udl_best_single_encoder
,
180 static const struct drm_connector_funcs udl_connector_funcs
= {
181 .dpms
= drm_helper_connector_dpms
,
182 .detect
= udl_detect
,
183 .fill_modes
= drm_helper_probe_single_connector_modes
,
184 .destroy
= udl_connector_destroy
,
185 .set_property
= udl_connector_set_property
,
188 int udl_connector_init(struct drm_device
*dev
, struct drm_encoder
*encoder
)
190 struct udl_drm_connector
*udl_connector
;
191 struct drm_connector
*connector
;
193 udl_connector
= kzalloc(sizeof(struct udl_drm_connector
), GFP_KERNEL
);
197 connector
= &udl_connector
->connector
;
198 drm_connector_init(dev
, connector
, &udl_connector_funcs
,
199 DRM_MODE_CONNECTOR_DVII
);
200 drm_connector_helper_add(connector
, &udl_connector_helper_funcs
);
202 drm_connector_register(connector
);
203 drm_mode_connector_attach_encoder(connector
, encoder
);
204 connector
->polled
= DRM_CONNECTOR_POLL_HPD
|
205 DRM_CONNECTOR_POLL_CONNECT
| DRM_CONNECTOR_POLL_DISCONNECT
;