diff options
Diffstat (limited to 'drivers/video/fbdev/via/lcd.c')
-rw-r--r-- | drivers/video/fbdev/via/lcd.c | 1005 |
1 files changed, 1005 insertions, 0 deletions
diff --git a/drivers/video/fbdev/via/lcd.c b/drivers/video/fbdev/via/lcd.c new file mode 100644 index 000000000000..5d21ff436ec8 --- /dev/null +++ b/drivers/video/fbdev/via/lcd.c | |||
@@ -0,0 +1,1005 @@ | |||
1 | /* | ||
2 | * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved. | ||
3 | * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved. | ||
4 | |||
5 | * This program is free software; you can redistribute it and/or | ||
6 | * modify it under the terms of the GNU General Public | ||
7 | * License as published by the Free Software Foundation; | ||
8 | * either version 2, or (at your option) any later version. | ||
9 | |||
10 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even | ||
12 | * the implied warranty of MERCHANTABILITY or FITNESS FOR | ||
13 | * A PARTICULAR PURPOSE.See the GNU General Public License | ||
14 | * for more details. | ||
15 | |||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program; if not, write to the Free Software | ||
18 | * Foundation, Inc., | ||
19 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | ||
20 | */ | ||
21 | #include <linux/via-core.h> | ||
22 | #include <linux/via_i2c.h> | ||
23 | #include "global.h" | ||
24 | |||
25 | #define viafb_compact_res(x, y) (((x)<<16)|(y)) | ||
26 | |||
27 | /* CLE266 Software Power Sequence */ | ||
28 | /* {Mask}, {Data}, {Delay} */ | ||
29 | static const int PowerSequenceOn[3][3] = { | ||
30 | {0x10, 0x08, 0x06}, {0x10, 0x08, 0x06}, {0x19, 0x1FE, 0x01} | ||
31 | }; | ||
32 | static const int PowerSequenceOff[3][3] = { | ||
33 | {0x06, 0x08, 0x10}, {0x00, 0x00, 0x00}, {0xD2, 0x19, 0x01} | ||
34 | }; | ||
35 | |||
36 | static struct _lcd_scaling_factor lcd_scaling_factor = { | ||
37 | /* LCD Horizontal Scaling Factor Register */ | ||
38 | {LCD_HOR_SCALING_FACTOR_REG_NUM, | ||
39 | {{CR9F, 0, 1}, {CR77, 0, 7}, {CR79, 4, 5} } }, | ||
40 | /* LCD Vertical Scaling Factor Register */ | ||
41 | {LCD_VER_SCALING_FACTOR_REG_NUM, | ||
42 | {{CR79, 3, 3}, {CR78, 0, 7}, {CR79, 6, 7} } } | ||
43 | }; | ||
44 | static struct _lcd_scaling_factor lcd_scaling_factor_CLE = { | ||
45 | /* LCD Horizontal Scaling Factor Register */ | ||
46 | {LCD_HOR_SCALING_FACTOR_REG_NUM_CLE, {{CR77, 0, 7}, {CR79, 4, 5} } }, | ||
47 | /* LCD Vertical Scaling Factor Register */ | ||
48 | {LCD_VER_SCALING_FACTOR_REG_NUM_CLE, {{CR78, 0, 7}, {CR79, 6, 7} } } | ||
49 | }; | ||
50 | |||
51 | static bool lvds_identify_integratedlvds(void); | ||
52 | static void fp_id_to_vindex(int panel_id); | ||
53 | static int lvds_register_read(int index); | ||
54 | static void load_lcd_scaling(int set_hres, int set_vres, int panel_hres, | ||
55 | int panel_vres); | ||
56 | static void lcd_patch_skew_dvp0(struct lvds_setting_information | ||
57 | *plvds_setting_info, | ||
58 | struct lvds_chip_information *plvds_chip_info); | ||
59 | static void lcd_patch_skew_dvp1(struct lvds_setting_information | ||
60 | *plvds_setting_info, | ||
61 | struct lvds_chip_information *plvds_chip_info); | ||
62 | static void lcd_patch_skew(struct lvds_setting_information | ||
63 | *plvds_setting_info, struct lvds_chip_information *plvds_chip_info); | ||
64 | |||
65 | static void integrated_lvds_disable(struct lvds_setting_information | ||
66 | *plvds_setting_info, | ||
67 | struct lvds_chip_information *plvds_chip_info); | ||
68 | static void integrated_lvds_enable(struct lvds_setting_information | ||
69 | *plvds_setting_info, | ||
70 | struct lvds_chip_information *plvds_chip_info); | ||
71 | static void lcd_powersequence_off(void); | ||
72 | static void lcd_powersequence_on(void); | ||
73 | static void fill_lcd_format(void); | ||
74 | static void check_diport_of_integrated_lvds( | ||
75 | struct lvds_chip_information *plvds_chip_info, | ||
76 | struct lvds_setting_information | ||
77 | *plvds_setting_info); | ||
78 | |||
79 | static inline bool check_lvds_chip(int device_id_subaddr, int device_id) | ||
80 | { | ||
81 | return lvds_register_read(device_id_subaddr) == device_id; | ||
82 | } | ||
83 | |||
84 | void viafb_init_lcd_size(void) | ||
85 | { | ||
86 | DEBUG_MSG(KERN_INFO "viafb_init_lcd_size()\n"); | ||
87 | |||
88 | fp_id_to_vindex(viafb_lcd_panel_id); | ||
89 | viaparinfo->lvds_setting_info2->lcd_panel_hres = | ||
90 | viaparinfo->lvds_setting_info->lcd_panel_hres; | ||
91 | viaparinfo->lvds_setting_info2->lcd_panel_vres = | ||
92 | viaparinfo->lvds_setting_info->lcd_panel_vres; | ||
93 | viaparinfo->lvds_setting_info2->device_lcd_dualedge = | ||
94 | viaparinfo->lvds_setting_info->device_lcd_dualedge; | ||
95 | viaparinfo->lvds_setting_info2->LCDDithering = | ||
96 | viaparinfo->lvds_setting_info->LCDDithering; | ||
97 | } | ||
98 | |||
99 | static bool lvds_identify_integratedlvds(void) | ||
100 | { | ||
101 | if (viafb_display_hardware_layout == HW_LAYOUT_LCD_EXTERNAL_LCD2) { | ||
102 | /* Two dual channel LCD (Internal LVDS + External LVDS): */ | ||
103 | /* If we have an external LVDS, such as VT1636, we should | ||
104 | have its chip ID already. */ | ||
105 | if (viaparinfo->chip_info->lvds_chip_info.lvds_chip_name) { | ||
106 | viaparinfo->chip_info->lvds_chip_info2.lvds_chip_name = | ||
107 | INTEGRATED_LVDS; | ||
108 | DEBUG_MSG(KERN_INFO "Support two dual channel LVDS! " | ||
109 | "(Internal LVDS + External LVDS)\n"); | ||
110 | } else { | ||
111 | viaparinfo->chip_info->lvds_chip_info.lvds_chip_name = | ||
112 | INTEGRATED_LVDS; | ||
113 | DEBUG_MSG(KERN_INFO "Not found external LVDS, " | ||
114 | "so can't support two dual channel LVDS!\n"); | ||
115 | } | ||
116 | } else if (viafb_display_hardware_layout == HW_LAYOUT_LCD1_LCD2) { | ||
117 | /* Two single channel LCD (Internal LVDS + Internal LVDS): */ | ||
118 | viaparinfo->chip_info->lvds_chip_info.lvds_chip_name = | ||
119 | INTEGRATED_LVDS; | ||
120 | viaparinfo->chip_info->lvds_chip_info2.lvds_chip_name = | ||
121 | INTEGRATED_LVDS; | ||
122 | DEBUG_MSG(KERN_INFO "Support two single channel LVDS! " | ||
123 | "(Internal LVDS + Internal LVDS)\n"); | ||
124 | } else if (viafb_display_hardware_layout != HW_LAYOUT_DVI_ONLY) { | ||
125 | /* If we have found external LVDS, just use it, | ||
126 | otherwise, we will use internal LVDS as default. */ | ||
127 | if (!viaparinfo->chip_info->lvds_chip_info.lvds_chip_name) { | ||
128 | viaparinfo->chip_info->lvds_chip_info.lvds_chip_name = | ||
129 | INTEGRATED_LVDS; | ||
130 | DEBUG_MSG(KERN_INFO "Found Integrated LVDS!\n"); | ||
131 | } | ||
132 | } else { | ||
133 | viaparinfo->chip_info->lvds_chip_info.lvds_chip_name = | ||
134 | NON_LVDS_TRANSMITTER; | ||
135 | DEBUG_MSG(KERN_INFO "Do not support LVDS!\n"); | ||
136 | return false; | ||
137 | } | ||
138 | |||
139 | return true; | ||
140 | } | ||
141 | |||
142 | bool viafb_lvds_trasmitter_identify(void) | ||
143 | { | ||
144 | if (viafb_lvds_identify_vt1636(VIA_PORT_31)) { | ||
145 | viaparinfo->chip_info->lvds_chip_info.i2c_port = VIA_PORT_31; | ||
146 | DEBUG_MSG(KERN_INFO | ||
147 | "Found VIA VT1636 LVDS on port i2c 0x31\n"); | ||
148 | } else { | ||
149 | if (viafb_lvds_identify_vt1636(VIA_PORT_2C)) { | ||
150 | viaparinfo->chip_info->lvds_chip_info.i2c_port = | ||
151 | VIA_PORT_2C; | ||
152 | DEBUG_MSG(KERN_INFO | ||
153 | "Found VIA VT1636 LVDS on port gpio 0x2c\n"); | ||
154 | } | ||
155 | } | ||
156 | |||
157 | if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CX700) | ||
158 | lvds_identify_integratedlvds(); | ||
159 | |||
160 | if (viaparinfo->chip_info->lvds_chip_info.lvds_chip_name) | ||
161 | return true; | ||
162 | /* Check for VT1631: */ | ||
163 | viaparinfo->chip_info->lvds_chip_info.lvds_chip_name = VT1631_LVDS; | ||
164 | viaparinfo->chip_info->lvds_chip_info.lvds_chip_slave_addr = | ||
165 | VT1631_LVDS_I2C_ADDR; | ||
166 | |||
167 | if (check_lvds_chip(VT1631_DEVICE_ID_REG, VT1631_DEVICE_ID)) { | ||
168 | DEBUG_MSG(KERN_INFO "\n VT1631 LVDS ! \n"); | ||
169 | DEBUG_MSG(KERN_INFO "\n %2d", | ||
170 | viaparinfo->chip_info->lvds_chip_info.lvds_chip_name); | ||
171 | DEBUG_MSG(KERN_INFO "\n %2d", | ||
172 | viaparinfo->chip_info->lvds_chip_info.lvds_chip_name); | ||
173 | return true; | ||
174 | } | ||
175 | |||
176 | viaparinfo->chip_info->lvds_chip_info.lvds_chip_name = | ||
177 | NON_LVDS_TRANSMITTER; | ||
178 | viaparinfo->chip_info->lvds_chip_info.lvds_chip_slave_addr = | ||
179 | VT1631_LVDS_I2C_ADDR; | ||
180 | return false; | ||
181 | } | ||
182 | |||
183 | static void fp_id_to_vindex(int panel_id) | ||
184 | { | ||
185 | DEBUG_MSG(KERN_INFO "fp_get_panel_id()\n"); | ||
186 | |||
187 | if (panel_id > LCD_PANEL_ID_MAXIMUM) | ||
188 | viafb_lcd_panel_id = panel_id = | ||
189 | viafb_read_reg(VIACR, CR3F) & 0x0F; | ||
190 | |||
191 | switch (panel_id) { | ||
192 | case 0x0: | ||
193 | viaparinfo->lvds_setting_info->lcd_panel_hres = 640; | ||
194 | viaparinfo->lvds_setting_info->lcd_panel_vres = 480; | ||
195 | viaparinfo->lvds_setting_info->device_lcd_dualedge = 0; | ||
196 | viaparinfo->lvds_setting_info->LCDDithering = 1; | ||
197 | break; | ||
198 | case 0x1: | ||
199 | viaparinfo->lvds_setting_info->lcd_panel_hres = 800; | ||
200 | viaparinfo->lvds_setting_info->lcd_panel_vres = 600; | ||
201 | viaparinfo->lvds_setting_info->device_lcd_dualedge = 0; | ||
202 | viaparinfo->lvds_setting_info->LCDDithering = 1; | ||
203 | break; | ||
204 | case 0x2: | ||
205 | viaparinfo->lvds_setting_info->lcd_panel_hres = 1024; | ||
206 | viaparinfo->lvds_setting_info->lcd_panel_vres = 768; | ||
207 | viaparinfo->lvds_setting_info->device_lcd_dualedge = 0; | ||
208 | viaparinfo->lvds_setting_info->LCDDithering = 1; | ||
209 | break; | ||
210 | case 0x3: | ||
211 | viaparinfo->lvds_setting_info->lcd_panel_hres = 1280; | ||
212 | viaparinfo->lvds_setting_info->lcd_panel_vres = 768; | ||
213 | viaparinfo->lvds_setting_info->device_lcd_dualedge = 0; | ||
214 | viaparinfo->lvds_setting_info->LCDDithering = 1; | ||
215 | break; | ||
216 | case 0x4: | ||
217 | viaparinfo->lvds_setting_info->lcd_panel_hres = 1280; | ||
218 | viaparinfo->lvds_setting_info->lcd_panel_vres = 1024; | ||
219 | viaparinfo->lvds_setting_info->device_lcd_dualedge = 1; | ||
220 | viaparinfo->lvds_setting_info->LCDDithering = 1; | ||
221 | break; | ||
222 | case 0x5: | ||
223 | viaparinfo->lvds_setting_info->lcd_panel_hres = 1400; | ||
224 | viaparinfo->lvds_setting_info->lcd_panel_vres = 1050; | ||
225 | viaparinfo->lvds_setting_info->device_lcd_dualedge = 1; | ||
226 | viaparinfo->lvds_setting_info->LCDDithering = 1; | ||
227 | break; | ||
228 | case 0x6: | ||
229 | viaparinfo->lvds_setting_info->lcd_panel_hres = 1600; | ||
230 | viaparinfo->lvds_setting_info->lcd_panel_vres = 1200; | ||
231 | viaparinfo->lvds_setting_info->device_lcd_dualedge = 1; | ||
232 | viaparinfo->lvds_setting_info->LCDDithering = 1; | ||
233 | break; | ||
234 | case 0x8: | ||
235 | viaparinfo->lvds_setting_info->lcd_panel_hres = 800; | ||
236 | viaparinfo->lvds_setting_info->lcd_panel_vres = 480; | ||
237 | viaparinfo->lvds_setting_info->device_lcd_dualedge = 0; | ||
238 | viaparinfo->lvds_setting_info->LCDDithering = 1; | ||
239 | break; | ||
240 | case 0x9: | ||
241 | viaparinfo->lvds_setting_info->lcd_panel_hres = 1024; | ||
242 | viaparinfo->lvds_setting_info->lcd_panel_vres = 768; | ||
243 | viaparinfo->lvds_setting_info->device_lcd_dualedge = 1; | ||
244 | viaparinfo->lvds_setting_info->LCDDithering = 1; | ||
245 | break; | ||
246 | case 0xA: | ||
247 | viaparinfo->lvds_setting_info->lcd_panel_hres = 1024; | ||
248 | viaparinfo->lvds_setting_info->lcd_panel_vres = 768; | ||
249 | viaparinfo->lvds_setting_info->device_lcd_dualedge = 0; | ||
250 | viaparinfo->lvds_setting_info->LCDDithering = 0; | ||
251 | break; | ||
252 | case 0xB: | ||
253 | viaparinfo->lvds_setting_info->lcd_panel_hres = 1024; | ||
254 | viaparinfo->lvds_setting_info->lcd_panel_vres = 768; | ||
255 | viaparinfo->lvds_setting_info->device_lcd_dualedge = 1; | ||
256 | viaparinfo->lvds_setting_info->LCDDithering = 0; | ||
257 | break; | ||
258 | case 0xC: | ||
259 | viaparinfo->lvds_setting_info->lcd_panel_hres = 1280; | ||
260 | viaparinfo->lvds_setting_info->lcd_panel_vres = 768; | ||
261 | viaparinfo->lvds_setting_info->device_lcd_dualedge = 0; | ||
262 | viaparinfo->lvds_setting_info->LCDDithering = 0; | ||
263 | break; | ||
264 | case 0xD: | ||
265 | viaparinfo->lvds_setting_info->lcd_panel_hres = 1280; | ||
266 | viaparinfo->lvds_setting_info->lcd_panel_vres = 1024; | ||
267 | viaparinfo->lvds_setting_info->device_lcd_dualedge = 1; | ||
268 | viaparinfo->lvds_setting_info->LCDDithering = 0; | ||
269 | break; | ||
270 | case 0xE: | ||
271 | viaparinfo->lvds_setting_info->lcd_panel_hres = 1400; | ||
272 | viaparinfo->lvds_setting_info->lcd_panel_vres = 1050; | ||
273 | viaparinfo->lvds_setting_info->device_lcd_dualedge = 1; | ||
274 | viaparinfo->lvds_setting_info->LCDDithering = 0; | ||
275 | break; | ||
276 | case 0xF: | ||
277 | viaparinfo->lvds_setting_info->lcd_panel_hres = 1600; | ||
278 | viaparinfo->lvds_setting_info->lcd_panel_vres = 1200; | ||
279 | viaparinfo->lvds_setting_info->device_lcd_dualedge = 1; | ||
280 | viaparinfo->lvds_setting_info->LCDDithering = 0; | ||
281 | break; | ||
282 | case 0x10: | ||
283 | viaparinfo->lvds_setting_info->lcd_panel_hres = 1366; | ||
284 | viaparinfo->lvds_setting_info->lcd_panel_vres = 768; | ||
285 | viaparinfo->lvds_setting_info->device_lcd_dualedge = 0; | ||
286 | viaparinfo->lvds_setting_info->LCDDithering = 0; | ||
287 | break; | ||
288 | case 0x11: | ||
289 | viaparinfo->lvds_setting_info->lcd_panel_hres = 1024; | ||
290 | viaparinfo->lvds_setting_info->lcd_panel_vres = 600; | ||
291 | viaparinfo->lvds_setting_info->device_lcd_dualedge = 0; | ||
292 | viaparinfo->lvds_setting_info->LCDDithering = 1; | ||
293 | break; | ||
294 | case 0x12: | ||
295 | viaparinfo->lvds_setting_info->lcd_panel_hres = 1280; | ||
296 | viaparinfo->lvds_setting_info->lcd_panel_vres = 768; | ||
297 | viaparinfo->lvds_setting_info->device_lcd_dualedge = 1; | ||
298 | viaparinfo->lvds_setting_info->LCDDithering = 1; | ||
299 | break; | ||
300 | case 0x13: | ||
301 | viaparinfo->lvds_setting_info->lcd_panel_hres = 1280; | ||
302 | viaparinfo->lvds_setting_info->lcd_panel_vres = 800; | ||
303 | viaparinfo->lvds_setting_info->device_lcd_dualedge = 0; | ||
304 | viaparinfo->lvds_setting_info->LCDDithering = 1; | ||
305 | break; | ||
306 | case 0x14: | ||
307 | viaparinfo->lvds_setting_info->lcd_panel_hres = 1360; | ||
308 | viaparinfo->lvds_setting_info->lcd_panel_vres = 768; | ||
309 | viaparinfo->lvds_setting_info->device_lcd_dualedge = 0; | ||
310 | viaparinfo->lvds_setting_info->LCDDithering = 0; | ||
311 | break; | ||
312 | case 0x15: | ||
313 | viaparinfo->lvds_setting_info->lcd_panel_hres = 1280; | ||
314 | viaparinfo->lvds_setting_info->lcd_panel_vres = 768; | ||
315 | viaparinfo->lvds_setting_info->device_lcd_dualedge = 1; | ||
316 | viaparinfo->lvds_setting_info->LCDDithering = 0; | ||
317 | break; | ||
318 | case 0x16: | ||
319 | viaparinfo->lvds_setting_info->lcd_panel_hres = 480; | ||
320 | viaparinfo->lvds_setting_info->lcd_panel_vres = 640; | ||
321 | viaparinfo->lvds_setting_info->device_lcd_dualedge = 0; | ||
322 | viaparinfo->lvds_setting_info->LCDDithering = 1; | ||
323 | break; | ||
324 | case 0x17: | ||
325 | /* OLPC XO-1.5 panel */ | ||
326 | viaparinfo->lvds_setting_info->lcd_panel_hres = 1200; | ||
327 | viaparinfo->lvds_setting_info->lcd_panel_vres = 900; | ||
328 | viaparinfo->lvds_setting_info->device_lcd_dualedge = 0; | ||
329 | viaparinfo->lvds_setting_info->LCDDithering = 0; | ||
330 | break; | ||
331 | default: | ||
332 | viaparinfo->lvds_setting_info->lcd_panel_hres = 800; | ||
333 | viaparinfo->lvds_setting_info->lcd_panel_vres = 600; | ||
334 | viaparinfo->lvds_setting_info->device_lcd_dualedge = 0; | ||
335 | viaparinfo->lvds_setting_info->LCDDithering = 1; | ||
336 | } | ||
337 | } | ||
338 | |||
339 | static int lvds_register_read(int index) | ||
340 | { | ||
341 | u8 data; | ||
342 | |||
343 | viafb_i2c_readbyte(VIA_PORT_2C, | ||
344 | (u8) viaparinfo->chip_info->lvds_chip_info.lvds_chip_slave_addr, | ||
345 | (u8) index, &data); | ||
346 | return data; | ||
347 | } | ||
348 | |||
349 | static void load_lcd_scaling(int set_hres, int set_vres, int panel_hres, | ||
350 | int panel_vres) | ||
351 | { | ||
352 | int reg_value = 0; | ||
353 | int viafb_load_reg_num; | ||
354 | struct io_register *reg = NULL; | ||
355 | |||
356 | DEBUG_MSG(KERN_INFO "load_lcd_scaling()!!\n"); | ||
357 | |||
358 | /* LCD Scaling Enable */ | ||
359 | viafb_write_reg_mask(CR79, VIACR, 0x07, BIT0 + BIT1 + BIT2); | ||
360 | |||
361 | /* Check if expansion for horizontal */ | ||
362 | if (set_hres < panel_hres) { | ||
363 | /* Load Horizontal Scaling Factor */ | ||
364 | switch (viaparinfo->chip_info->gfx_chip_name) { | ||
365 | case UNICHROME_CLE266: | ||
366 | case UNICHROME_K400: | ||
367 | reg_value = | ||
368 | CLE266_LCD_HOR_SCF_FORMULA(set_hres, panel_hres); | ||
369 | viafb_load_reg_num = | ||
370 | lcd_scaling_factor_CLE.lcd_hor_scaling_factor. | ||
371 | reg_num; | ||
372 | reg = lcd_scaling_factor_CLE.lcd_hor_scaling_factor.reg; | ||
373 | viafb_load_reg(reg_value, | ||
374 | viafb_load_reg_num, reg, VIACR); | ||
375 | break; | ||
376 | case UNICHROME_K800: | ||
377 | case UNICHROME_PM800: | ||
378 | case UNICHROME_CN700: | ||
379 | case UNICHROME_CX700: | ||
380 | case UNICHROME_K8M890: | ||
381 | case UNICHROME_P4M890: | ||
382 | case UNICHROME_P4M900: | ||
383 | case UNICHROME_CN750: | ||
384 | case UNICHROME_VX800: | ||
385 | case UNICHROME_VX855: | ||
386 | case UNICHROME_VX900: | ||
387 | reg_value = | ||
388 | K800_LCD_HOR_SCF_FORMULA(set_hres, panel_hres); | ||
389 | /* Horizontal scaling enabled */ | ||
390 | viafb_write_reg_mask(CRA2, VIACR, 0xC0, BIT7 + BIT6); | ||
391 | viafb_load_reg_num = | ||
392 | lcd_scaling_factor.lcd_hor_scaling_factor.reg_num; | ||
393 | reg = lcd_scaling_factor.lcd_hor_scaling_factor.reg; | ||
394 | viafb_load_reg(reg_value, | ||
395 | viafb_load_reg_num, reg, VIACR); | ||
396 | break; | ||
397 | } | ||
398 | |||
399 | DEBUG_MSG(KERN_INFO "Horizontal Scaling value = %d", reg_value); | ||
400 | } else { | ||
401 | /* Horizontal scaling disabled */ | ||
402 | viafb_write_reg_mask(CRA2, VIACR, 0x00, BIT7); | ||
403 | } | ||
404 | |||
405 | /* Check if expansion for vertical */ | ||
406 | if (set_vres < panel_vres) { | ||
407 | /* Load Vertical Scaling Factor */ | ||
408 | switch (viaparinfo->chip_info->gfx_chip_name) { | ||
409 | case UNICHROME_CLE266: | ||
410 | case UNICHROME_K400: | ||
411 | reg_value = | ||
412 | CLE266_LCD_VER_SCF_FORMULA(set_vres, panel_vres); | ||
413 | viafb_load_reg_num = | ||
414 | lcd_scaling_factor_CLE.lcd_ver_scaling_factor. | ||
415 | reg_num; | ||
416 | reg = lcd_scaling_factor_CLE.lcd_ver_scaling_factor.reg; | ||
417 | viafb_load_reg(reg_value, | ||
418 | viafb_load_reg_num, reg, VIACR); | ||
419 | break; | ||
420 | case UNICHROME_K800: | ||
421 | case UNICHROME_PM800: | ||
422 | case UNICHROME_CN700: | ||
423 | case UNICHROME_CX700: | ||
424 | case UNICHROME_K8M890: | ||
425 | case UNICHROME_P4M890: | ||
426 | case UNICHROME_P4M900: | ||
427 | case UNICHROME_CN750: | ||
428 | case UNICHROME_VX800: | ||
429 | case UNICHROME_VX855: | ||
430 | case UNICHROME_VX900: | ||
431 | reg_value = | ||
432 | K800_LCD_VER_SCF_FORMULA(set_vres, panel_vres); | ||
433 | /* Vertical scaling enabled */ | ||
434 | viafb_write_reg_mask(CRA2, VIACR, 0x08, BIT3); | ||
435 | viafb_load_reg_num = | ||
436 | lcd_scaling_factor.lcd_ver_scaling_factor.reg_num; | ||
437 | reg = lcd_scaling_factor.lcd_ver_scaling_factor.reg; | ||
438 | viafb_load_reg(reg_value, | ||
439 | viafb_load_reg_num, reg, VIACR); | ||
440 | break; | ||
441 | } | ||
442 | |||
443 | DEBUG_MSG(KERN_INFO "Vertical Scaling value = %d", reg_value); | ||
444 | } else { | ||
445 | /* Vertical scaling disabled */ | ||
446 | viafb_write_reg_mask(CRA2, VIACR, 0x00, BIT3); | ||
447 | } | ||
448 | } | ||
449 | |||
450 | static void via_pitch_alignment_patch_lcd(int iga_path, int hres, int bpp) | ||
451 | { | ||
452 | unsigned char cr13, cr35, cr65, cr66, cr67; | ||
453 | unsigned long dwScreenPitch = 0; | ||
454 | unsigned long dwPitch; | ||
455 | |||
456 | dwPitch = hres * (bpp >> 3); | ||
457 | if (dwPitch & 0x1F) { | ||
458 | dwScreenPitch = ((dwPitch + 31) & ~31) >> 3; | ||
459 | if (iga_path == IGA2) { | ||
460 | if (bpp > 8) { | ||
461 | cr66 = (unsigned char)(dwScreenPitch & 0xFF); | ||
462 | viafb_write_reg(CR66, VIACR, cr66); | ||
463 | cr67 = viafb_read_reg(VIACR, CR67) & 0xFC; | ||
464 | cr67 |= | ||
465 | (unsigned | ||
466 | char)((dwScreenPitch & 0x300) >> 8); | ||
467 | viafb_write_reg(CR67, VIACR, cr67); | ||
468 | } | ||
469 | |||
470 | /* Fetch Count */ | ||
471 | cr67 = viafb_read_reg(VIACR, CR67) & 0xF3; | ||
472 | cr67 |= (unsigned char)((dwScreenPitch & 0x600) >> 7); | ||
473 | viafb_write_reg(CR67, VIACR, cr67); | ||
474 | cr65 = (unsigned char)((dwScreenPitch >> 1) & 0xFF); | ||
475 | cr65 += 2; | ||
476 | viafb_write_reg(CR65, VIACR, cr65); | ||
477 | } else { | ||
478 | if (bpp > 8) { | ||
479 | cr13 = (unsigned char)(dwScreenPitch & 0xFF); | ||
480 | viafb_write_reg(CR13, VIACR, cr13); | ||
481 | cr35 = viafb_read_reg(VIACR, CR35) & 0x1F; | ||
482 | cr35 |= | ||
483 | (unsigned | ||
484 | char)((dwScreenPitch & 0x700) >> 3); | ||
485 | viafb_write_reg(CR35, VIACR, cr35); | ||
486 | } | ||
487 | } | ||
488 | } | ||
489 | } | ||
490 | static void lcd_patch_skew_dvp0(struct lvds_setting_information | ||
491 | *plvds_setting_info, | ||
492 | struct lvds_chip_information *plvds_chip_info) | ||
493 | { | ||
494 | if (VT1636_LVDS == plvds_chip_info->lvds_chip_name) { | ||
495 | switch (viaparinfo->chip_info->gfx_chip_name) { | ||
496 | case UNICHROME_P4M900: | ||
497 | viafb_vt1636_patch_skew_on_vt3364(plvds_setting_info, | ||
498 | plvds_chip_info); | ||
499 | break; | ||
500 | case UNICHROME_P4M890: | ||
501 | viafb_vt1636_patch_skew_on_vt3327(plvds_setting_info, | ||
502 | plvds_chip_info); | ||
503 | break; | ||
504 | } | ||
505 | } | ||
506 | } | ||
507 | static void lcd_patch_skew_dvp1(struct lvds_setting_information | ||
508 | *plvds_setting_info, | ||
509 | struct lvds_chip_information *plvds_chip_info) | ||
510 | { | ||
511 | if (VT1636_LVDS == plvds_chip_info->lvds_chip_name) { | ||
512 | switch (viaparinfo->chip_info->gfx_chip_name) { | ||
513 | case UNICHROME_CX700: | ||
514 | viafb_vt1636_patch_skew_on_vt3324(plvds_setting_info, | ||
515 | plvds_chip_info); | ||
516 | break; | ||
517 | } | ||
518 | } | ||
519 | } | ||
520 | static void lcd_patch_skew(struct lvds_setting_information | ||
521 | *plvds_setting_info, struct lvds_chip_information *plvds_chip_info) | ||
522 | { | ||
523 | DEBUG_MSG(KERN_INFO "lcd_patch_skew\n"); | ||
524 | switch (plvds_chip_info->output_interface) { | ||
525 | case INTERFACE_DVP0: | ||
526 | lcd_patch_skew_dvp0(plvds_setting_info, plvds_chip_info); | ||
527 | break; | ||
528 | case INTERFACE_DVP1: | ||
529 | lcd_patch_skew_dvp1(plvds_setting_info, plvds_chip_info); | ||
530 | break; | ||
531 | case INTERFACE_DFP_LOW: | ||
532 | if (UNICHROME_P4M900 == viaparinfo->chip_info->gfx_chip_name) { | ||
533 | viafb_write_reg_mask(CR99, VIACR, 0x08, | ||
534 | BIT0 + BIT1 + BIT2 + BIT3); | ||
535 | } | ||
536 | break; | ||
537 | } | ||
538 | } | ||
539 | |||
540 | /* LCD Set Mode */ | ||
541 | void viafb_lcd_set_mode(const struct fb_var_screeninfo *var, u16 cxres, | ||
542 | u16 cyres, struct lvds_setting_information *plvds_setting_info, | ||
543 | struct lvds_chip_information *plvds_chip_info) | ||
544 | { | ||
545 | int set_iga = plvds_setting_info->iga_path; | ||
546 | int mode_bpp = var->bits_per_pixel; | ||
547 | int set_hres = cxres ? cxres : var->xres; | ||
548 | int set_vres = cyres ? cyres : var->yres; | ||
549 | int panel_hres = plvds_setting_info->lcd_panel_hres; | ||
550 | int panel_vres = plvds_setting_info->lcd_panel_vres; | ||
551 | u32 clock; | ||
552 | struct via_display_timing timing; | ||
553 | struct fb_var_screeninfo panel_var; | ||
554 | const struct fb_videomode *mode_crt_table, *panel_crt_table; | ||
555 | |||
556 | DEBUG_MSG(KERN_INFO "viafb_lcd_set_mode!!\n"); | ||
557 | /* Get mode table */ | ||
558 | mode_crt_table = viafb_get_best_mode(set_hres, set_vres, 60); | ||
559 | /* Get panel table Pointer */ | ||
560 | panel_crt_table = viafb_get_best_mode(panel_hres, panel_vres, 60); | ||
561 | viafb_fill_var_timing_info(&panel_var, panel_crt_table); | ||
562 | DEBUG_MSG(KERN_INFO "bellow viafb_lcd_set_mode!!\n"); | ||
563 | if (VT1636_LVDS == plvds_chip_info->lvds_chip_name) | ||
564 | viafb_init_lvds_vt1636(plvds_setting_info, plvds_chip_info); | ||
565 | clock = PICOS2KHZ(panel_crt_table->pixclock) * 1000; | ||
566 | plvds_setting_info->vclk = clock; | ||
567 | |||
568 | if (set_iga == IGA2 && (set_hres < panel_hres || set_vres < panel_vres) | ||
569 | && plvds_setting_info->display_method == LCD_EXPANDSION) { | ||
570 | timing = var_to_timing(&panel_var, panel_hres, panel_vres); | ||
571 | load_lcd_scaling(set_hres, set_vres, panel_hres, panel_vres); | ||
572 | } else { | ||
573 | timing = var_to_timing(&panel_var, set_hres, set_vres); | ||
574 | if (set_iga == IGA2) | ||
575 | /* disable scaling */ | ||
576 | via_write_reg_mask(VIACR, 0x79, 0x00, | ||
577 | BIT0 + BIT1 + BIT2); | ||
578 | } | ||
579 | |||
580 | if (set_iga == IGA1) | ||
581 | via_set_primary_timing(&timing); | ||
582 | else if (set_iga == IGA2) | ||
583 | via_set_secondary_timing(&timing); | ||
584 | |||
585 | /* Fetch count for IGA2 only */ | ||
586 | viafb_load_fetch_count_reg(set_hres, mode_bpp / 8, set_iga); | ||
587 | |||
588 | if ((viaparinfo->chip_info->gfx_chip_name != UNICHROME_CLE266) | ||
589 | && (viaparinfo->chip_info->gfx_chip_name != UNICHROME_K400)) | ||
590 | viafb_load_FIFO_reg(set_iga, set_hres, set_vres); | ||
591 | |||
592 | fill_lcd_format(); | ||
593 | viafb_set_vclock(clock, set_iga); | ||
594 | lcd_patch_skew(plvds_setting_info, plvds_chip_info); | ||
595 | |||
596 | /* If K8M800, enable LCD Prefetch Mode. */ | ||
597 | if ((viaparinfo->chip_info->gfx_chip_name == UNICHROME_K800) | ||
598 | || (UNICHROME_K8M890 == viaparinfo->chip_info->gfx_chip_name)) | ||
599 | viafb_write_reg_mask(CR6A, VIACR, 0x01, BIT0); | ||
600 | |||
601 | /* Patch for non 32bit alignment mode */ | ||
602 | via_pitch_alignment_patch_lcd(plvds_setting_info->iga_path, set_hres, | ||
603 | var->bits_per_pixel); | ||
604 | } | ||
605 | |||
606 | static void integrated_lvds_disable(struct lvds_setting_information | ||
607 | *plvds_setting_info, | ||
608 | struct lvds_chip_information *plvds_chip_info) | ||
609 | { | ||
610 | bool turn_off_first_powersequence = false; | ||
611 | bool turn_off_second_powersequence = false; | ||
612 | if (INTERFACE_LVDS0LVDS1 == plvds_chip_info->output_interface) | ||
613 | turn_off_first_powersequence = true; | ||
614 | if (INTERFACE_LVDS0 == plvds_chip_info->output_interface) | ||
615 | turn_off_first_powersequence = true; | ||
616 | if (INTERFACE_LVDS1 == plvds_chip_info->output_interface) | ||
617 | turn_off_second_powersequence = true; | ||
618 | if (turn_off_second_powersequence) { | ||
619 | /* Use second power sequence control: */ | ||
620 | |||
621 | /* Turn off power sequence. */ | ||
622 | viafb_write_reg_mask(CRD4, VIACR, 0, BIT1); | ||
623 | |||
624 | /* Turn off back light. */ | ||
625 | viafb_write_reg_mask(CRD3, VIACR, 0xC0, BIT6 + BIT7); | ||
626 | } | ||
627 | if (turn_off_first_powersequence) { | ||
628 | /* Use first power sequence control: */ | ||
629 | |||
630 | /* Turn off power sequence. */ | ||
631 | viafb_write_reg_mask(CR6A, VIACR, 0, BIT3); | ||
632 | |||
633 | /* Turn off back light. */ | ||
634 | viafb_write_reg_mask(CR91, VIACR, 0xC0, BIT6 + BIT7); | ||
635 | } | ||
636 | |||
637 | /* Power off LVDS channel. */ | ||
638 | switch (plvds_chip_info->output_interface) { | ||
639 | case INTERFACE_LVDS0: | ||
640 | { | ||
641 | viafb_write_reg_mask(CRD2, VIACR, 0x80, BIT7); | ||
642 | break; | ||
643 | } | ||
644 | |||
645 | case INTERFACE_LVDS1: | ||
646 | { | ||
647 | viafb_write_reg_mask(CRD2, VIACR, 0x40, BIT6); | ||
648 | break; | ||
649 | } | ||
650 | |||
651 | case INTERFACE_LVDS0LVDS1: | ||
652 | { | ||
653 | viafb_write_reg_mask(CRD2, VIACR, 0xC0, BIT6 + BIT7); | ||
654 | break; | ||
655 | } | ||
656 | } | ||
657 | } | ||
658 | |||
659 | static void integrated_lvds_enable(struct lvds_setting_information | ||
660 | *plvds_setting_info, | ||
661 | struct lvds_chip_information *plvds_chip_info) | ||
662 | { | ||
663 | DEBUG_MSG(KERN_INFO "integrated_lvds_enable, out_interface:%d\n", | ||
664 | plvds_chip_info->output_interface); | ||
665 | if (plvds_setting_info->lcd_mode == LCD_SPWG) | ||
666 | viafb_write_reg_mask(CRD2, VIACR, 0x00, BIT0 + BIT1); | ||
667 | else | ||
668 | viafb_write_reg_mask(CRD2, VIACR, 0x03, BIT0 + BIT1); | ||
669 | |||
670 | switch (plvds_chip_info->output_interface) { | ||
671 | case INTERFACE_LVDS0LVDS1: | ||
672 | case INTERFACE_LVDS0: | ||
673 | /* Use first power sequence control: */ | ||
674 | /* Use hardware control power sequence. */ | ||
675 | viafb_write_reg_mask(CR91, VIACR, 0, BIT0); | ||
676 | /* Turn on back light. */ | ||
677 | viafb_write_reg_mask(CR91, VIACR, 0, BIT6 + BIT7); | ||
678 | /* Turn on hardware power sequence. */ | ||
679 | viafb_write_reg_mask(CR6A, VIACR, 0x08, BIT3); | ||
680 | break; | ||
681 | case INTERFACE_LVDS1: | ||
682 | /* Use second power sequence control: */ | ||
683 | /* Use hardware control power sequence. */ | ||
684 | viafb_write_reg_mask(CRD3, VIACR, 0, BIT0); | ||
685 | /* Turn on back light. */ | ||
686 | viafb_write_reg_mask(CRD3, VIACR, 0, BIT6 + BIT7); | ||
687 | /* Turn on hardware power sequence. */ | ||
688 | viafb_write_reg_mask(CRD4, VIACR, 0x02, BIT1); | ||
689 | break; | ||
690 | } | ||
691 | |||
692 | /* Power on LVDS channel. */ | ||
693 | switch (plvds_chip_info->output_interface) { | ||
694 | case INTERFACE_LVDS0: | ||
695 | { | ||
696 | viafb_write_reg_mask(CRD2, VIACR, 0, BIT7); | ||
697 | break; | ||
698 | } | ||
699 | |||
700 | case INTERFACE_LVDS1: | ||
701 | { | ||
702 | viafb_write_reg_mask(CRD2, VIACR, 0, BIT6); | ||
703 | break; | ||
704 | } | ||
705 | |||
706 | case INTERFACE_LVDS0LVDS1: | ||
707 | { | ||
708 | viafb_write_reg_mask(CRD2, VIACR, 0, BIT6 + BIT7); | ||
709 | break; | ||
710 | } | ||
711 | } | ||
712 | } | ||
713 | |||
714 | void viafb_lcd_disable(void) | ||
715 | { | ||
716 | |||
717 | if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266) { | ||
718 | lcd_powersequence_off(); | ||
719 | /* DI1 pad off */ | ||
720 | viafb_write_reg_mask(SR1E, VIASR, 0x00, 0x30); | ||
721 | } else if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CX700) { | ||
722 | if (viafb_LCD2_ON | ||
723 | && (INTEGRATED_LVDS == | ||
724 | viaparinfo->chip_info->lvds_chip_info2.lvds_chip_name)) | ||
725 | integrated_lvds_disable(viaparinfo->lvds_setting_info, | ||
726 | &viaparinfo->chip_info->lvds_chip_info2); | ||
727 | if (INTEGRATED_LVDS == | ||
728 | viaparinfo->chip_info->lvds_chip_info.lvds_chip_name) | ||
729 | integrated_lvds_disable(viaparinfo->lvds_setting_info, | ||
730 | &viaparinfo->chip_info->lvds_chip_info); | ||
731 | if (VT1636_LVDS == viaparinfo->chip_info-> | ||
732 | lvds_chip_info.lvds_chip_name) | ||
733 | viafb_disable_lvds_vt1636(viaparinfo->lvds_setting_info, | ||
734 | &viaparinfo->chip_info->lvds_chip_info); | ||
735 | } else if (VT1636_LVDS == | ||
736 | viaparinfo->chip_info->lvds_chip_info.lvds_chip_name) { | ||
737 | viafb_disable_lvds_vt1636(viaparinfo->lvds_setting_info, | ||
738 | &viaparinfo->chip_info->lvds_chip_info); | ||
739 | } else { | ||
740 | /* Backlight off */ | ||
741 | viafb_write_reg_mask(SR3D, VIASR, 0x00, 0x20); | ||
742 | /* 24 bit DI data paht off */ | ||
743 | viafb_write_reg_mask(CR91, VIACR, 0x80, 0x80); | ||
744 | } | ||
745 | |||
746 | /* Disable expansion bit */ | ||
747 | viafb_write_reg_mask(CR79, VIACR, 0x00, 0x01); | ||
748 | /* Simultaneout disabled */ | ||
749 | viafb_write_reg_mask(CR6B, VIACR, 0x00, 0x08); | ||
750 | } | ||
751 | |||
752 | static void set_lcd_output_path(int set_iga, int output_interface) | ||
753 | { | ||
754 | switch (output_interface) { | ||
755 | case INTERFACE_DFP: | ||
756 | if ((UNICHROME_K8M890 == viaparinfo->chip_info->gfx_chip_name) | ||
757 | || (UNICHROME_P4M890 == | ||
758 | viaparinfo->chip_info->gfx_chip_name)) | ||
759 | viafb_write_reg_mask(CR97, VIACR, 0x84, | ||
760 | BIT7 + BIT2 + BIT1 + BIT0); | ||
761 | case INTERFACE_DVP0: | ||
762 | case INTERFACE_DVP1: | ||
763 | case INTERFACE_DFP_HIGH: | ||
764 | case INTERFACE_DFP_LOW: | ||
765 | if (set_iga == IGA2) | ||
766 | viafb_write_reg(CR91, VIACR, 0x00); | ||
767 | break; | ||
768 | } | ||
769 | } | ||
770 | |||
771 | void viafb_lcd_enable(void) | ||
772 | { | ||
773 | viafb_write_reg_mask(CR6B, VIACR, 0x00, BIT3); | ||
774 | viafb_write_reg_mask(CR6A, VIACR, 0x08, BIT3); | ||
775 | set_lcd_output_path(viaparinfo->lvds_setting_info->iga_path, | ||
776 | viaparinfo->chip_info->lvds_chip_info.output_interface); | ||
777 | if (viafb_LCD2_ON) | ||
778 | set_lcd_output_path(viaparinfo->lvds_setting_info2->iga_path, | ||
779 | viaparinfo->chip_info-> | ||
780 | lvds_chip_info2.output_interface); | ||
781 | |||
782 | if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266) { | ||
783 | /* DI1 pad on */ | ||
784 | viafb_write_reg_mask(SR1E, VIASR, 0x30, 0x30); | ||
785 | lcd_powersequence_on(); | ||
786 | } else if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CX700) { | ||
787 | if (viafb_LCD2_ON && (INTEGRATED_LVDS == | ||
788 | viaparinfo->chip_info->lvds_chip_info2.lvds_chip_name)) | ||
789 | integrated_lvds_enable(viaparinfo->lvds_setting_info2, \ | ||
790 | &viaparinfo->chip_info->lvds_chip_info2); | ||
791 | if (INTEGRATED_LVDS == | ||
792 | viaparinfo->chip_info->lvds_chip_info.lvds_chip_name) | ||
793 | integrated_lvds_enable(viaparinfo->lvds_setting_info, | ||
794 | &viaparinfo->chip_info->lvds_chip_info); | ||
795 | if (VT1636_LVDS == viaparinfo->chip_info-> | ||
796 | lvds_chip_info.lvds_chip_name) | ||
797 | viafb_enable_lvds_vt1636(viaparinfo-> | ||
798 | lvds_setting_info, &viaparinfo->chip_info-> | ||
799 | lvds_chip_info); | ||
800 | } else if (VT1636_LVDS == | ||
801 | viaparinfo->chip_info->lvds_chip_info.lvds_chip_name) { | ||
802 | viafb_enable_lvds_vt1636(viaparinfo->lvds_setting_info, | ||
803 | &viaparinfo->chip_info->lvds_chip_info); | ||
804 | } else { | ||
805 | /* Backlight on */ | ||
806 | viafb_write_reg_mask(SR3D, VIASR, 0x20, 0x20); | ||
807 | /* 24 bit DI data paht on */ | ||
808 | viafb_write_reg_mask(CR91, VIACR, 0x00, 0x80); | ||
809 | /* LCD enabled */ | ||
810 | viafb_write_reg_mask(CR6A, VIACR, 0x48, 0x48); | ||
811 | } | ||
812 | } | ||
813 | |||
814 | static void lcd_powersequence_off(void) | ||
815 | { | ||
816 | int i, mask, data; | ||
817 | |||
818 | /* Software control power sequence */ | ||
819 | viafb_write_reg_mask(CR91, VIACR, 0x11, 0x11); | ||
820 | |||
821 | for (i = 0; i < 3; i++) { | ||
822 | mask = PowerSequenceOff[0][i]; | ||
823 | data = PowerSequenceOff[1][i] & mask; | ||
824 | viafb_write_reg_mask(CR91, VIACR, (u8) data, (u8) mask); | ||
825 | udelay(PowerSequenceOff[2][i]); | ||
826 | } | ||
827 | |||
828 | /* Disable LCD */ | ||
829 | viafb_write_reg_mask(CR6A, VIACR, 0x00, 0x08); | ||
830 | } | ||
831 | |||
832 | static void lcd_powersequence_on(void) | ||
833 | { | ||
834 | int i, mask, data; | ||
835 | |||
836 | /* Software control power sequence */ | ||
837 | viafb_write_reg_mask(CR91, VIACR, 0x11, 0x11); | ||
838 | |||
839 | /* Enable LCD */ | ||
840 | viafb_write_reg_mask(CR6A, VIACR, 0x08, 0x08); | ||
841 | |||
842 | for (i = 0; i < 3; i++) { | ||
843 | mask = PowerSequenceOn[0][i]; | ||
844 | data = PowerSequenceOn[1][i] & mask; | ||
845 | viafb_write_reg_mask(CR91, VIACR, (u8) data, (u8) mask); | ||
846 | udelay(PowerSequenceOn[2][i]); | ||
847 | } | ||
848 | |||
849 | udelay(1); | ||
850 | } | ||
851 | |||
852 | static void fill_lcd_format(void) | ||
853 | { | ||
854 | u8 bdithering = 0, bdual = 0; | ||
855 | |||
856 | if (viaparinfo->lvds_setting_info->device_lcd_dualedge) | ||
857 | bdual = BIT4; | ||
858 | if (viaparinfo->lvds_setting_info->LCDDithering) | ||
859 | bdithering = BIT0; | ||
860 | /* Dual & Dithering */ | ||
861 | viafb_write_reg_mask(CR88, VIACR, (bdithering | bdual), BIT4 + BIT0); | ||
862 | } | ||
863 | |||
864 | static void check_diport_of_integrated_lvds( | ||
865 | struct lvds_chip_information *plvds_chip_info, | ||
866 | struct lvds_setting_information | ||
867 | *plvds_setting_info) | ||
868 | { | ||
869 | /* Determine LCD DI Port by hardware layout. */ | ||
870 | switch (viafb_display_hardware_layout) { | ||
871 | case HW_LAYOUT_LCD_ONLY: | ||
872 | { | ||
873 | if (plvds_setting_info->device_lcd_dualedge) { | ||
874 | plvds_chip_info->output_interface = | ||
875 | INTERFACE_LVDS0LVDS1; | ||
876 | } else { | ||
877 | plvds_chip_info->output_interface = | ||
878 | INTERFACE_LVDS0; | ||
879 | } | ||
880 | |||
881 | break; | ||
882 | } | ||
883 | |||
884 | case HW_LAYOUT_DVI_ONLY: | ||
885 | { | ||
886 | plvds_chip_info->output_interface = INTERFACE_NONE; | ||
887 | break; | ||
888 | } | ||
889 | |||
890 | case HW_LAYOUT_LCD1_LCD2: | ||
891 | case HW_LAYOUT_LCD_EXTERNAL_LCD2: | ||
892 | { | ||
893 | plvds_chip_info->output_interface = | ||
894 | INTERFACE_LVDS0LVDS1; | ||
895 | break; | ||
896 | } | ||
897 | |||
898 | case HW_LAYOUT_LCD_DVI: | ||
899 | { | ||
900 | plvds_chip_info->output_interface = INTERFACE_LVDS1; | ||
901 | break; | ||
902 | } | ||
903 | |||
904 | default: | ||
905 | { | ||
906 | plvds_chip_info->output_interface = INTERFACE_LVDS1; | ||
907 | break; | ||
908 | } | ||
909 | } | ||
910 | |||
911 | DEBUG_MSG(KERN_INFO | ||
912 | "Display Hardware Layout: 0x%x, LCD DI Port: 0x%x\n", | ||
913 | viafb_display_hardware_layout, | ||
914 | plvds_chip_info->output_interface); | ||
915 | } | ||
916 | |||
917 | void viafb_init_lvds_output_interface(struct lvds_chip_information | ||
918 | *plvds_chip_info, | ||
919 | struct lvds_setting_information | ||
920 | *plvds_setting_info) | ||
921 | { | ||
922 | if (INTERFACE_NONE != plvds_chip_info->output_interface) { | ||
923 | /*Do nothing, lcd port is specified by module parameter */ | ||
924 | return; | ||
925 | } | ||
926 | |||
927 | switch (plvds_chip_info->lvds_chip_name) { | ||
928 | |||
929 | case VT1636_LVDS: | ||
930 | switch (viaparinfo->chip_info->gfx_chip_name) { | ||
931 | case UNICHROME_CX700: | ||
932 | plvds_chip_info->output_interface = INTERFACE_DVP1; | ||
933 | break; | ||
934 | case UNICHROME_CN700: | ||
935 | plvds_chip_info->output_interface = INTERFACE_DFP_LOW; | ||
936 | break; | ||
937 | default: | ||
938 | plvds_chip_info->output_interface = INTERFACE_DVP0; | ||
939 | break; | ||
940 | } | ||
941 | break; | ||
942 | |||
943 | case INTEGRATED_LVDS: | ||
944 | check_diport_of_integrated_lvds(plvds_chip_info, | ||
945 | plvds_setting_info); | ||
946 | break; | ||
947 | |||
948 | default: | ||
949 | switch (viaparinfo->chip_info->gfx_chip_name) { | ||
950 | case UNICHROME_K8M890: | ||
951 | case UNICHROME_P4M900: | ||
952 | case UNICHROME_P4M890: | ||
953 | plvds_chip_info->output_interface = INTERFACE_DFP_LOW; | ||
954 | break; | ||
955 | default: | ||
956 | plvds_chip_info->output_interface = INTERFACE_DFP; | ||
957 | break; | ||
958 | } | ||
959 | break; | ||
960 | } | ||
961 | } | ||
962 | |||
963 | bool viafb_lcd_get_mobile_state(bool *mobile) | ||
964 | { | ||
965 | unsigned char __iomem *romptr, *tableptr, *biosptr; | ||
966 | u8 core_base; | ||
967 | /* Rom address */ | ||
968 | const u32 romaddr = 0x000C0000; | ||
969 | u16 start_pattern; | ||
970 | |||
971 | biosptr = ioremap(romaddr, 0x10000); | ||
972 | start_pattern = readw(biosptr); | ||
973 | |||
974 | /* Compare pattern */ | ||
975 | if (start_pattern == 0xAA55) { | ||
976 | /* Get the start of Table */ | ||
977 | /* 0x1B means BIOS offset position */ | ||
978 | romptr = biosptr + 0x1B; | ||
979 | tableptr = biosptr + readw(romptr); | ||
980 | |||
981 | /* Get the start of biosver structure */ | ||
982 | /* 18 means BIOS version position. */ | ||
983 | romptr = tableptr + 18; | ||
984 | romptr = biosptr + readw(romptr); | ||
985 | |||
986 | /* The offset should be 44, but the | ||
987 | actual image is less three char. */ | ||
988 | /* pRom += 44; */ | ||
989 | romptr += 41; | ||
990 | |||
991 | core_base = readb(romptr); | ||
992 | |||
993 | if (core_base & 0x8) | ||
994 | *mobile = false; | ||
995 | else | ||
996 | *mobile = true; | ||
997 | /* release memory */ | ||
998 | iounmap(biosptr); | ||
999 | |||
1000 | return true; | ||
1001 | } else { | ||
1002 | iounmap(biosptr); | ||
1003 | return false; | ||
1004 | } | ||
1005 | } | ||