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>
19 /* dummy connector to just get EDID,
20 all UDL appear to have a DVI-D */
22 static u8
*udl_get_edid(struct udl_device
*udl
)
28 block
= kmalloc(EDID_LENGTH
, GFP_KERNEL
);
32 rbuf
= kmalloc(2, GFP_KERNEL
);
36 for (i
= 0; i
< EDID_LENGTH
; i
++) {
37 ret
= usb_control_msg(udl
->ddev
->usbdev
,
38 usb_rcvctrlpipe(udl
->ddev
->usbdev
, 0), (0x02),
39 (0x80 | (0x02 << 5)), i
<< 8, 0xA1, rbuf
, 2,
42 DRM_ERROR("Read EDID byte %d failed err %x\n", i
, ret
);
57 static int udl_get_modes(struct drm_connector
*connector
)
59 struct udl_device
*udl
= connector
->dev
->dev_private
;
63 edid
= (struct edid
*)udl_get_edid(udl
);
65 drm_mode_connector_update_edid_property(connector
, NULL
);
70 * We only read the main block, but if the monitor reports extension
71 * blocks then the drm edid code expects them to be present, so patch
72 * the extension count to 0.
74 edid
->checksum
+= edid
->extensions
;
77 drm_mode_connector_update_edid_property(connector
, edid
);
78 ret
= drm_add_edid_modes(connector
, edid
);
83 static int udl_mode_valid(struct drm_connector
*connector
,
84 struct drm_display_mode
*mode
)
86 struct udl_device
*udl
= connector
->dev
->dev_private
;
87 if (!udl
->sku_pixel_limit
)
90 if (mode
->vdisplay
* mode
->hdisplay
> udl
->sku_pixel_limit
)
91 return MODE_VIRTUAL_Y
;
96 static enum drm_connector_status
97 udl_detect(struct drm_connector
*connector
, bool force
)
99 if (drm_device_is_unplugged(connector
->dev
))
100 return connector_status_disconnected
;
101 return connector_status_connected
;
104 static struct drm_encoder
*
105 udl_best_single_encoder(struct drm_connector
*connector
)
107 int enc_id
= connector
->encoder_ids
[0];
108 struct drm_mode_object
*obj
;
109 struct drm_encoder
*encoder
;
111 obj
= drm_mode_object_find(connector
->dev
, enc_id
, DRM_MODE_OBJECT_ENCODER
);
114 encoder
= obj_to_encoder(obj
);
118 static int udl_connector_set_property(struct drm_connector
*connector
,
119 struct drm_property
*property
,
125 static void udl_connector_destroy(struct drm_connector
*connector
)
127 drm_sysfs_connector_remove(connector
);
128 drm_connector_cleanup(connector
);
132 static struct drm_connector_helper_funcs udl_connector_helper_funcs
= {
133 .get_modes
= udl_get_modes
,
134 .mode_valid
= udl_mode_valid
,
135 .best_encoder
= udl_best_single_encoder
,
138 static struct drm_connector_funcs udl_connector_funcs
= {
139 .dpms
= drm_helper_connector_dpms
,
140 .detect
= udl_detect
,
141 .fill_modes
= drm_helper_probe_single_connector_modes
,
142 .destroy
= udl_connector_destroy
,
143 .set_property
= udl_connector_set_property
,
146 int udl_connector_init(struct drm_device
*dev
, struct drm_encoder
*encoder
)
148 struct drm_connector
*connector
;
150 connector
= kzalloc(sizeof(struct drm_connector
), GFP_KERNEL
);
154 drm_connector_init(dev
, connector
, &udl_connector_funcs
, DRM_MODE_CONNECTOR_DVII
);
155 drm_connector_helper_add(connector
, &udl_connector_helper_funcs
);
157 drm_sysfs_connector_add(connector
);
158 drm_mode_connector_attach_encoder(connector
, encoder
);
160 drm_object_attach_property(&connector
->base
,
161 dev
->mode_config
.dirty_info_property
,