31#include <sys/callout.h>
33#include <sys/kernel.h>
35#include <sys/module.h>
37#include <sys/condvar.h>
38#include <sys/sysctl.h>
40#include <sys/consio.h>
43#include <dev/fb/fbreg.h>
44#include <dev/syscons/syscons.h>
46#include <dev/videomode/videomode.h>
47#include <dev/videomode/edidvar.h>
60#define USB_DEBUG_VAR udl_debug
63static SYSCTL_NODE(_hw_usb, OID_AUTO, udl, CTLFLAG_RW | CTLFLAG_MPSAFE, 0,
67static int udl_debug = 0;
70 &udl_debug, 0,
"Debug level");
78 &
udl_fps, 0,
"Frames Per Second, 1-60");
115 .flags = {.pipe_bof = 1,.force_short_xfer = 1,.ext_buffer = 1,},
125 .flags = {.pipe_bof = 1,.force_short_xfer = 1,.ext_buffer = 1,},
162 {
USB_VPI(USB_VENDOR_DISPLAYLINK, USB_PRODUCT_DISPLAYLINK_LCD4300U,
DL120)},
163 {
USB_VPI(USB_VENDOR_DISPLAYLINK, USB_PRODUCT_DISPLAYLINK_LCD8000U,
DL120)},
164 {
USB_VPI(USB_VENDOR_DISPLAYLINK, USB_PRODUCT_DISPLAYLINK_GUC2020,
DL160)},
165 {
USB_VPI(USB_VENDOR_DISPLAYLINK, USB_PRODUCT_DISPLAYLINK_LD220,
DL165)},
166 {
USB_VPI(USB_VENDOR_DISPLAYLINK, USB_PRODUCT_DISPLAYLINK_VCUD60,
DL160)},
167 {
USB_VPI(USB_VENDOR_DISPLAYLINK, USB_PRODUCT_DISPLAYLINK_DLDVI,
DL160)},
168 {
USB_VPI(USB_VENDOR_DISPLAYLINK, USB_PRODUCT_DISPLAYLINK_VGA10,
DL120)},
169 {
USB_VPI(USB_VENDOR_DISPLAYLINK, USB_PRODUCT_DISPLAYLINK_WSDVI,
DLUNK)},
170 {
USB_VPI(USB_VENDOR_DISPLAYLINK, USB_PRODUCT_DISPLAYLINK_EC008,
DL160)},
171 {
USB_VPI(USB_VENDOR_DISPLAYLINK, USB_PRODUCT_DISPLAYLINK_HPDOCK,
DL160)},
172 {
USB_VPI(USB_VENDOR_DISPLAYLINK, USB_PRODUCT_DISPLAYLINK_NL571,
DL160)},
173 {
USB_VPI(USB_VENDOR_DISPLAYLINK, USB_PRODUCT_DISPLAYLINK_M01061,
DL195)},
174 {
USB_VPI(USB_VENDOR_DISPLAYLINK, USB_PRODUCT_DISPLAYLINK_NBDOCK,
DL165)},
175 {
USB_VPI(USB_VENDOR_DISPLAYLINK, USB_PRODUCT_DISPLAYLINK_SWDVI,
DLUNK)},
176 {
USB_VPI(USB_VENDOR_DISPLAYLINK, USB_PRODUCT_DISPLAYLINK_UM7X0,
DL120)},
177 {
USB_VPI(USB_VENDOR_DISPLAYLINK, USB_PRODUCT_DISPLAYLINK_CONV,
DL160)},
178 {
USB_VPI(USB_VENDOR_DISPLAYLINK, USB_PRODUCT_DISPLAYLINK_PLUGABLE,
DL160)},
179 {
USB_VPI(USB_VENDOR_DISPLAYLINK, USB_PRODUCT_DISPLAYLINK_LUM70,
DL125)},
180 {
USB_VPI(USB_VENDOR_DISPLAYLINK, USB_PRODUCT_DISPLAYLINK_POLARIS2,
DLUNK)},
181 {
USB_VPI(USB_VENDOR_DISPLAYLINK, USB_PRODUCT_DISPLAYLINK_LT1421,
DLUNK)},
182 {
USB_VPI(USB_VENDOR_DISPLAYLINK, USB_PRODUCT_DISPLAYLINK_ITEC,
DL165)},
183 {
USB_VPI(USB_VENDOR_DISPLAYLINK, USB_PRODUCT_DISPLAYLINK_DVI_19,
DL165)},
209 uint8_t *ptr = ((uint8_t *)buf) -
size;
211 memset(ptr, 0,
size);
216 return (malloc(
size +
sizeof(*buf), M_USB_DL, M_WAITOK | M_ZERO));
245 return ((uint32_t)
udl_modes[i].hdisplay *
317 struct sysctl_ctx_list *ctx = device_get_sysctl_ctx(
dev);
318 struct sysctl_oid *tree = device_get_sysctl_tree(
dev);
326 mtx_init(&sc->
sc_mtx,
"UDL lock", NULL, MTX_DEF);
327 cv_init(&sc->
sc_cv,
"UDLCV");
352 SYSCTL_ADD_INT(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
"chipid_force",
356 SYSCTL_ADD_INT(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
"chipid",
357 CTLFLAG_RD, &sc->
sc_chip, 0,
"chip ID");
360 device_printf(
dev,
"Forcing chip ID to 0x%04x\n", sc->
sc_def_chip);
388 SYSCTL_ADD_INT(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
"mode_force",
392 SYSCTL_ADD_INT(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
"mode",
398 device_printf(
dev,
"Forcing mode to %d\n", i);
403 device_printf(
dev,
"Mode selected %dx%d @ %dHz\n",
432 if (device_probe_and_attach(sc->
sc_fbdev) != 0)
449 device_delete_children(
dev);
461 cv_destroy(&sc->
sc_cv);
472static struct fb_info *
489 case V_DISPLAY_BLANK:
497 case V_DISPLAY_STAND_BY:
498 case V_DISPLAY_SUSPEND:
511 if (flags != M_WAITOK)
611 TAILQ_INSERT_TAIL(phead, cb, entry);
629 cv_signal(&sc->
sc_cv);
642 DPRINTF(
"screen %s\n", on ?
"ON" :
"OFF");
658 uint16_t index, uint16_t value, uint8_t *buf,
size_t len)
663 req.bmRequestType = rt;
686 *buf = le32toh(lbuf);
699 *buf = *(uint8_t *)lbuf;
726 bcopy(lbuf + 1, buf +
offset, 63);
733 bcopy(lbuf + 1, buf +
offset, 63);
740 bcopy(lbuf + 1, buf +
offset, 2);
747 uint16_t chip, uint32_t clock)
755 if ((
udl_modes[idx].hdisplay == hdisplay) &&
767 if ((
udl_modes[idx].hdisplay == hdisplay) &&
794 if (strlen(pserial) > 7) {
795 if (strncmp(pserial,
"0198-13", 7) == 0)
798 DPRINTF(
"iSerialNumber (%s) used to select chip (%d)\n",
818 DPRINTF(
"bcdDevice (%02x) used to select chip (%d)\n",
862udl_cmd_insert_int_2(
struct udl_cmd_buf *cb, uint16_t value)
866 lvalue = htobe16(value);
867 bcopy(&lvalue, cb->buf + cb->
off, 2);
879#if BYTE_ORDER == BIG_ENDIAN
880 lvalue = htobe32(
value) << 8;
882 lvalue = htobe32(
value) >> 8;
884 bcopy(&lvalue, cb->buf + cb->
off, 3);
891udl_cmd_insert_int_4(
struct udl_cmd_buf *cb, uint32_t value)
895 lvalue = htobe32(value);
896 bcopy(&lvalue, cb->buf + cb->
off, 4);
908 for (x = 0; x !=
len; x += 2) {
910 cb->buf[cb->
off + x + 0] = buf[x + 1];
911 cb->buf[cb->
off + x + 1] = buf[x + 0];
945 DPRINTF(
"poll=0x%08x\n", ui32);
948 switch (ui32 & 0xff) {
965 DPRINTF(
"read 0x%02x from 0xc484\n", ui8);
970 DPRINTF(
"write 0x01 to 0xc41f\n");
981 DPRINTF(
"set encryption key\n");
986 DPRINTF(
"write 0x00 to 0xc40b\n");
993 uint32_t start8, uint32_t stride8)
1028 for (i = 0; i < max; i += delta) {
1068 (sc->
sc_edid_info.edid_preferred_mode->dot_clock * 1000) /
1081 DPRINTF(
"no preferred mode found!\n");
1085 DPRINTF(
"no mode line found\n");
1088 while (i < sc->sc_edid_info.edid_nmodes) {
1117 uint8_t pixels,
int flags)
1137 uint8_t pixels,
int flags)
struct ehci_hw_softc __aligned
struct usb_xfer * sc_xfer[UDL_N_TRANSFER]
struct udl_cmd_head sc_cmd_buf_pending
struct callout sc_callout
struct fb_info sc_fb_info
struct udl_cmd_head sc_cmd_buf_free
struct edid_info sc_edid_info
struct usb_device * sc_udev
struct udl_cmd_head sc_xfer_head[2]
struct udl_cmd_buf sc_cmd_buf_temp[UDL_CMD_MAX_BUFFERS]
enum usb_hc_mode usb_mode
struct usbd_lookup_info info
struct usb_device * device
MODULE_DEPEND(udl, usb, 1, 1, 1)
DRIVER_MODULE(udl, uhub, udl_driver, udl_devclass, NULL, NULL)
static int udl_init_resolution(struct udl_softc *)
static void udl_select_chip(struct udl_softc *, struct usb_attach_arg *)
static struct mtx udl_buffer_mtx
static void udl_cmd_insert_int_3(struct udl_cmd_buf *, uint32_t)
static void udl_init_fb_offsets(struct udl_cmd_buf *cb, uint32_t start16, uint32_t stride16, uint32_t start8, uint32_t stride8)
static usb_callback_t udl_bulk_write_callback
static device_method_t udl_methods[]
SYSINIT(udl_buffer_init, SI_SUB_LOCK, SI_ORDER_FIRST, udl_buffer_init, NULL)
static int udl_ctrl_msg(struct udl_softc *sc, uint8_t rt, uint8_t r, uint16_t index, uint16_t value, uint8_t *buf, size_t len)
static void udl_cmd_write_reg_3(struct udl_cmd_buf *, uint8_t, uint32_t)
static void udl_cmd_write_reg_1(struct udl_cmd_buf *, uint8_t, uint8_t)
static int udl_read_1(struct udl_softc *sc, uint16_t addr, uint8_t *buf)
static void udl_buffer_free(void *_buf, uint32_t size)
static const STRUCT_USB_HOST_ID udl_devs[]
static void udl_cmd_buf_send(struct udl_softc *sc, struct udl_cmd_buf *cb)
static int udl_cmd_buf_copy_le16(struct udl_softc *, uint32_t, uint32_t, uint8_t, int)
static void * udl_buffer_alloc(uint32_t size)
static int udl_set_enc_key(struct udl_softc *sc, uint8_t *buf, uint8_t len)
static SYSCTL_NODE(_hw_usb, OID_AUTO, udl, CTLFLAG_RW|CTLFLAG_MPSAFE, 0, "USB UDL")
static uint32_t udl_get_fb_hz(struct udl_softc *sc)
static device_detach_t udl_detach
static struct udl_cmd_buf * udl_fb_synchronize_locked(struct udl_softc *sc)
static void udl_cmd_insert_int_1(struct udl_cmd_buf *, uint8_t)
MALLOC_DEFINE(M_USB_DL, "USB", "USB DisplayLink")
static int udl_init_chip(struct udl_softc *)
static const struct usb_config udl_config[UDL_N_TRANSFER]
static int udl_poll(struct udl_softc *sc, uint32_t *buf)
static device_attach_t udl_attach
static int udl_cmd_write_buf_le16(struct udl_softc *, const uint8_t *, uint32_t, uint8_t, int)
static void udl_select_mode(struct udl_softc *)
CTASSERT(sizeof(struct udl_buffer)< PAGE_SIZE)
static void udl_buffer_init(void *arg)
static struct udl_cmd_buf * udl_cmd_buf_alloc_locked(struct udl_softc *sc, int flags)
static int udl_write_1(struct udl_softc *sc, uint16_t addr, uint8_t buf)
static struct udl_buffer_head udl_buffer_head
static devclass_t udl_devclass
static fb_setblankmode_t udl_fb_setblankmode
static int udl_power_save(struct udl_softc *, int, int)
static uint8_t udl_lookup_mode(uint16_t hdisplay, uint16_t vdisplay, uint8_t hz, uint16_t chip, uint32_t clock)
static void udl_fbmem_alloc(struct udl_softc *)
static driver_t udl_driver
static struct udl_cmd_buf * udl_cmd_buf_alloc(struct udl_softc *sc, int flags)
static uint32_t udl_get_fb_height(struct udl_softc *sc)
SYSCTL_INT(_hw_usb_udl, OID_AUTO, fps, CTLFLAG_RWTUN, &udl_fps, 0, "Frames Per Second, 1-60")
static uint32_t udl_get_fb_width(struct udl_softc *sc)
static int udl_read_edid(struct udl_softc *sc, uint8_t *buf)
static void udl_cmd_insert_buf_le16(struct udl_cmd_buf *, const uint8_t *, uint32_t)
static uint32_t udl_get_fb_size(struct udl_softc *sc)
static device_probe_t udl_probe
static void udl_callout(void *arg)
static fb_getinfo_t udl_fb_getinfo
#define UDL_REG_ADDR_START8
#define UDL_REG_ADDR_STRIDE8
#define UDL_CMD_MAX_FRAMES
#define UDL_REG_SCREEN_OFF
#define UDL_CTRL_CMD_WRITE_1
#define UDL_BULK_CMD_FB_WRITE
#define UDL_BULK_CMD_FB_WORD
#define UDL_CTRL_CMD_READ_1
#define UDL_CTRL_CMD_SET_KEY
#define UDL_CMD_MAX_PIXEL_COUNT
static const struct udl_mode udl_modes[UDL_MAX_MODES]
#define UDL_REG_SCREEN_ON
#define UDL_REG_ADDR_STRIDE16
#define UDL_BULK_CMD_REG_WRITE_1
#define UDL_CTRL_CMD_READ_EDID
#define UDL_CMD_MAX_BUFFERS
static const uint8_t udl_null_key_1[]
#define UDL_BULK_CMD_FB_COPY
#define UDL_CMD_MAX_DATA_SIZE
#define UDL_CTRL_CMD_POLL
#define UDL_REG_ADDR_START16
#define UT_WRITE_VENDOR_DEVICE
#define UT_READ_VENDOR_DEVICE
const char * usb_get_serial(struct usb_device *udev)
const char * usbd_errstr(usb_error_t err)
int usbd_lookup_id_by_uaa(const struct usb_device_id *id, usb_size_t sizeof_id, struct usb_attach_arg *uaa)
usb_error_t usbd_do_request_flags(struct usb_device *udev, struct mtx *mtx, struct usb_device_request *req, void *data, uint16_t flags, uint16_t *actlen, usb_timeout_t timeout)
void usbd_transfer_submit(struct usb_xfer *xfer)
void usbd_xfer_set_frames(struct usb_xfer *xfer, usb_frcount_t n)
void * usbd_xfer_get_priv(struct usb_xfer *xfer)
void usbd_transfer_unsetup(struct usb_xfer **pxfer, uint16_t n_setup)
void usbd_xfer_set_frame_data(struct usb_xfer *xfer, usb_frcount_t frindex, void *ptr, usb_frlength_t len)
usb_error_t usbd_transfer_setup(struct usb_device *udev, const uint8_t *ifaces, struct usb_xfer **ppxfer, const struct usb_config *setup_start, uint16_t n_setup, void *priv_sc, struct mtx *xfer_mtx)
void usbd_transfer_start(struct usb_xfer *xfer)
void usbd_xfer_set_priv(struct usb_xfer *xfer, void *ptr)
void * usbd_xfer_softc(struct usb_xfer *xfer)
void usbd_xfer_set_stall(struct usb_xfer *xfer)
void device_set_usb_desc(device_t dev)
#define USB_DEFAULT_TIMEOUT
@ USB_ERR_NORMAL_COMPLETION
#define USB_ST_TRANSFERRED
void() usb_callback_t(struct usb_xfer *, usb_error_t)
#define USB_VPI(vend, prod, info)
#define STRUCT_USB_HOST_ID
#define USB_GET_DRIVER_INFO(did)
#define USB_GET_STATE(xfer)