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