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