3 * Copyright (c) 2012 Gilles Dartiguelongue, Thomas Richter
7 * Permission is hereby granted, free of charge, to any person obtaining a
8 * copy of this software and associated documentation files (the
9 * "Software"), to deal in the Software without restriction, including
10 * without limitation the rights to use, copy, modify, merge, publish,
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
13 * the following conditions:
15 * The above copyright notice and this permission notice (including the
16 * next paragraph) shall be included in all copies or substantial portions
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
20 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
21 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
22 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
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
25 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
33 #define NS2501_VID 0x1305
34 #define NS2501_DID 0x6726
36 #define NS2501_VID_LO 0x00
37 #define NS2501_VID_HI 0x01
38 #define NS2501_DID_LO 0x02
39 #define NS2501_DID_HI 0x03
40 #define NS2501_REV 0x04
41 #define NS2501_RSVD 0x05
42 #define NS2501_FREQ_LO 0x06
43 #define NS2501_FREQ_HI 0x07
45 #define NS2501_REG8 0x08
46 #define NS2501_8_VEN (1<<5)
47 #define NS2501_8_HEN (1<<4)
48 #define NS2501_8_DSEL (1<<3)
49 #define NS2501_8_BPAS (1<<2)
50 #define NS2501_8_RSVD (1<<1)
51 #define NS2501_8_PD (1<<0)
53 #define NS2501_REG9 0x09
54 #define NS2501_9_VLOW (1<<7)
55 #define NS2501_9_MSEL_MASK (0x7<<4)
56 #define NS2501_9_TSEL (1<<3)
57 #define NS2501_9_RSEN (1<<2)
58 #define NS2501_9_RSVD (1<<1)
59 #define NS2501_9_MDI (1<<0)
61 #define NS2501_REGC 0x0c
75 * Magic values based on what the BIOS on
76 * Fujitsu-Siemens Lifebook S6010 programs (1024x768 panel).
78 static const struct ns2501_reg regs_1024x768
[][86] = {
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, },
93 [13] = { .offset
= 0xc4, .value
= 0x03, },
94 [14] = { .offset
= 0xc5, .value
= 0x16, },
95 [15] = { .offset
= 0xc6, .value
= 0x00, },
96 [16] = { .offset
= 0xc7, .value
= 0x02, },
97 [17] = { .offset
= 0xc8, .value
= 0x02, },
98 [18] = { .offset
= 0xf4, .value
= 0x00, },
99 [19] = { .offset
= 0x80, .value
= 0xff, },
100 [20] = { .offset
= 0x81, .value
= 0x07, },
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, },
112 [32] = { .offset
= 0xf8, .value
= 0x0a, },
113 [33] = { .offset
= 0x9c, .value
= 0x24, },
114 [34] = { .offset
= 0x9d, .value
= 0x00, },
115 [35] = { .offset
= 0x9e, .value
= 0x25, },
116 [36] = { .offset
= 0x9f, .value
= 0x03, },
117 [37] = { .offset
= 0xa0, .value
= 0x28, },
118 [38] = { .offset
= 0xa1, .value
= 0x01, },
119 [39] = { .offset
= 0xa2, .value
= 0x28, },
120 [40] = { .offset
= 0xa3, .value
= 0x05, },
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, },
137 [57] = { .offset
= 0x8f, .value
= 0x00, },
138 [58] = { .offset
= 0x90, .value
= 0xff, },
139 [59] = { .offset
= 0x91, .value
= 0x07, },
140 [60] = { .offset
= 0x92, .value
= 0xa0, },
141 [61] = { .offset
= 0x93, .value
= 0x02, },
142 [62] = { .offset
= 0xa5, .value
= 0x00, },
143 [63] = { .offset
= 0xa6, .value
= 0x00, },
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, },
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, },
168 [0] = { .offset
= 0x0a, .value
= 0x81, },
169 [1] = { .offset
= 0x18, .value
= 0x07, },
170 [2] = { .offset
= 0x19, .value
= 0x00, },
171 [3] = { .offset
= 0x1a, .value
= 0x00, },
172 [4] = { .offset
= 0x1b, .value
= 0x19, },
173 [5] = { .offset
= 0x1c, .value
= 0x64, },
174 [6] = { .offset
= 0x1d, .value
= 0x02, },
175 [7] = { .offset
= 0x1e, .value
= 0x02, },
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, },
183 [15] = { .offset
= 0xc6, .value
= 0x00, },
184 [16] = { .offset
= 0xc7, .value
= 0x73, },
185 [17] = { .offset
= 0xc8, .value
= 0x02, },
186 [18] = { .offset
= 0xf4, .value
= 0x00, },
187 [19] = { .offset
= 0x80, .value
= 0x27, },
188 [20] = { .offset
= 0x81, .value
= 0x03, },
189 [21] = { .offset
= 0x82, .value
= 0x41, },
190 [22] = { .offset
= 0x83, .value
= 0x05, },
191 [23] = { .offset
= 0x94, .value
= 0x00, },
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, },
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, },
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, },
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, },
256 [0] = { .offset
= 0x0a, .value
= 0x81, },
257 [1] = { .offset
= 0x18, .value
= 0x07, },
258 [2] = { .offset
= 0x19, .value
= 0x00, },
259 [3] = { .offset
= 0x1a, .value
= 0x00, },
260 [4] = { .offset
= 0x1b, .value
= 0x11, },
261 [5] = { .offset
= 0x1c, .value
= 0x54, },
262 [6] = { .offset
= 0x1d, .value
= 0x03, },
263 [7] = { .offset
= 0x1e, .value
= 0x02, },
264 [8] = { .offset
= 0xf3, .value
= 0x90, },
265 [9] = { .offset
= 0xf9, .value
= 0x00, },
266 [10] = { .offset
= 0xc1, .value
= 0x90, },
267 [11] = { .offset
= 0xc2, .value
= 0x00, },
268 [12] = { .offset
= 0xc3, .value
= 0x0f, },
269 [13] = { .offset
= 0xc4, .value
= 0x03, },
270 [14] = { .offset
= 0xc5, .value
= 0x16, },
271 [15] = { .offset
= 0xc6, .value
= 0x00, },
272 [16] = { .offset
= 0xc7, .value
= 0x02, },
273 [17] = { .offset
= 0xc8, .value
= 0x02, },
274 [18] = { .offset
= 0xf4, .value
= 0x00, },
275 [19] = { .offset
= 0x80, .value
= 0xff, },
276 [20] = { .offset
= 0x81, .value
= 0x07, },
277 [21] = { .offset
= 0x82, .value
= 0x3d, },
278 [22] = { .offset
= 0x83, .value
= 0x05, },
279 [23] = { .offset
= 0x94, .value
= 0x00, },
280 [24] = { .offset
= 0x95, .value
= 0x00, },
281 [25] = { .offset
= 0x96, .value
= 0x05, },
282 [26] = { .offset
= 0x97, .value
= 0x00, },
283 [27] = { .offset
= 0x9a, .value
= 0x88, },
284 [28] = { .offset
= 0x9b, .value
= 0x00, },
285 [29] = { .offset
= 0x98, .value
= 0x00, },
286 [30] = { .offset
= 0x99, .value
= 0x00, },
287 [31] = { .offset
= 0xf7, .value
= 0x88, },
288 [32] = { .offset
= 0xf8, .value
= 0x0a, },
289 [33] = { .offset
= 0x9c, .value
= 0x24, },
290 [34] = { .offset
= 0x9d, .value
= 0x00, },
291 [35] = { .offset
= 0x9e, .value
= 0x25, },
292 [36] = { .offset
= 0x9f, .value
= 0x03, },
293 [37] = { .offset
= 0xa0, .value
= 0x28, },
294 [38] = { .offset
= 0xa1, .value
= 0x01, },
295 [39] = { .offset
= 0xa2, .value
= 0x28, },
296 [40] = { .offset
= 0xa3, .value
= 0x05, },
297 [41] = { .offset
= 0xb6, .value
= 0x09, },
298 [42] = { .offset
= 0xb8, .value
= 0x00, },
299 [43] = { .offset
= 0xb9, .value
= 0xa0, },
300 [44] = { .offset
= 0xba, .value
= 0x00, },
301 [45] = { .offset
= 0xbb, .value
= 0x20, },
302 [46] = { .offset
= 0x10, .value
= 0x00, },
303 [47] = { .offset
= 0x11, .value
= 0xa0, },
304 [48] = { .offset
= 0x12, .value
= 0x02, },
305 [49] = { .offset
= 0x20, .value
= 0x00, },
306 [50] = { .offset
= 0x22, .value
= 0x00, },
307 [51] = { .offset
= 0x23, .value
= 0x00, },
308 [52] = { .offset
= 0x24, .value
= 0x00, },
309 [53] = { .offset
= 0x25, .value
= 0x00, },
310 [54] = { .offset
= 0x8c, .value
= 0x10, },
311 [55] = { .offset
= 0x8d, .value
= 0x02, },
312 [56] = { .offset
= 0x8e, .value
= 0x10, },
313 [57] = { .offset
= 0x8f, .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, },
319 [63] = { .offset
= 0xa6, .value
= 0x00, },
320 [64] = { .offset
= 0xa7, .value
= 0x00, },
321 [65] = { .offset
= 0xa8, .value
= 0x00, },
322 [66] = { .offset
= 0xa9, .value
= 0x04, },
323 [67] = { .offset
= 0xaa, .value
= 0x70, },
324 [68] = { .offset
= 0xab, .value
= 0x4f, },
325 [69] = { .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, },
330 [74] = { .offset
= 0x86, .value
= 0x00, },
331 [75] = { .offset
= 0x87, .value
= 0x00, },
332 [76] = { .offset
= 0x88, .value
= 0x00, },
333 [77] = { .offset
= 0x89, .value
= 0x00, },
334 [78] = { .offset
= 0x8a, .value
= 0x00, },
335 [79] = { .offset
= 0x8b, .value
= 0x00, },
336 [80] = { .offset
= 0x26, .value
= 0x00, },
337 [81] = { .offset
= 0x27, .value
= 0x00, },
338 [82] = { .offset
= 0xad, .value
= 0x00, },
339 [83] = { .offset
= 0x08, .value
= 0x34, }, /* 0x35 */
340 [84] = { .offset
= 0x41, .value
= 0x00, },
341 [85] = { .offset
= 0xc0, .value
= 0x01, },
345 static const struct ns2501_reg regs_init
[] = {
346 [0] = { .offset
= 0x35, .value
= 0xff, },
347 [1] = { .offset
= 0x34, .value
= 0x00, },
348 [2] = { .offset
= 0x08, .value
= 0x30, },
353 const struct ns2501_reg
*regs
;
356 #define NSPTR(d) ((NS2501Ptr)(d->DriverPrivate.ptr))
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
363 * This function forces the DVO on, and stores the registers it touches.
364 * Afterwards, registers are restored to regular values.
366 * This is pretty much a hack, though it works.
367 * Without that, ns2501_readb and ns2501_writeb fail
368 * when switching the resolution.
372 ** Read a register from the ns2501.
373 ** Returns true if successful, false otherwise.
374 ** If it returns false, it might be wise to enable the
375 ** DVO with the above function.
377 static bool ns2501_readb(struct intel_dvo_device
*dvo
, int addr
, uint8_t * ch
)
379 struct ns2501_priv
*ns
= dvo
->dev_priv
;
380 struct i2c_adapter
*adapter
= dvo
->i2c_bus
;
384 struct i2c_msg msgs
[] = {
386 .addr
= dvo
->slave_addr
,
392 .addr
= dvo
->slave_addr
,
402 if (i2c_transfer(adapter
, msgs
, 2) == 2) {
409 ("Unable to read register 0x%02x from %s:0x%02x.\n", addr
,
410 adapter
->name
, dvo
->slave_addr
);
417 ** Write a register to the ns2501.
418 ** Returns true if successful, false otherwise.
419 ** If it returns false, it might be wise to enable the
420 ** DVO with the above function.
422 static bool ns2501_writeb(struct intel_dvo_device
*dvo
, int addr
, uint8_t ch
)
424 struct ns2501_priv
*ns
= dvo
->dev_priv
;
425 struct i2c_adapter
*adapter
= dvo
->i2c_bus
;
428 struct i2c_msg msg
= {
429 .addr
= dvo
->slave_addr
,
438 if (i2c_transfer(adapter
, &msg
, 1) == 1) {
443 DRM_DEBUG_KMS("Unable to write register 0x%02x to %s:%d\n",
444 addr
, adapter
->name
, dvo
->slave_addr
);
450 /* National Semiconductor 2501 driver for chip on i2c bus
451 * scan for the chip on the bus.
452 * Hope the VBIOS initialized the PLL correctly so we can
453 * talk to it. If not, it will not be seen and not detected.
456 static bool ns2501_init(struct intel_dvo_device
*dvo
,
457 struct i2c_adapter
*adapter
)
459 /* this will detect the NS2501 chip on the specified i2c bus */
460 struct ns2501_priv
*ns
;
463 ns
= kzalloc(sizeof(struct ns2501_priv
), GFP_KERNEL
);
467 dvo
->i2c_bus
= adapter
;
471 if (!ns2501_readb(dvo
, NS2501_VID_LO
, &ch
))
474 if (ch
!= (NS2501_VID
& 0xff)) {
475 DRM_DEBUG_KMS("ns2501 not detected got %d: from %s Slave %d.\n",
476 ch
, adapter
->name
, dvo
->slave_addr
);
480 if (!ns2501_readb(dvo
, NS2501_DID_LO
, &ch
))
483 if (ch
!= (NS2501_DID
& 0xff)) {
484 DRM_DEBUG_KMS("ns2501 not detected got %d: from %s Slave %d.\n",
485 ch
, adapter
->name
, dvo
->slave_addr
);
490 DRM_DEBUG_KMS("init ns2501 dvo controller successfully!\n");
499 static enum drm_connector_status
ns2501_detect(struct intel_dvo_device
*dvo
)
502 * This is a Laptop display, it doesn't have hotplugging.
503 * Even if not, the detection bit of the 2501 is unreliable as
504 * it only works for some display types.
505 * It is even more unreliable as the PLL must be active for
506 * allowing reading from the chiop.
508 return connector_status_connected
;
511 static enum drm_mode_status
ns2501_mode_valid(struct intel_dvo_device
*dvo
,
512 struct drm_display_mode
*mode
)
515 ("is mode valid (hdisplay=%d,htotal=%d,vdisplay=%d,vtotal=%d)\n",
516 mode
->hdisplay
, mode
->htotal
, mode
->vdisplay
, mode
->vtotal
);
519 * Currently, these are all the modes I have data from.
520 * More might exist. Unclear how to find the native resolution
521 * of the panel in here so we could always accept it
522 * by disabling the scaler.
524 if ((mode
->hdisplay
== 640 && mode
->vdisplay
== 480 && mode
->clock
== 25175) ||
525 (mode
->hdisplay
== 800 && mode
->vdisplay
== 600 && mode
->clock
== 40000) ||
526 (mode
->hdisplay
== 1024 && mode
->vdisplay
== 768 && mode
->clock
== 65000)) {
529 return MODE_ONE_SIZE
; /* Is this a reasonable error? */
533 static void ns2501_mode_set(struct intel_dvo_device
*dvo
,
534 struct drm_display_mode
*mode
,
535 struct drm_display_mode
*adjusted_mode
)
537 struct ns2501_priv
*ns
= (struct ns2501_priv
*)(dvo
->dev_priv
);
541 ("set mode (hdisplay=%d,htotal=%d,vdisplay=%d,vtotal=%d).\n",
542 mode
->hdisplay
, mode
->htotal
, mode
->vdisplay
, mode
->vtotal
);
544 if (mode
->hdisplay
== 640 && mode
->vdisplay
== 480)
545 mode_idx
= MODE_640x480
;
546 else if (mode
->hdisplay
== 800 && mode
->vdisplay
== 600)
547 mode_idx
= MODE_800x600
;
548 else if (mode
->hdisplay
== 1024 && mode
->vdisplay
== 768)
549 mode_idx
= MODE_1024x768
;
553 /* Hopefully doing it every time won't hurt... */
554 for (i
= 0; i
< ARRAY_SIZE(regs_init
); i
++)
555 ns2501_writeb(dvo
, regs_init
[i
].offset
, regs_init
[i
].value
);
557 ns
->regs
= regs_1024x768
[mode_idx
];
559 for (i
= 0; i
< 84; i
++)
560 ns2501_writeb(dvo
, ns
->regs
[i
].offset
, ns
->regs
[i
].value
);
563 /* set the NS2501 power state */
564 static bool ns2501_get_hw_state(struct intel_dvo_device
*dvo
)
568 if (!ns2501_readb(dvo
, NS2501_REG8
, &ch
))
571 return ch
& NS2501_8_PD
;
574 /* set the NS2501 power state */
575 static void ns2501_dpms(struct intel_dvo_device
*dvo
, bool enable
)
577 struct ns2501_priv
*ns
= (struct ns2501_priv
*)(dvo
->dev_priv
);
579 DRM_DEBUG_KMS("Trying set the dpms of the DVO to %i\n", enable
);
582 if (WARN_ON(ns
->regs
[83].offset
!= 0x08 ||
583 ns
->regs
[84].offset
!= 0x41 ||
584 ns
->regs
[85].offset
!= 0xc0))
587 ns2501_writeb(dvo
, 0xc0, ns
->regs
[85].value
| 0x08);
589 ns2501_writeb(dvo
, 0x41, ns
->regs
[84].value
);
591 ns2501_writeb(dvo
, 0x34, 0x01);
594 ns2501_writeb(dvo
, 0x08, 0x35);
595 if (!(ns
->regs
[83].value
& NS2501_8_BPAS
))
596 ns2501_writeb(dvo
, 0x08, 0x31);
599 ns2501_writeb(dvo
, 0x34, 0x03);
601 ns2501_writeb(dvo
, 0xc0, ns
->regs
[85].value
);
603 ns2501_writeb(dvo
, 0x34, 0x01);
606 ns2501_writeb(dvo
, 0x08, 0x34);
609 ns2501_writeb(dvo
, 0x34, 0x00);
613 static void ns2501_destroy(struct intel_dvo_device
*dvo
)
615 struct ns2501_priv
*ns
= dvo
->dev_priv
;
619 dvo
->dev_priv
= NULL
;
623 struct intel_dvo_dev_ops ns2501_ops
= {
625 .detect
= ns2501_detect
,
626 .mode_valid
= ns2501_mode_valid
,
627 .mode_set
= ns2501_mode_set
,
629 .get_hw_state
= ns2501_get_hw_state
,
630 .destroy
= ns2501_destroy
,