1 /* $OpenBSD: udl.h,v 1.21 2013/04/15 09:23:02 mglocker Exp $ */ 2 /* $FreeBSD$ */ 3 4 /* 5 * Copyright (c) 2009 Marcus Glocker <mglocker@openbsd.org> 6 * 7 * Permission to use, copy, modify, and distribute this software for any 8 * purpose with or without fee is hereby granted, provided that the above 9 * copyright notice and this permission notice appear in all copies. 10 * 11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 17 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 18 */ 19 20 #ifndef _UDL_H_ 21 #define _UDL_H_ 22 23 #include <sys/types.h> 24 #include <sys/queue.h> 25 26 /* 27 * BULK command transfer structure. 28 */ 29 #define UDL_CMD_MAX_FRAMES 64 /* units */ 30 #define UDL_CMD_MAX_DATA_SIZE 512 /* bytes */ 31 #define UDL_CMD_MAX_HEAD_SIZE 16 /* bytes */ 32 #define UDL_CMD_MAX_PIXEL_COUNT ((UDL_CMD_MAX_DATA_SIZE - UDL_CMD_MAX_HEAD_SIZE) / 2) 33 #define UDL_CMD_MAX_BUFFERS (3 * UDL_CMD_MAX_FRAMES) 34 #define UDL_FONT_HEIGHT 16 /* pixels */ 35 #define UDL_MAX_MODES 25 /* units */ 36 37 struct udl_cmd_buf { 38 TAILQ_ENTRY(udl_cmd_buf) entry; 39 uint32_t off; 40 uint8_t buf[UDL_CMD_MAX_DATA_SIZE] __aligned(4); 41 }; 42 43 TAILQ_HEAD(udl_cmd_head, udl_cmd_buf); 44 45 enum { 46 UDL_BULK_WRITE_0, 47 UDL_BULK_WRITE_1, 48 UDL_N_TRANSFER, 49 }; 50 51 /* 52 * Our per device structure. 53 */ 54 struct udl_softc { 55 struct mtx sc_mtx; 56 struct cv sc_cv; 57 struct callout sc_callout; 58 struct usb_xfer *sc_xfer[UDL_N_TRANSFER]; 59 struct usb_device *sc_udev; 60 device_t sc_fbdev; 61 struct fb_info sc_fb_info; 62 uint8_t sc_edid[128]; 63 struct edid_info sc_edid_info; 64 struct udl_cmd_head sc_xfer_head[2]; 65 struct udl_cmd_head sc_cmd_buf_free; 66 struct udl_cmd_head sc_cmd_buf_pending; 67 struct udl_cmd_buf sc_cmd_buf_temp[UDL_CMD_MAX_BUFFERS]; 68 uint32_t sc_sync_off; 69 uint32_t sc_fb_size; 70 uint8_t *sc_fb_addr; 71 uint8_t *sc_fb_copy; 72 int sc_def_chip; /* default chip version */ 73 int sc_chip; 74 #define DLALL 0x0000 75 #define DL125 0x0000 /* max 1280x1024, 1440x900 */ 76 #define DL120 0x0001 /* max 1280x1024, 1440x1050 */ 77 #define DL160 0x0002 /* max 1600x1200, 1680x1050 */ 78 #define DL165 0x0003 /* max 1600x1200, 1920x1080 */ 79 #define DL195 0x0004 /* max 1920x1200, 2048x1152 */ 80 #define DLMAX 0x0004 81 #define DLUNK 0x00ff /* unknown */ 82 int sc_def_mode; /* default mode */ 83 int sc_cur_mode; 84 uint8_t sc_power_save; /* set if power save is enabled */ 85 uint8_t sc_gone; 86 }; 87 88 #define UDL_LOCK(sc) mtx_lock(&(sc)->sc_mtx) 89 #define UDL_UNLOCK(sc) mtx_unlock(&(sc)->sc_mtx) 90 91 /* 92 * Chip commands. 93 */ 94 #define UDL_CTRL_CMD_READ_EDID 0x02 95 #define UDL_CTRL_CMD_WRITE_1 0x03 96 #define UDL_CTRL_CMD_READ_1 0x04 97 #define UDL_CTRL_CMD_POLL 0x06 98 #define UDL_CTRL_CMD_SET_KEY 0x12 99 100 #define UDL_BULK_SOC 0xaf /* start of command token */ 101 102 #define UDL_BULK_CMD_REG_WRITE_1 0x20 /* write 1 byte to register */ 103 #define UDL_BULK_CMD_EOC 0xa0 /* end of command stack */ 104 #define UDL_BULK_CMD_DECOMP 0xe0 /* send decompression table */ 105 106 #define UDL_BULK_CMD_FB_BASE 0x60 107 #define UDL_BULK_CMD_FB_WORD 0x08 108 #define UDL_BULK_CMD_FB_COMP 0x10 109 #define UDL_BULK_CMD_FB_WRITE (UDL_BULK_CMD_FB_BASE | 0x00) 110 #define UDL_BULK_CMD_FB_COPY (UDL_BULK_CMD_FB_BASE | 0x02) 111 112 /* 113 * Chip registers. 114 */ 115 #define UDL_REG_ADDR_START16 0x20 116 #define UDL_REG_ADDR_STRIDE16 0x23 117 #define UDL_REG_ADDR_START8 0x26 118 #define UDL_REG_ADDR_STRIDE8 0x29 119 120 #define UDL_REG_SCREEN 0x1f 121 #define UDL_REG_SCREEN_ON 0x00 122 #define UDL_REG_SCREEN_OFF 0x01 123 #define UDL_REG_SYNC 0xff 124 125 #define UDL_MODE_SIZE 29 126 127 /* 128 * Register values for screen resolution initialization. 129 */ 130 static const uint8_t udl_reg_vals_640x480_60[UDL_MODE_SIZE] = { /* 25.17 Mhz 59.9 Hz 131 * VESA std */ 132 0x00, 0x99, 0x30, 0x26, 0x94, 0x60, 0xa9, 0xce, 0x60, 0x07, 0xb3, 0x0f, 133 0x79, 0xff, 0xff, 0x02, 0x80, 0x83, 0xbc, 0xff, 0xfc, 0xff, 0xff, 0x01, 134 0xe0, 0x01, 0x02, 0xab, 0x13 135 }; 136 static const uint8_t udl_reg_vals_640x480_67[UDL_MODE_SIZE] = { /* 30.25 MHz 66.6 Hz MAC 137 * std */ 138 0x00, 0x1d, 0x33, 0x07, 0xb3, 0x60, 0xa9, 0xce, 0x60, 0xb6, 0xa8, 0xff, 139 0xff, 0xbf, 0x70, 0x02, 0x80, 0x83, 0xbc, 0xff, 0xff, 0xff, 0xf9, 0x01, 140 0xe0, 0x01, 0x02, 0xa2, 0x17 141 }; 142 static const uint8_t udl_reg_vals_640x480_72[UDL_MODE_SIZE] = { /* 31.50 Mhz 72.8 Hz 143 * VESA std */ 144 0x00, 0x2b, 0xeb, 0x35, 0xd3, 0x0a, 0x95, 0xe6, 0x0e, 0x0f, 0xb5, 0x15, 145 0x2a, 0xff, 0xff, 0x02, 0x80, 0xcc, 0x1d, 0xff, 0xf9, 0xff, 0xff, 0x01, 146 0xe0, 0x01, 0x02, 0x9c, 0x18 147 }; 148 static const uint8_t udl_reg_vals_640x480_75[UDL_MODE_SIZE] = { /* 31.50 Mhz 75.7 Hz 149 * VESA std */ 150 0x00, 0xeb, 0xf7, 0xd3, 0x0f, 0x4f, 0x93, 0xfa, 0x47, 0xb5, 0x58, 0xff, 151 0xff, 0xbf, 0x70, 0x02, 0x80, 0xf4, 0x8f, 0xff, 0xff, 0xff, 0xf9, 0x01, 152 0xe0, 0x01, 0x02, 0x9c, 0x18 153 }; 154 static const uint8_t udl_reg_vals_800x480_61[UDL_MODE_SIZE] = { /* 33.00 MHz 61.9 Hz */ 155 0x00, 0x20, 0x3c, 0x7a, 0xc9, 0xf2, 0x6c, 0x48, 0xf9, 0x70, 0x53, 0xff, 156 0xff, 0x21, 0x27, 0x03, 0x20, 0x91, 0xf3, 0xff, 0xff, 0xff, 0xf9, 0x01, 157 0xe0, 0x01, 0x02, 0xc8, 0x19 158 }; 159 static const uint8_t udl_reg_vals_800x600_56[UDL_MODE_SIZE] = { /* 36.00 MHz 56.2 Hz 160 * VESA std */ 161 0x00, 0x65, 0x35, 0x48, 0xf4, 0xf2, 0x6c, 0x19, 0x18, 0xc9, 0x4b, 0xff, 162 0xff, 0x70, 0x35, 0x03, 0x20, 0x32, 0x31, 0xff, 0xff, 0xff, 0xfc, 0x02, 163 0x58, 0x01, 0x02, 0x20, 0x1c 164 }; 165 static const uint8_t udl_reg_vals_800x600_60[UDL_MODE_SIZE] = { /* 40.00 MHz 60.3 Hz 166 * VESA std */ 167 0x00, 0x20, 0x3c, 0x7a, 0xc9, 0x93, 0x60, 0xc8, 0xc7, 0x70, 0x53, 0xff, 168 0xff, 0x21, 0x27, 0x03, 0x20, 0x91, 0x8f, 0xff, 0xff, 0xff, 0xf2, 0x02, 169 0x58, 0x01, 0x02, 0x40, 0x1f 170 }; 171 static const uint8_t udl_reg_vals_800x600_72[UDL_MODE_SIZE] = { /* 50.00 MHz 72.1 Hz 172 * VESA std */ 173 0x00, 0xeb, 0xf7, 0xd1, 0x90, 0x4d, 0x82, 0x23, 0x1f, 0x39, 0xcf, 0xff, 174 0xff, 0x43, 0x21, 0x03, 0x20, 0x62, 0xc5, 0xff, 0xff, 0xff, 0xca, 0x02, 175 0x58, 0x01, 0x02, 0x10, 0x27 176 }; 177 static const uint8_t udl_reg_vals_800x600_74[UDL_MODE_SIZE] = { /* 50.00 MHz 74.4 Hz */ 178 0x00, 0xb3, 0x76, 0x39, 0xcf, 0x60, 0xa9, 0xc7, 0xf4, 0x70, 0x53, 0xff, 179 0xff, 0x35, 0x33, 0x03, 0x20, 0x8f, 0xe9, 0xff, 0xff, 0xff, 0xf9, 0x02, 180 0x58, 0x01, 0x02, 0x10, 0x27 181 }; 182 static const uint8_t udl_reg_vals_800x600_75[UDL_MODE_SIZE] = { /* 49.50 MHz 75.0 Hz 183 * VESA std */ 184 0x00, 0xb3, 0x76, 0x39, 0xcf, 0xf2, 0x6c, 0x19, 0x18, 0x70, 0x53, 0xff, 185 0xff, 0x35, 0x33, 0x03, 0x20, 0x32, 0x31, 0xff, 0xff, 0xff, 0xf9, 0x02, 186 0x58, 0x01, 0x02, 0xac, 0x26 187 }; 188 static const uint8_t udl_reg_vals_1024x768_60[UDL_MODE_SIZE] = { /* 65.00 MHz 60.0 Hz 189 * VESA std */ 190 0x00, 0x36, 0x18, 0xd5, 0x10, 0x60, 0xa9, 0x7b, 0x33, 0xa1, 0x2b, 0x27, 191 0x32, 0xff, 0xff, 0x04, 0x00, 0xd9, 0x9a, 0xff, 0xca, 0xff, 0xff, 0x03, 192 0x00, 0x04, 0x03, 0xc8, 0x32 193 }; 194 static const uint8_t udl_reg_vals_1024x768_70[UDL_MODE_SIZE] = { /* 75.00 MHz 70.0 Hz 195 * VESA std */ 196 0x00, 0xb4, 0xed, 0x4c, 0x5e, 0x60, 0xa9, 0x7b, 0x33, 0x10, 0x4d, 0xff, 197 0xff, 0x27, 0x32, 0x04, 0x00, 0xd9, 0x9a, 0xff, 0xff, 0xff, 0xca, 0x03, 198 0x00, 0x04, 0x02, 0x98, 0x3a 199 }; 200 static const uint8_t udl_reg_vals_1024x768_75[UDL_MODE_SIZE] = { /* 78.75 MHz 75.0 Hz 201 * VESA std */ 202 0x00, 0xec, 0xb4, 0xa0, 0x4c, 0x36, 0x0a, 0x07, 0xb3, 0x5e, 0xd5, 0xff, 203 0xff, 0x0f, 0x79, 0x04, 0x00, 0x0f, 0x66, 0xff, 0xff, 0xff, 0xf9, 0x03, 204 0x00, 0x04, 0x02, 0x86, 0x3d 205 }; 206 static const uint8_t udl_reg_vals_1280x800_60[UDL_MODE_SIZE] = { /* 83.46 MHz 59.9 MHz */ 207 0x00, 0xb2, 0x19, 0x34, 0xdf, 0x93, 0x60, 0x30, 0xfb, 0x9f, 0xca, 0xff, 208 0xff, 0x27, 0x32, 0x05, 0x00, 0x61, 0xf6, 0xff, 0xff, 0xff, 0xf9, 0x03, 209 0x20, 0x04, 0x02, 0x34, 0x41 210 }; 211 static const uint8_t udl_reg_vals_1280x960_60[UDL_MODE_SIZE] = { /* 108.00 MHz 60.0 Hz 212 * VESA std */ 213 0x00, 0xa6, 0x03, 0x5c, 0x7e, 0x0a, 0x95, 0x48, 0xf4, 0x61, 0xbd, 0xff, 214 0xff, 0x94, 0x43, 0x05, 0x00, 0x91, 0xe8, 0xff, 0xff, 0xff, 0xf9, 0x03, 215 0xc0, 0x04, 0x02, 0x60, 0x54 216 }; 217 static const uint8_t udl_reg_vals_1280x1024_60[UDL_MODE_SIZE] = { /* 108.00 MHz 60.0 Hz 218 * VESA std */ 219 0x00, 0x98, 0xf8, 0x0d, 0x57, 0x2a, 0x55, 0x4d, 0x54, 0xca, 0x0d, 0xff, 220 0xff, 0x94, 0x43, 0x05, 0x00, 0x9a, 0xa8, 0xff, 0xff, 0xff, 0xf9, 0x04, 221 0x00, 0x04, 0x02, 0x60, 0x54 222 }; 223 static const uint8_t udl_reg_vals_1280x1024_75[UDL_MODE_SIZE] = { /* 135.00 MHz 75.0 Hz 224 * VESA std */ 225 0x00, 0xce, 0x12, 0x3f, 0x9f, 0x2a, 0x55, 0x4d, 0x54, 0xca, 0x0d, 0xff, 226 0xff, 0x32, 0x60, 0x05, 0x00, 0x9a, 0xa8, 0xff, 0xff, 0xff, 0xf9, 0x04, 227 0x00, 0x04, 0x02, 0x78, 0x69 228 }; 229 static const uint8_t udl_reg_vals_1366x768_60[UDL_MODE_SIZE] = { /* 90 MHz 60.0 Hz */ 230 0x01, 0x19, 0x1e, 0x1f, 0xb0, 0x93, 0x60, 0x40, 0x7b, 0x36, 0xe8, 0x27, 231 0x32, 0xff, 0xff, 0x05, 0x56, 0x03, 0xd9, 0xff, 0xff, 0xfc, 0xa7, 0x03, 232 0x00, 0x04, 0x02, 0x9a, 0x42 233 }; 234 static const uint8_t udl_reg_vals_1440x900_60[UDL_MODE_SIZE] = { /* 106.47 MHz 59.9 Hz */ 235 0x00, 0x24, 0xce, 0xe7, 0x72, 0x36, 0x0a, 0x86, 0xca, 0x1c, 0x10, 0xff, 236 0xff, 0x60, 0x3a, 0x05, 0xa0, 0x0d, 0x94, 0xff, 0xff, 0xff, 0xf9, 0x03, 237 0x84, 0x04, 0x02, 0x2e, 0x53 238 }; 239 static const uint8_t udl_reg_vals_1440x900_59[UDL_MODE_SIZE] = { /* 106.50 MHz 59.8 Hz */ 240 0x00, 0x24, 0xce, 0xe7, 0x72, 0xd8, 0x2a, 0x1b, 0x28, 0x1c, 0x10, 0xff, 241 0xff, 0x60, 0x3a, 0x05, 0xa0, 0x36, 0x50, 0xff, 0xff, 0xff, 0xf9, 0x03, 242 0x84, 0x04, 0x02, 0x34, 0x53 243 }; 244 static const uint8_t udl_reg_vals_1440x900_75[UDL_MODE_SIZE] = { /* 136.49 MHz 75.0 Hz */ 245 0x00, 0x73, 0xa6, 0x14, 0xea, 0x0a, 0x95, 0xca, 0x10, 0x7f, 0x46, 0xff, 246 0xff, 0x60, 0x3a, 0x05, 0xa0, 0x94, 0x20, 0xff, 0xff, 0xff, 0xf9, 0x03, 247 0x84, 0x04, 0x02, 0xa2, 0x6a 248 }; 249 static const uint8_t udl_reg_vals_1680x1050_60[UDL_MODE_SIZE] = { /* 147.14 MHz 60.0 Hz */ 250 0x00, 0x53, 0x43, 0xa6, 0x71, 0xc1, 0x52, 0xd9, 0x29, 0x69, 0x9f, 0xff, 251 0xff, 0xd7, 0xee, 0x06, 0x90, 0xb2, 0x53, 0xff, 0xff, 0xff, 0xf9, 0x04, 252 0x1a, 0x04, 0x02, 0xf4, 0x72 253 }; 254 static const uint8_t udl_reg_vals_1600x1200_60[UDL_MODE_SIZE] = { /* 162.00 MHz 60.0 Hz 255 * VESA std */ 256 0x00, 0xcf, 0xa4, 0x3c, 0x4e, 0x55, 0x73, 0x71, 0x2b, 0x71, 0x52, 0xff, 257 0xff, 0xee, 0xca, 0x06, 0x40, 0xe2, 0x57, 0xff, 0xff, 0xff, 0xf9, 0x04, 258 0xb0, 0x04, 0x02, 0x90, 0x7e 259 }; 260 static const uint8_t udl_reg_vals_1920x1080_60[UDL_MODE_SIZE] = { /* 138.50 MHz 59.9 Hz */ 261 0x00, 0x73, 0xa6, 0x28, 0xb3, 0x54, 0xaa, 0x41, 0x5d, 0x0d, 0x9f, 0x32, 262 0x60, 0xff, 0xff, 0x07, 0x80, 0x0a, 0xea, 0xff, 0xf9, 0xff, 0xff, 0x04, 263 0x38, 0x04, 0x02, 0xe0, 0x7c 264 }; 265 266 struct udl_mode { 267 uint16_t hdisplay; 268 uint16_t vdisplay; 269 uint8_t hz; 270 uint16_t chip; 271 uint32_t clock; 272 const uint8_t *mode; 273 }; 274 275 static const struct udl_mode udl_modes[UDL_MAX_MODES] = { 276 {640, 480, 60, DLALL, 2520, udl_reg_vals_640x480_60}, 277 {640, 480, 67, DLALL, 3025, udl_reg_vals_640x480_67}, 278 {640, 480, 72, DLALL, 3150, udl_reg_vals_640x480_72}, 279 {640, 480, 75, DLALL, 3150, udl_reg_vals_640x480_75}, 280 {800, 480, 59, DLALL, 5000, udl_reg_vals_800x480_61}, 281 {800, 480, 61, DLALL, 3300, udl_reg_vals_800x480_61}, 282 {800, 600, 56, DLALL, 3600, udl_reg_vals_800x600_56}, 283 {800, 600, 60, DLALL, 4000, udl_reg_vals_800x600_60}, 284 {800, 600, 72, DLALL, 5000, udl_reg_vals_800x600_72}, 285 {800, 600, 74, DLALL, 5000, udl_reg_vals_800x600_74}, 286 {800, 600, 75, DLALL, 4950, udl_reg_vals_800x600_75}, 287 {1024, 768, 60, DLALL, 6500, udl_reg_vals_1024x768_60}, 288 {1024, 768, 70, DLALL, 7500, udl_reg_vals_1024x768_70}, 289 {1024, 768, 75, DLALL, 7850, udl_reg_vals_1024x768_75}, 290 {1280, 800, 60, DLALL, 8346, udl_reg_vals_1280x800_60}, 291 {1280, 960, 60, DLALL, 10800, udl_reg_vals_1280x960_60}, 292 {1280, 1024, 60, DLALL, 10800, udl_reg_vals_1280x1024_60}, 293 {1280, 1024, 75, DLALL, 13500, udl_reg_vals_1280x1024_75}, 294 {1366, 768, 60, DLALL, 9000, udl_reg_vals_1366x768_60}, 295 {1440, 900, 59, DL125, 10650, udl_reg_vals_1440x900_59}, 296 {1440, 900, 60, DL125, 10647, udl_reg_vals_1440x900_60}, 297 {1440, 900, 75, DL125, 13649, udl_reg_vals_1440x900_75}, 298 {1680, 1050, 60, DL160, 14714, udl_reg_vals_1680x1050_60}, 299 {1600, 1200, 60, DL160, 16200, udl_reg_vals_1600x1200_60}, 300 {1920, 1080, 60, DL165, 13850, udl_reg_vals_1920x1080_60} 301 }; 302 303 /* 304 * Encryption. 305 */ 306 static const uint8_t udl_null_key_1[] = { 307 0x57, 0xcd, 0xdc, 0xa7, 0x1c, 0x88, 0x5e, 0x15, 0x60, 0xfe, 0xc6, 0x97, 308 0x16, 0x3d, 0x47, 0xf2 309 }; 310 311 #endif /* _UDL_H_ */ 312