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