xref: /freebsd/sys/dev/usb/video/udl.c (revision cc4a90c445aa04be36c3ef745cbe67fa339b94b5)
1 /*	$OpenBSD: udl.c,v 1.81 2014/12/09 07:05:06 doug Exp $ */
2 /*	$FreeBSD$ */
3 
4 /*-
5  * Copyright (c) 2015 Hans Petter Selasky <hselasky@freebsd.org>
6  * Copyright (c) 2009 Marcus Glocker <mglocker@openbsd.org>
7  *
8  * Permission to use, copy, modify, and distribute this software for any
9  * purpose with or without fee is hereby granted, provided that the above
10  * copyright notice and this permission notice appear in all copies.
11  *
12  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
13  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
14  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
15  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
16  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
17  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
18  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19  */
20 
21 /*
22  * Driver for the "DisplayLink DL-120 / DL-160" graphic chips based on
23  * the reversed engineered specifications of Florian Echtler
24  * <floe@butterbrot.org>:
25  *
26  * 	http://floe.butterbrot.org/displaylink/doku.php
27  */
28 
29 #include <sys/param.h>
30 #include <sys/bus.h>
31 #include <sys/callout.h>
32 #include <sys/conf.h>
33 #include <sys/kernel.h>
34 #include <sys/lock.h>
35 #include <sys/module.h>
36 #include <sys/mutex.h>
37 #include <sys/condvar.h>
38 #include <sys/sysctl.h>
39 #include <sys/systm.h>
40 #include <sys/consio.h>
41 #include <sys/fbio.h>
42 
43 #include <dev/fb/fbreg.h>
44 #include <dev/syscons/syscons.h>
45 
46 #include <dev/videomode/videomode.h>
47 #include <dev/videomode/edidvar.h>
48 
49 #include <dev/usb/usb.h>
50 #include <dev/usb/usbdi.h>
51 #include <dev/usb/usbdi_util.h>
52 #include "usbdevs.h"
53 
54 #include <dev/usb/video/udl.h>
55 
56 #include "fb_if.h"
57 
58 #undef DPRINTF
59 #undef DPRINTFN
60 #define	USB_DEBUG_VAR udl_debug
61 #include <dev/usb/usb_debug.h>
62 
63 #ifdef USB_DEBUG
64 static int udl_debug = 0;
65 
66 static	SYSCTL_NODE(_hw_usb, OID_AUTO, udl, CTLFLAG_RW, 0, "USB UDL");
67 
68 SYSCTL_INT(_hw_usb_udl, OID_AUTO, debug, CTLFLAG_RWTUN,
69     &udl_debug, 0, "Debug level");
70 #endif
71 
72 /*
73  * Prototypes.
74  */
75 static usb_callback_t udl_bulk_write_callback;
76 
77 static device_probe_t udl_probe;
78 static device_attach_t udl_attach;
79 static device_detach_t udl_detach;
80 static fb_getinfo_t udl_fb_getinfo;
81 static fb_setblankmode_t udl_fb_setblankmode;
82 
83 static void udl_select_chip(struct udl_softc *, struct usb_attach_arg *);
84 static int udl_init_chip(struct udl_softc *);
85 static void udl_select_mode(struct udl_softc *);
86 static int udl_init_resolution(struct udl_softc *);
87 static void udl_fbmem_alloc(struct udl_softc *);
88 static int udl_cmd_write_buf_le16(struct udl_softc *, const uint8_t *, uint32_t, uint8_t, int);
89 static int udl_cmd_buf_copy_le16(struct udl_softc *, uint32_t, uint32_t, uint8_t, int);
90 static void udl_cmd_insert_int_1(struct udl_cmd_buf *, uint8_t);
91 static void udl_cmd_insert_int_3(struct udl_cmd_buf *, uint32_t);
92 static void udl_cmd_insert_buf_le16(struct udl_cmd_buf *, const uint8_t *, uint32_t);
93 static void udl_cmd_write_reg_1(struct udl_cmd_buf *, uint8_t, uint8_t);
94 static void udl_cmd_write_reg_3(struct udl_cmd_buf *, uint8_t, uint32_t);
95 static int udl_power_save(struct udl_softc *, int, int);
96 
97 static const struct usb_config udl_config[UDL_N_TRANSFER] = {
98 	[UDL_BULK_WRITE_0] = {
99 		.type = UE_BULK,
100 		.endpoint = UE_ADDR_ANY,
101 		.direction = UE_DIR_TX,
102 		.flags = {.pipe_bof = 1,.force_short_xfer = 1,.ext_buffer = 1,},
103 		.bufsize = UDL_CMD_MAX_DATA_SIZE * UDL_CMD_MAX_FRAMES,
104 		.callback = &udl_bulk_write_callback,
105 		.frames = UDL_CMD_MAX_FRAMES,
106 		.timeout = 5000,	/* 5 seconds */
107 	},
108 	[UDL_BULK_WRITE_1] = {
109 		.type = UE_BULK,
110 		.endpoint = UE_ADDR_ANY,
111 		.direction = UE_DIR_TX,
112 		.flags = {.pipe_bof = 1,.force_short_xfer = 1,.ext_buffer = 1,},
113 		.bufsize = UDL_CMD_MAX_DATA_SIZE * UDL_CMD_MAX_FRAMES,
114 		.callback = &udl_bulk_write_callback,
115 		.frames = UDL_CMD_MAX_FRAMES,
116 		.timeout = 5000,	/* 5 seconds */
117 	},
118 };
119 
120 /*
121  * Driver glue.
122  */
123 static devclass_t udl_devclass;
124 
125 static device_method_t udl_methods[] = {
126 	DEVMETHOD(device_probe, udl_probe),
127 	DEVMETHOD(device_attach, udl_attach),
128 	DEVMETHOD(device_detach, udl_detach),
129 	DEVMETHOD(fb_getinfo, udl_fb_getinfo),
130 	DEVMETHOD_END
131 };
132 
133 static driver_t udl_driver = {
134 	.name = "udl",
135 	.methods = udl_methods,
136 	.size = sizeof(struct udl_softc),
137 };
138 
139 DRIVER_MODULE(udl, uhub, udl_driver, udl_devclass, NULL, NULL);
140 MODULE_DEPEND(udl, usb, 1, 1, 1);
141 MODULE_DEPEND(udl, fbd, 1, 1, 1);
142 MODULE_DEPEND(udl, videomode, 1, 1, 1);
143 MODULE_VERSION(udl, 1);
144 
145 /*
146  * Matching devices.
147  */
148 static const STRUCT_USB_HOST_ID udl_devs[] = {
149 	{USB_VPI(USB_VENDOR_DISPLAYLINK, USB_PRODUCT_DISPLAYLINK_LCD4300U, DL120)},
150 	{USB_VPI(USB_VENDOR_DISPLAYLINK, USB_PRODUCT_DISPLAYLINK_LCD8000U, DL120)},
151 	{USB_VPI(USB_VENDOR_DISPLAYLINK, USB_PRODUCT_DISPLAYLINK_GUC2020, DL160)},
152 	{USB_VPI(USB_VENDOR_DISPLAYLINK, USB_PRODUCT_DISPLAYLINK_LD220, DL165)},
153 	{USB_VPI(USB_VENDOR_DISPLAYLINK, USB_PRODUCT_DISPLAYLINK_VCUD60, DL160)},
154 	{USB_VPI(USB_VENDOR_DISPLAYLINK, USB_PRODUCT_DISPLAYLINK_DLDVI, DL160)},
155 	{USB_VPI(USB_VENDOR_DISPLAYLINK, USB_PRODUCT_DISPLAYLINK_VGA10, DL120)},
156 	{USB_VPI(USB_VENDOR_DISPLAYLINK, USB_PRODUCT_DISPLAYLINK_WSDVI, DLUNK)},
157 	{USB_VPI(USB_VENDOR_DISPLAYLINK, USB_PRODUCT_DISPLAYLINK_EC008, DL160)},
158 	{USB_VPI(USB_VENDOR_DISPLAYLINK, USB_PRODUCT_DISPLAYLINK_HPDOCK, DL160)},
159 	{USB_VPI(USB_VENDOR_DISPLAYLINK, USB_PRODUCT_DISPLAYLINK_NL571, DL160)},
160 	{USB_VPI(USB_VENDOR_DISPLAYLINK, USB_PRODUCT_DISPLAYLINK_M01061, DL195)},
161 	{USB_VPI(USB_VENDOR_DISPLAYLINK, USB_PRODUCT_DISPLAYLINK_NBDOCK, DL165)},
162 	{USB_VPI(USB_VENDOR_DISPLAYLINK, USB_PRODUCT_DISPLAYLINK_SWDVI, DLUNK)},
163 	{USB_VPI(USB_VENDOR_DISPLAYLINK, USB_PRODUCT_DISPLAYLINK_UM7X0, DL120)},
164 	{USB_VPI(USB_VENDOR_DISPLAYLINK, USB_PRODUCT_DISPLAYLINK_CONV, DL160)},
165 	{USB_VPI(USB_VENDOR_DISPLAYLINK, USB_PRODUCT_DISPLAYLINK_PLUGABLE, DL160)},
166 	{USB_VPI(USB_VENDOR_DISPLAYLINK, USB_PRODUCT_DISPLAYLINK_LUM70, DL125)},
167 	{USB_VPI(USB_VENDOR_DISPLAYLINK, USB_PRODUCT_DISPLAYLINK_POLARIS2, DLUNK)},
168 	{USB_VPI(USB_VENDOR_DISPLAYLINK, USB_PRODUCT_DISPLAYLINK_LT1421, DLUNK)}
169 };
170 
171 static uint32_t
172 udl_get_fb_size(struct udl_softc *sc)
173 {
174 	unsigned i = sc->sc_cur_mode;
175 
176 	return ((uint32_t)udl_modes[i].hdisplay *
177 	    (uint32_t)udl_modes[i].vdisplay * 2);
178 }
179 
180 static uint32_t
181 udl_get_fb_width(struct udl_softc *sc)
182 {
183 	unsigned i = sc->sc_cur_mode;
184 
185 	return (udl_modes[i].hdisplay);
186 }
187 
188 static uint32_t
189 udl_get_fb_height(struct udl_softc *sc)
190 {
191 	unsigned i = sc->sc_cur_mode;
192 
193 	return (udl_modes[i].vdisplay);
194 }
195 
196 static uint32_t
197 udl_get_fb_hz(struct udl_softc *sc)
198 {
199 	unsigned i = sc->sc_cur_mode;
200 
201 	return (udl_modes[i].hz);
202 }
203 
204 static void
205 udl_callout(void *arg)
206 {
207 	struct udl_softc *sc = arg;
208 	const uint32_t max = udl_get_fb_size(sc);
209 
210 	if (sc->sc_power_save == 0) {
211 		if (sc->sc_sync_off >= max)
212 			sc->sc_sync_off = 0;
213 		usbd_transfer_start(sc->sc_xfer[UDL_BULK_WRITE_0]);
214 		usbd_transfer_start(sc->sc_xfer[UDL_BULK_WRITE_1]);
215 	}
216 	callout_reset(&sc->sc_callout, hz / 5, &udl_callout, sc);
217 }
218 
219 static int
220 udl_probe(device_t dev)
221 {
222 	struct usb_attach_arg *uaa = device_get_ivars(dev);
223 
224 	if (uaa->usb_mode != USB_MODE_HOST)
225 		return (ENXIO);
226 	if (uaa->info.bConfigIndex != 0)
227 		return (ENXIO);
228 	if (uaa->info.bIfaceIndex != 0)
229 		return (ENXIO);
230 
231 	return (usbd_lookup_id_by_uaa(udl_devs, sizeof(udl_devs), uaa));
232 }
233 
234 static int
235 udl_attach(device_t dev)
236 {
237 	struct sysctl_ctx_list *ctx = device_get_sysctl_ctx(dev);
238 	struct sysctl_oid *tree = device_get_sysctl_tree(dev);
239 	struct udl_softc *sc = device_get_softc(dev);
240 	struct usb_attach_arg *uaa = device_get_ivars(dev);
241 	int error;
242 	int i;
243 
244 	device_set_usb_desc(dev);
245 
246 	mtx_init(&sc->sc_mtx, "UDL lock", NULL, MTX_DEF);
247 	cv_init(&sc->sc_cv, "UDLCV");
248 	callout_init_mtx(&sc->sc_callout, &sc->sc_mtx, 0);
249 	sc->sc_udev = uaa->device;
250 
251 	error = usbd_transfer_setup(uaa->device, &uaa->info.bIfaceIndex,
252 	    sc->sc_xfer, udl_config, UDL_N_TRANSFER, sc, &sc->sc_mtx);
253 
254 	if (error) {
255 		DPRINTF("usbd_transfer_setup error=%s\n", usbd_errstr(error));
256 		goto detach;
257 	}
258 	usbd_xfer_set_priv(sc->sc_xfer[UDL_BULK_WRITE_0], &sc->sc_xfer_head[0]);
259 	usbd_xfer_set_priv(sc->sc_xfer[UDL_BULK_WRITE_1], &sc->sc_xfer_head[1]);
260 
261 	TAILQ_INIT(&sc->sc_xfer_head[0]);
262 	TAILQ_INIT(&sc->sc_xfer_head[1]);
263 	TAILQ_INIT(&sc->sc_cmd_buf_free);
264 	TAILQ_INIT(&sc->sc_cmd_buf_pending);
265 
266 	sc->sc_def_chip = -1;
267 	sc->sc_chip = USB_GET_DRIVER_INFO(uaa);
268 	sc->sc_def_mode = -1;
269 	sc->sc_cur_mode = UDL_MAX_MODES;
270 
271 	/* Allow chip ID to be overwritten */
272 	SYSCTL_ADD_INT(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, "chipid_force",
273 	    CTLFLAG_RWTUN, &sc->sc_def_chip, 0, "chip ID");
274 
275 	/* Export current chip ID */
276 	SYSCTL_ADD_INT(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, "chipid",
277 	    CTLFLAG_RD, &sc->sc_chip, 0, "chip ID");
278 
279 	if (sc->sc_def_chip > -1 && sc->sc_def_chip <= DLMAX) {
280 		device_printf(dev, "Forcing chip ID to 0x%04x\n", sc->sc_def_chip);
281 		sc->sc_chip = sc->sc_def_chip;
282 	}
283 	/*
284 	 * The product might have more than one chip
285 	 */
286 	if (sc->sc_chip == DLUNK)
287 		udl_select_chip(sc, uaa);
288 
289 	for (i = 0; i != UDL_CMD_MAX_BUFFERS; i++) {
290 		struct udl_cmd_buf *cb = &sc->sc_cmd_buf_temp[i];
291 
292 		TAILQ_INSERT_TAIL(&sc->sc_cmd_buf_free, cb, entry);
293 	}
294 
295 	/*
296 	 * Initialize chip.
297 	 */
298 	error = udl_init_chip(sc);
299 	if (error != USB_ERR_NORMAL_COMPLETION)
300 		goto detach;
301 
302 	/*
303 	 * Select edid mode.
304 	 */
305 	udl_select_mode(sc);
306 
307 	/* Allow default mode to be overwritten */
308 	SYSCTL_ADD_INT(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, "mode_force",
309 	    CTLFLAG_RWTUN, &sc->sc_def_mode, 0, "mode");
310 
311 	/* Export current mode */
312 	SYSCTL_ADD_INT(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, "mode",
313 	    CTLFLAG_RD, &sc->sc_cur_mode, 0, "mode");
314 
315 	i = sc->sc_def_mode;
316 	if (i > -1 && i < UDL_MAX_MODES) {
317 		if (udl_modes[i].chip <= sc->sc_chip) {
318 			device_printf(dev, "Forcing mode to %d\n", i);
319 			sc->sc_cur_mode = i;
320 		}
321 	}
322 	/* Printout current mode */
323 	device_printf(dev, "Mode selected %dx%d @ %dHz\n",
324 	    (int)udl_get_fb_width(sc),
325 	    (int)udl_get_fb_height(sc),
326 	    (int)udl_get_fb_hz(sc));
327 
328 	udl_init_resolution(sc);
329 
330 	/* Allocate frame buffer */
331 	udl_fbmem_alloc(sc);
332 
333 	UDL_LOCK(sc);
334 	udl_callout(sc);
335 	UDL_UNLOCK(sc);
336 
337 	sc->sc_fb_info.fb_name = device_get_nameunit(dev);
338 	sc->sc_fb_info.fb_size = sc->sc_fb_size;
339 	sc->sc_fb_info.fb_bpp = 16;
340 	sc->sc_fb_info.fb_depth = 16;
341 	sc->sc_fb_info.fb_width = udl_get_fb_width(sc);
342 	sc->sc_fb_info.fb_height = udl_get_fb_height(sc);
343 	sc->sc_fb_info.fb_stride = sc->sc_fb_info.fb_width * 2;
344 	sc->sc_fb_info.fb_pbase = 0;
345 	sc->sc_fb_info.fb_vbase = (uintptr_t)sc->sc_fb_addr;
346 	sc->sc_fb_info.fb_priv = sc;
347 	sc->sc_fb_info.setblankmode = &udl_fb_setblankmode;
348 
349 	sc->sc_fbdev = device_add_child(dev, "fbd", -1);
350 	if (sc->sc_fbdev == NULL)
351 		goto detach;
352 	if (device_probe_and_attach(sc->sc_fbdev) != 0)
353 		goto detach;
354 
355 	return (0);
356 
357 detach:
358 	udl_detach(dev);
359 
360 	return (ENXIO);
361 }
362 
363 static int
364 udl_detach(device_t dev)
365 {
366 	struct udl_softc *sc = device_get_softc(dev);
367 
368 	if (sc->sc_fbdev != NULL) {
369 		device_t bdev;
370 
371 		bdev = sc->sc_fbdev;
372 		sc->sc_fbdev = NULL;
373 		device_detach(bdev);
374 		device_delete_child(dev, bdev);
375 	}
376 	UDL_LOCK(sc);
377 	sc->sc_gone = 1;
378 	callout_stop(&sc->sc_callout);
379 	UDL_UNLOCK(sc);
380 
381 	usbd_transfer_unsetup(sc->sc_xfer, UDL_N_TRANSFER);
382 
383 	callout_drain(&sc->sc_callout);
384 
385 	mtx_destroy(&sc->sc_mtx);
386 	cv_destroy(&sc->sc_cv);
387 
388 	/*
389 	 * Free framebuffer memory, if any.
390 	 */
391 	free(sc->sc_fb_addr, M_DEVBUF);
392 	free(sc->sc_fb_copy, M_DEVBUF);
393 
394 	return (0);
395 }
396 
397 static struct fb_info *
398 udl_fb_getinfo(device_t dev)
399 {
400 	struct udl_softc *sc = device_get_softc(dev);
401 
402 	return (&sc->sc_fb_info);
403 }
404 
405 static int
406 udl_fb_setblankmode(void *arg, int mode)
407 {
408 	struct udl_softc *sc = arg;
409 
410 	switch (mode) {
411 	case V_DISPLAY_ON:
412 		udl_power_save(sc, 1, M_WAITOK);
413 		break;
414 	case V_DISPLAY_BLANK:
415 		udl_power_save(sc, 1, M_WAITOK);
416 		if (sc->sc_fb_addr != 0) {
417 			const uint32_t max = udl_get_fb_size(sc);
418 
419 			memset((void *)sc->sc_fb_addr, 0, max);
420 		}
421 		break;
422 	case V_DISPLAY_STAND_BY:
423 	case V_DISPLAY_SUSPEND:
424 		udl_power_save(sc, 0, M_WAITOK);
425 		break;
426 	}
427 	return (0);
428 }
429 
430 static struct udl_cmd_buf *
431 udl_cmd_buf_alloc_locked(struct udl_softc *sc, int flags)
432 {
433 	struct udl_cmd_buf *cb;
434 
435 	while ((cb = TAILQ_FIRST(&sc->sc_cmd_buf_free)) == NULL) {
436 		if (flags != M_WAITOK)
437 			break;
438 		cv_wait(&sc->sc_cv, &sc->sc_mtx);
439 	}
440 	if (cb != NULL) {
441 		TAILQ_REMOVE(&sc->sc_cmd_buf_free, cb, entry);
442 		cb->off = 0;
443 	}
444 	return (cb);
445 }
446 
447 static struct udl_cmd_buf *
448 udl_cmd_buf_alloc(struct udl_softc *sc, int flags)
449 {
450 	struct udl_cmd_buf *cb;
451 
452 	UDL_LOCK(sc);
453 	cb = udl_cmd_buf_alloc_locked(sc, flags);
454 	UDL_UNLOCK(sc);
455 	return (cb);
456 }
457 
458 static void
459 udl_cmd_buf_send(struct udl_softc *sc, struct udl_cmd_buf *cb)
460 {
461 	UDL_LOCK(sc);
462 	if (sc->sc_gone) {
463 		TAILQ_INSERT_TAIL(&sc->sc_cmd_buf_free, cb, entry);
464 	} else {
465 		/* mark end of command stack */
466 		udl_cmd_insert_int_1(cb, UDL_BULK_SOC);
467 		udl_cmd_insert_int_1(cb, UDL_BULK_CMD_EOC);
468 
469 		TAILQ_INSERT_TAIL(&sc->sc_cmd_buf_pending, cb, entry);
470 		usbd_transfer_start(sc->sc_xfer[UDL_BULK_WRITE_0]);
471 		usbd_transfer_start(sc->sc_xfer[UDL_BULK_WRITE_1]);
472 	}
473 	UDL_UNLOCK(sc);
474 }
475 
476 static struct udl_cmd_buf *
477 udl_fb_synchronize_locked(struct udl_softc *sc)
478 {
479 	const uint32_t max = udl_get_fb_size(sc);
480 
481 	/* check if framebuffer is not ready */
482 	if (sc->sc_fb_addr == NULL ||
483 	    sc->sc_fb_copy == NULL)
484 		return (NULL);
485 
486 	while (sc->sc_sync_off < max) {
487 		uint32_t delta = max - sc->sc_sync_off;
488 
489 		if (delta > UDL_CMD_MAX_PIXEL_COUNT * 2)
490 			delta = UDL_CMD_MAX_PIXEL_COUNT * 2;
491 		if (bcmp(sc->sc_fb_addr + sc->sc_sync_off, sc->sc_fb_copy + sc->sc_sync_off, delta) != 0) {
492 			struct udl_cmd_buf *cb;
493 
494 			cb = udl_cmd_buf_alloc_locked(sc, M_NOWAIT);
495 			if (cb == NULL)
496 				goto done;
497 			memcpy(sc->sc_fb_copy + sc->sc_sync_off,
498 			    sc->sc_fb_addr + sc->sc_sync_off, delta);
499 			udl_cmd_insert_int_1(cb, UDL_BULK_SOC);
500 			udl_cmd_insert_int_1(cb, UDL_BULK_CMD_FB_WRITE | UDL_BULK_CMD_FB_WORD);
501 			udl_cmd_insert_int_3(cb, sc->sc_sync_off);
502 			udl_cmd_insert_int_1(cb, delta / 2);
503 			udl_cmd_insert_buf_le16(cb, sc->sc_fb_copy + sc->sc_sync_off, delta);
504 			sc->sc_sync_off += delta;
505 			return (cb);
506 		} else {
507 			sc->sc_sync_off += delta;
508 		}
509 	}
510 done:
511 	return (NULL);
512 }
513 
514 static void
515 udl_bulk_write_callback(struct usb_xfer *xfer, usb_error_t error)
516 {
517 	struct udl_softc *sc = usbd_xfer_softc(xfer);
518 	struct udl_cmd_head *phead = usbd_xfer_get_priv(xfer);
519 	struct udl_cmd_buf *cb;
520 	unsigned i;
521 
522 	switch (USB_GET_STATE(xfer)) {
523 	case USB_ST_TRANSFERRED:
524 		TAILQ_CONCAT(&sc->sc_cmd_buf_free, phead, entry);
525 	case USB_ST_SETUP:
526 tr_setup:
527 		for (i = 0; i != UDL_CMD_MAX_FRAMES; i++) {
528 			cb = TAILQ_FIRST(&sc->sc_cmd_buf_pending);
529 			if (cb == NULL) {
530 				cb = udl_fb_synchronize_locked(sc);
531 				if (cb == NULL)
532 					break;
533 			} else {
534 				TAILQ_REMOVE(&sc->sc_cmd_buf_pending, cb, entry);
535 			}
536 			TAILQ_INSERT_TAIL(phead, cb, entry);
537 			usbd_xfer_set_frame_data(xfer, i, cb->buf, cb->off);
538 		}
539 		if (i != 0) {
540 			usbd_xfer_set_frames(xfer, i);
541 			usbd_transfer_submit(xfer);
542 		}
543 		break;
544 	default:
545 		TAILQ_CONCAT(&sc->sc_cmd_buf_free, phead, entry);
546 		if (error != USB_ERR_CANCELLED) {
547 			/* try clear stall first */
548 			usbd_xfer_set_stall(xfer);
549 			goto tr_setup;
550 		}
551 		break;
552 	}
553 	/* wakeup any waiters */
554 	cv_signal(&sc->sc_cv);
555 }
556 
557 static int
558 udl_power_save(struct udl_softc *sc, int on, int flags)
559 {
560 	struct udl_cmd_buf *cb;
561 
562 	/* get new buffer */
563 	cb = udl_cmd_buf_alloc(sc, flags);
564 	if (cb == NULL)
565 		return (EAGAIN);
566 
567 	DPRINTF("screen %s\n", on ? "ON" : "OFF");
568 
569 	sc->sc_power_save = on ? 0 : 1;
570 
571 	if (on)
572 		udl_cmd_write_reg_1(cb, UDL_REG_SCREEN, UDL_REG_SCREEN_ON);
573 	else
574 		udl_cmd_write_reg_1(cb, UDL_REG_SCREEN, UDL_REG_SCREEN_OFF);
575 
576 	udl_cmd_write_reg_1(cb, UDL_REG_SYNC, 0xff);
577 	udl_cmd_buf_send(sc, cb);
578 	return (0);
579 }
580 
581 static int
582 udl_ctrl_msg(struct udl_softc *sc, uint8_t rt, uint8_t r,
583     uint16_t index, uint16_t value, uint8_t *buf, size_t len)
584 {
585 	usb_device_request_t req;
586 	int error;
587 
588 	req.bmRequestType = rt;
589 	req.bRequest = r;
590 	USETW(req.wIndex, index);
591 	USETW(req.wValue, value);
592 	USETW(req.wLength, len);
593 
594 	error = usbd_do_request_flags(sc->sc_udev, NULL,
595 	    &req, buf, 0, NULL, USB_DEFAULT_TIMEOUT);
596 
597 	DPRINTF("%s\n", usbd_errstr(error));
598 
599 	return (error);
600 }
601 
602 static int
603 udl_poll(struct udl_softc *sc, uint32_t *buf)
604 {
605 	uint32_t lbuf;
606 	int error;
607 
608 	error = udl_ctrl_msg(sc, UT_READ_VENDOR_DEVICE,
609 	    UDL_CTRL_CMD_POLL, 0x0000, 0x0000, (uint8_t *)&lbuf, sizeof(lbuf));
610 	if (error == USB_ERR_NORMAL_COMPLETION)
611 		*buf = le32toh(lbuf);
612 	return (error);
613 }
614 
615 static int
616 udl_read_1(struct udl_softc *sc, uint16_t addr, uint8_t *buf)
617 {
618 	uint8_t lbuf[1];
619 	int error;
620 
621 	error = udl_ctrl_msg(sc, UT_READ_VENDOR_DEVICE,
622 	    UDL_CTRL_CMD_READ_1, addr, 0x0000, lbuf, 1);
623 	if (error == USB_ERR_NORMAL_COMPLETION)
624 		*buf = *(uint8_t *)lbuf;
625 	return (error);
626 }
627 
628 static int
629 udl_write_1(struct udl_softc *sc, uint16_t addr, uint8_t buf)
630 {
631 	int error;
632 
633 	error = udl_ctrl_msg(sc, UT_WRITE_VENDOR_DEVICE,
634 	    UDL_CTRL_CMD_WRITE_1, addr, 0x0000, &buf, 1);
635 	return (error);
636 }
637 
638 static int
639 udl_read_edid(struct udl_softc *sc, uint8_t *buf)
640 {
641 	uint8_t lbuf[64];
642 	uint16_t offset;
643 	int error;
644 
645 	offset = 0;
646 
647 	error = udl_ctrl_msg(sc, UT_READ_VENDOR_DEVICE,
648 	    UDL_CTRL_CMD_READ_EDID, 0x00a1, (offset << 8), lbuf, 64);
649 	if (error != USB_ERR_NORMAL_COMPLETION)
650 		goto fail;
651 	bcopy(lbuf + 1, buf + offset, 63);
652 	offset += 63;
653 
654 	error = udl_ctrl_msg(sc, UT_READ_VENDOR_DEVICE,
655 	    UDL_CTRL_CMD_READ_EDID, 0x00a1, (offset << 8), lbuf, 64);
656 	if (error != USB_ERR_NORMAL_COMPLETION)
657 		goto fail;
658 	bcopy(lbuf + 1, buf + offset, 63);
659 	offset += 63;
660 
661 	error = udl_ctrl_msg(sc, UT_READ_VENDOR_DEVICE,
662 	    UDL_CTRL_CMD_READ_EDID, 0x00a1, (offset << 8), lbuf, 3);
663 	if (error != USB_ERR_NORMAL_COMPLETION)
664 		goto fail;
665 	bcopy(lbuf + 1, buf + offset, 2);
666 fail:
667 	return (error);
668 }
669 
670 static uint8_t
671 udl_lookup_mode(uint16_t hdisplay, uint16_t vdisplay, uint8_t hz,
672     uint16_t chip, uint32_t clock)
673 {
674 	uint8_t idx;
675 
676 	/*
677 	 * Check first if we have a matching mode with pixelclock
678 	 */
679 	for (idx = 0; idx != UDL_MAX_MODES; idx++) {
680 		if ((udl_modes[idx].hdisplay == hdisplay) &&
681 		    (udl_modes[idx].vdisplay == vdisplay) &&
682 		    (udl_modes[idx].clock == clock) &&
683 		    (udl_modes[idx].chip <= chip)) {
684 			return (idx);
685 		}
686 	}
687 
688 	/*
689 	 * If not, check for matching mode with update frequency
690 	 */
691 	for (idx = 0; idx != UDL_MAX_MODES; idx++) {
692 		if ((udl_modes[idx].hdisplay == hdisplay) &&
693 		    (udl_modes[idx].vdisplay == vdisplay) &&
694 		    (udl_modes[idx].hz == hz) &&
695 		    (udl_modes[idx].chip <= chip)) {
696 			return (idx);
697 		}
698 	}
699 	return (idx);
700 }
701 
702 static void
703 udl_select_chip(struct udl_softc *sc, struct usb_attach_arg *uaa)
704 {
705 	const char *pserial;
706 
707 	pserial = usb_get_serial(uaa->device);
708 
709 	sc->sc_chip = DL120;
710 
711 	if ((uaa->info.idVendor == USB_VENDOR_DISPLAYLINK) &&
712 	    (uaa->info.idProduct == USB_PRODUCT_DISPLAYLINK_WSDVI)) {
713 
714 		/*
715 		 * WS Tech DVI is DL120 or DL160. All deviced uses the
716 		 * same revision (0.04) so iSerialNumber must be used
717 		 * to determin which chip it is.
718 		 */
719 
720 		if (strlen(pserial) > 7) {
721 			if (strncmp(pserial, "0198-13", 7) == 0)
722 				sc->sc_chip = DL160;
723 		}
724 		DPRINTF("iSerialNumber (%s) used to select chip (%d)\n",
725 		    pserial, sc->sc_chip);
726 	}
727 	if ((uaa->info.idVendor == USB_VENDOR_DISPLAYLINK) &&
728 	    (uaa->info.idProduct == USB_PRODUCT_DISPLAYLINK_SWDVI)) {
729 
730 		/*
731 		 * SUNWEIT DVI is DL160, DL125, DL165 or DL195. Major revision
732 		 * can be used to differ between DL1x0 and DL1x5. Minor to
733 		 * differ between DL1x5. iSerialNumber seems not to be uniqe.
734 		 */
735 
736 		sc->sc_chip = DL160;
737 
738 		if (uaa->info.bcdDevice >= 0x100) {
739 			sc->sc_chip = DL165;
740 			if (uaa->info.bcdDevice == 0x104)
741 				sc->sc_chip = DL195;
742 			if (uaa->info.bcdDevice == 0x108)
743 				sc->sc_chip = DL125;
744 		}
745 		DPRINTF("bcdDevice (%02x) used to select chip (%d)\n",
746 		    uaa->info.bcdDevice, sc->sc_chip);
747 	}
748 }
749 
750 static int
751 udl_set_enc_key(struct udl_softc *sc, uint8_t *buf, uint8_t len)
752 {
753 	int error;
754 
755 	error = udl_ctrl_msg(sc, UT_WRITE_VENDOR_DEVICE,
756 	    UDL_CTRL_CMD_SET_KEY, 0x0000, 0x0000, buf, len);
757 	return (error);
758 }
759 
760 static void
761 udl_fbmem_alloc(struct udl_softc *sc)
762 {
763 	uint32_t size;
764 
765 	size = udl_get_fb_size(sc);
766 	size = round_page(size);
767 
768 	sc->sc_fb_addr = malloc(size, M_DEVBUF, M_WAITOK | M_ZERO);
769 	sc->sc_fb_copy = malloc(size, M_DEVBUF, M_WAITOK | M_ZERO);
770 	sc->sc_fb_size = size;
771 }
772 
773 static void
774 udl_cmd_insert_int_1(struct udl_cmd_buf *cb, uint8_t value)
775 {
776 
777 	cb->buf[cb->off] = value;
778 	cb->off += 1;
779 }
780 
781 #if 0
782 static void
783 udl_cmd_insert_int_2(struct udl_cmd_buf *cb, uint16_t value)
784 {
785 	uint16_t lvalue;
786 
787 	lvalue = htobe16(value);
788 	bcopy(&lvalue, cb->buf + cb->off, 2);
789 
790 	cb->off += 2;
791 }
792 
793 #endif
794 
795 static void
796 udl_cmd_insert_int_3(struct udl_cmd_buf *cb, uint32_t value)
797 {
798 	uint32_t lvalue;
799 
800 #if BYTE_ORDER == BIG_ENDIAN
801 	lvalue = htobe32(value) << 8;
802 #else
803 	lvalue = htobe32(value) >> 8;
804 #endif
805 	bcopy(&lvalue, cb->buf + cb->off, 3);
806 
807 	cb->off += 3;
808 }
809 
810 #if 0
811 static void
812 udl_cmd_insert_int_4(struct udl_cmd_buf *cb, uint32_t value)
813 {
814 	uint32_t lvalue;
815 
816 	lvalue = htobe32(value);
817 	bcopy(&lvalue, cb->buf + cb->off, 4);
818 
819 	cb->off += 4;
820 }
821 
822 #endif
823 
824 static void
825 udl_cmd_insert_buf_le16(struct udl_cmd_buf *cb, const uint8_t *buf, uint32_t len)
826 {
827 	uint32_t x;
828 
829 	for (x = 0; x != len; x += 2) {
830 		/* byte swap from little endian to big endian */
831 		cb->buf[cb->off + x + 0] = buf[x + 1];
832 		cb->buf[cb->off + x + 1] = buf[x + 0];
833 	}
834 	cb->off += len;
835 }
836 
837 static void
838 udl_cmd_write_reg_1(struct udl_cmd_buf *cb, uint8_t reg, uint8_t val)
839 {
840 
841 	udl_cmd_insert_int_1(cb, UDL_BULK_SOC);
842 	udl_cmd_insert_int_1(cb, UDL_BULK_CMD_REG_WRITE_1);
843 	udl_cmd_insert_int_1(cb, reg);
844 	udl_cmd_insert_int_1(cb, val);
845 }
846 
847 static void
848 udl_cmd_write_reg_3(struct udl_cmd_buf *cb, uint8_t reg, uint32_t val)
849 {
850 
851 	udl_cmd_write_reg_1(cb, reg + 0, (val >> 16) & 0xff);
852 	udl_cmd_write_reg_1(cb, reg + 1, (val >> 8) & 0xff);
853 	udl_cmd_write_reg_1(cb, reg + 2, (val >> 0) & 0xff);
854 }
855 
856 static int
857 udl_init_chip(struct udl_softc *sc)
858 {
859 	uint32_t ui32;
860 	uint8_t ui8;
861 	int error;
862 
863 	error = udl_poll(sc, &ui32);
864 	if (error != USB_ERR_NORMAL_COMPLETION)
865 		return (error);
866 	DPRINTF("poll=0x%08x\n", ui32);
867 
868 	/* Some products may use later chip too */
869 	switch (ui32 & 0xff) {
870 	case 0xf1:			/* DL1x5 */
871 		switch (sc->sc_chip) {
872 		case DL120:
873 			sc->sc_chip = DL125;
874 			break;
875 		case DL160:
876 			sc->sc_chip = DL165;
877 			break;
878 		}
879 		break;
880 	}
881 	DPRINTF("chip 0x%04x\n", sc->sc_chip);
882 
883 	error = udl_read_1(sc, 0xc484, &ui8);
884 	if (error != USB_ERR_NORMAL_COMPLETION)
885 		return (error);
886 	DPRINTF("read 0x%02x from 0xc484\n", ui8);
887 
888 	error = udl_write_1(sc, 0xc41f, 0x01);
889 	if (error != USB_ERR_NORMAL_COMPLETION)
890 		return (error);
891 	DPRINTF("write 0x01 to 0xc41f\n");
892 
893 	error = udl_read_edid(sc, sc->sc_edid);
894 	if (error != USB_ERR_NORMAL_COMPLETION)
895 		return (error);
896 	DPRINTF("read EDID\n");
897 
898 	error = udl_set_enc_key(sc, __DECONST(void *, udl_null_key_1),
899 	    sizeof(udl_null_key_1));
900 	if (error != USB_ERR_NORMAL_COMPLETION)
901 		return (error);
902 	DPRINTF("set encryption key\n");
903 
904 	error = udl_write_1(sc, 0xc40b, 0x00);
905 	if (error != USB_ERR_NORMAL_COMPLETION)
906 		return (error);
907 	DPRINTF("write 0x00 to 0xc40b\n");
908 
909 	return (USB_ERR_NORMAL_COMPLETION);
910 }
911 
912 static void
913 udl_init_fb_offsets(struct udl_cmd_buf *cb, uint32_t start16, uint32_t stride16,
914     uint32_t start8, uint32_t stride8)
915 {
916 	udl_cmd_write_reg_1(cb, UDL_REG_SYNC, 0x00);
917 	udl_cmd_write_reg_3(cb, UDL_REG_ADDR_START16, start16);
918 	udl_cmd_write_reg_3(cb, UDL_REG_ADDR_STRIDE16, stride16);
919 	udl_cmd_write_reg_3(cb, UDL_REG_ADDR_START8, start8);
920 	udl_cmd_write_reg_3(cb, UDL_REG_ADDR_STRIDE8, stride8);
921 	udl_cmd_write_reg_1(cb, UDL_REG_SYNC, 0xff);
922 }
923 
924 static int
925 udl_init_resolution(struct udl_softc *sc)
926 {
927 	const uint32_t max = udl_get_fb_size(sc);
928 	const uint8_t *buf = udl_modes[sc->sc_cur_mode].mode;
929 	struct udl_cmd_buf *cb;
930 	uint32_t delta;
931 	uint32_t i;
932 	int error;
933 
934 	/* get new buffer */
935 	cb = udl_cmd_buf_alloc(sc, M_WAITOK);
936 	if (cb == NULL)
937 		return (EAGAIN);
938 
939 	/* write resolution values and set video memory offsets */
940 	udl_cmd_write_reg_1(cb, UDL_REG_SYNC, 0x00);
941 	for (i = 0; i < UDL_MODE_SIZE; i++)
942 		udl_cmd_write_reg_1(cb, i, buf[i]);
943 	udl_cmd_write_reg_1(cb, UDL_REG_SYNC, 0xff);
944 
945 	udl_init_fb_offsets(cb, 0x000000, 0x000a00, 0x555555, 0x000500);
946 	udl_cmd_buf_send(sc, cb);
947 
948 	/* fill screen with black color */
949 	for (i = 0; i < max; i += delta) {
950 		static const uint8_t udl_black[UDL_CMD_MAX_PIXEL_COUNT * 2] __aligned(4);
951 
952 		delta = max - i;
953 		if (delta > UDL_CMD_MAX_PIXEL_COUNT * 2)
954 			delta = UDL_CMD_MAX_PIXEL_COUNT * 2;
955 		if (i == 0)
956 			error = udl_cmd_write_buf_le16(sc, udl_black, i, delta / 2, M_WAITOK);
957 		else
958 			error = udl_cmd_buf_copy_le16(sc, 0, i, delta / 2, M_WAITOK);
959 		if (error)
960 			return (error);
961 	}
962 
963 	/* get new buffer */
964 	cb = udl_cmd_buf_alloc(sc, M_WAITOK);
965 	if (cb == NULL)
966 		return (EAGAIN);
967 
968 	/* show framebuffer content */
969 	udl_cmd_write_reg_1(cb, UDL_REG_SCREEN, UDL_REG_SCREEN_ON);
970 	udl_cmd_write_reg_1(cb, UDL_REG_SYNC, 0xff);
971 	udl_cmd_buf_send(sc, cb);
972 	return (0);
973 }
974 
975 static void
976 udl_select_mode(struct udl_softc *sc)
977 {
978 	struct udl_mode mode;
979 	int index = UDL_MAX_MODES;
980 	int i;
981 
982 	/* try to get the preferred mode from EDID */
983 	edid_parse(sc->sc_edid, &sc->sc_edid_info);
984 #ifdef USB_DEBUG
985 	edid_print(&sc->sc_edid_info);
986 #endif
987 	if (sc->sc_edid_info.edid_preferred_mode != NULL) {
988 		mode.hz =
989 		    (sc->sc_edid_info.edid_preferred_mode->dot_clock * 1000) /
990 		    (sc->sc_edid_info.edid_preferred_mode->htotal *
991 		    sc->sc_edid_info.edid_preferred_mode->vtotal);
992 		mode.clock =
993 		    sc->sc_edid_info.edid_preferred_mode->dot_clock / 10;
994 		mode.hdisplay =
995 		    sc->sc_edid_info.edid_preferred_mode->hdisplay;
996 		mode.vdisplay =
997 		    sc->sc_edid_info.edid_preferred_mode->vdisplay;
998 		index = udl_lookup_mode(mode.hdisplay, mode.vdisplay, mode.hz,
999 		    sc->sc_chip, mode.clock);
1000 		sc->sc_cur_mode = index;
1001 	} else {
1002 		DPRINTF("no preferred mode found!\n");
1003 	}
1004 
1005 	if (index == UDL_MAX_MODES) {
1006 		DPRINTF("no mode line found for %dx%d @ %dHz!\n",
1007 		    mode.hdisplay, mode.vdisplay, mode.hz);
1008 
1009 		i = 0;
1010 		while (i < sc->sc_edid_info.edid_nmodes) {
1011 			mode.hz =
1012 			    (sc->sc_edid_info.edid_modes[i].dot_clock * 1000) /
1013 			    (sc->sc_edid_info.edid_modes[i].htotal *
1014 			    sc->sc_edid_info.edid_modes[i].vtotal);
1015 			mode.clock =
1016 			    sc->sc_edid_info.edid_modes[i].dot_clock / 10;
1017 			mode.hdisplay =
1018 			    sc->sc_edid_info.edid_modes[i].hdisplay;
1019 			mode.vdisplay =
1020 			    sc->sc_edid_info.edid_modes[i].vdisplay;
1021 			index = udl_lookup_mode(mode.hdisplay, mode.vdisplay,
1022 			    mode.hz, sc->sc_chip, mode.clock);
1023 			if (index < UDL_MAX_MODES)
1024 				if ((sc->sc_cur_mode == UDL_MAX_MODES) ||
1025 				    (index > sc->sc_cur_mode))
1026 					sc->sc_cur_mode = index;
1027 			i++;
1028 		}
1029 	}
1030 	/*
1031 	 * If no mode found use default.
1032 	 */
1033 	if (sc->sc_cur_mode == UDL_MAX_MODES)
1034 		sc->sc_cur_mode = udl_lookup_mode(800, 600, 60, sc->sc_chip, 0);
1035 }
1036 
1037 static int
1038 udl_cmd_write_buf_le16(struct udl_softc *sc, const uint8_t *buf, uint32_t off,
1039     uint8_t pixels, int flags)
1040 {
1041 	struct udl_cmd_buf *cb;
1042 
1043 	cb = udl_cmd_buf_alloc(sc, flags);
1044 	if (cb == NULL)
1045 		return (EAGAIN);
1046 
1047 	udl_cmd_insert_int_1(cb, UDL_BULK_SOC);
1048 	udl_cmd_insert_int_1(cb, UDL_BULK_CMD_FB_WRITE | UDL_BULK_CMD_FB_WORD);
1049 	udl_cmd_insert_int_3(cb, off);
1050 	udl_cmd_insert_int_1(cb, pixels);
1051 	udl_cmd_insert_buf_le16(cb, buf, 2 * pixels);
1052 	udl_cmd_buf_send(sc, cb);
1053 
1054 	return (0);
1055 }
1056 
1057 static int
1058 udl_cmd_buf_copy_le16(struct udl_softc *sc, uint32_t src, uint32_t dst,
1059     uint8_t pixels, int flags)
1060 {
1061 	struct udl_cmd_buf *cb;
1062 
1063 	cb = udl_cmd_buf_alloc(sc, flags);
1064 	if (cb == NULL)
1065 		return (EAGAIN);
1066 
1067 	udl_cmd_insert_int_1(cb, UDL_BULK_SOC);
1068 	udl_cmd_insert_int_1(cb, UDL_BULK_CMD_FB_COPY | UDL_BULK_CMD_FB_WORD);
1069 	udl_cmd_insert_int_3(cb, dst);
1070 	udl_cmd_insert_int_1(cb, pixels);
1071 	udl_cmd_insert_int_3(cb, src);
1072 	udl_cmd_buf_send(sc, cb);
1073 
1074 	return (0);
1075 }
1076