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