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