Subversion Repositories Kolibri OS

Rev

Rev 5354 | Go to most recent revision | Only display areas with differences | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 5354 Rev 6084
1
/*
1
/*
2
 *
2
 *
3
 * Copyright (c) 2012 Gilles Dartiguelongue, Thomas Richter
3
 * Copyright (c) 2012 Gilles Dartiguelongue, Thomas Richter
4
 *
4
 *
5
 * All Rights Reserved.
5
 * All Rights Reserved.
6
 *
6
 *
7
 * Permission is hereby granted, free of charge, to any person obtaining a
7
 * Permission is hereby granted, free of charge, to any person obtaining a
8
 * copy of this software and associated documentation files (the
8
 * copy of this software and associated documentation files (the
9
 * "Software"), to deal in the Software without restriction, including
9
 * "Software"), to deal in the Software without restriction, including
10
 * without limitation the rights to use, copy, modify, merge, publish,
10
 * without limitation the rights to use, copy, modify, merge, publish,
11
 * distribute, sub license, and/or sell copies of the Software, and to
11
 * distribute, sub license, and/or sell copies of the Software, and to
12
 * permit persons to whom the Software is furnished to do so, subject to
12
 * permit persons to whom the Software is furnished to do so, subject to
13
 * the following conditions:
13
 * the following conditions:
14
 *
14
 *
15
 * The above copyright notice and this permission notice (including the
15
 * The above copyright notice and this permission notice (including the
16
 * next paragraph) shall be included in all copies or substantial portions
16
 * next paragraph) shall be included in all copies or substantial portions
17
 * of the Software.
17
 * of the Software.
18
 *
18
 *
19
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
20
 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20
 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
21
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
22
 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
22
 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
23
 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23
 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
24
 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24
 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
25
 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25
 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26
 *
26
 *
27
 */
27
 */
28
 
28
 
29
#include "dvo.h"
29
#include "dvo.h"
30
#include "i915_reg.h"
30
#include "i915_reg.h"
31
#include "i915_drv.h"
31
#include "i915_drv.h"
32
 
32
 
33
#define NS2501_VID 0x1305
33
#define NS2501_VID 0x1305
34
#define NS2501_DID 0x6726
34
#define NS2501_DID 0x6726
35
 
35
 
36
#define NS2501_VID_LO 0x00
36
#define NS2501_VID_LO 0x00
37
#define NS2501_VID_HI 0x01
37
#define NS2501_VID_HI 0x01
38
#define NS2501_DID_LO 0x02
38
#define NS2501_DID_LO 0x02
39
#define NS2501_DID_HI 0x03
39
#define NS2501_DID_HI 0x03
40
#define NS2501_REV 0x04
40
#define NS2501_REV 0x04
41
#define NS2501_RSVD 0x05
41
#define NS2501_RSVD 0x05
42
#define NS2501_FREQ_LO 0x06
42
#define NS2501_FREQ_LO 0x06
43
#define NS2501_FREQ_HI 0x07
43
#define NS2501_FREQ_HI 0x07
44
 
44
 
45
#define NS2501_REG8 0x08
45
#define NS2501_REG8 0x08
46
#define NS2501_8_VEN (1<<5)
46
#define NS2501_8_VEN (1<<5)
47
#define NS2501_8_HEN (1<<4)
47
#define NS2501_8_HEN (1<<4)
48
#define NS2501_8_DSEL (1<<3)
48
#define NS2501_8_DSEL (1<<3)
49
#define NS2501_8_BPAS (1<<2)
49
#define NS2501_8_BPAS (1<<2)
50
#define NS2501_8_RSVD (1<<1)
50
#define NS2501_8_RSVD (1<<1)
51
#define NS2501_8_PD (1<<0)
51
#define NS2501_8_PD (1<<0)
52
 
52
 
53
#define NS2501_REG9 0x09
53
#define NS2501_REG9 0x09
54
#define NS2501_9_VLOW (1<<7)
54
#define NS2501_9_VLOW (1<<7)
55
#define NS2501_9_MSEL_MASK (0x7<<4)
55
#define NS2501_9_MSEL_MASK (0x7<<4)
56
#define NS2501_9_TSEL (1<<3)
56
#define NS2501_9_TSEL (1<<3)
57
#define NS2501_9_RSEN (1<<2)
57
#define NS2501_9_RSEN (1<<2)
58
#define NS2501_9_RSVD (1<<1)
58
#define NS2501_9_RSVD (1<<1)
59
#define NS2501_9_MDI (1<<0)
59
#define NS2501_9_MDI (1<<0)
60
 
60
 
61
#define NS2501_REGC 0x0c
61
#define NS2501_REGC 0x0c
-
 
62
 
-
 
63
/*
-
 
64
 * The following registers are not part of the official datasheet
-
 
65
 * and are the result of reverse engineering.
-
 
66
 */
-
 
67
 
-
 
68
/*
-
 
69
 * Register c0 controls how the DVO synchronizes with
-
 
70
 * its input.
-
 
71
 */
-
 
72
#define NS2501_REGC0 0xc0
-
 
73
#define NS2501_C0_ENABLE (1<<0)	/* enable the DVO sync in general */
-
 
74
#define NS2501_C0_HSYNC (1<<1)	/* synchronize horizontal with input */
-
 
75
#define NS2501_C0_VSYNC (1<<2)	/* synchronize vertical with input */
-
 
76
#define NS2501_C0_RESET (1<<7)	/* reset the synchronization flip/flops */
-
 
77
 
-
 
78
/*
-
 
79
 * Register 41 is somehow related to the sync register and sync
-
 
80
 * configuration. It should be 0x32 whenever regC0 is 0x05 (hsync off)
-
 
81
 * and 0x00 otherwise.
-
 
82
 */
-
 
83
#define NS2501_REG41 0x41
-
 
84
 
-
 
85
/*
-
 
86
 * this register controls the dithering of the DVO
-
 
87
 * One bit enables it, the other define the dithering depth.
-
 
88
 * The higher the value, the lower the dithering depth.
-
 
89
 */
-
 
90
#define NS2501_F9_REG 0xf9
-
 
91
#define NS2501_F9_ENABLE (1<<0)		/* if set, dithering is enabled */
-
 
92
#define NS2501_F9_DITHER_MASK (0x7f<<1)	/* controls the dither depth */
-
 
93
#define NS2501_F9_DITHER_SHIFT 1	/* shifts the dither mask */
-
 
94
 
-
 
95
/*
-
 
96
 * PLL configuration register. This is a pair of registers,
-
 
97
 * one single byte register at 1B, and a pair at 1C,1D.
-
 
98
 * These registers are counters/dividers.
-
 
99
 */
-
 
100
#define NS2501_REG1B 0x1b /* one byte PLL control register */
-
 
101
#define NS2501_REG1C 0x1c /* low-part of the second register */
-
 
102
#define NS2501_REG1D 0x1d /* high-part of the second register */
-
 
103
 
-
 
104
/*
-
 
105
 * Scaler control registers. Horizontal at b8,b9,
-
 
106
 * vertical at 10,11. The scale factor is computed as
-
 
107
 * 2^16/control-value. The low-byte comes first.
-
 
108
 */
-
 
109
#define NS2501_REG10 0x10 /* low-byte vertical scaler */
-
 
110
#define NS2501_REG11 0x11 /* high-byte vertical scaler */
-
 
111
#define NS2501_REGB8 0xb8 /* low-byte horizontal scaler */
-
 
112
#define NS2501_REGB9 0xb9 /* high-byte horizontal scaler */
-
 
113
 
-
 
114
/*
-
 
115
 * Display window definition. This consists of four registers
-
 
116
 * per dimension. One register pair defines the start of the
-
 
117
 * display, one the end.
-
 
118
 * As far as I understand, this defines the window within which
-
 
119
 * the scaler samples the input.
-
 
120
 */
-
 
121
#define NS2501_REGC1 0xc1 /* low-byte horizontal display start */
-
 
122
#define NS2501_REGC2 0xc2 /* high-byte horizontal display start */
-
 
123
#define NS2501_REGC3 0xc3 /* low-byte horizontal display stop */
-
 
124
#define NS2501_REGC4 0xc4 /* high-byte horizontal display stop */
-
 
125
#define NS2501_REGC5 0xc5 /* low-byte vertical display start */
-
 
126
#define NS2501_REGC6 0xc6 /* high-byte vertical display start */
-
 
127
#define NS2501_REGC7 0xc7 /* low-byte vertical display stop */
-
 
128
#define NS2501_REGC8 0xc8 /* high-byte vertical display stop */
-
 
129
 
-
 
130
/*
-
 
131
 * The following register pair seems to define the start of
-
 
132
 * the vertical sync. If automatic syncing is enabled, and the
-
 
133
 * register value defines a sync pulse that is later than the
-
 
134
 * incoming sync, then the register value is ignored and the
-
 
135
 * external hsync triggers the synchronization.
-
 
136
 */
-
 
137
#define NS2501_REG80 0x80 /* low-byte vsync-start */
-
 
138
#define NS2501_REG81 0x81 /* high-byte vsync-start */
-
 
139
 
-
 
140
/*
-
 
141
 * The following register pair seems to define the total number
-
 
142
 * of lines created at the output side of the scaler.
-
 
143
 * This is again a low-high register pair.
-
 
144
 */
-
 
145
#define NS2501_REG82 0x82 /* output display height, low byte */
-
 
146
#define NS2501_REG83 0x83 /* output display height, high byte */
-
 
147
 
-
 
148
/*
-
 
149
 * The following registers define the end of the front-porch
-
 
150
 * in horizontal and vertical position and hence allow to shift
-
 
151
 * the image left/right or up/down.
-
 
152
 */
-
 
153
#define NS2501_REG98 0x98 /* horizontal start of display + 256, low */
-
 
154
#define NS2501_REG99 0x99 /* horizontal start of display + 256, high */
-
 
155
#define NS2501_REG8E 0x8e /* vertical start of the display, low byte */
-
 
156
#define NS2501_REG8F 0x8f /* vertical start of the display, high byte */
-
 
157
 
-
 
158
/*
-
 
159
 * The following register pair control the function of the
-
 
160
 * backlight and the DVO output. To enable the corresponding
-
 
161
 * function, the corresponding bit must be set in both registers.
-
 
162
 */
-
 
163
#define NS2501_REG34 0x34 /* DVO enable functions, first register */
-
 
164
#define NS2501_REG35 0x35 /* DVO enable functions, second register */
-
 
165
#define NS2501_34_ENABLE_OUTPUT (1<<0) /* enable DVO output */
-
 
166
#define NS2501_34_ENABLE_BACKLIGHT (1<<1) /* enable backlight */
-
 
167
 
-
 
168
/*
-
 
169
 * Registers 9C and 9D define the vertical output offset
-
 
170
 * of the visible region.
-
 
171
 */
-
 
172
#define NS2501_REG9C 0x9c
-
 
173
#define NS2501_REG9D 0x9d
-
 
174
 
-
 
175
/*
-
 
176
 * The register 9F defines the dithering. This requires the
-
 
177
 * scaler to be ON. Bit 0 enables dithering, the remaining
-
 
178
 * bits control the depth of the dither. The higher the value,
-
 
179
 * the LOWER the dithering amplitude. A good value seems to be
-
 
180
 * 15 (total register value).
-
 
181
 */
-
 
182
#define NS2501_REGF9 0xf9
-
 
183
#define NS2501_F9_ENABLE_DITHER (1<<0) /* enable dithering */
-
 
184
#define NS2501_F9_DITHER_MASK (0x7f<<1) /* dither masking */
-
 
185
#define NS2501_F9_DITHER_SHIFT 1	/* upshift of the dither mask */
62
 
186
 
63
enum {
187
enum {
64
	MODE_640x480,
188
	MODE_640x480,
65
	MODE_800x600,
189
	MODE_800x600,
66
	MODE_1024x768,
190
	MODE_1024x768,
67
};
191
};
68
 
192
 
69
struct ns2501_reg {
193
struct ns2501_reg {
70
	 uint8_t offset;
194
	 uint8_t offset;
71
	 uint8_t value;
195
	 uint8_t value;
72
};
196
};
73
 
197
 
74
/*
198
/*
-
 
199
 * The following structure keeps the complete configuration of
75
 * Magic values based on what the BIOS on
200
 * the DVO, given a specific output configuration.
76
 * Fujitsu-Siemens Lifebook S6010 programs (1024x768 panel).
201
 * This is pretty much guess-work from reverse-engineering, so
-
 
202
 * read all this with a grain of salt.
77
 */
203
 */
-
 
204
struct ns2501_configuration {
-
 
205
	uint8_t sync;		/* configuration of the C0 register */
-
 
206
	uint8_t conf;		/* configuration register 8 */
-
 
207
	uint8_t syncb;		/* configuration register 41 */
-
 
208
	uint8_t	dither;		/* configuration of the dithering */
-
 
209
	uint8_t pll_a;		/* PLL configuration, register A, 1B */
-
 
210
	uint16_t pll_b;		/* PLL configuration, register B, 1C/1D */
-
 
211
	uint16_t hstart;	/* horizontal start, registers C1/C2 */
-
 
212
	uint16_t hstop;		/* horizontal total, registers C3/C4 */
-
 
213
	uint16_t vstart;	/* vertical start, registers C5/C6 */
-
 
214
	uint16_t vstop;		/* vertical total, registers C7/C8 */
-
 
215
	uint16_t vsync;         /* manual vertical sync start, 80/81 */
-
 
216
	uint16_t vtotal;        /* number of lines generated, 82/83 */
-
 
217
	uint16_t hpos;		/* horizontal position + 256, 98/99  */
-
 
218
	uint16_t vpos;		/* vertical position, 8e/8f */
-
 
219
	uint16_t voffs;		/* vertical output offset, 9c/9d */
-
 
220
	uint16_t hscale;	/* horizontal scaling factor, b8/b9 */
-
 
221
	uint16_t vscale;	/* vertical scaling factor, 10/11 */
-
 
222
};
-
 
223
 
-
 
224
/*
-
 
225
 * DVO configuration values, partially based on what the BIOS
-
 
226
 * of the Fujitsu Lifebook S6010 writes into registers,
-
 
227
 * partially found by manual tweaking. These configurations assume
-
 
228
 * a 1024x768 panel.
-
 
229
 */
78
static const struct ns2501_reg regs_1024x768[][86] = {
230
static const struct ns2501_configuration ns2501_modes[] = {
79
	[MODE_640x480] = {
231
	[MODE_640x480] = {
80
		[0] = { .offset = 0x0a, .value = 0x81, },
-
 
81
		[1] = { .offset = 0x18, .value = 0x07, },
-
 
82
		[2] = { .offset = 0x19, .value = 0x00, },
-
 
83
		[3] = { .offset = 0x1a, .value = 0x00, },
-
 
84
		[4] = { .offset = 0x1b, .value = 0x11, },
-
 
85
		[5] = { .offset = 0x1c, .value = 0x54, },
-
 
86
		[6] = { .offset = 0x1d, .value = 0x03, },
-
 
87
		[7] = { .offset = 0x1e, .value = 0x02, },
-
 
88
		[8] = { .offset = 0xf3, .value = 0x90, },
-
 
89
		[9] = { .offset = 0xf9, .value = 0x00, },
-
 
90
		[10] = { .offset = 0xc1, .value = 0x90, },
-
 
91
		[11] = { .offset = 0xc2, .value = 0x00, },
-
 
92
		[12] = { .offset = 0xc3, .value = 0x0f, },
232
		.sync	= NS2501_C0_ENABLE | NS2501_C0_VSYNC,
93
		[13] = { .offset = 0xc4, .value = 0x03, },
-
 
94
		[14] = { .offset = 0xc5, .value = 0x16, },
233
		.conf	= NS2501_8_VEN | NS2501_8_HEN | NS2501_8_PD,
95
		[15] = { .offset = 0xc6, .value = 0x00, },
-
 
96
		[16] = { .offset = 0xc7, .value = 0x02, },
-
 
97
		[17] = { .offset = 0xc8, .value = 0x02, },
234
		.syncb	= 0x32,
98
		[18] = { .offset = 0xf4, .value = 0x00, },
-
 
99
		[19] = { .offset = 0x80, .value = 0xff, },
235
		.dither	= 0x0f,
100
		[20] = { .offset = 0x81, .value = 0x07, },
236
		.pll_a	= 17,
101
		[21] = { .offset = 0x82, .value = 0x3d, },
-
 
102
		[22] = { .offset = 0x83, .value = 0x05, },
-
 
103
		[23] = { .offset = 0x94, .value = 0x00, },
-
 
104
		[24] = { .offset = 0x95, .value = 0x00, },
-
 
105
		[25] = { .offset = 0x96, .value = 0x05, },
-
 
106
		[26] = { .offset = 0x97, .value = 0x00, },
-
 
107
		[27] = { .offset = 0x9a, .value = 0x88, },
-
 
108
		[28] = { .offset = 0x9b, .value = 0x00, },
-
 
109
		[29] = { .offset = 0x98, .value = 0x00, },
-
 
110
		[30] = { .offset = 0x99, .value = 0x00, },
-
 
111
		[31] = { .offset = 0xf7, .value = 0x88, },
237
		.pll_b	= 852,
112
		[32] = { .offset = 0xf8, .value = 0x0a, },
-
 
113
		[33] = { .offset = 0x9c, .value = 0x24, },
238
		.hstart	= 144,
114
		[34] = { .offset = 0x9d, .value = 0x00, },
-
 
115
		[35] = { .offset = 0x9e, .value = 0x25, },
-
 
116
		[36] = { .offset = 0x9f, .value = 0x03, },
239
		.hstop	= 783,
117
		[37] = { .offset = 0xa0, .value = 0x28, },
240
		.vstart	= 22,
118
		[38] = { .offset = 0xa1, .value = 0x01, },
241
		.vstop	= 514,
119
		[39] = { .offset = 0xa2, .value = 0x28, },
-
 
120
		[40] = { .offset = 0xa3, .value = 0x05, },
242
		.vsync	= 2047, /* actually, ignored with this config */
121
		[41] = { .offset = 0xb6, .value = 0x09, },
-
 
122
		[42] = { .offset = 0xb8, .value = 0x00, },
-
 
123
		[43] = { .offset = 0xb9, .value = 0xa0, },
-
 
124
		[44] = { .offset = 0xba, .value = 0x00, },
-
 
125
		[45] = { .offset = 0xbb, .value = 0x20, },
-
 
126
		[46] = { .offset = 0x10, .value = 0x00, },
-
 
127
		[47] = { .offset = 0x11, .value = 0xa0, },
-
 
128
		[48] = { .offset = 0x12, .value = 0x02, },
-
 
129
		[49] = { .offset = 0x20, .value = 0x00, },
-
 
130
		[50] = { .offset = 0x22, .value = 0x00, },
-
 
131
		[51] = { .offset = 0x23, .value = 0x00, },
-
 
132
		[52] = { .offset = 0x24, .value = 0x00, },
-
 
133
		[53] = { .offset = 0x25, .value = 0x00, },
-
 
134
		[54] = { .offset = 0x8c, .value = 0x10, },
-
 
135
		[55] = { .offset = 0x8d, .value = 0x02, },
-
 
136
		[56] = { .offset = 0x8e, .value = 0x10, },
243
		.vtotal	= 1341,
137
		[57] = { .offset = 0x8f, .value = 0x00, },
-
 
138
		[58] = { .offset = 0x90, .value = 0xff, },
244
		.hpos	= 0,
139
		[59] = { .offset = 0x91, .value = 0x07, },
245
		.vpos	= 16,
140
		[60] = { .offset = 0x92, .value = 0xa0, },
-
 
141
		[61] = { .offset = 0x93, .value = 0x02, },
-
 
142
		[62] = { .offset = 0xa5, .value = 0x00, },
-
 
143
		[63] = { .offset = 0xa6, .value = 0x00, },
246
		.voffs	= 36,
144
		[64] = { .offset = 0xa7, .value = 0x00, },
-
 
145
		[65] = { .offset = 0xa8, .value = 0x00, },
-
 
146
		[66] = { .offset = 0xa9, .value = 0x04, },
-
 
147
		[67] = { .offset = 0xaa, .value = 0x70, },
-
 
148
		[68] = { .offset = 0xab, .value = 0x4f, },
-
 
149
		[69] = { .offset = 0xac, .value = 0x00, },
247
		.hscale	= 40960,
150
		[70] = { .offset = 0xa4, .value = 0x84, },
-
 
151
		[71] = { .offset = 0x7e, .value = 0x18, },
-
 
152
		[72] = { .offset = 0x84, .value = 0x00, },
-
 
153
		[73] = { .offset = 0x85, .value = 0x00, },
-
 
154
		[74] = { .offset = 0x86, .value = 0x00, },
-
 
155
		[75] = { .offset = 0x87, .value = 0x00, },
-
 
156
		[76] = { .offset = 0x88, .value = 0x00, },
-
 
157
		[77] = { .offset = 0x89, .value = 0x00, },
-
 
158
		[78] = { .offset = 0x8a, .value = 0x00, },
-
 
159
		[79] = { .offset = 0x8b, .value = 0x00, },
-
 
160
		[80] = { .offset = 0x26, .value = 0x00, },
-
 
161
		[81] = { .offset = 0x27, .value = 0x00, },
-
 
162
		[82] = { .offset = 0xad, .value = 0x00, },
-
 
163
		[83] = { .offset = 0x08, .value = 0x30, }, /* 0x31 */
-
 
164
		[84] = { .offset = 0x41, .value = 0x00, },
-
 
165
		[85] = { .offset = 0xc0, .value = 0x05, },
248
		.vscale	= 40960
166
	},
249
	},
167
	[MODE_800x600] = {
250
	[MODE_800x600] = {
168
		[0] = { .offset = 0x0a, .value = 0x81, },
251
		.sync	= NS2501_C0_ENABLE |
169
		[1] = { .offset = 0x18, .value = 0x07, },
252
			  NS2501_C0_HSYNC | NS2501_C0_VSYNC,
170
		[2] = { .offset = 0x19, .value = 0x00, },
253
		.conf   = NS2501_8_VEN | NS2501_8_HEN | NS2501_8_PD,
171
		[3] = { .offset = 0x1a, .value = 0x00, },
254
		.syncb	= 0x00,
172
		[4] = { .offset = 0x1b, .value = 0x19, },
-
 
173
		[5] = { .offset = 0x1c, .value = 0x64, },
255
		.dither	= 0x0f,
174
		[6] = { .offset = 0x1d, .value = 0x02, },
256
		.pll_a	= 25,
175
		[7] = { .offset = 0x1e, .value = 0x02, },
257
		.pll_b	= 612,
176
		[8] = { .offset = 0xf3, .value = 0x90, },
-
 
177
		[9] = { .offset = 0xf9, .value = 0x00, },
-
 
178
		[10] = { .offset = 0xc1, .value = 0xd7, },
-
 
179
		[11] = { .offset = 0xc2, .value = 0x00, },
-
 
180
		[12] = { .offset = 0xc3, .value = 0xf8, },
-
 
181
		[13] = { .offset = 0xc4, .value = 0x03, },
-
 
182
		[14] = { .offset = 0xc5, .value = 0x1a, },
258
		.hstart	= 215,
183
		[15] = { .offset = 0xc6, .value = 0x00, },
259
		.hstop	= 1016,
184
		[16] = { .offset = 0xc7, .value = 0x73, },
-
 
185
		[17] = { .offset = 0xc8, .value = 0x02, },
260
		.vstart	= 26,
186
		[18] = { .offset = 0xf4, .value = 0x00, },
-
 
187
		[19] = { .offset = 0x80, .value = 0x27, },
261
		.vstop	= 627,
188
		[20] = { .offset = 0x81, .value = 0x03, },
262
		.vsync	= 807,
189
		[21] = { .offset = 0x82, .value = 0x41, },
263
		.vtotal	= 1341,
190
		[22] = { .offset = 0x83, .value = 0x05, },
264
		.hpos	= 0,
191
		[23] = { .offset = 0x94, .value = 0x00, },
265
		.vpos	= 4,
192
		[24] = { .offset = 0x95, .value = 0x00, },
-
 
193
		[25] = { .offset = 0x96, .value = 0x05, },
-
 
194
		[26] = { .offset = 0x97, .value = 0x00, },
-
 
195
		[27] = { .offset = 0x9a, .value = 0x88, },
-
 
196
		[28] = { .offset = 0x9b, .value = 0x00, },
-
 
197
		[29] = { .offset = 0x98, .value = 0x00, },
-
 
198
		[30] = { .offset = 0x99, .value = 0x00, },
-
 
199
		[31] = { .offset = 0xf7, .value = 0x88, },
-
 
200
		[32] = { .offset = 0xf8, .value = 0x06, },
-
 
201
		[33] = { .offset = 0x9c, .value = 0x23, },
-
 
202
		[34] = { .offset = 0x9d, .value = 0x00, },
-
 
203
		[35] = { .offset = 0x9e, .value = 0x25, },
-
 
204
		[36] = { .offset = 0x9f, .value = 0x03, },
-
 
205
		[37] = { .offset = 0xa0, .value = 0x28, },
-
 
206
		[38] = { .offset = 0xa1, .value = 0x01, },
-
 
207
		[39] = { .offset = 0xa2, .value = 0x28, },
-
 
208
		[40] = { .offset = 0xa3, .value = 0x05, },
266
		.voffs	= 35,
209
		[41] = { .offset = 0xb6, .value = 0x09, },
-
 
210
		[42] = { .offset = 0xb8, .value = 0x30, },
-
 
211
		[43] = { .offset = 0xb9, .value = 0xc8, },
-
 
212
		[44] = { .offset = 0xba, .value = 0x00, },
-
 
213
		[45] = { .offset = 0xbb, .value = 0x20, },
-
 
214
		[46] = { .offset = 0x10, .value = 0x20, },
-
 
215
		[47] = { .offset = 0x11, .value = 0xc8, },
-
 
216
		[48] = { .offset = 0x12, .value = 0x02, },
267
		.hscale	= 51248,
217
		[49] = { .offset = 0x20, .value = 0x00, },
-
 
218
		[50] = { .offset = 0x22, .value = 0x00, },
-
 
219
		[51] = { .offset = 0x23, .value = 0x00, },
-
 
220
		[52] = { .offset = 0x24, .value = 0x00, },
-
 
221
		[53] = { .offset = 0x25, .value = 0x00, },
-
 
222
		[54] = { .offset = 0x8c, .value = 0x10, },
268
		.vscale	= 51232
223
		[55] = { .offset = 0x8d, .value = 0x02, },
-
 
224
		[56] = { .offset = 0x8e, .value = 0x04, },
-
 
225
		[57] = { .offset = 0x8f, .value = 0x00, },
-
 
226
		[58] = { .offset = 0x90, .value = 0xff, },
-
 
227
		[59] = { .offset = 0x91, .value = 0x07, },
-
 
228
		[60] = { .offset = 0x92, .value = 0xa0, },
-
 
229
		[61] = { .offset = 0x93, .value = 0x02, },
-
 
230
		[62] = { .offset = 0xa5, .value = 0x00, },
-
 
231
		[63] = { .offset = 0xa6, .value = 0x00, },
-
 
232
		[64] = { .offset = 0xa7, .value = 0x00, },
-
 
233
		[65] = { .offset = 0xa8, .value = 0x00, },
-
 
234
		[66] = { .offset = 0xa9, .value = 0x83, },
-
 
235
		[67] = { .offset = 0xaa, .value = 0x40, },
-
 
236
		[68] = { .offset = 0xab, .value = 0x32, },
-
 
237
		[69] = { .offset = 0xac, .value = 0x00, },
-
 
238
		[70] = { .offset = 0xa4, .value = 0x80, },
-
 
239
		[71] = { .offset = 0x7e, .value = 0x18, },
-
 
240
		[72] = { .offset = 0x84, .value = 0x00, },
-
 
241
		[73] = { .offset = 0x85, .value = 0x00, },
-
 
242
		[74] = { .offset = 0x86, .value = 0x00, },
-
 
243
		[75] = { .offset = 0x87, .value = 0x00, },
-
 
244
		[76] = { .offset = 0x88, .value = 0x00, },
-
 
245
		[77] = { .offset = 0x89, .value = 0x00, },
-
 
246
		[78] = { .offset = 0x8a, .value = 0x00, },
-
 
247
		[79] = { .offset = 0x8b, .value = 0x00, },
-
 
248
		[80] = { .offset = 0x26, .value = 0x00, },
-
 
249
		[81] = { .offset = 0x27, .value = 0x00, },
-
 
250
		[82] = { .offset = 0xad, .value = 0x00, },
-
 
251
		[83] = { .offset = 0x08, .value = 0x30, }, /* 0x31 */
-
 
252
		[84] = { .offset = 0x41, .value = 0x00, },
-
 
253
		[85] = { .offset = 0xc0, .value = 0x07, },
-
 
254
	},
269
	},
255
	[MODE_1024x768] = {
270
	[MODE_1024x768] = {
-
 
271
		.sync	= NS2501_C0_ENABLE | NS2501_C0_VSYNC,
-
 
272
		.conf   = NS2501_8_VEN | NS2501_8_HEN | NS2501_8_PD,
-
 
273
		.syncb	= 0x32,
-
 
274
		.dither	= 0x0f,
-
 
275
		.pll_a	= 11,
-
 
276
		.pll_b	= 1350,
-
 
277
		.hstart	= 276,
-
 
278
		.hstop	= 1299,
-
 
279
		.vstart	= 15,
-
 
280
		.vstop	= 1056,
-
 
281
		.vsync	= 2047,
-
 
282
		.vtotal	= 1341,
-
 
283
		.hpos	= 0,
-
 
284
		.vpos	= 7,
-
 
285
		.voffs	= 27,
-
 
286
		.hscale	= 65535,
-
 
287
		.vscale	= 65535
-
 
288
	}
-
 
289
};
-
 
290
 
-
 
291
/*
-
 
292
 * Other configuration values left by the BIOS of the
-
 
293
 * Fujitsu S6010 in the DVO control registers. Their
-
 
294
 * value does not depend on the BIOS and their meaning
-
 
295
 * is unknown.
-
 
296
 */
-
 
297
 
-
 
298
static const struct ns2501_reg mode_agnostic_values[] = {
-
 
299
	/* 08 is mode specific */
256
		[0] = { .offset = 0x0a, .value = 0x81, },
300
	[0] = { .offset = 0x0a, .value = 0x81, },
257
		[1] = { .offset = 0x18, .value = 0x07, },
301
	/* 10,11 are part of the mode specific configuration */
258
		[2] = { .offset = 0x19, .value = 0x00, },
302
	[1] = { .offset = 0x12, .value = 0x02, },
259
		[3] = { .offset = 0x1a, .value = 0x00, },
303
	[2] = { .offset = 0x18, .value = 0x07, },
260
		[4] = { .offset = 0x1b, .value = 0x11, },
304
	[3] = { .offset = 0x19, .value = 0x00, },
261
		[5] = { .offset = 0x1c, .value = 0x54, },
305
	[4] = { .offset = 0x1a, .value = 0x00, }, /* PLL?, ignored */
262
		[6] = { .offset = 0x1d, .value = 0x03, },
306
	/* 1b,1c,1d are part of the mode specific configuration */
263
		[7] = { .offset = 0x1e, .value = 0x02, },
307
	[5] = { .offset = 0x1e, .value = 0x02, },
264
		[8] = { .offset = 0xf3, .value = 0x90, },
308
	[6] = { .offset = 0x1f, .value = 0x40, },
265
		[9] = { .offset = 0xf9, .value = 0x00, },
309
	[7] = { .offset = 0x20, .value = 0x00, },
266
		[10] = { .offset = 0xc1, .value = 0x90, },
310
	[8] = { .offset = 0x21, .value = 0x00, },
267
		[11] = { .offset = 0xc2, .value = 0x00, },
311
	[9] = { .offset = 0x22, .value = 0x00, },
268
		[12] = { .offset = 0xc3, .value = 0x0f, },
312
	[10] = { .offset = 0x23, .value = 0x00, },
269
		[13] = { .offset = 0xc4, .value = 0x03, },
313
	[11] = { .offset = 0x24, .value = 0x00, },
270
		[14] = { .offset = 0xc5, .value = 0x16, },
314
	[12] = { .offset = 0x25, .value = 0x00, },
271
		[15] = { .offset = 0xc6, .value = 0x00, },
315
	[13] = { .offset = 0x26, .value = 0x00, },
272
		[16] = { .offset = 0xc7, .value = 0x02, },
316
	[14] = { .offset = 0x27, .value = 0x00, },
273
		[17] = { .offset = 0xc8, .value = 0x02, },
317
	[15] = { .offset = 0x7e, .value = 0x18, },
274
		[18] = { .offset = 0xf4, .value = 0x00, },
318
	/* 80-84 are part of the mode-specific configuration */
275
		[19] = { .offset = 0x80, .value = 0xff, },
319
	[16] = { .offset = 0x84, .value = 0x00, },
276
		[20] = { .offset = 0x81, .value = 0x07, },
320
	[17] = { .offset = 0x85, .value = 0x00, },
277
		[21] = { .offset = 0x82, .value = 0x3d, },
321
	[18] = { .offset = 0x86, .value = 0x00, },
278
		[22] = { .offset = 0x83, .value = 0x05, },
322
	[19] = { .offset = 0x87, .value = 0x00, },
279
		[23] = { .offset = 0x94, .value = 0x00, },
323
	[20] = { .offset = 0x88, .value = 0x00, },
280
		[24] = { .offset = 0x95, .value = 0x00, },
324
	[21] = { .offset = 0x89, .value = 0x00, },
281
		[25] = { .offset = 0x96, .value = 0x05, },
325
	[22] = { .offset = 0x8a, .value = 0x00, },
282
		[26] = { .offset = 0x97, .value = 0x00, },
326
	[23] = { .offset = 0x8b, .value = 0x00, },
283
		[27] = { .offset = 0x9a, .value = 0x88, },
327
	[24] = { .offset = 0x8c, .value = 0x10, },
284
		[28] = { .offset = 0x9b, .value = 0x00, },
328
	[25] = { .offset = 0x8d, .value = 0x02, },
285
		[29] = { .offset = 0x98, .value = 0x00, },
329
	/* 8e,8f are part of the mode-specific configuration */
286
		[30] = { .offset = 0x99, .value = 0x00, },
330
	[26] = { .offset = 0x90, .value = 0xff, },
287
		[31] = { .offset = 0xf7, .value = 0x88, },
331
	[27] = { .offset = 0x91, .value = 0x07, },
288
		[32] = { .offset = 0xf8, .value = 0x0a, },
332
	[28] = { .offset = 0x92, .value = 0xa0, },
289
		[33] = { .offset = 0x9c, .value = 0x24, },
333
	[29] = { .offset = 0x93, .value = 0x02, },
290
		[34] = { .offset = 0x9d, .value = 0x00, },
334
	[30] = { .offset = 0x94, .value = 0x00, },
291
		[35] = { .offset = 0x9e, .value = 0x25, },
335
	[31] = { .offset = 0x95, .value = 0x00, },
292
		[36] = { .offset = 0x9f, .value = 0x03, },
336
	[32] = { .offset = 0x96, .value = 0x05, },
293
		[37] = { .offset = 0xa0, .value = 0x28, },
337
	[33] = { .offset = 0x97, .value = 0x00, },
294
		[38] = { .offset = 0xa1, .value = 0x01, },
338
	/* 98,99 are part of the mode-specific configuration */
295
		[39] = { .offset = 0xa2, .value = 0x28, },
339
	[34] = { .offset = 0x9a, .value = 0x88, },
296
		[40] = { .offset = 0xa3, .value = 0x05, },
-
 
297
		[41] = { .offset = 0xb6, .value = 0x09, },
-
 
298
		[42] = { .offset = 0xb8, .value = 0x00, },
340
	[35] = { .offset = 0x9b, .value = 0x00, },
299
		[43] = { .offset = 0xb9, .value = 0xa0, },
341
	/* 9c,9d are part of the mode-specific configuration */
300
		[44] = { .offset = 0xba, .value = 0x00, },
-
 
301
		[45] = { .offset = 0xbb, .value = 0x20, },
-
 
302
		[46] = { .offset = 0x10, .value = 0x00, },
342
	[36] = { .offset = 0x9e, .value = 0x25, },
303
		[47] = { .offset = 0x11, .value = 0xa0, },
343
	[37] = { .offset = 0x9f, .value = 0x03, },
304
		[48] = { .offset = 0x12, .value = 0x02, },
344
	[38] = { .offset = 0xa0, .value = 0x28, },
305
		[49] = { .offset = 0x20, .value = 0x00, },
345
	[39] = { .offset = 0xa1, .value = 0x01, },
306
		[50] = { .offset = 0x22, .value = 0x00, },
346
	[40] = { .offset = 0xa2, .value = 0x28, },
307
		[51] = { .offset = 0x23, .value = 0x00, },
347
	[41] = { .offset = 0xa3, .value = 0x05, },
308
		[52] = { .offset = 0x24, .value = 0x00, },
-
 
309
		[53] = { .offset = 0x25, .value = 0x00, },
-
 
310
		[54] = { .offset = 0x8c, .value = 0x10, },
-
 
311
		[55] = { .offset = 0x8d, .value = 0x02, },
348
	/* register 0xa4 is mode specific, but 0x80..0x84 works always */
312
		[56] = { .offset = 0x8e, .value = 0x10, },
349
	[42] = { .offset = 0xa4, .value = 0x84, },
313
		[57] = { .offset = 0x8f, .value = 0x00, },
350
	[43] = { .offset = 0xa5, .value = 0x00, },
314
		[58] = { .offset = 0x90, .value = 0xff, },
-
 
315
		[59] = { .offset = 0x91, .value = 0x07, },
-
 
316
		[60] = { .offset = 0x92, .value = 0xa0, },
-
 
317
		[61] = { .offset = 0x93, .value = 0x02, },
-
 
318
		[62] = { .offset = 0xa5, .value = 0x00, },
351
	[44] = { .offset = 0xa6, .value = 0x00, },
319
		[63] = { .offset = 0xa6, .value = 0x00, },
352
	[45] = { .offset = 0xa7, .value = 0x00, },
320
		[64] = { .offset = 0xa7, .value = 0x00, },
353
	[46] = { .offset = 0xa8, .value = 0x00, },
321
		[65] = { .offset = 0xa8, .value = 0x00, },
354
	/* 0xa9 to 0xab are mode specific, but have no visible effect */
322
		[66] = { .offset = 0xa9, .value = 0x04, },
355
	[47] = { .offset = 0xa9, .value = 0x04, },
323
		[67] = { .offset = 0xaa, .value = 0x70, },
356
	[48] = { .offset = 0xaa, .value = 0x70, },
324
		[68] = { .offset = 0xab, .value = 0x4f, },
357
	[49] = { .offset = 0xab, .value = 0x4f, },
325
		[69] = { .offset = 0xac, .value = 0x00, },
358
	[50] = { .offset = 0xac, .value = 0x00, },
326
		[70] = { .offset = 0xa4, .value = 0x84, },
-
 
327
		[71] = { .offset = 0x7e, .value = 0x18, },
-
 
328
		[72] = { .offset = 0x84, .value = 0x00, },
-
 
329
		[73] = { .offset = 0x85, .value = 0x00, },
359
	[51] = { .offset = 0xad, .value = 0x00, },
330
		[74] = { .offset = 0x86, .value = 0x00, },
360
	[52] = { .offset = 0xb6, .value = 0x09, },
331
		[75] = { .offset = 0x87, .value = 0x00, },
361
	[53] = { .offset = 0xb7, .value = 0x03, },
332
		[76] = { .offset = 0x88, .value = 0x00, },
-
 
333
		[77] = { .offset = 0x89, .value = 0x00, },
362
	/* b8,b9 are part of the mode-specific configuration */
334
		[78] = { .offset = 0x8a, .value = 0x00, },
363
	[54] = { .offset = 0xba, .value = 0x00, },
335
		[79] = { .offset = 0x8b, .value = 0x00, },
364
	[55] = { .offset = 0xbb, .value = 0x20, },
336
		[80] = { .offset = 0x26, .value = 0x00, },
365
	[56] = { .offset = 0xf3, .value = 0x90, },
337
		[81] = { .offset = 0x27, .value = 0x00, },
366
	[57] = { .offset = 0xf4, .value = 0x00, },
338
		[82] = { .offset = 0xad, .value = 0x00, },
367
	[58] = { .offset = 0xf7, .value = 0x88, },
339
		[83] = { .offset = 0x08, .value = 0x34, }, /* 0x35 */
368
	/* f8 is mode specific, but the value does not matter */
340
		[84] = { .offset = 0x41, .value = 0x00, },
369
	[59] = { .offset = 0xf8, .value = 0x0a, },
341
		[85] = { .offset = 0xc0, .value = 0x01, },
370
	[60] = { .offset = 0xf9, .value = 0x00, }
342
	},
-
 
343
};
371
};
344
 
372
 
345
static const struct ns2501_reg regs_init[] = {
373
static const struct ns2501_reg regs_init[] = {
346
	[0] = { .offset = 0x35, .value = 0xff, },
374
	[0] = { .offset = 0x35, .value = 0xff, },
347
	[1] = { .offset = 0x34, .value = 0x00, },
375
	[1] = { .offset = 0x34, .value = 0x00, },
348
	[2] = { .offset = 0x08, .value = 0x30, },
376
	[2] = { .offset = 0x08, .value = 0x30, },
349
};
377
};
350
 
378
 
351
struct ns2501_priv {
379
struct ns2501_priv {
352
	bool quiet;
380
	bool quiet;
353
	const struct ns2501_reg *regs;
381
	const struct ns2501_configuration *conf;
354
};
382
};
355
 
383
 
356
#define NSPTR(d) ((NS2501Ptr)(d->DriverPrivate.ptr))
384
#define NSPTR(d) ((NS2501Ptr)(d->DriverPrivate.ptr))
357
 
385
 
358
/*
386
/*
359
 * For reasons unclear to me, the ns2501 at least on the Fujitsu/Siemens
-
 
360
 * laptops does not react on the i2c bus unless
-
 
361
 * both the PLL is running and the display is configured in its native
-
 
362
 * resolution.
-
 
363
 * This function forces the DVO on, and stores the registers it touches.
-
 
364
 * Afterwards, registers are restored to regular values.
-
 
365
 *
-
 
366
 * This is pretty much a hack, though it works.
-
 
367
 * Without that, ns2501_readb and ns2501_writeb fail
-
 
368
 * when switching the resolution.
-
 
369
 */
-
 
370
 
-
 
371
/*
-
 
372
** Read a register from the ns2501.
387
** Read a register from the ns2501.
373
** Returns true if successful, false otherwise.
388
** Returns true if successful, false otherwise.
374
** If it returns false, it might be wise to enable the
389
** If it returns false, it might be wise to enable the
375
** DVO with the above function.
390
** DVO with the above function.
376
*/
391
*/
377
static bool ns2501_readb(struct intel_dvo_device *dvo, int addr, uint8_t * ch)
392
static bool ns2501_readb(struct intel_dvo_device *dvo, int addr, uint8_t * ch)
378
{
393
{
379
	struct ns2501_priv *ns = dvo->dev_priv;
394
	struct ns2501_priv *ns = dvo->dev_priv;
380
	struct i2c_adapter *adapter = dvo->i2c_bus;
395
	struct i2c_adapter *adapter = dvo->i2c_bus;
381
	u8 out_buf[2];
396
	u8 out_buf[2];
382
	u8 in_buf[2];
397
	u8 in_buf[2];
383
 
398
 
384
	struct i2c_msg msgs[] = {
399
	struct i2c_msg msgs[] = {
385
		{
400
		{
386
		 .addr = dvo->slave_addr,
401
		 .addr = dvo->slave_addr,
387
		 .flags = 0,
402
		 .flags = 0,
388
		 .len = 1,
403
		 .len = 1,
389
		 .buf = out_buf,
404
		 .buf = out_buf,
390
		 },
405
		 },
391
		{
406
		{
392
		 .addr = dvo->slave_addr,
407
		 .addr = dvo->slave_addr,
393
		 .flags = I2C_M_RD,
408
		 .flags = I2C_M_RD,
394
		 .len = 1,
409
		 .len = 1,
395
		 .buf = in_buf,
410
		 .buf = in_buf,
396
		 }
411
		 }
397
	};
412
	};
398
 
413
 
399
	out_buf[0] = addr;
414
	out_buf[0] = addr;
400
	out_buf[1] = 0;
415
	out_buf[1] = 0;
401
 
416
 
402
	if (i2c_transfer(adapter, msgs, 2) == 2) {
417
	if (i2c_transfer(adapter, msgs, 2) == 2) {
403
		*ch = in_buf[0];
418
		*ch = in_buf[0];
404
		return true;
419
		return true;
405
	}
420
	}
406
 
421
 
407
	if (!ns->quiet) {
422
	if (!ns->quiet) {
408
		DRM_DEBUG_KMS
423
		DRM_DEBUG_KMS
409
		    ("Unable to read register 0x%02x from %s:0x%02x.\n", addr,
424
		    ("Unable to read register 0x%02x from %s:0x%02x.\n", addr,
410
		     adapter->name, dvo->slave_addr);
425
		     adapter->name, dvo->slave_addr);
411
	}
426
	}
412
 
427
 
413
	return false;
428
	return false;
414
}
429
}
415
 
430
 
416
/*
431
/*
417
** Write a register to the ns2501.
432
** Write a register to the ns2501.
418
** Returns true if successful, false otherwise.
433
** Returns true if successful, false otherwise.
419
** If it returns false, it might be wise to enable the
434
** If it returns false, it might be wise to enable the
420
** DVO with the above function.
435
** DVO with the above function.
421
*/
436
*/
422
static bool ns2501_writeb(struct intel_dvo_device *dvo, int addr, uint8_t ch)
437
static bool ns2501_writeb(struct intel_dvo_device *dvo, int addr, uint8_t ch)
423
{
438
{
424
	struct ns2501_priv *ns = dvo->dev_priv;
439
	struct ns2501_priv *ns = dvo->dev_priv;
425
	struct i2c_adapter *adapter = dvo->i2c_bus;
440
	struct i2c_adapter *adapter = dvo->i2c_bus;
426
	uint8_t out_buf[2];
441
	uint8_t out_buf[2];
427
 
442
 
428
	struct i2c_msg msg = {
443
	struct i2c_msg msg = {
429
		.addr = dvo->slave_addr,
444
		.addr = dvo->slave_addr,
430
		.flags = 0,
445
		.flags = 0,
431
		.len = 2,
446
		.len = 2,
432
		.buf = out_buf,
447
		.buf = out_buf,
433
	};
448
	};
434
 
449
 
435
	out_buf[0] = addr;
450
	out_buf[0] = addr;
436
	out_buf[1] = ch;
451
	out_buf[1] = ch;
437
 
452
 
438
	if (i2c_transfer(adapter, &msg, 1) == 1) {
453
	if (i2c_transfer(adapter, &msg, 1) == 1) {
439
		return true;
454
		return true;
440
	}
455
	}
441
 
456
 
442
	if (!ns->quiet) {
457
	if (!ns->quiet) {
443
		DRM_DEBUG_KMS("Unable to write register 0x%02x to %s:%d\n",
458
		DRM_DEBUG_KMS("Unable to write register 0x%02x to %s:%d\n",
444
			      addr, adapter->name, dvo->slave_addr);
459
			      addr, adapter->name, dvo->slave_addr);
445
	}
460
	}
446
 
461
 
447
	return false;
462
	return false;
448
}
463
}
449
 
464
 
450
/* National Semiconductor 2501 driver for chip on i2c bus
465
/* National Semiconductor 2501 driver for chip on i2c bus
451
 * scan for the chip on the bus.
466
 * scan for the chip on the bus.
452
 * Hope the VBIOS initialized the PLL correctly so we can
467
 * Hope the VBIOS initialized the PLL correctly so we can
453
 * talk to it. If not, it will not be seen and not detected.
468
 * talk to it. If not, it will not be seen and not detected.
454
 * Bummer!
469
 * Bummer!
455
 */
470
 */
456
static bool ns2501_init(struct intel_dvo_device *dvo,
471
static bool ns2501_init(struct intel_dvo_device *dvo,
457
			struct i2c_adapter *adapter)
472
			struct i2c_adapter *adapter)
458
{
473
{
459
	/* this will detect the NS2501 chip on the specified i2c bus */
474
	/* this will detect the NS2501 chip on the specified i2c bus */
460
	struct ns2501_priv *ns;
475
	struct ns2501_priv *ns;
461
	unsigned char ch;
476
	unsigned char ch;
462
 
477
 
463
	ns = kzalloc(sizeof(struct ns2501_priv), GFP_KERNEL);
478
	ns = kzalloc(sizeof(struct ns2501_priv), GFP_KERNEL);
464
	if (ns == NULL)
479
	if (ns == NULL)
465
		return false;
480
		return false;
466
 
481
 
467
	dvo->i2c_bus = adapter;
482
	dvo->i2c_bus = adapter;
468
	dvo->dev_priv = ns;
483
	dvo->dev_priv = ns;
469
	ns->quiet = true;
484
	ns->quiet = true;
470
 
485
 
471
	if (!ns2501_readb(dvo, NS2501_VID_LO, &ch))
486
	if (!ns2501_readb(dvo, NS2501_VID_LO, &ch))
472
		goto out;
487
		goto out;
473
 
488
 
474
	if (ch != (NS2501_VID & 0xff)) {
489
	if (ch != (NS2501_VID & 0xff)) {
475
		DRM_DEBUG_KMS("ns2501 not detected got %d: from %s Slave %d.\n",
490
		DRM_DEBUG_KMS("ns2501 not detected got %d: from %s Slave %d.\n",
476
			      ch, adapter->name, dvo->slave_addr);
491
			      ch, adapter->name, dvo->slave_addr);
477
		goto out;
492
		goto out;
478
	}
493
	}
479
 
494
 
480
	if (!ns2501_readb(dvo, NS2501_DID_LO, &ch))
495
	if (!ns2501_readb(dvo, NS2501_DID_LO, &ch))
481
		goto out;
496
		goto out;
482
 
497
 
483
	if (ch != (NS2501_DID & 0xff)) {
498
	if (ch != (NS2501_DID & 0xff)) {
484
		DRM_DEBUG_KMS("ns2501 not detected got %d: from %s Slave %d.\n",
499
		DRM_DEBUG_KMS("ns2501 not detected got %d: from %s Slave %d.\n",
485
			      ch, adapter->name, dvo->slave_addr);
500
			      ch, adapter->name, dvo->slave_addr);
486
		goto out;
501
		goto out;
487
	}
502
	}
488
	ns->quiet = false;
503
	ns->quiet = false;
489
 
504
 
490
	DRM_DEBUG_KMS("init ns2501 dvo controller successfully!\n");
505
	DRM_DEBUG_KMS("init ns2501 dvo controller successfully!\n");
491
 
506
 
492
	return true;
507
	return true;
493
 
508
 
494
out:
509
out:
495
	kfree(ns);
510
	kfree(ns);
496
	return false;
511
	return false;
497
}
512
}
498
 
513
 
499
static enum drm_connector_status ns2501_detect(struct intel_dvo_device *dvo)
514
static enum drm_connector_status ns2501_detect(struct intel_dvo_device *dvo)
500
{
515
{
501
	/*
516
	/*
502
	 * This is a Laptop display, it doesn't have hotplugging.
517
	 * This is a Laptop display, it doesn't have hotplugging.
503
	 * Even if not, the detection bit of the 2501 is unreliable as
518
	 * Even if not, the detection bit of the 2501 is unreliable as
504
	 * it only works for some display types.
519
	 * it only works for some display types.
505
	 * It is even more unreliable as the PLL must be active for
520
	 * It is even more unreliable as the PLL must be active for
506
	 * allowing reading from the chiop.
521
	 * allowing reading from the chiop.
507
	 */
522
	 */
508
	return connector_status_connected;
523
	return connector_status_connected;
509
}
524
}
510
 
525
 
511
static enum drm_mode_status ns2501_mode_valid(struct intel_dvo_device *dvo,
526
static enum drm_mode_status ns2501_mode_valid(struct intel_dvo_device *dvo,
512
					      struct drm_display_mode *mode)
527
					      struct drm_display_mode *mode)
513
{
528
{
514
	DRM_DEBUG_KMS
529
	DRM_DEBUG_KMS
515
	    ("is mode valid (hdisplay=%d,htotal=%d,vdisplay=%d,vtotal=%d)\n",
530
	    ("is mode valid (hdisplay=%d,htotal=%d,vdisplay=%d,vtotal=%d)\n",
516
	     mode->hdisplay, mode->htotal, mode->vdisplay, mode->vtotal);
531
	     mode->hdisplay, mode->htotal, mode->vdisplay, mode->vtotal);
517
 
532
 
518
	/*
533
	/*
519
	 * Currently, these are all the modes I have data from.
534
	 * Currently, these are all the modes I have data from.
520
	 * More might exist. Unclear how to find the native resolution
535
	 * More might exist. Unclear how to find the native resolution
521
	 * of the panel in here so we could always accept it
536
	 * of the panel in here so we could always accept it
522
	 * by disabling the scaler.
537
	 * by disabling the scaler.
523
	 */
538
	 */
524
	if ((mode->hdisplay == 640 && mode->vdisplay == 480 && mode->clock == 25175) ||
539
	if ((mode->hdisplay == 640 && mode->vdisplay == 480 && mode->clock == 25175) ||
525
	    (mode->hdisplay == 800 && mode->vdisplay == 600 && mode->clock == 40000) ||
540
	    (mode->hdisplay == 800 && mode->vdisplay == 600 && mode->clock == 40000) ||
526
	    (mode->hdisplay == 1024 && mode->vdisplay == 768 && mode->clock == 65000)) {
541
	    (mode->hdisplay == 1024 && mode->vdisplay == 768 && mode->clock == 65000)) {
527
		return MODE_OK;
542
		return MODE_OK;
528
	} else {
543
	} else {
529
		return MODE_ONE_SIZE;	/* Is this a reasonable error? */
544
		return MODE_ONE_SIZE;	/* Is this a reasonable error? */
530
	}
545
	}
531
}
546
}
532
 
547
 
533
static void ns2501_mode_set(struct intel_dvo_device *dvo,
548
static void ns2501_mode_set(struct intel_dvo_device *dvo,
534
			    struct drm_display_mode *mode,
549
			    const struct drm_display_mode *mode,
535
			    struct drm_display_mode *adjusted_mode)
550
			    const struct drm_display_mode *adjusted_mode)
536
{
551
{
-
 
552
	const struct ns2501_configuration *conf;
537
	struct ns2501_priv *ns = (struct ns2501_priv *)(dvo->dev_priv);
553
	struct ns2501_priv *ns = (struct ns2501_priv *)(dvo->dev_priv);
538
	int mode_idx, i;
554
	int mode_idx, i;
539
 
555
 
540
	DRM_DEBUG_KMS
556
	DRM_DEBUG_KMS
541
	    ("set mode (hdisplay=%d,htotal=%d,vdisplay=%d,vtotal=%d).\n",
557
	    ("set mode (hdisplay=%d,htotal=%d,vdisplay=%d,vtotal=%d).\n",
542
	     mode->hdisplay, mode->htotal, mode->vdisplay, mode->vtotal);
558
	     mode->hdisplay, mode->htotal, mode->vdisplay, mode->vtotal);
-
 
559
 
-
 
560
	DRM_DEBUG_KMS("Detailed requested mode settings are:\n"
-
 
561
			"clock		: %d kHz\n"
-
 
562
			"hdisplay	: %d\n"
-
 
563
			"hblank start	: %d\n"
-
 
564
			"hblank end	: %d\n"
-
 
565
			"hsync start	: %d\n"
-
 
566
			"hsync end	: %d\n"
-
 
567
			"htotal		: %d\n"
-
 
568
			"hskew		: %d\n"
-
 
569
			"vdisplay	: %d\n"
-
 
570
			"vblank start	: %d\n"
-
 
571
			"hblank end	: %d\n"
-
 
572
			"vsync start	: %d\n"
-
 
573
			"vsync end	: %d\n"
-
 
574
			"vtotal		: %d\n",
-
 
575
			adjusted_mode->crtc_clock,
-
 
576
			adjusted_mode->crtc_hdisplay,
-
 
577
			adjusted_mode->crtc_hblank_start,
-
 
578
			adjusted_mode->crtc_hblank_end,
-
 
579
			adjusted_mode->crtc_hsync_start,
-
 
580
			adjusted_mode->crtc_hsync_end,
-
 
581
			adjusted_mode->crtc_htotal,
-
 
582
			adjusted_mode->crtc_hskew,
-
 
583
			adjusted_mode->crtc_vdisplay,
-
 
584
			adjusted_mode->crtc_vblank_start,
-
 
585
			adjusted_mode->crtc_vblank_end,
-
 
586
			adjusted_mode->crtc_vsync_start,
-
 
587
			adjusted_mode->crtc_vsync_end,
-
 
588
			adjusted_mode->crtc_vtotal);
543
 
589
 
544
	if (mode->hdisplay == 640 && mode->vdisplay == 480)
590
	if (mode->hdisplay == 640 && mode->vdisplay == 480)
545
		mode_idx = MODE_640x480;
591
		mode_idx = MODE_640x480;
546
	else if (mode->hdisplay == 800 && mode->vdisplay == 600)
592
	else if (mode->hdisplay == 800 && mode->vdisplay == 600)
547
		mode_idx = MODE_800x600;
593
		mode_idx = MODE_800x600;
548
	else if (mode->hdisplay == 1024 && mode->vdisplay == 768)
594
	else if (mode->hdisplay == 1024 && mode->vdisplay == 768)
549
		mode_idx = MODE_1024x768;
595
		mode_idx = MODE_1024x768;
550
	else
596
	else
551
		return;
597
		return;
552
 
598
 
553
	/* Hopefully doing it every time won't hurt... */
599
	/* Hopefully doing it every time won't hurt... */
554
	for (i = 0; i < ARRAY_SIZE(regs_init); i++)
600
	for (i = 0; i < ARRAY_SIZE(regs_init); i++)
555
		ns2501_writeb(dvo, regs_init[i].offset, regs_init[i].value);
601
		ns2501_writeb(dvo, regs_init[i].offset, regs_init[i].value);
-
 
602
 
-
 
603
	/* Write the mode-agnostic values */
-
 
604
	for (i = 0; i < ARRAY_SIZE(mode_agnostic_values); i++)
-
 
605
		ns2501_writeb(dvo, mode_agnostic_values[i].offset,
-
 
606
				mode_agnostic_values[i].value);
-
 
607
 
556
 
608
	/* Write now the mode-specific configuration */
-
 
609
	conf = ns2501_modes + mode_idx;
557
	ns->regs = regs_1024x768[mode_idx];
610
	ns->conf = conf;
558
 
611
 
-
 
612
	ns2501_writeb(dvo, NS2501_REG8, conf->conf);
-
 
613
	ns2501_writeb(dvo, NS2501_REG1B, conf->pll_a);
-
 
614
	ns2501_writeb(dvo, NS2501_REG1C, conf->pll_b & 0xff);
-
 
615
	ns2501_writeb(dvo, NS2501_REG1D, conf->pll_b >> 8);
-
 
616
	ns2501_writeb(dvo, NS2501_REGC1, conf->hstart & 0xff);
-
 
617
	ns2501_writeb(dvo, NS2501_REGC2, conf->hstart >> 8);
-
 
618
	ns2501_writeb(dvo, NS2501_REGC3, conf->hstop & 0xff);
-
 
619
	ns2501_writeb(dvo, NS2501_REGC4, conf->hstop >> 8);
-
 
620
	ns2501_writeb(dvo, NS2501_REGC5, conf->vstart & 0xff);
-
 
621
	ns2501_writeb(dvo, NS2501_REGC6, conf->vstart >> 8);
-
 
622
	ns2501_writeb(dvo, NS2501_REGC7, conf->vstop & 0xff);
-
 
623
	ns2501_writeb(dvo, NS2501_REGC8, conf->vstop >> 8);
-
 
624
	ns2501_writeb(dvo, NS2501_REG80, conf->vsync & 0xff);
-
 
625
	ns2501_writeb(dvo, NS2501_REG81, conf->vsync >> 8);
-
 
626
	ns2501_writeb(dvo, NS2501_REG82, conf->vtotal & 0xff);
-
 
627
	ns2501_writeb(dvo, NS2501_REG83, conf->vtotal >> 8);
-
 
628
	ns2501_writeb(dvo, NS2501_REG98, conf->hpos & 0xff);
-
 
629
	ns2501_writeb(dvo, NS2501_REG99, conf->hpos >> 8);
-
 
630
	ns2501_writeb(dvo, NS2501_REG8E, conf->vpos & 0xff);
-
 
631
	ns2501_writeb(dvo, NS2501_REG8F, conf->vpos >> 8);
-
 
632
	ns2501_writeb(dvo, NS2501_REG9C, conf->voffs & 0xff);
-
 
633
	ns2501_writeb(dvo, NS2501_REG9D, conf->voffs >> 8);
-
 
634
	ns2501_writeb(dvo, NS2501_REGB8, conf->hscale & 0xff);
-
 
635
	ns2501_writeb(dvo, NS2501_REGB9, conf->hscale >> 8);
559
	for (i = 0; i < 84; i++)
636
	ns2501_writeb(dvo, NS2501_REG10, conf->vscale & 0xff);
-
 
637
	ns2501_writeb(dvo, NS2501_REG11, conf->vscale >> 8);
-
 
638
	ns2501_writeb(dvo, NS2501_REGF9, conf->dither);
-
 
639
	ns2501_writeb(dvo, NS2501_REG41, conf->syncb);
560
		ns2501_writeb(dvo, ns->regs[i].offset, ns->regs[i].value);
640
	ns2501_writeb(dvo, NS2501_REGC0, conf->sync);
561
}
641
}
562
 
642
 
563
/* set the NS2501 power state */
643
/* set the NS2501 power state */
564
static bool ns2501_get_hw_state(struct intel_dvo_device *dvo)
644
static bool ns2501_get_hw_state(struct intel_dvo_device *dvo)
565
{
645
{
566
	unsigned char ch;
646
	unsigned char ch;
567
 
647
 
568
	if (!ns2501_readb(dvo, NS2501_REG8, &ch))
648
	if (!ns2501_readb(dvo, NS2501_REG8, &ch))
569
		return false;
649
		return false;
570
 
650
 
571
	return ch & NS2501_8_PD;
651
	return ch & NS2501_8_PD;
572
}
652
}
573
 
653
 
574
/* set the NS2501 power state */
654
/* set the NS2501 power state */
575
static void ns2501_dpms(struct intel_dvo_device *dvo, bool enable)
655
static void ns2501_dpms(struct intel_dvo_device *dvo, bool enable)
576
{
656
{
577
	struct ns2501_priv *ns = (struct ns2501_priv *)(dvo->dev_priv);
657
	struct ns2501_priv *ns = (struct ns2501_priv *)(dvo->dev_priv);
578
 
658
 
579
	DRM_DEBUG_KMS("Trying set the dpms of the DVO to %i\n", enable);
659
	DRM_DEBUG_KMS("Trying set the dpms of the DVO to %i\n", enable);
580
 
660
 
581
	if (enable) {
661
	if (enable) {
582
		if (WARN_ON(ns->regs[83].offset != 0x08 ||
-
 
583
			    ns->regs[84].offset != 0x41 ||
-
 
584
			    ns->regs[85].offset != 0xc0))
-
 
585
			return;
-
 
586
 
-
 
587
		ns2501_writeb(dvo, 0xc0, ns->regs[85].value | 0x08);
662
		ns2501_writeb(dvo, NS2501_REGC0, ns->conf->sync | 0x08);
588
 
663
 
589
		ns2501_writeb(dvo, 0x41, ns->regs[84].value);
664
		ns2501_writeb(dvo, NS2501_REG41, ns->conf->syncb);
590
 
665
 
591
		ns2501_writeb(dvo, 0x34, 0x01);
666
		ns2501_writeb(dvo, NS2501_REG34, NS2501_34_ENABLE_OUTPUT);
-
 
667
		msleep(15);
592
		msleep(15);
668
 
593
 
669
		ns2501_writeb(dvo, NS2501_REG8,
594
		ns2501_writeb(dvo, 0x08, 0x35);
670
				ns->conf->conf | NS2501_8_BPAS);
595
		if (!(ns->regs[83].value & NS2501_8_BPAS))
671
		if (!(ns->conf->conf & NS2501_8_BPAS))
-
 
672
			ns2501_writeb(dvo, NS2501_REG8, ns->conf->conf);
596
			ns2501_writeb(dvo, 0x08, 0x31);
673
		msleep(200);
597
		msleep(200);
674
 
598
 
675
		ns2501_writeb(dvo, NS2501_REG34,
599
		ns2501_writeb(dvo, 0x34, 0x03);
676
			NS2501_34_ENABLE_OUTPUT | NS2501_34_ENABLE_BACKLIGHT);
600
 
677
 
-
 
678
		ns2501_writeb(dvo, NS2501_REGC0, ns->conf->sync);
601
		ns2501_writeb(dvo, 0xc0, ns->regs[85].value);
679
	} else {
602
	} else {
680
		ns2501_writeb(dvo, NS2501_REG34, NS2501_34_ENABLE_OUTPUT);
603
		ns2501_writeb(dvo, 0x34, 0x01);
681
		msleep(200);
604
		msleep(200);
682
 
605
 
683
		ns2501_writeb(dvo, NS2501_REG8, NS2501_8_VEN | NS2501_8_HEN |
606
		ns2501_writeb(dvo, 0x08, 0x34);
684
				NS2501_8_BPAS);
607
		msleep(15);
685
		msleep(15);
608
 
686
 
609
		ns2501_writeb(dvo, 0x34, 0x00);
687
		ns2501_writeb(dvo, NS2501_REG34, 0x00);
610
	}
688
	}
611
}
689
}
612
 
690
 
613
static void ns2501_destroy(struct intel_dvo_device *dvo)
691
static void ns2501_destroy(struct intel_dvo_device *dvo)
614
{
692
{
615
	struct ns2501_priv *ns = dvo->dev_priv;
693
	struct ns2501_priv *ns = dvo->dev_priv;
616
 
694
 
617
	if (ns) {
695
	if (ns) {
618
		kfree(ns);
696
		kfree(ns);
619
		dvo->dev_priv = NULL;
697
		dvo->dev_priv = NULL;
620
	}
698
	}
621
}
699
}
622
 
700
 
623
struct intel_dvo_dev_ops ns2501_ops = {
701
struct intel_dvo_dev_ops ns2501_ops = {
624
	.init = ns2501_init,
702
	.init = ns2501_init,
625
	.detect = ns2501_detect,
703
	.detect = ns2501_detect,
626
	.mode_valid = ns2501_mode_valid,
704
	.mode_valid = ns2501_mode_valid,
627
	.mode_set = ns2501_mode_set,
705
	.mode_set = ns2501_mode_set,
628
	.dpms = ns2501_dpms,
706
	.dpms = ns2501_dpms,
629
	.get_hw_state = ns2501_get_hw_state,
707
	.get_hw_state = ns2501_get_hw_state,
630
	.destroy = ns2501_destroy,
708
	.destroy = ns2501_destroy,
631
};
709
};
632
 
710
 
633
#define>
711
#define>
634
 
712
 
635
#define>
713
#define>
636
#define>
714
#define>
637
#define>
715
#define>
638
#define>
716
#define>
639
#define>
717
#define>
640
#define>
718
#define>
641
#define>
719
#define>
642
#define>
720
#define>
643
#define>
721
#define>
644
#define>
722
#define>
645
#define>
723
#define>
646
 
724
 
647
#define>
725
#define>
648
 
726
 
649
#define>
727
#define>
650
#define>
728
#define>
651
#define>
729
#define>
652
#define>
730
#define>
653
#define>
731
#define>
654
#define>
732
#define>
655
#define>
733
#define>
656
#define>
734
#define>
657
#define>
735
#define>
658
#define>
736
#define>
659
#define>
737
#define>