blob: 3e083ff67ae20b458704f89c1a56ceab061d2278 [file] [log] [blame]
Joseph Chand61e0bf2008-10-15 22:03:23 -07001/*
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
22#include "global.h"
23
Joseph Chand61e0bf2008-10-15 22:03:23 -070024static struct pll_map pll_value[] = {
Harald Welte0306ab12009-09-22 16:47:35 -070025 {CLK_25_175M, CLE266_PLL_25_175M, K800_PLL_25_175M,
26 CX700_25_175M, VX855_25_175M},
27 {CLK_29_581M, CLE266_PLL_29_581M, K800_PLL_29_581M,
28 CX700_29_581M, VX855_29_581M},
29 {CLK_26_880M, CLE266_PLL_26_880M, K800_PLL_26_880M,
30 CX700_26_880M, VX855_26_880M},
31 {CLK_31_490M, CLE266_PLL_31_490M, K800_PLL_31_490M,
32 CX700_31_490M, VX855_31_490M},
33 {CLK_31_500M, CLE266_PLL_31_500M, K800_PLL_31_500M,
34 CX700_31_500M, VX855_31_500M},
35 {CLK_31_728M, CLE266_PLL_31_728M, K800_PLL_31_728M,
36 CX700_31_728M, VX855_31_728M},
37 {CLK_32_668M, CLE266_PLL_32_668M, K800_PLL_32_668M,
38 CX700_32_668M, VX855_32_668M},
39 {CLK_36_000M, CLE266_PLL_36_000M, K800_PLL_36_000M,
40 CX700_36_000M, VX855_36_000M},
41 {CLK_40_000M, CLE266_PLL_40_000M, K800_PLL_40_000M,
42 CX700_40_000M, VX855_40_000M},
43 {CLK_41_291M, CLE266_PLL_41_291M, K800_PLL_41_291M,
44 CX700_41_291M, VX855_41_291M},
45 {CLK_43_163M, CLE266_PLL_43_163M, K800_PLL_43_163M,
46 CX700_43_163M, VX855_43_163M},
47 {CLK_45_250M, CLE266_PLL_45_250M, K800_PLL_45_250M,
48 CX700_45_250M, VX855_45_250M},
49 {CLK_46_000M, CLE266_PLL_46_000M, K800_PLL_46_000M,
50 CX700_46_000M, VX855_46_000M},
51 {CLK_46_996M, CLE266_PLL_46_996M, K800_PLL_46_996M,
52 CX700_46_996M, VX855_46_996M},
53 {CLK_48_000M, CLE266_PLL_48_000M, K800_PLL_48_000M,
54 CX700_48_000M, VX855_48_000M},
55 {CLK_48_875M, CLE266_PLL_48_875M, K800_PLL_48_875M,
56 CX700_48_875M, VX855_48_875M},
57 {CLK_49_500M, CLE266_PLL_49_500M, K800_PLL_49_500M,
58 CX700_49_500M, VX855_49_500M},
59 {CLK_52_406M, CLE266_PLL_52_406M, K800_PLL_52_406M,
60 CX700_52_406M, VX855_52_406M},
61 {CLK_52_977M, CLE266_PLL_52_977M, K800_PLL_52_977M,
62 CX700_52_977M, VX855_52_977M},
63 {CLK_56_250M, CLE266_PLL_56_250M, K800_PLL_56_250M,
64 CX700_56_250M, VX855_56_250M},
65 {CLK_60_466M, CLE266_PLL_60_466M, K800_PLL_60_466M,
66 CX700_60_466M, VX855_60_466M},
67 {CLK_61_500M, CLE266_PLL_61_500M, K800_PLL_61_500M,
68 CX700_61_500M, VX855_61_500M},
69 {CLK_65_000M, CLE266_PLL_65_000M, K800_PLL_65_000M,
70 CX700_65_000M, VX855_65_000M},
71 {CLK_65_178M, CLE266_PLL_65_178M, K800_PLL_65_178M,
72 CX700_65_178M, VX855_65_178M},
73 {CLK_66_750M, CLE266_PLL_66_750M, K800_PLL_66_750M,
74 CX700_66_750M, VX855_66_750M},
75 {CLK_68_179M, CLE266_PLL_68_179M, K800_PLL_68_179M,
76 CX700_68_179M, VX855_68_179M},
77 {CLK_69_924M, CLE266_PLL_69_924M, K800_PLL_69_924M,
78 CX700_69_924M, VX855_69_924M},
79 {CLK_70_159M, CLE266_PLL_70_159M, K800_PLL_70_159M,
80 CX700_70_159M, VX855_70_159M},
81 {CLK_72_000M, CLE266_PLL_72_000M, K800_PLL_72_000M,
82 CX700_72_000M, VX855_72_000M},
83 {CLK_78_750M, CLE266_PLL_78_750M, K800_PLL_78_750M,
84 CX700_78_750M, VX855_78_750M},
85 {CLK_80_136M, CLE266_PLL_80_136M, K800_PLL_80_136M,
86 CX700_80_136M, VX855_80_136M},
87 {CLK_83_375M, CLE266_PLL_83_375M, K800_PLL_83_375M,
88 CX700_83_375M, VX855_83_375M},
89 {CLK_83_950M, CLE266_PLL_83_950M, K800_PLL_83_950M,
90 CX700_83_950M, VX855_83_950M},
91 {CLK_84_750M, CLE266_PLL_84_750M, K800_PLL_84_750M,
92 CX700_84_750M, VX855_84_750M},
93 {CLK_85_860M, CLE266_PLL_85_860M, K800_PLL_85_860M,
94 CX700_85_860M, VX855_85_860M},
95 {CLK_88_750M, CLE266_PLL_88_750M, K800_PLL_88_750M,
96 CX700_88_750M, VX855_88_750M},
97 {CLK_94_500M, CLE266_PLL_94_500M, K800_PLL_94_500M,
98 CX700_94_500M, VX855_94_500M},
99 {CLK_97_750M, CLE266_PLL_97_750M, K800_PLL_97_750M,
100 CX700_97_750M, VX855_97_750M},
Joseph Chand61e0bf2008-10-15 22:03:23 -0700101 {CLK_101_000M, CLE266_PLL_101_000M, K800_PLL_101_000M,
Harald Welte0306ab12009-09-22 16:47:35 -0700102 CX700_101_000M, VX855_101_000M},
Joseph Chand61e0bf2008-10-15 22:03:23 -0700103 {CLK_106_500M, CLE266_PLL_106_500M, K800_PLL_106_500M,
Harald Welte0306ab12009-09-22 16:47:35 -0700104 CX700_106_500M, VX855_106_500M},
Joseph Chand61e0bf2008-10-15 22:03:23 -0700105 {CLK_108_000M, CLE266_PLL_108_000M, K800_PLL_108_000M,
Harald Welte0306ab12009-09-22 16:47:35 -0700106 CX700_108_000M, VX855_108_000M},
Joseph Chand61e0bf2008-10-15 22:03:23 -0700107 {CLK_113_309M, CLE266_PLL_113_309M, K800_PLL_113_309M,
Harald Welte0306ab12009-09-22 16:47:35 -0700108 CX700_113_309M, VX855_113_309M},
Joseph Chand61e0bf2008-10-15 22:03:23 -0700109 {CLK_118_840M, CLE266_PLL_118_840M, K800_PLL_118_840M,
Harald Welte0306ab12009-09-22 16:47:35 -0700110 CX700_118_840M, VX855_118_840M},
Joseph Chand61e0bf2008-10-15 22:03:23 -0700111 {CLK_119_000M, CLE266_PLL_119_000M, K800_PLL_119_000M,
Harald Welte0306ab12009-09-22 16:47:35 -0700112 CX700_119_000M, VX855_119_000M},
Joseph Chand61e0bf2008-10-15 22:03:23 -0700113 {CLK_121_750M, CLE266_PLL_121_750M, K800_PLL_121_750M,
Harald Welte0306ab12009-09-22 16:47:35 -0700114 CX700_121_750M, 0},
Joseph Chand61e0bf2008-10-15 22:03:23 -0700115 {CLK_125_104M, CLE266_PLL_125_104M, K800_PLL_125_104M,
Harald Welte0306ab12009-09-22 16:47:35 -0700116 CX700_125_104M, 0},
Joseph Chand61e0bf2008-10-15 22:03:23 -0700117 {CLK_133_308M, CLE266_PLL_133_308M, K800_PLL_133_308M,
Harald Welte0306ab12009-09-22 16:47:35 -0700118 CX700_133_308M, 0},
Joseph Chand61e0bf2008-10-15 22:03:23 -0700119 {CLK_135_000M, CLE266_PLL_135_000M, K800_PLL_135_000M,
Harald Welte0306ab12009-09-22 16:47:35 -0700120 CX700_135_000M, VX855_135_000M},
Joseph Chand61e0bf2008-10-15 22:03:23 -0700121 {CLK_136_700M, CLE266_PLL_136_700M, K800_PLL_136_700M,
Harald Welte0306ab12009-09-22 16:47:35 -0700122 CX700_136_700M, VX855_136_700M},
Joseph Chand61e0bf2008-10-15 22:03:23 -0700123 {CLK_138_400M, CLE266_PLL_138_400M, K800_PLL_138_400M,
Harald Welte0306ab12009-09-22 16:47:35 -0700124 CX700_138_400M, VX855_138_400M},
Joseph Chand61e0bf2008-10-15 22:03:23 -0700125 {CLK_146_760M, CLE266_PLL_146_760M, K800_PLL_146_760M,
Harald Welte0306ab12009-09-22 16:47:35 -0700126 CX700_146_760M, VX855_146_760M},
Joseph Chand61e0bf2008-10-15 22:03:23 -0700127 {CLK_153_920M, CLE266_PLL_153_920M, K800_PLL_153_920M,
Harald Welte0306ab12009-09-22 16:47:35 -0700128 CX700_153_920M, VX855_153_920M},
Joseph Chand61e0bf2008-10-15 22:03:23 -0700129 {CLK_156_000M, CLE266_PLL_156_000M, K800_PLL_156_000M,
Harald Welte0306ab12009-09-22 16:47:35 -0700130 CX700_156_000M, VX855_156_000M},
Joseph Chand61e0bf2008-10-15 22:03:23 -0700131 {CLK_157_500M, CLE266_PLL_157_500M, K800_PLL_157_500M,
Harald Welte0306ab12009-09-22 16:47:35 -0700132 CX700_157_500M, VX855_157_500M},
Joseph Chand61e0bf2008-10-15 22:03:23 -0700133 {CLK_162_000M, CLE266_PLL_162_000M, K800_PLL_162_000M,
Harald Welte0306ab12009-09-22 16:47:35 -0700134 CX700_162_000M, VX855_162_000M},
Joseph Chand61e0bf2008-10-15 22:03:23 -0700135 {CLK_187_000M, CLE266_PLL_187_000M, K800_PLL_187_000M,
Harald Welte0306ab12009-09-22 16:47:35 -0700136 CX700_187_000M, VX855_187_000M},
Joseph Chand61e0bf2008-10-15 22:03:23 -0700137 {CLK_193_295M, CLE266_PLL_193_295M, K800_PLL_193_295M,
Harald Welte0306ab12009-09-22 16:47:35 -0700138 CX700_193_295M, VX855_193_295M},
Joseph Chand61e0bf2008-10-15 22:03:23 -0700139 {CLK_202_500M, CLE266_PLL_202_500M, K800_PLL_202_500M,
Harald Welte0306ab12009-09-22 16:47:35 -0700140 CX700_202_500M, VX855_202_500M},
Joseph Chand61e0bf2008-10-15 22:03:23 -0700141 {CLK_204_000M, CLE266_PLL_204_000M, K800_PLL_204_000M,
Harald Welte0306ab12009-09-22 16:47:35 -0700142 CX700_204_000M, VX855_204_000M},
Joseph Chand61e0bf2008-10-15 22:03:23 -0700143 {CLK_218_500M, CLE266_PLL_218_500M, K800_PLL_218_500M,
Harald Welte0306ab12009-09-22 16:47:35 -0700144 CX700_218_500M, VX855_218_500M},
Joseph Chand61e0bf2008-10-15 22:03:23 -0700145 {CLK_234_000M, CLE266_PLL_234_000M, K800_PLL_234_000M,
Harald Welte0306ab12009-09-22 16:47:35 -0700146 CX700_234_000M, VX855_234_000M},
Joseph Chand61e0bf2008-10-15 22:03:23 -0700147 {CLK_267_250M, CLE266_PLL_267_250M, K800_PLL_267_250M,
Harald Welte0306ab12009-09-22 16:47:35 -0700148 CX700_267_250M, VX855_267_250M},
Joseph Chand61e0bf2008-10-15 22:03:23 -0700149 {CLK_297_500M, CLE266_PLL_297_500M, K800_PLL_297_500M,
Harald Welte0306ab12009-09-22 16:47:35 -0700150 CX700_297_500M, VX855_297_500M},
151 {CLK_74_481M, CLE266_PLL_74_481M, K800_PLL_74_481M,
152 CX700_74_481M, VX855_74_481M},
Joseph Chand61e0bf2008-10-15 22:03:23 -0700153 {CLK_172_798M, CLE266_PLL_172_798M, K800_PLL_172_798M,
Harald Welte0306ab12009-09-22 16:47:35 -0700154 CX700_172_798M, VX855_172_798M},
Joseph Chand61e0bf2008-10-15 22:03:23 -0700155 {CLK_122_614M, CLE266_PLL_122_614M, K800_PLL_122_614M,
Harald Welte0306ab12009-09-22 16:47:35 -0700156 CX700_122_614M, VX855_122_614M},
157 {CLK_74_270M, CLE266_PLL_74_270M, K800_PLL_74_270M,
158 CX700_74_270M, 0},
Joseph Chand61e0bf2008-10-15 22:03:23 -0700159 {CLK_148_500M, CLE266_PLL_148_500M, K800_PLL_148_500M,
Harald Welte0306ab12009-09-22 16:47:35 -0700160 CX700_148_500M, VX855_148_500M}
Joseph Chand61e0bf2008-10-15 22:03:23 -0700161};
162
163static struct fifo_depth_select display_fifo_depth_reg = {
164 /* IGA1 FIFO Depth_Select */
165 {IGA1_FIFO_DEPTH_SELECT_REG_NUM, {{SR17, 0, 7} } },
166 /* IGA2 FIFO Depth_Select */
167 {IGA2_FIFO_DEPTH_SELECT_REG_NUM,
168 {{CR68, 4, 7}, {CR94, 7, 7}, {CR95, 7, 7} } }
169};
170
171static struct fifo_threshold_select fifo_threshold_select_reg = {
172 /* IGA1 FIFO Threshold Select */
173 {IGA1_FIFO_THRESHOLD_REG_NUM, {{SR16, 0, 5}, {SR16, 7, 7} } },
174 /* IGA2 FIFO Threshold Select */
175 {IGA2_FIFO_THRESHOLD_REG_NUM, {{CR68, 0, 3}, {CR95, 4, 6} } }
176};
177
178static struct fifo_high_threshold_select fifo_high_threshold_select_reg = {
179 /* IGA1 FIFO High Threshold Select */
180 {IGA1_FIFO_HIGH_THRESHOLD_REG_NUM, {{SR18, 0, 5}, {SR18, 7, 7} } },
181 /* IGA2 FIFO High Threshold Select */
182 {IGA2_FIFO_HIGH_THRESHOLD_REG_NUM, {{CR92, 0, 3}, {CR95, 0, 2} } }
183};
184
185static struct display_queue_expire_num display_queue_expire_num_reg = {
186 /* IGA1 Display Queue Expire Num */
187 {IGA1_DISPLAY_QUEUE_EXPIRE_NUM_REG_NUM, {{SR22, 0, 4} } },
188 /* IGA2 Display Queue Expire Num */
189 {IGA2_DISPLAY_QUEUE_EXPIRE_NUM_REG_NUM, {{CR94, 0, 6} } }
190};
191
192/* Definition Fetch Count Registers*/
193static struct fetch_count fetch_count_reg = {
194 /* IGA1 Fetch Count Register */
195 {IGA1_FETCH_COUNT_REG_NUM, {{SR1C, 0, 7}, {SR1D, 0, 1} } },
196 /* IGA2 Fetch Count Register */
197 {IGA2_FETCH_COUNT_REG_NUM, {{CR65, 0, 7}, {CR67, 2, 3} } }
198};
199
200static struct iga1_crtc_timing iga1_crtc_reg = {
201 /* IGA1 Horizontal Total */
202 {IGA1_HOR_TOTAL_REG_NUM, {{CR00, 0, 7}, {CR36, 3, 3} } },
203 /* IGA1 Horizontal Addressable Video */
204 {IGA1_HOR_ADDR_REG_NUM, {{CR01, 0, 7} } },
205 /* IGA1 Horizontal Blank Start */
206 {IGA1_HOR_BLANK_START_REG_NUM, {{CR02, 0, 7} } },
207 /* IGA1 Horizontal Blank End */
208 {IGA1_HOR_BLANK_END_REG_NUM,
209 {{CR03, 0, 4}, {CR05, 7, 7}, {CR33, 5, 5} } },
210 /* IGA1 Horizontal Sync Start */
211 {IGA1_HOR_SYNC_START_REG_NUM, {{CR04, 0, 7}, {CR33, 4, 4} } },
212 /* IGA1 Horizontal Sync End */
213 {IGA1_HOR_SYNC_END_REG_NUM, {{CR05, 0, 4} } },
214 /* IGA1 Vertical Total */
215 {IGA1_VER_TOTAL_REG_NUM,
216 {{CR06, 0, 7}, {CR07, 0, 0}, {CR07, 5, 5}, {CR35, 0, 0} } },
217 /* IGA1 Vertical Addressable Video */
218 {IGA1_VER_ADDR_REG_NUM,
219 {{CR12, 0, 7}, {CR07, 1, 1}, {CR07, 6, 6}, {CR35, 2, 2} } },
220 /* IGA1 Vertical Blank Start */
221 {IGA1_VER_BLANK_START_REG_NUM,
222 {{CR15, 0, 7}, {CR07, 3, 3}, {CR09, 5, 5}, {CR35, 3, 3} } },
223 /* IGA1 Vertical Blank End */
224 {IGA1_VER_BLANK_END_REG_NUM, {{CR16, 0, 7} } },
225 /* IGA1 Vertical Sync Start */
226 {IGA1_VER_SYNC_START_REG_NUM,
227 {{CR10, 0, 7}, {CR07, 2, 2}, {CR07, 7, 7}, {CR35, 1, 1} } },
228 /* IGA1 Vertical Sync End */
229 {IGA1_VER_SYNC_END_REG_NUM, {{CR11, 0, 3} } }
230};
231
232static struct iga2_crtc_timing iga2_crtc_reg = {
233 /* IGA2 Horizontal Total */
234 {IGA2_HOR_TOTAL_REG_NUM, {{CR50, 0, 7}, {CR55, 0, 3} } },
235 /* IGA2 Horizontal Addressable Video */
236 {IGA2_HOR_ADDR_REG_NUM, {{CR51, 0, 7}, {CR55, 4, 6} } },
237 /* IGA2 Horizontal Blank Start */
238 {IGA2_HOR_BLANK_START_REG_NUM, {{CR52, 0, 7}, {CR54, 0, 2} } },
239 /* IGA2 Horizontal Blank End */
240 {IGA2_HOR_BLANK_END_REG_NUM,
241 {{CR53, 0, 7}, {CR54, 3, 5}, {CR5D, 6, 6} } },
242 /* IGA2 Horizontal Sync Start */
243 {IGA2_HOR_SYNC_START_REG_NUM,
244 {{CR56, 0, 7}, {CR54, 6, 7}, {CR5C, 7, 7}, {CR5D, 7, 7} } },
245 /* IGA2 Horizontal Sync End */
246 {IGA2_HOR_SYNC_END_REG_NUM, {{CR57, 0, 7}, {CR5C, 6, 6} } },
247 /* IGA2 Vertical Total */
248 {IGA2_VER_TOTAL_REG_NUM, {{CR58, 0, 7}, {CR5D, 0, 2} } },
249 /* IGA2 Vertical Addressable Video */
250 {IGA2_VER_ADDR_REG_NUM, {{CR59, 0, 7}, {CR5D, 3, 5} } },
251 /* IGA2 Vertical Blank Start */
252 {IGA2_VER_BLANK_START_REG_NUM, {{CR5A, 0, 7}, {CR5C, 0, 2} } },
253 /* IGA2 Vertical Blank End */
254 {IGA2_VER_BLANK_END_REG_NUM, {{CR5B, 0, 7}, {CR5C, 3, 5} } },
255 /* IGA2 Vertical Sync Start */
256 {IGA2_VER_SYNC_START_REG_NUM, {{CR5E, 0, 7}, {CR5F, 5, 7} } },
257 /* IGA2 Vertical Sync End */
258 {IGA2_VER_SYNC_END_REG_NUM, {{CR5F, 0, 4} } }
259};
260
261static struct rgbLUT palLUT_table[] = {
262 /* {R,G,B} */
263 /* Index 0x00~0x03 */
264 {0x00, 0x00, 0x00}, {0x00, 0x00, 0x2A}, {0x00, 0x2A, 0x00}, {0x00,
265 0x2A,
266 0x2A},
267 /* Index 0x04~0x07 */
268 {0x2A, 0x00, 0x00}, {0x2A, 0x00, 0x2A}, {0x2A, 0x15, 0x00}, {0x2A,
269 0x2A,
270 0x2A},
271 /* Index 0x08~0x0B */
272 {0x15, 0x15, 0x15}, {0x15, 0x15, 0x3F}, {0x15, 0x3F, 0x15}, {0x15,
273 0x3F,
274 0x3F},
275 /* Index 0x0C~0x0F */
276 {0x3F, 0x15, 0x15}, {0x3F, 0x15, 0x3F}, {0x3F, 0x3F, 0x15}, {0x3F,
277 0x3F,
278 0x3F},
279 /* Index 0x10~0x13 */
280 {0x00, 0x00, 0x00}, {0x05, 0x05, 0x05}, {0x08, 0x08, 0x08}, {0x0B,
281 0x0B,
282 0x0B},
283 /* Index 0x14~0x17 */
284 {0x0E, 0x0E, 0x0E}, {0x11, 0x11, 0x11}, {0x14, 0x14, 0x14}, {0x18,
285 0x18,
286 0x18},
287 /* Index 0x18~0x1B */
288 {0x1C, 0x1C, 0x1C}, {0x20, 0x20, 0x20}, {0x24, 0x24, 0x24}, {0x28,
289 0x28,
290 0x28},
291 /* Index 0x1C~0x1F */
292 {0x2D, 0x2D, 0x2D}, {0x32, 0x32, 0x32}, {0x38, 0x38, 0x38}, {0x3F,
293 0x3F,
294 0x3F},
295 /* Index 0x20~0x23 */
296 {0x00, 0x00, 0x3F}, {0x10, 0x00, 0x3F}, {0x1F, 0x00, 0x3F}, {0x2F,
297 0x00,
298 0x3F},
299 /* Index 0x24~0x27 */
300 {0x3F, 0x00, 0x3F}, {0x3F, 0x00, 0x2F}, {0x3F, 0x00, 0x1F}, {0x3F,
301 0x00,
302 0x10},
303 /* Index 0x28~0x2B */
304 {0x3F, 0x00, 0x00}, {0x3F, 0x10, 0x00}, {0x3F, 0x1F, 0x00}, {0x3F,
305 0x2F,
306 0x00},
307 /* Index 0x2C~0x2F */
308 {0x3F, 0x3F, 0x00}, {0x2F, 0x3F, 0x00}, {0x1F, 0x3F, 0x00}, {0x10,
309 0x3F,
310 0x00},
311 /* Index 0x30~0x33 */
312 {0x00, 0x3F, 0x00}, {0x00, 0x3F, 0x10}, {0x00, 0x3F, 0x1F}, {0x00,
313 0x3F,
314 0x2F},
315 /* Index 0x34~0x37 */
316 {0x00, 0x3F, 0x3F}, {0x00, 0x2F, 0x3F}, {0x00, 0x1F, 0x3F}, {0x00,
317 0x10,
318 0x3F},
319 /* Index 0x38~0x3B */
320 {0x1F, 0x1F, 0x3F}, {0x27, 0x1F, 0x3F}, {0x2F, 0x1F, 0x3F}, {0x37,
321 0x1F,
322 0x3F},
323 /* Index 0x3C~0x3F */
324 {0x3F, 0x1F, 0x3F}, {0x3F, 0x1F, 0x37}, {0x3F, 0x1F, 0x2F}, {0x3F,
325 0x1F,
326 0x27},
327 /* Index 0x40~0x43 */
328 {0x3F, 0x1F, 0x1F}, {0x3F, 0x27, 0x1F}, {0x3F, 0x2F, 0x1F}, {0x3F,
329 0x3F,
330 0x1F},
331 /* Index 0x44~0x47 */
332 {0x3F, 0x3F, 0x1F}, {0x37, 0x3F, 0x1F}, {0x2F, 0x3F, 0x1F}, {0x27,
333 0x3F,
334 0x1F},
335 /* Index 0x48~0x4B */
336 {0x1F, 0x3F, 0x1F}, {0x1F, 0x3F, 0x27}, {0x1F, 0x3F, 0x2F}, {0x1F,
337 0x3F,
338 0x37},
339 /* Index 0x4C~0x4F */
340 {0x1F, 0x3F, 0x3F}, {0x1F, 0x37, 0x3F}, {0x1F, 0x2F, 0x3F}, {0x1F,
341 0x27,
342 0x3F},
343 /* Index 0x50~0x53 */
344 {0x2D, 0x2D, 0x3F}, {0x31, 0x2D, 0x3F}, {0x36, 0x2D, 0x3F}, {0x3A,
345 0x2D,
346 0x3F},
347 /* Index 0x54~0x57 */
348 {0x3F, 0x2D, 0x3F}, {0x3F, 0x2D, 0x3A}, {0x3F, 0x2D, 0x36}, {0x3F,
349 0x2D,
350 0x31},
351 /* Index 0x58~0x5B */
352 {0x3F, 0x2D, 0x2D}, {0x3F, 0x31, 0x2D}, {0x3F, 0x36, 0x2D}, {0x3F,
353 0x3A,
354 0x2D},
355 /* Index 0x5C~0x5F */
356 {0x3F, 0x3F, 0x2D}, {0x3A, 0x3F, 0x2D}, {0x36, 0x3F, 0x2D}, {0x31,
357 0x3F,
358 0x2D},
359 /* Index 0x60~0x63 */
360 {0x2D, 0x3F, 0x2D}, {0x2D, 0x3F, 0x31}, {0x2D, 0x3F, 0x36}, {0x2D,
361 0x3F,
362 0x3A},
363 /* Index 0x64~0x67 */
364 {0x2D, 0x3F, 0x3F}, {0x2D, 0x3A, 0x3F}, {0x2D, 0x36, 0x3F}, {0x2D,
365 0x31,
366 0x3F},
367 /* Index 0x68~0x6B */
368 {0x00, 0x00, 0x1C}, {0x07, 0x00, 0x1C}, {0x0E, 0x00, 0x1C}, {0x15,
369 0x00,
370 0x1C},
371 /* Index 0x6C~0x6F */
372 {0x1C, 0x00, 0x1C}, {0x1C, 0x00, 0x15}, {0x1C, 0x00, 0x0E}, {0x1C,
373 0x00,
374 0x07},
375 /* Index 0x70~0x73 */
376 {0x1C, 0x00, 0x00}, {0x1C, 0x07, 0x00}, {0x1C, 0x0E, 0x00}, {0x1C,
377 0x15,
378 0x00},
379 /* Index 0x74~0x77 */
380 {0x1C, 0x1C, 0x00}, {0x15, 0x1C, 0x00}, {0x0E, 0x1C, 0x00}, {0x07,
381 0x1C,
382 0x00},
383 /* Index 0x78~0x7B */
384 {0x00, 0x1C, 0x00}, {0x00, 0x1C, 0x07}, {0x00, 0x1C, 0x0E}, {0x00,
385 0x1C,
386 0x15},
387 /* Index 0x7C~0x7F */
388 {0x00, 0x1C, 0x1C}, {0x00, 0x15, 0x1C}, {0x00, 0x0E, 0x1C}, {0x00,
389 0x07,
390 0x1C},
391 /* Index 0x80~0x83 */
392 {0x0E, 0x0E, 0x1C}, {0x11, 0x0E, 0x1C}, {0x15, 0x0E, 0x1C}, {0x18,
393 0x0E,
394 0x1C},
395 /* Index 0x84~0x87 */
396 {0x1C, 0x0E, 0x1C}, {0x1C, 0x0E, 0x18}, {0x1C, 0x0E, 0x15}, {0x1C,
397 0x0E,
398 0x11},
399 /* Index 0x88~0x8B */
400 {0x1C, 0x0E, 0x0E}, {0x1C, 0x11, 0x0E}, {0x1C, 0x15, 0x0E}, {0x1C,
401 0x18,
402 0x0E},
403 /* Index 0x8C~0x8F */
404 {0x1C, 0x1C, 0x0E}, {0x18, 0x1C, 0x0E}, {0x15, 0x1C, 0x0E}, {0x11,
405 0x1C,
406 0x0E},
407 /* Index 0x90~0x93 */
408 {0x0E, 0x1C, 0x0E}, {0x0E, 0x1C, 0x11}, {0x0E, 0x1C, 0x15}, {0x0E,
409 0x1C,
410 0x18},
411 /* Index 0x94~0x97 */
412 {0x0E, 0x1C, 0x1C}, {0x0E, 0x18, 0x1C}, {0x0E, 0x15, 0x1C}, {0x0E,
413 0x11,
414 0x1C},
415 /* Index 0x98~0x9B */
416 {0x14, 0x14, 0x1C}, {0x16, 0x14, 0x1C}, {0x18, 0x14, 0x1C}, {0x1A,
417 0x14,
418 0x1C},
419 /* Index 0x9C~0x9F */
420 {0x1C, 0x14, 0x1C}, {0x1C, 0x14, 0x1A}, {0x1C, 0x14, 0x18}, {0x1C,
421 0x14,
422 0x16},
423 /* Index 0xA0~0xA3 */
424 {0x1C, 0x14, 0x14}, {0x1C, 0x16, 0x14}, {0x1C, 0x18, 0x14}, {0x1C,
425 0x1A,
426 0x14},
427 /* Index 0xA4~0xA7 */
428 {0x1C, 0x1C, 0x14}, {0x1A, 0x1C, 0x14}, {0x18, 0x1C, 0x14}, {0x16,
429 0x1C,
430 0x14},
431 /* Index 0xA8~0xAB */
432 {0x14, 0x1C, 0x14}, {0x14, 0x1C, 0x16}, {0x14, 0x1C, 0x18}, {0x14,
433 0x1C,
434 0x1A},
435 /* Index 0xAC~0xAF */
436 {0x14, 0x1C, 0x1C}, {0x14, 0x1A, 0x1C}, {0x14, 0x18, 0x1C}, {0x14,
437 0x16,
438 0x1C},
439 /* Index 0xB0~0xB3 */
440 {0x00, 0x00, 0x10}, {0x04, 0x00, 0x10}, {0x08, 0x00, 0x10}, {0x0C,
441 0x00,
442 0x10},
443 /* Index 0xB4~0xB7 */
444 {0x10, 0x00, 0x10}, {0x10, 0x00, 0x0C}, {0x10, 0x00, 0x08}, {0x10,
445 0x00,
446 0x04},
447 /* Index 0xB8~0xBB */
448 {0x10, 0x00, 0x00}, {0x10, 0x04, 0x00}, {0x10, 0x08, 0x00}, {0x10,
449 0x0C,
450 0x00},
451 /* Index 0xBC~0xBF */
452 {0x10, 0x10, 0x00}, {0x0C, 0x10, 0x00}, {0x08, 0x10, 0x00}, {0x04,
453 0x10,
454 0x00},
455 /* Index 0xC0~0xC3 */
456 {0x00, 0x10, 0x00}, {0x00, 0x10, 0x04}, {0x00, 0x10, 0x08}, {0x00,
457 0x10,
458 0x0C},
459 /* Index 0xC4~0xC7 */
460 {0x00, 0x10, 0x10}, {0x00, 0x0C, 0x10}, {0x00, 0x08, 0x10}, {0x00,
461 0x04,
462 0x10},
463 /* Index 0xC8~0xCB */
464 {0x08, 0x08, 0x10}, {0x0A, 0x08, 0x10}, {0x0C, 0x08, 0x10}, {0x0E,
465 0x08,
466 0x10},
467 /* Index 0xCC~0xCF */
468 {0x10, 0x08, 0x10}, {0x10, 0x08, 0x0E}, {0x10, 0x08, 0x0C}, {0x10,
469 0x08,
470 0x0A},
471 /* Index 0xD0~0xD3 */
472 {0x10, 0x08, 0x08}, {0x10, 0x0A, 0x08}, {0x10, 0x0C, 0x08}, {0x10,
473 0x0E,
474 0x08},
475 /* Index 0xD4~0xD7 */
476 {0x10, 0x10, 0x08}, {0x0E, 0x10, 0x08}, {0x0C, 0x10, 0x08}, {0x0A,
477 0x10,
478 0x08},
479 /* Index 0xD8~0xDB */
480 {0x08, 0x10, 0x08}, {0x08, 0x10, 0x0A}, {0x08, 0x10, 0x0C}, {0x08,
481 0x10,
482 0x0E},
483 /* Index 0xDC~0xDF */
484 {0x08, 0x10, 0x10}, {0x08, 0x0E, 0x10}, {0x08, 0x0C, 0x10}, {0x08,
485 0x0A,
486 0x10},
487 /* Index 0xE0~0xE3 */
488 {0x0B, 0x0B, 0x10}, {0x0C, 0x0B, 0x10}, {0x0D, 0x0B, 0x10}, {0x0F,
489 0x0B,
490 0x10},
491 /* Index 0xE4~0xE7 */
492 {0x10, 0x0B, 0x10}, {0x10, 0x0B, 0x0F}, {0x10, 0x0B, 0x0D}, {0x10,
493 0x0B,
494 0x0C},
495 /* Index 0xE8~0xEB */
496 {0x10, 0x0B, 0x0B}, {0x10, 0x0C, 0x0B}, {0x10, 0x0D, 0x0B}, {0x10,
497 0x0F,
498 0x0B},
499 /* Index 0xEC~0xEF */
500 {0x10, 0x10, 0x0B}, {0x0F, 0x10, 0x0B}, {0x0D, 0x10, 0x0B}, {0x0C,
501 0x10,
502 0x0B},
503 /* Index 0xF0~0xF3 */
504 {0x0B, 0x10, 0x0B}, {0x0B, 0x10, 0x0C}, {0x0B, 0x10, 0x0D}, {0x0B,
505 0x10,
506 0x0F},
507 /* Index 0xF4~0xF7 */
508 {0x0B, 0x10, 0x10}, {0x0B, 0x0F, 0x10}, {0x0B, 0x0D, 0x10}, {0x0B,
509 0x0C,
510 0x10},
511 /* Index 0xF8~0xFB */
512 {0x00, 0x00, 0x00}, {0x00, 0x00, 0x00}, {0x00, 0x00, 0x00}, {0x00,
513 0x00,
514 0x00},
515 /* Index 0xFC~0xFF */
516 {0x00, 0x00, 0x00}, {0x00, 0x00, 0x00}, {0x00, 0x00, 0x00}, {0x00,
517 0x00,
518 0x00}
519};
520
521static void set_crt_output_path(int set_iga);
522static void dvi_patch_skew_dvp0(void);
523static void dvi_patch_skew_dvp1(void);
524static void dvi_patch_skew_dvp_low(void);
525static void set_dvi_output_path(int set_iga, int output_interface);
526static void set_lcd_output_path(int set_iga, int output_interface);
527static int search_mode_setting(int ModeInfoIndex);
528static void load_fix_bit_crtc_reg(void);
Harald Welte2d280f72009-09-22 16:47:37 -0700529static void init_gfx_chip_info(struct pci_dev *pdev,
530 const struct pci_device_id *pdi);
Joseph Chand61e0bf2008-10-15 22:03:23 -0700531static void init_tmds_chip_info(void);
532static void init_lvds_chip_info(void);
533static void device_screen_off(void);
534static void device_screen_on(void);
535static void set_display_channel(void);
536static void device_off(void);
537static void device_on(void);
538static void enable_second_display_channel(void);
539static void disable_second_display_channel(void);
Joseph Chand61e0bf2008-10-15 22:03:23 -0700540
541void viafb_write_reg(u8 index, u16 io_port, u8 data)
542{
543 outb(index, io_port);
544 outb(data, io_port + 1);
545 /*DEBUG_MSG(KERN_INFO "\nIndex=%2d Value=%2d", index, data); */
546}
547u8 viafb_read_reg(int io_port, u8 index)
548{
549 outb(index, io_port);
550 return inb(io_port + 1);
551}
552
553void viafb_lock_crt(void)
554{
555 viafb_write_reg_mask(CR11, VIACR, BIT7, BIT7);
556}
557
558void viafb_unlock_crt(void)
559{
560 viafb_write_reg_mask(CR11, VIACR, 0, BIT7);
561 viafb_write_reg_mask(CR47, VIACR, 0, BIT0);
562}
563
564void viafb_write_reg_mask(u8 index, int io_port, u8 data, u8 mask)
565{
566 u8 tmp;
567
568 outb(index, io_port);
569 tmp = inb(io_port + 1);
570 outb((data & mask) | (tmp & (~mask)), io_port + 1);
571 /*DEBUG_MSG(KERN_INFO "\nIndex=%2d Value=%2d", index, tmp); */
572}
573
574void write_dac_reg(u8 index, u8 r, u8 g, u8 b)
575{
576 outb(index, LUT_INDEX_WRITE);
577 outb(r, LUT_DATA);
578 outb(g, LUT_DATA);
579 outb(b, LUT_DATA);
580}
581
582/*Set IGA path for each device*/
583void viafb_set_iga_path(void)
584{
585
586 if (viafb_SAMM_ON == 1) {
587 if (viafb_CRT_ON) {
588 if (viafb_primary_dev == CRT_Device)
589 viaparinfo->crt_setting_info->iga_path = IGA1;
590 else
591 viaparinfo->crt_setting_info->iga_path = IGA2;
592 }
593
594 if (viafb_DVI_ON) {
595 if (viafb_primary_dev == DVI_Device)
596 viaparinfo->tmds_setting_info->iga_path = IGA1;
597 else
598 viaparinfo->tmds_setting_info->iga_path = IGA2;
599 }
600
601 if (viafb_LCD_ON) {
602 if (viafb_primary_dev == LCD_Device) {
603 if (viafb_dual_fb &&
604 (viaparinfo->chip_info->gfx_chip_name ==
605 UNICHROME_CLE266)) {
606 viaparinfo->
607 lvds_setting_info->iga_path = IGA2;
608 viaparinfo->
609 crt_setting_info->iga_path = IGA1;
610 viaparinfo->
611 tmds_setting_info->iga_path = IGA1;
612 } else
613 viaparinfo->
614 lvds_setting_info->iga_path = IGA1;
615 } else {
616 viaparinfo->lvds_setting_info->iga_path = IGA2;
617 }
618 }
619 if (viafb_LCD2_ON) {
620 if (LCD2_Device == viafb_primary_dev)
621 viaparinfo->lvds_setting_info2->iga_path = IGA1;
622 else
623 viaparinfo->lvds_setting_info2->iga_path = IGA2;
624 }
625 } else {
626 viafb_SAMM_ON = 0;
627
628 if (viafb_CRT_ON && viafb_LCD_ON) {
629 viaparinfo->crt_setting_info->iga_path = IGA1;
630 viaparinfo->lvds_setting_info->iga_path = IGA2;
631 } else if (viafb_CRT_ON && viafb_DVI_ON) {
632 viaparinfo->crt_setting_info->iga_path = IGA1;
633 viaparinfo->tmds_setting_info->iga_path = IGA2;
634 } else if (viafb_LCD_ON && viafb_DVI_ON) {
635 viaparinfo->tmds_setting_info->iga_path = IGA1;
636 viaparinfo->lvds_setting_info->iga_path = IGA2;
637 } else if (viafb_LCD_ON && viafb_LCD2_ON) {
638 viaparinfo->lvds_setting_info->iga_path = IGA2;
639 viaparinfo->lvds_setting_info2->iga_path = IGA2;
640 } else if (viafb_CRT_ON) {
641 viaparinfo->crt_setting_info->iga_path = IGA1;
642 } else if (viafb_LCD_ON) {
643 viaparinfo->lvds_setting_info->iga_path = IGA2;
644 } else if (viafb_DVI_ON) {
645 viaparinfo->tmds_setting_info->iga_path = IGA1;
646 }
647 }
648}
649
Florian Tobias Schandinat09cf1182009-09-22 16:47:14 -0700650void viafb_set_primary_address(u32 addr)
Joseph Chand61e0bf2008-10-15 22:03:23 -0700651{
Florian Tobias Schandinat09cf1182009-09-22 16:47:14 -0700652 DEBUG_MSG(KERN_DEBUG "viafb_set_primary_address(0x%08X)\n", addr);
653 viafb_write_reg(CR0D, VIACR, addr & 0xFF);
654 viafb_write_reg(CR0C, VIACR, (addr >> 8) & 0xFF);
655 viafb_write_reg(CR34, VIACR, (addr >> 16) & 0xFF);
656 viafb_write_reg_mask(CR48, VIACR, (addr >> 24) & 0x1F, 0x1F);
657}
Joseph Chand61e0bf2008-10-15 22:03:23 -0700658
Florian Tobias Schandinat09cf1182009-09-22 16:47:14 -0700659void viafb_set_secondary_address(u32 addr)
660{
661 DEBUG_MSG(KERN_DEBUG "viafb_set_secondary_address(0x%08X)\n", addr);
662 /* secondary display supports only quadword aligned memory */
663 viafb_write_reg_mask(CR62, VIACR, (addr >> 2) & 0xFE, 0xFE);
664 viafb_write_reg(CR63, VIACR, (addr >> 10) & 0xFF);
665 viafb_write_reg(CR64, VIACR, (addr >> 18) & 0xFF);
666 viafb_write_reg_mask(CRA3, VIACR, (addr >> 26) & 0x07, 0x07);
Joseph Chand61e0bf2008-10-15 22:03:23 -0700667}
668
Florian Tobias Schandinat2d6e8852009-09-22 16:47:29 -0700669void viafb_set_primary_pitch(u32 pitch)
670{
671 DEBUG_MSG(KERN_DEBUG "viafb_set_primary_pitch(0x%08X)\n", pitch);
672 /* spec does not say that first adapter skips 3 bits but old
673 * code did it and seems to be reasonable in analogy to 2nd adapter
674 */
675 pitch = pitch >> 3;
676 viafb_write_reg(0x13, VIACR, pitch & 0xFF);
677 viafb_write_reg_mask(0x35, VIACR, (pitch >> (8 - 5)) & 0xE0, 0xE0);
678}
679
680void viafb_set_secondary_pitch(u32 pitch)
681{
682 DEBUG_MSG(KERN_DEBUG "viafb_set_secondary_pitch(0x%08X)\n", pitch);
683 pitch = pitch >> 3;
684 viafb_write_reg(0x66, VIACR, pitch & 0xFF);
685 viafb_write_reg_mask(0x67, VIACR, (pitch >> 8) & 0x03, 0x03);
686 viafb_write_reg_mask(0x71, VIACR, (pitch >> (10 - 7)) & 0x80, 0x80);
687}
688
Joseph Chand61e0bf2008-10-15 22:03:23 -0700689void viafb_set_output_path(int device, int set_iga, int output_interface)
690{
691 switch (device) {
692 case DEVICE_CRT:
693 set_crt_output_path(set_iga);
694 break;
695 case DEVICE_DVI:
696 set_dvi_output_path(set_iga, output_interface);
697 break;
698 case DEVICE_LCD:
699 set_lcd_output_path(set_iga, output_interface);
700 break;
701 }
702}
703
704static void set_crt_output_path(int set_iga)
705{
706 viafb_write_reg_mask(CR36, VIACR, 0x00, BIT4 + BIT5);
707
708 switch (set_iga) {
709 case IGA1:
710 viafb_write_reg_mask(SR16, VIASR, 0x00, BIT6);
711 break;
712 case IGA2:
713 case IGA1_IGA2:
714 viafb_write_reg_mask(CR6A, VIACR, 0xC0, BIT6 + BIT7);
715 viafb_write_reg_mask(SR16, VIASR, 0x40, BIT6);
716 if (set_iga == IGA1_IGA2)
717 viafb_write_reg_mask(CR6B, VIACR, 0x08, BIT3);
718 break;
719 }
720}
721
722static void dvi_patch_skew_dvp0(void)
723{
724 /* Reset data driving first: */
725 viafb_write_reg_mask(SR1B, VIASR, 0, BIT1);
726 viafb_write_reg_mask(SR2A, VIASR, 0, BIT4);
727
728 switch (viaparinfo->chip_info->gfx_chip_name) {
729 case UNICHROME_P4M890:
730 {
731 if ((viaparinfo->tmds_setting_info->h_active == 1600) &&
732 (viaparinfo->tmds_setting_info->v_active ==
733 1200))
734 viafb_write_reg_mask(CR96, VIACR, 0x03,
735 BIT0 + BIT1 + BIT2);
736 else
737 viafb_write_reg_mask(CR96, VIACR, 0x07,
738 BIT0 + BIT1 + BIT2);
739 break;
740 }
741
742 case UNICHROME_P4M900:
743 {
744 viafb_write_reg_mask(CR96, VIACR, 0x07,
745 BIT0 + BIT1 + BIT2 + BIT3);
746 viafb_write_reg_mask(SR1B, VIASR, 0x02, BIT1);
747 viafb_write_reg_mask(SR2A, VIASR, 0x10, BIT4);
748 break;
749 }
750
751 default:
752 {
753 break;
754 }
755 }
756}
757
758static void dvi_patch_skew_dvp1(void)
759{
760 switch (viaparinfo->chip_info->gfx_chip_name) {
761 case UNICHROME_CX700:
762 {
763 break;
764 }
765
766 default:
767 {
768 break;
769 }
770 }
771}
772
773static void dvi_patch_skew_dvp_low(void)
774{
775 switch (viaparinfo->chip_info->gfx_chip_name) {
776 case UNICHROME_K8M890:
777 {
778 viafb_write_reg_mask(CR99, VIACR, 0x03, BIT0 + BIT1);
779 break;
780 }
781
782 case UNICHROME_P4M900:
783 {
784 viafb_write_reg_mask(CR99, VIACR, 0x08,
785 BIT0 + BIT1 + BIT2 + BIT3);
786 break;
787 }
788
789 case UNICHROME_P4M890:
790 {
791 viafb_write_reg_mask(CR99, VIACR, 0x0F,
792 BIT0 + BIT1 + BIT2 + BIT3);
793 break;
794 }
795
796 default:
797 {
798 break;
799 }
800 }
801}
802
803static void set_dvi_output_path(int set_iga, int output_interface)
804{
805 switch (output_interface) {
806 case INTERFACE_DVP0:
807 viafb_write_reg_mask(CR6B, VIACR, 0x01, BIT0);
808
809 if (set_iga == IGA1) {
810 viafb_write_reg_mask(CR96, VIACR, 0x00, BIT4);
811 viafb_write_reg_mask(CR6C, VIACR, 0x21, BIT0 +
812 BIT5 + BIT7);
813 } else {
814 viafb_write_reg_mask(CR96, VIACR, 0x10, BIT4);
815 viafb_write_reg_mask(CR6C, VIACR, 0xA1, BIT0 +
816 BIT5 + BIT7);
817 }
818
819 viafb_write_reg_mask(SR1E, VIASR, 0xC0, BIT7 + BIT6);
820
821 dvi_patch_skew_dvp0();
822 break;
823
824 case INTERFACE_DVP1:
825 if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266) {
826 if (set_iga == IGA1)
827 viafb_write_reg_mask(CR93, VIACR, 0x21,
828 BIT0 + BIT5 + BIT7);
829 else
830 viafb_write_reg_mask(CR93, VIACR, 0xA1,
831 BIT0 + BIT5 + BIT7);
832 } else {
833 if (set_iga == IGA1)
834 viafb_write_reg_mask(CR9B, VIACR, 0x00, BIT4);
835 else
836 viafb_write_reg_mask(CR9B, VIACR, 0x10, BIT4);
837 }
838
839 viafb_write_reg_mask(SR1E, VIASR, 0x30, BIT4 + BIT5);
840 dvi_patch_skew_dvp1();
841 break;
842 case INTERFACE_DFP_HIGH:
843 if (viaparinfo->chip_info->gfx_chip_name != UNICHROME_CLE266) {
844 if (set_iga == IGA1) {
845 viafb_write_reg_mask(CR96, VIACR, 0x00, BIT4);
846 viafb_write_reg_mask(CR97, VIACR, 0x03,
847 BIT0 + BIT1 + BIT4);
848 } else {
849 viafb_write_reg_mask(CR96, VIACR, 0x10, BIT4);
850 viafb_write_reg_mask(CR97, VIACR, 0x13,
851 BIT0 + BIT1 + BIT4);
852 }
853 }
854 viafb_write_reg_mask(SR2A, VIASR, 0x0C, BIT2 + BIT3);
855 break;
856
857 case INTERFACE_DFP_LOW:
858 if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266)
859 break;
860
861 if (set_iga == IGA1) {
862 viafb_write_reg_mask(CR99, VIACR, 0x00, BIT4);
863 viafb_write_reg_mask(CR9B, VIACR, 0x00, BIT4);
864 } else {
865 viafb_write_reg_mask(CR99, VIACR, 0x10, BIT4);
866 viafb_write_reg_mask(CR9B, VIACR, 0x10, BIT4);
867 }
868
869 viafb_write_reg_mask(SR2A, VIASR, 0x03, BIT0 + BIT1);
870 dvi_patch_skew_dvp_low();
871 break;
872
873 case INTERFACE_TMDS:
874 if (set_iga == IGA1)
875 viafb_write_reg_mask(CR99, VIACR, 0x00, BIT4);
876 else
877 viafb_write_reg_mask(CR99, VIACR, 0x10, BIT4);
878 break;
879 }
880
881 if (set_iga == IGA2) {
882 enable_second_display_channel();
883 /* Disable LCD Scaling */
884 viafb_write_reg_mask(CR79, VIACR, 0x00, BIT0);
885 }
886}
887
888static void set_lcd_output_path(int set_iga, int output_interface)
889{
890 DEBUG_MSG(KERN_INFO
891 "set_lcd_output_path, iga:%d,out_interface:%d\n",
892 set_iga, output_interface);
893 switch (set_iga) {
894 case IGA1:
895 viafb_write_reg_mask(CR6B, VIACR, 0x00, BIT3);
896 viafb_write_reg_mask(CR6A, VIACR, 0x08, BIT3);
897
898 disable_second_display_channel();
899 break;
900
901 case IGA2:
902 viafb_write_reg_mask(CR6B, VIACR, 0x00, BIT3);
903 viafb_write_reg_mask(CR6A, VIACR, 0x08, BIT3);
904
905 enable_second_display_channel();
906 break;
907
908 case IGA1_IGA2:
909 viafb_write_reg_mask(CR6B, VIACR, 0x08, BIT3);
910 viafb_write_reg_mask(CR6A, VIACR, 0x08, BIT3);
911
912 disable_second_display_channel();
913 break;
914 }
915
916 switch (output_interface) {
917 case INTERFACE_DVP0:
918 if (set_iga == IGA1) {
919 viafb_write_reg_mask(CR96, VIACR, 0x00, BIT4);
920 } else {
921 viafb_write_reg(CR91, VIACR, 0x00);
922 viafb_write_reg_mask(CR96, VIACR, 0x10, BIT4);
923 }
924 break;
925
926 case INTERFACE_DVP1:
927 if (set_iga == IGA1)
928 viafb_write_reg_mask(CR9B, VIACR, 0x00, BIT4);
929 else {
930 viafb_write_reg(CR91, VIACR, 0x00);
931 viafb_write_reg_mask(CR9B, VIACR, 0x10, BIT4);
932 }
933 break;
934
935 case INTERFACE_DFP_HIGH:
936 if (set_iga == IGA1)
937 viafb_write_reg_mask(CR97, VIACR, 0x00, BIT4);
938 else {
939 viafb_write_reg(CR91, VIACR, 0x00);
940 viafb_write_reg_mask(CR97, VIACR, 0x10, BIT4);
941 viafb_write_reg_mask(CR96, VIACR, 0x10, BIT4);
942 }
943 break;
944
945 case INTERFACE_DFP_LOW:
946 if (set_iga == IGA1)
947 viafb_write_reg_mask(CR99, VIACR, 0x00, BIT4);
948 else {
949 viafb_write_reg(CR91, VIACR, 0x00);
950 viafb_write_reg_mask(CR99, VIACR, 0x10, BIT4);
951 viafb_write_reg_mask(CR9B, VIACR, 0x10, BIT4);
952 }
953
954 break;
955
956 case INTERFACE_DFP:
957 if ((UNICHROME_K8M890 == viaparinfo->chip_info->gfx_chip_name)
958 || (UNICHROME_P4M890 ==
959 viaparinfo->chip_info->gfx_chip_name))
960 viafb_write_reg_mask(CR97, VIACR, 0x84,
961 BIT7 + BIT2 + BIT1 + BIT0);
962 if (set_iga == IGA1) {
963 viafb_write_reg_mask(CR97, VIACR, 0x00, BIT4);
964 viafb_write_reg_mask(CR99, VIACR, 0x00, BIT4);
965 } else {
966 viafb_write_reg(CR91, VIACR, 0x00);
967 viafb_write_reg_mask(CR97, VIACR, 0x10, BIT4);
968 viafb_write_reg_mask(CR99, VIACR, 0x10, BIT4);
969 }
970 break;
971
972 case INTERFACE_LVDS0:
973 case INTERFACE_LVDS0LVDS1:
974 if (set_iga == IGA1)
975 viafb_write_reg_mask(CR99, VIACR, 0x00, BIT4);
976 else
977 viafb_write_reg_mask(CR99, VIACR, 0x10, BIT4);
978
979 break;
980
981 case INTERFACE_LVDS1:
982 if (set_iga == IGA1)
983 viafb_write_reg_mask(CR97, VIACR, 0x00, BIT4);
984 else
985 viafb_write_reg_mask(CR97, VIACR, 0x10, BIT4);
986 break;
987 }
988}
989
990/* Search Mode Index */
991static int search_mode_setting(int ModeInfoIndex)
992{
993 int i = 0;
994
995 while ((i < NUM_TOTAL_MODETABLE) &&
996 (ModeInfoIndex != CLE266Modes[i].ModeIndex))
997 i++;
998 if (i >= NUM_TOTAL_MODETABLE)
999 i = 0;
1000 return i;
1001
1002}
1003
1004struct VideoModeTable *viafb_get_modetbl_pointer(int Index)
1005{
1006 struct VideoModeTable *TmpTbl = NULL;
1007 TmpTbl = &CLE266Modes[search_mode_setting(Index)];
1008 return TmpTbl;
1009}
1010
1011struct VideoModeTable *viafb_get_cea_mode_tbl_pointer(int Index)
1012{
1013 struct VideoModeTable *TmpTbl = NULL;
1014 int i = 0;
1015 while ((i < NUM_TOTAL_CEA_MODES) &&
1016 (Index != CEA_HDMI_Modes[i].ModeIndex))
1017 i++;
1018 if ((i < NUM_TOTAL_CEA_MODES))
1019 TmpTbl = &CEA_HDMI_Modes[i];
1020 else {
1021 /*Still use general timing if don't find CEA timing */
1022 i = 0;
1023 while ((i < NUM_TOTAL_MODETABLE) &&
1024 (Index != CLE266Modes[i].ModeIndex))
1025 i++;
1026 if (i >= NUM_TOTAL_MODETABLE)
1027 i = 0;
1028 TmpTbl = &CLE266Modes[i];
1029 }
1030 return TmpTbl;
1031}
1032
1033static void load_fix_bit_crtc_reg(void)
1034{
1035 /* always set to 1 */
1036 viafb_write_reg_mask(CR03, VIACR, 0x80, BIT7);
1037 /* line compare should set all bits = 1 (extend modes) */
1038 viafb_write_reg(CR18, VIACR, 0xff);
1039 /* line compare should set all bits = 1 (extend modes) */
1040 viafb_write_reg_mask(CR07, VIACR, 0x10, BIT4);
1041 /* line compare should set all bits = 1 (extend modes) */
1042 viafb_write_reg_mask(CR09, VIACR, 0x40, BIT6);
1043 /* line compare should set all bits = 1 (extend modes) */
1044 viafb_write_reg_mask(CR35, VIACR, 0x10, BIT4);
1045 /* line compare should set all bits = 1 (extend modes) */
1046 viafb_write_reg_mask(CR33, VIACR, 0x06, BIT0 + BIT1 + BIT2);
1047 /*viafb_write_reg_mask(CR32, VIACR, 0x01, BIT0); */
1048 /* extend mode always set to e3h */
1049 viafb_write_reg(CR17, VIACR, 0xe3);
1050 /* extend mode always set to 0h */
1051 viafb_write_reg(CR08, VIACR, 0x00);
1052 /* extend mode always set to 0h */
1053 viafb_write_reg(CR14, VIACR, 0x00);
1054
1055 /* If K8M800, enable Prefetch Mode. */
1056 if ((viaparinfo->chip_info->gfx_chip_name == UNICHROME_K800)
1057 || (viaparinfo->chip_info->gfx_chip_name == UNICHROME_K8M890))
1058 viafb_write_reg_mask(CR33, VIACR, 0x08, BIT3);
1059 if ((viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266)
1060 && (viaparinfo->chip_info->gfx_chip_revision == CLE266_REVISION_AX))
1061 viafb_write_reg_mask(SR1A, VIASR, 0x02, BIT1);
1062
1063}
1064
1065void viafb_load_reg(int timing_value, int viafb_load_reg_num,
1066 struct io_register *reg,
1067 int io_type)
1068{
1069 int reg_mask;
1070 int bit_num = 0;
1071 int data;
1072 int i, j;
1073 int shift_next_reg;
1074 int start_index, end_index, cr_index;
1075 u16 get_bit;
1076
1077 for (i = 0; i < viafb_load_reg_num; i++) {
1078 reg_mask = 0;
1079 data = 0;
1080 start_index = reg[i].start_bit;
1081 end_index = reg[i].end_bit;
1082 cr_index = reg[i].io_addr;
1083
1084 shift_next_reg = bit_num;
1085 for (j = start_index; j <= end_index; j++) {
1086 /*if (bit_num==8) timing_value = timing_value >>8; */
1087 reg_mask = reg_mask | (BIT0 << j);
1088 get_bit = (timing_value & (BIT0 << bit_num));
1089 data =
1090 data | ((get_bit >> shift_next_reg) << start_index);
1091 bit_num++;
1092 }
1093 if (io_type == VIACR)
1094 viafb_write_reg_mask(cr_index, VIACR, data, reg_mask);
1095 else
1096 viafb_write_reg_mask(cr_index, VIASR, data, reg_mask);
1097 }
1098
1099}
1100
1101/* Write Registers */
1102void viafb_write_regx(struct io_reg RegTable[], int ItemNum)
1103{
1104 int i;
1105 unsigned char RegTemp;
1106
1107 /*DEBUG_MSG(KERN_INFO "Table Size : %x!!\n",ItemNum ); */
1108
1109 for (i = 0; i < ItemNum; i++) {
1110 outb(RegTable[i].index, RegTable[i].port);
1111 RegTemp = inb(RegTable[i].port + 1);
1112 RegTemp = (RegTemp & (~RegTable[i].mask)) | RegTable[i].value;
1113 outb(RegTemp, RegTable[i].port + 1);
1114 }
1115}
1116
Joseph Chand61e0bf2008-10-15 22:03:23 -07001117void viafb_load_fetch_count_reg(int h_addr, int bpp_byte, int set_iga)
1118{
1119 int reg_value;
1120 int viafb_load_reg_num;
1121 struct io_register *reg = NULL;
1122
1123 switch (set_iga) {
1124 case IGA1_IGA2:
1125 case IGA1:
1126 reg_value = IGA1_FETCH_COUNT_FORMULA(h_addr, bpp_byte);
1127 viafb_load_reg_num = fetch_count_reg.
1128 iga1_fetch_count_reg.reg_num;
1129 reg = fetch_count_reg.iga1_fetch_count_reg.reg;
1130 viafb_load_reg(reg_value, viafb_load_reg_num, reg, VIASR);
1131 if (set_iga == IGA1)
1132 break;
1133 case IGA2:
1134 reg_value = IGA2_FETCH_COUNT_FORMULA(h_addr, bpp_byte);
1135 viafb_load_reg_num = fetch_count_reg.
1136 iga2_fetch_count_reg.reg_num;
1137 reg = fetch_count_reg.iga2_fetch_count_reg.reg;
1138 viafb_load_reg(reg_value, viafb_load_reg_num, reg, VIACR);
1139 break;
1140 }
1141
1142}
1143
1144void viafb_load_FIFO_reg(int set_iga, int hor_active, int ver_active)
1145{
1146 int reg_value;
1147 int viafb_load_reg_num;
1148 struct io_register *reg = NULL;
1149 int iga1_fifo_max_depth = 0, iga1_fifo_threshold =
1150 0, iga1_fifo_high_threshold = 0, iga1_display_queue_expire_num = 0;
1151 int iga2_fifo_max_depth = 0, iga2_fifo_threshold =
1152 0, iga2_fifo_high_threshold = 0, iga2_display_queue_expire_num = 0;
1153
1154 if (set_iga == IGA1) {
1155 if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_K800) {
1156 iga1_fifo_max_depth = K800_IGA1_FIFO_MAX_DEPTH;
1157 iga1_fifo_threshold = K800_IGA1_FIFO_THRESHOLD;
1158 iga1_fifo_high_threshold =
1159 K800_IGA1_FIFO_HIGH_THRESHOLD;
1160 /* If resolution > 1280x1024, expire length = 64, else
1161 expire length = 128 */
1162 if ((hor_active > 1280) && (ver_active > 1024))
1163 iga1_display_queue_expire_num = 16;
1164 else
1165 iga1_display_queue_expire_num =
1166 K800_IGA1_DISPLAY_QUEUE_EXPIRE_NUM;
1167
1168 }
1169
1170 if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_PM800) {
1171 iga1_fifo_max_depth = P880_IGA1_FIFO_MAX_DEPTH;
1172 iga1_fifo_threshold = P880_IGA1_FIFO_THRESHOLD;
1173 iga1_fifo_high_threshold =
1174 P880_IGA1_FIFO_HIGH_THRESHOLD;
1175 iga1_display_queue_expire_num =
1176 P880_IGA1_DISPLAY_QUEUE_EXPIRE_NUM;
1177
1178 /* If resolution > 1280x1024, expire length = 64, else
1179 expire length = 128 */
1180 if ((hor_active > 1280) && (ver_active > 1024))
1181 iga1_display_queue_expire_num = 16;
1182 else
1183 iga1_display_queue_expire_num =
1184 P880_IGA1_DISPLAY_QUEUE_EXPIRE_NUM;
1185 }
1186
1187 if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CN700) {
1188 iga1_fifo_max_depth = CN700_IGA1_FIFO_MAX_DEPTH;
1189 iga1_fifo_threshold = CN700_IGA1_FIFO_THRESHOLD;
1190 iga1_fifo_high_threshold =
1191 CN700_IGA1_FIFO_HIGH_THRESHOLD;
1192
1193 /* If resolution > 1280x1024, expire length = 64,
1194 else expire length = 128 */
1195 if ((hor_active > 1280) && (ver_active > 1024))
1196 iga1_display_queue_expire_num = 16;
1197 else
1198 iga1_display_queue_expire_num =
1199 CN700_IGA1_DISPLAY_QUEUE_EXPIRE_NUM;
1200 }
1201
1202 if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CX700) {
1203 iga1_fifo_max_depth = CX700_IGA1_FIFO_MAX_DEPTH;
1204 iga1_fifo_threshold = CX700_IGA1_FIFO_THRESHOLD;
1205 iga1_fifo_high_threshold =
1206 CX700_IGA1_FIFO_HIGH_THRESHOLD;
1207 iga1_display_queue_expire_num =
1208 CX700_IGA1_DISPLAY_QUEUE_EXPIRE_NUM;
1209 }
1210
1211 if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_K8M890) {
1212 iga1_fifo_max_depth = K8M890_IGA1_FIFO_MAX_DEPTH;
1213 iga1_fifo_threshold = K8M890_IGA1_FIFO_THRESHOLD;
1214 iga1_fifo_high_threshold =
1215 K8M890_IGA1_FIFO_HIGH_THRESHOLD;
1216 iga1_display_queue_expire_num =
1217 K8M890_IGA1_DISPLAY_QUEUE_EXPIRE_NUM;
1218 }
1219
1220 if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_P4M890) {
1221 iga1_fifo_max_depth = P4M890_IGA1_FIFO_MAX_DEPTH;
1222 iga1_fifo_threshold = P4M890_IGA1_FIFO_THRESHOLD;
1223 iga1_fifo_high_threshold =
1224 P4M890_IGA1_FIFO_HIGH_THRESHOLD;
1225 iga1_display_queue_expire_num =
1226 P4M890_IGA1_DISPLAY_QUEUE_EXPIRE_NUM;
1227 }
1228
1229 if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_P4M900) {
1230 iga1_fifo_max_depth = P4M900_IGA1_FIFO_MAX_DEPTH;
1231 iga1_fifo_threshold = P4M900_IGA1_FIFO_THRESHOLD;
1232 iga1_fifo_high_threshold =
1233 P4M900_IGA1_FIFO_HIGH_THRESHOLD;
1234 iga1_display_queue_expire_num =
1235 P4M900_IGA1_DISPLAY_QUEUE_EXPIRE_NUM;
1236 }
1237
1238 if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_VX800) {
1239 iga1_fifo_max_depth = VX800_IGA1_FIFO_MAX_DEPTH;
1240 iga1_fifo_threshold = VX800_IGA1_FIFO_THRESHOLD;
1241 iga1_fifo_high_threshold =
1242 VX800_IGA1_FIFO_HIGH_THRESHOLD;
1243 iga1_display_queue_expire_num =
1244 VX800_IGA1_DISPLAY_QUEUE_EXPIRE_NUM;
1245 }
1246
Harald Welte0306ab12009-09-22 16:47:35 -07001247 if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_VX855) {
1248 iga1_fifo_max_depth = VX855_IGA1_FIFO_MAX_DEPTH;
1249 iga1_fifo_threshold = VX855_IGA1_FIFO_THRESHOLD;
1250 iga1_fifo_high_threshold =
1251 VX855_IGA1_FIFO_HIGH_THRESHOLD;
1252 iga1_display_queue_expire_num =
1253 VX855_IGA1_DISPLAY_QUEUE_EXPIRE_NUM;
1254 }
1255
Joseph Chand61e0bf2008-10-15 22:03:23 -07001256 /* Set Display FIFO Depath Select */
1257 reg_value = IGA1_FIFO_DEPTH_SELECT_FORMULA(iga1_fifo_max_depth);
1258 viafb_load_reg_num =
1259 display_fifo_depth_reg.iga1_fifo_depth_select_reg.reg_num;
1260 reg = display_fifo_depth_reg.iga1_fifo_depth_select_reg.reg;
1261 viafb_load_reg(reg_value, viafb_load_reg_num, reg, VIASR);
1262
1263 /* Set Display FIFO Threshold Select */
1264 reg_value = IGA1_FIFO_THRESHOLD_FORMULA(iga1_fifo_threshold);
1265 viafb_load_reg_num =
1266 fifo_threshold_select_reg.
1267 iga1_fifo_threshold_select_reg.reg_num;
1268 reg =
1269 fifo_threshold_select_reg.
1270 iga1_fifo_threshold_select_reg.reg;
1271 viafb_load_reg(reg_value, viafb_load_reg_num, reg, VIASR);
1272
1273 /* Set FIFO High Threshold Select */
1274 reg_value =
1275 IGA1_FIFO_HIGH_THRESHOLD_FORMULA(iga1_fifo_high_threshold);
1276 viafb_load_reg_num =
1277 fifo_high_threshold_select_reg.
1278 iga1_fifo_high_threshold_select_reg.reg_num;
1279 reg =
1280 fifo_high_threshold_select_reg.
1281 iga1_fifo_high_threshold_select_reg.reg;
1282 viafb_load_reg(reg_value, viafb_load_reg_num, reg, VIASR);
1283
1284 /* Set Display Queue Expire Num */
1285 reg_value =
1286 IGA1_DISPLAY_QUEUE_EXPIRE_NUM_FORMULA
1287 (iga1_display_queue_expire_num);
1288 viafb_load_reg_num =
1289 display_queue_expire_num_reg.
1290 iga1_display_queue_expire_num_reg.reg_num;
1291 reg =
1292 display_queue_expire_num_reg.
1293 iga1_display_queue_expire_num_reg.reg;
1294 viafb_load_reg(reg_value, viafb_load_reg_num, reg, VIASR);
1295
1296 } else {
1297 if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_K800) {
1298 iga2_fifo_max_depth = K800_IGA2_FIFO_MAX_DEPTH;
1299 iga2_fifo_threshold = K800_IGA2_FIFO_THRESHOLD;
1300 iga2_fifo_high_threshold =
1301 K800_IGA2_FIFO_HIGH_THRESHOLD;
1302
1303 /* If resolution > 1280x1024, expire length = 64,
1304 else expire length = 128 */
1305 if ((hor_active > 1280) && (ver_active > 1024))
1306 iga2_display_queue_expire_num = 16;
1307 else
1308 iga2_display_queue_expire_num =
1309 K800_IGA2_DISPLAY_QUEUE_EXPIRE_NUM;
1310 }
1311
1312 if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_PM800) {
1313 iga2_fifo_max_depth = P880_IGA2_FIFO_MAX_DEPTH;
1314 iga2_fifo_threshold = P880_IGA2_FIFO_THRESHOLD;
1315 iga2_fifo_high_threshold =
1316 P880_IGA2_FIFO_HIGH_THRESHOLD;
1317
1318 /* If resolution > 1280x1024, expire length = 64,
1319 else expire length = 128 */
1320 if ((hor_active > 1280) && (ver_active > 1024))
1321 iga2_display_queue_expire_num = 16;
1322 else
1323 iga2_display_queue_expire_num =
1324 P880_IGA2_DISPLAY_QUEUE_EXPIRE_NUM;
1325 }
1326
1327 if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CN700) {
1328 iga2_fifo_max_depth = CN700_IGA2_FIFO_MAX_DEPTH;
1329 iga2_fifo_threshold = CN700_IGA2_FIFO_THRESHOLD;
1330 iga2_fifo_high_threshold =
1331 CN700_IGA2_FIFO_HIGH_THRESHOLD;
1332
1333 /* If resolution > 1280x1024, expire length = 64,
1334 else expire length = 128 */
1335 if ((hor_active > 1280) && (ver_active > 1024))
1336 iga2_display_queue_expire_num = 16;
1337 else
1338 iga2_display_queue_expire_num =
1339 CN700_IGA2_DISPLAY_QUEUE_EXPIRE_NUM;
1340 }
1341
1342 if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CX700) {
1343 iga2_fifo_max_depth = CX700_IGA2_FIFO_MAX_DEPTH;
1344 iga2_fifo_threshold = CX700_IGA2_FIFO_THRESHOLD;
1345 iga2_fifo_high_threshold =
1346 CX700_IGA2_FIFO_HIGH_THRESHOLD;
1347 iga2_display_queue_expire_num =
1348 CX700_IGA2_DISPLAY_QUEUE_EXPIRE_NUM;
1349 }
1350
1351 if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_K8M890) {
1352 iga2_fifo_max_depth = K8M890_IGA2_FIFO_MAX_DEPTH;
1353 iga2_fifo_threshold = K8M890_IGA2_FIFO_THRESHOLD;
1354 iga2_fifo_high_threshold =
1355 K8M890_IGA2_FIFO_HIGH_THRESHOLD;
1356 iga2_display_queue_expire_num =
1357 K8M890_IGA2_DISPLAY_QUEUE_EXPIRE_NUM;
1358 }
1359
1360 if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_P4M890) {
1361 iga2_fifo_max_depth = P4M890_IGA2_FIFO_MAX_DEPTH;
1362 iga2_fifo_threshold = P4M890_IGA2_FIFO_THRESHOLD;
1363 iga2_fifo_high_threshold =
1364 P4M890_IGA2_FIFO_HIGH_THRESHOLD;
1365 iga2_display_queue_expire_num =
1366 P4M890_IGA2_DISPLAY_QUEUE_EXPIRE_NUM;
1367 }
1368
1369 if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_P4M900) {
1370 iga2_fifo_max_depth = P4M900_IGA2_FIFO_MAX_DEPTH;
1371 iga2_fifo_threshold = P4M900_IGA2_FIFO_THRESHOLD;
1372 iga2_fifo_high_threshold =
1373 P4M900_IGA2_FIFO_HIGH_THRESHOLD;
1374 iga2_display_queue_expire_num =
1375 P4M900_IGA2_DISPLAY_QUEUE_EXPIRE_NUM;
1376 }
1377
1378 if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_VX800) {
1379 iga2_fifo_max_depth = VX800_IGA2_FIFO_MAX_DEPTH;
1380 iga2_fifo_threshold = VX800_IGA2_FIFO_THRESHOLD;
1381 iga2_fifo_high_threshold =
1382 VX800_IGA2_FIFO_HIGH_THRESHOLD;
1383 iga2_display_queue_expire_num =
1384 VX800_IGA2_DISPLAY_QUEUE_EXPIRE_NUM;
1385 }
1386
Harald Welte0306ab12009-09-22 16:47:35 -07001387 if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_VX855) {
1388 iga2_fifo_max_depth = VX855_IGA2_FIFO_MAX_DEPTH;
1389 iga2_fifo_threshold = VX855_IGA2_FIFO_THRESHOLD;
1390 iga2_fifo_high_threshold =
1391 VX855_IGA2_FIFO_HIGH_THRESHOLD;
1392 iga2_display_queue_expire_num =
1393 VX855_IGA2_DISPLAY_QUEUE_EXPIRE_NUM;
1394 }
1395
Joseph Chand61e0bf2008-10-15 22:03:23 -07001396 if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_K800) {
1397 /* Set Display FIFO Depath Select */
1398 reg_value =
1399 IGA2_FIFO_DEPTH_SELECT_FORMULA(iga2_fifo_max_depth)
1400 - 1;
1401 /* Patch LCD in IGA2 case */
1402 viafb_load_reg_num =
1403 display_fifo_depth_reg.
1404 iga2_fifo_depth_select_reg.reg_num;
1405 reg =
1406 display_fifo_depth_reg.
1407 iga2_fifo_depth_select_reg.reg;
1408 viafb_load_reg(reg_value,
1409 viafb_load_reg_num, reg, VIACR);
1410 } else {
1411
1412 /* Set Display FIFO Depath Select */
1413 reg_value =
1414 IGA2_FIFO_DEPTH_SELECT_FORMULA(iga2_fifo_max_depth);
1415 viafb_load_reg_num =
1416 display_fifo_depth_reg.
1417 iga2_fifo_depth_select_reg.reg_num;
1418 reg =
1419 display_fifo_depth_reg.
1420 iga2_fifo_depth_select_reg.reg;
1421 viafb_load_reg(reg_value,
1422 viafb_load_reg_num, reg, VIACR);
1423 }
1424
1425 /* Set Display FIFO Threshold Select */
1426 reg_value = IGA2_FIFO_THRESHOLD_FORMULA(iga2_fifo_threshold);
1427 viafb_load_reg_num =
1428 fifo_threshold_select_reg.
1429 iga2_fifo_threshold_select_reg.reg_num;
1430 reg =
1431 fifo_threshold_select_reg.
1432 iga2_fifo_threshold_select_reg.reg;
1433 viafb_load_reg(reg_value, viafb_load_reg_num, reg, VIACR);
1434
1435 /* Set FIFO High Threshold Select */
1436 reg_value =
1437 IGA2_FIFO_HIGH_THRESHOLD_FORMULA(iga2_fifo_high_threshold);
1438 viafb_load_reg_num =
1439 fifo_high_threshold_select_reg.
1440 iga2_fifo_high_threshold_select_reg.reg_num;
1441 reg =
1442 fifo_high_threshold_select_reg.
1443 iga2_fifo_high_threshold_select_reg.reg;
1444 viafb_load_reg(reg_value, viafb_load_reg_num, reg, VIACR);
1445
1446 /* Set Display Queue Expire Num */
1447 reg_value =
1448 IGA2_DISPLAY_QUEUE_EXPIRE_NUM_FORMULA
1449 (iga2_display_queue_expire_num);
1450 viafb_load_reg_num =
1451 display_queue_expire_num_reg.
1452 iga2_display_queue_expire_num_reg.reg_num;
1453 reg =
1454 display_queue_expire_num_reg.
1455 iga2_display_queue_expire_num_reg.reg;
1456 viafb_load_reg(reg_value, viafb_load_reg_num, reg, VIACR);
1457
1458 }
1459
1460}
1461
1462u32 viafb_get_clk_value(int clk)
1463{
1464 int i;
1465
1466 for (i = 0; i < NUM_TOTAL_PLL_TABLE; i++) {
1467 if (clk == pll_value[i].clk) {
1468 switch (viaparinfo->chip_info->gfx_chip_name) {
1469 case UNICHROME_CLE266:
1470 case UNICHROME_K400:
1471 return pll_value[i].cle266_pll;
1472
1473 case UNICHROME_K800:
1474 case UNICHROME_PM800:
1475 case UNICHROME_CN700:
1476 return pll_value[i].k800_pll;
1477
1478 case UNICHROME_CX700:
1479 case UNICHROME_K8M890:
1480 case UNICHROME_P4M890:
1481 case UNICHROME_P4M900:
1482 case UNICHROME_VX800:
1483 return pll_value[i].cx700_pll;
Harald Welte0306ab12009-09-22 16:47:35 -07001484 case UNICHROME_VX855:
1485 return pll_value[i].vx855_pll;
Joseph Chand61e0bf2008-10-15 22:03:23 -07001486 }
1487 }
1488 }
1489
1490 DEBUG_MSG(KERN_INFO "Can't find match PLL value\n\n");
1491 return 0;
1492}
1493
1494/* Set VCLK*/
1495void viafb_set_vclock(u32 CLK, int set_iga)
1496{
1497 unsigned char RegTemp;
1498
1499 /* H.W. Reset : ON */
1500 viafb_write_reg_mask(CR17, VIACR, 0x00, BIT7);
1501
1502 if ((set_iga == IGA1) || (set_iga == IGA1_IGA2)) {
1503 /* Change D,N FOR VCLK */
1504 switch (viaparinfo->chip_info->gfx_chip_name) {
1505 case UNICHROME_CLE266:
1506 case UNICHROME_K400:
1507 viafb_write_reg(SR46, VIASR, CLK / 0x100);
1508 viafb_write_reg(SR47, VIASR, CLK % 0x100);
1509 break;
1510
1511 case UNICHROME_K800:
1512 case UNICHROME_PM800:
1513 case UNICHROME_CN700:
1514 case UNICHROME_CX700:
1515 case UNICHROME_K8M890:
1516 case UNICHROME_P4M890:
1517 case UNICHROME_P4M900:
1518 case UNICHROME_VX800:
Harald Welte0306ab12009-09-22 16:47:35 -07001519 case UNICHROME_VX855:
Joseph Chand61e0bf2008-10-15 22:03:23 -07001520 viafb_write_reg(SR44, VIASR, CLK / 0x10000);
1521 DEBUG_MSG(KERN_INFO "\nSR44=%x", CLK / 0x10000);
1522 viafb_write_reg(SR45, VIASR, (CLK & 0xFFFF) / 0x100);
1523 DEBUG_MSG(KERN_INFO "\nSR45=%x",
1524 (CLK & 0xFFFF) / 0x100);
1525 viafb_write_reg(SR46, VIASR, CLK % 0x100);
1526 DEBUG_MSG(KERN_INFO "\nSR46=%x", CLK % 0x100);
1527 break;
1528 }
1529 }
1530
1531 if ((set_iga == IGA2) || (set_iga == IGA1_IGA2)) {
1532 /* Change D,N FOR LCK */
1533 switch (viaparinfo->chip_info->gfx_chip_name) {
1534 case UNICHROME_CLE266:
1535 case UNICHROME_K400:
1536 viafb_write_reg(SR44, VIASR, CLK / 0x100);
1537 viafb_write_reg(SR45, VIASR, CLK % 0x100);
1538 break;
1539
1540 case UNICHROME_K800:
1541 case UNICHROME_PM800:
1542 case UNICHROME_CN700:
1543 case UNICHROME_CX700:
1544 case UNICHROME_K8M890:
1545 case UNICHROME_P4M890:
1546 case UNICHROME_P4M900:
1547 case UNICHROME_VX800:
Harald Welte0306ab12009-09-22 16:47:35 -07001548 case UNICHROME_VX855:
Joseph Chand61e0bf2008-10-15 22:03:23 -07001549 viafb_write_reg(SR4A, VIASR, CLK / 0x10000);
1550 viafb_write_reg(SR4B, VIASR, (CLK & 0xFFFF) / 0x100);
1551 viafb_write_reg(SR4C, VIASR, CLK % 0x100);
1552 break;
1553 }
1554 }
1555
1556 /* H.W. Reset : OFF */
1557 viafb_write_reg_mask(CR17, VIACR, 0x80, BIT7);
1558
1559 /* Reset PLL */
1560 if ((set_iga == IGA1) || (set_iga == IGA1_IGA2)) {
1561 viafb_write_reg_mask(SR40, VIASR, 0x02, BIT1);
1562 viafb_write_reg_mask(SR40, VIASR, 0x00, BIT1);
1563 }
1564
1565 if ((set_iga == IGA2) || (set_iga == IGA1_IGA2)) {
1566 viafb_write_reg_mask(SR40, VIASR, 0x01, BIT0);
1567 viafb_write_reg_mask(SR40, VIASR, 0x00, BIT0);
1568 }
1569
1570 /* Fire! */
1571 RegTemp = inb(VIARMisc);
1572 outb(RegTemp | (BIT2 + BIT3), VIAWMisc);
1573}
1574
1575void viafb_load_crtc_timing(struct display_timing device_timing,
1576 int set_iga)
1577{
1578 int i;
1579 int viafb_load_reg_num = 0;
1580 int reg_value = 0;
1581 struct io_register *reg = NULL;
1582
1583 viafb_unlock_crt();
1584
1585 for (i = 0; i < 12; i++) {
1586 if (set_iga == IGA1) {
1587 switch (i) {
1588 case H_TOTAL_INDEX:
1589 reg_value =
1590 IGA1_HOR_TOTAL_FORMULA(device_timing.
1591 hor_total);
1592 viafb_load_reg_num =
1593 iga1_crtc_reg.hor_total.reg_num;
1594 reg = iga1_crtc_reg.hor_total.reg;
1595 break;
1596 case H_ADDR_INDEX:
1597 reg_value =
1598 IGA1_HOR_ADDR_FORMULA(device_timing.
1599 hor_addr);
1600 viafb_load_reg_num =
1601 iga1_crtc_reg.hor_addr.reg_num;
1602 reg = iga1_crtc_reg.hor_addr.reg;
1603 break;
1604 case H_BLANK_START_INDEX:
1605 reg_value =
1606 IGA1_HOR_BLANK_START_FORMULA
1607 (device_timing.hor_blank_start);
1608 viafb_load_reg_num =
1609 iga1_crtc_reg.hor_blank_start.reg_num;
1610 reg = iga1_crtc_reg.hor_blank_start.reg;
1611 break;
1612 case H_BLANK_END_INDEX:
1613 reg_value =
1614 IGA1_HOR_BLANK_END_FORMULA
1615 (device_timing.hor_blank_start,
1616 device_timing.hor_blank_end);
1617 viafb_load_reg_num =
1618 iga1_crtc_reg.hor_blank_end.reg_num;
1619 reg = iga1_crtc_reg.hor_blank_end.reg;
1620 break;
1621 case H_SYNC_START_INDEX:
1622 reg_value =
1623 IGA1_HOR_SYNC_START_FORMULA
1624 (device_timing.hor_sync_start);
1625 viafb_load_reg_num =
1626 iga1_crtc_reg.hor_sync_start.reg_num;
1627 reg = iga1_crtc_reg.hor_sync_start.reg;
1628 break;
1629 case H_SYNC_END_INDEX:
1630 reg_value =
1631 IGA1_HOR_SYNC_END_FORMULA
1632 (device_timing.hor_sync_start,
1633 device_timing.hor_sync_end);
1634 viafb_load_reg_num =
1635 iga1_crtc_reg.hor_sync_end.reg_num;
1636 reg = iga1_crtc_reg.hor_sync_end.reg;
1637 break;
1638 case V_TOTAL_INDEX:
1639 reg_value =
1640 IGA1_VER_TOTAL_FORMULA(device_timing.
1641 ver_total);
1642 viafb_load_reg_num =
1643 iga1_crtc_reg.ver_total.reg_num;
1644 reg = iga1_crtc_reg.ver_total.reg;
1645 break;
1646 case V_ADDR_INDEX:
1647 reg_value =
1648 IGA1_VER_ADDR_FORMULA(device_timing.
1649 ver_addr);
1650 viafb_load_reg_num =
1651 iga1_crtc_reg.ver_addr.reg_num;
1652 reg = iga1_crtc_reg.ver_addr.reg;
1653 break;
1654 case V_BLANK_START_INDEX:
1655 reg_value =
1656 IGA1_VER_BLANK_START_FORMULA
1657 (device_timing.ver_blank_start);
1658 viafb_load_reg_num =
1659 iga1_crtc_reg.ver_blank_start.reg_num;
1660 reg = iga1_crtc_reg.ver_blank_start.reg;
1661 break;
1662 case V_BLANK_END_INDEX:
1663 reg_value =
1664 IGA1_VER_BLANK_END_FORMULA
1665 (device_timing.ver_blank_start,
1666 device_timing.ver_blank_end);
1667 viafb_load_reg_num =
1668 iga1_crtc_reg.ver_blank_end.reg_num;
1669 reg = iga1_crtc_reg.ver_blank_end.reg;
1670 break;
1671 case V_SYNC_START_INDEX:
1672 reg_value =
1673 IGA1_VER_SYNC_START_FORMULA
1674 (device_timing.ver_sync_start);
1675 viafb_load_reg_num =
1676 iga1_crtc_reg.ver_sync_start.reg_num;
1677 reg = iga1_crtc_reg.ver_sync_start.reg;
1678 break;
1679 case V_SYNC_END_INDEX:
1680 reg_value =
1681 IGA1_VER_SYNC_END_FORMULA
1682 (device_timing.ver_sync_start,
1683 device_timing.ver_sync_end);
1684 viafb_load_reg_num =
1685 iga1_crtc_reg.ver_sync_end.reg_num;
1686 reg = iga1_crtc_reg.ver_sync_end.reg;
1687 break;
1688
1689 }
1690 }
1691
1692 if (set_iga == IGA2) {
1693 switch (i) {
1694 case H_TOTAL_INDEX:
1695 reg_value =
1696 IGA2_HOR_TOTAL_FORMULA(device_timing.
1697 hor_total);
1698 viafb_load_reg_num =
1699 iga2_crtc_reg.hor_total.reg_num;
1700 reg = iga2_crtc_reg.hor_total.reg;
1701 break;
1702 case H_ADDR_INDEX:
1703 reg_value =
1704 IGA2_HOR_ADDR_FORMULA(device_timing.
1705 hor_addr);
1706 viafb_load_reg_num =
1707 iga2_crtc_reg.hor_addr.reg_num;
1708 reg = iga2_crtc_reg.hor_addr.reg;
1709 break;
1710 case H_BLANK_START_INDEX:
1711 reg_value =
1712 IGA2_HOR_BLANK_START_FORMULA
1713 (device_timing.hor_blank_start);
1714 viafb_load_reg_num =
1715 iga2_crtc_reg.hor_blank_start.reg_num;
1716 reg = iga2_crtc_reg.hor_blank_start.reg;
1717 break;
1718 case H_BLANK_END_INDEX:
1719 reg_value =
1720 IGA2_HOR_BLANK_END_FORMULA
1721 (device_timing.hor_blank_start,
1722 device_timing.hor_blank_end);
1723 viafb_load_reg_num =
1724 iga2_crtc_reg.hor_blank_end.reg_num;
1725 reg = iga2_crtc_reg.hor_blank_end.reg;
1726 break;
1727 case H_SYNC_START_INDEX:
1728 reg_value =
1729 IGA2_HOR_SYNC_START_FORMULA
1730 (device_timing.hor_sync_start);
1731 if (UNICHROME_CN700 <=
1732 viaparinfo->chip_info->gfx_chip_name)
1733 viafb_load_reg_num =
1734 iga2_crtc_reg.hor_sync_start.
1735 reg_num;
1736 else
1737 viafb_load_reg_num = 3;
1738 reg = iga2_crtc_reg.hor_sync_start.reg;
1739 break;
1740 case H_SYNC_END_INDEX:
1741 reg_value =
1742 IGA2_HOR_SYNC_END_FORMULA
1743 (device_timing.hor_sync_start,
1744 device_timing.hor_sync_end);
1745 viafb_load_reg_num =
1746 iga2_crtc_reg.hor_sync_end.reg_num;
1747 reg = iga2_crtc_reg.hor_sync_end.reg;
1748 break;
1749 case V_TOTAL_INDEX:
1750 reg_value =
1751 IGA2_VER_TOTAL_FORMULA(device_timing.
1752 ver_total);
1753 viafb_load_reg_num =
1754 iga2_crtc_reg.ver_total.reg_num;
1755 reg = iga2_crtc_reg.ver_total.reg;
1756 break;
1757 case V_ADDR_INDEX:
1758 reg_value =
1759 IGA2_VER_ADDR_FORMULA(device_timing.
1760 ver_addr);
1761 viafb_load_reg_num =
1762 iga2_crtc_reg.ver_addr.reg_num;
1763 reg = iga2_crtc_reg.ver_addr.reg;
1764 break;
1765 case V_BLANK_START_INDEX:
1766 reg_value =
1767 IGA2_VER_BLANK_START_FORMULA
1768 (device_timing.ver_blank_start);
1769 viafb_load_reg_num =
1770 iga2_crtc_reg.ver_blank_start.reg_num;
1771 reg = iga2_crtc_reg.ver_blank_start.reg;
1772 break;
1773 case V_BLANK_END_INDEX:
1774 reg_value =
1775 IGA2_VER_BLANK_END_FORMULA
1776 (device_timing.ver_blank_start,
1777 device_timing.ver_blank_end);
1778 viafb_load_reg_num =
1779 iga2_crtc_reg.ver_blank_end.reg_num;
1780 reg = iga2_crtc_reg.ver_blank_end.reg;
1781 break;
1782 case V_SYNC_START_INDEX:
1783 reg_value =
1784 IGA2_VER_SYNC_START_FORMULA
1785 (device_timing.ver_sync_start);
1786 viafb_load_reg_num =
1787 iga2_crtc_reg.ver_sync_start.reg_num;
1788 reg = iga2_crtc_reg.ver_sync_start.reg;
1789 break;
1790 case V_SYNC_END_INDEX:
1791 reg_value =
1792 IGA2_VER_SYNC_END_FORMULA
1793 (device_timing.ver_sync_start,
1794 device_timing.ver_sync_end);
1795 viafb_load_reg_num =
1796 iga2_crtc_reg.ver_sync_end.reg_num;
1797 reg = iga2_crtc_reg.ver_sync_end.reg;
1798 break;
1799
1800 }
1801 }
1802 viafb_load_reg(reg_value, viafb_load_reg_num, reg, VIACR);
1803 }
1804
1805 viafb_lock_crt();
1806}
1807
1808void viafb_set_color_depth(int bpp_byte, int set_iga)
1809{
1810 if (set_iga == IGA1) {
1811 switch (bpp_byte) {
1812 case MODE_8BPP:
1813 viafb_write_reg_mask(SR15, VIASR, 0x22, 0x7E);
1814 break;
1815 case MODE_16BPP:
1816 viafb_write_reg_mask(SR15, VIASR, 0xB6, 0xFE);
1817 break;
1818 case MODE_32BPP:
1819 viafb_write_reg_mask(SR15, VIASR, 0xAE, 0xFE);
1820 break;
1821 }
1822 } else {
1823 switch (bpp_byte) {
1824 case MODE_8BPP:
1825 viafb_write_reg_mask(CR67, VIACR, 0x00, BIT6 + BIT7);
1826 break;
1827 case MODE_16BPP:
1828 viafb_write_reg_mask(CR67, VIACR, 0x40, BIT6 + BIT7);
1829 break;
1830 case MODE_32BPP:
1831 viafb_write_reg_mask(CR67, VIACR, 0xC0, BIT6 + BIT7);
1832 break;
1833 }
1834 }
1835}
1836
1837void viafb_fill_crtc_timing(struct crt_mode_table *crt_table,
1838 int mode_index, int bpp_byte, int set_iga)
1839{
1840 struct VideoModeTable *video_mode;
1841 struct display_timing crt_reg;
1842 int i;
1843 int index = 0;
1844 int h_addr, v_addr;
1845 u32 pll_D_N;
1846
1847 video_mode = &CLE266Modes[search_mode_setting(mode_index)];
1848
1849 for (i = 0; i < video_mode->mode_array; i++) {
1850 index = i;
1851
1852 if (crt_table[i].refresh_rate == viaparinfo->
1853 crt_setting_info->refresh_rate)
1854 break;
1855 }
1856
1857 crt_reg = crt_table[index].crtc;
1858
1859 /* Mode 640x480 has border, but LCD/DFP didn't have border. */
1860 /* So we would delete border. */
1861 if ((viafb_LCD_ON | viafb_DVI_ON) && (mode_index == VIA_RES_640X480)
1862 && (viaparinfo->crt_setting_info->refresh_rate == 60)) {
1863 /* The border is 8 pixels. */
1864 crt_reg.hor_blank_start = crt_reg.hor_blank_start - 8;
1865
1866 /* Blanking time should add left and right borders. */
1867 crt_reg.hor_blank_end = crt_reg.hor_blank_end + 16;
1868 }
1869
1870 h_addr = crt_reg.hor_addr;
1871 v_addr = crt_reg.ver_addr;
1872
1873 /* update polarity for CRT timing */
1874 if (crt_table[index].h_sync_polarity == NEGATIVE) {
1875 if (crt_table[index].v_sync_polarity == NEGATIVE)
1876 outb((inb(VIARMisc) & (~(BIT6 + BIT7))) |
1877 (BIT6 + BIT7), VIAWMisc);
1878 else
1879 outb((inb(VIARMisc) & (~(BIT6 + BIT7))) | (BIT6),
1880 VIAWMisc);
1881 } else {
1882 if (crt_table[index].v_sync_polarity == NEGATIVE)
1883 outb((inb(VIARMisc) & (~(BIT6 + BIT7))) | (BIT7),
1884 VIAWMisc);
1885 else
1886 outb((inb(VIARMisc) & (~(BIT6 + BIT7))), VIAWMisc);
1887 }
1888
1889 if (set_iga == IGA1) {
1890 viafb_unlock_crt();
1891 viafb_write_reg(CR09, VIACR, 0x00); /*initial CR09=0 */
1892 viafb_write_reg_mask(CR11, VIACR, 0x00, BIT4 + BIT5 + BIT6);
1893 viafb_write_reg_mask(CR17, VIACR, 0x00, BIT7);
1894 }
1895
1896 switch (set_iga) {
1897 case IGA1:
1898 viafb_load_crtc_timing(crt_reg, IGA1);
1899 break;
1900 case IGA2:
1901 viafb_load_crtc_timing(crt_reg, IGA2);
1902 break;
1903 }
1904
1905 load_fix_bit_crtc_reg();
1906 viafb_lock_crt();
1907 viafb_write_reg_mask(CR17, VIACR, 0x80, BIT7);
Joseph Chand61e0bf2008-10-15 22:03:23 -07001908 viafb_load_fetch_count_reg(h_addr, bpp_byte, set_iga);
1909
1910 /* load FIFO */
1911 if ((viaparinfo->chip_info->gfx_chip_name != UNICHROME_CLE266)
1912 && (viaparinfo->chip_info->gfx_chip_name != UNICHROME_K400))
1913 viafb_load_FIFO_reg(set_iga, h_addr, v_addr);
1914
1915 /* load SR Register About Memory and Color part */
1916 viafb_set_color_depth(bpp_byte, set_iga);
1917
1918 pll_D_N = viafb_get_clk_value(crt_table[index].clk);
1919 DEBUG_MSG(KERN_INFO "PLL=%x", pll_D_N);
1920 viafb_set_vclock(pll_D_N, set_iga);
1921
1922}
1923
Harald Welte2d280f72009-09-22 16:47:37 -07001924void viafb_init_chip_info(struct pci_dev *pdev,
1925 const struct pci_device_id *pdi)
Joseph Chand61e0bf2008-10-15 22:03:23 -07001926{
Harald Welte2d280f72009-09-22 16:47:37 -07001927 init_gfx_chip_info(pdev, pdi);
Joseph Chand61e0bf2008-10-15 22:03:23 -07001928 init_tmds_chip_info();
1929 init_lvds_chip_info();
1930
1931 viaparinfo->crt_setting_info->iga_path = IGA1;
1932 viaparinfo->crt_setting_info->refresh_rate = viafb_refresh;
1933
1934 /*Set IGA path for each device */
1935 viafb_set_iga_path();
1936
1937 viaparinfo->lvds_setting_info->display_method = viafb_lcd_dsp_method;
1938 viaparinfo->lvds_setting_info->get_lcd_size_method =
1939 GET_LCD_SIZE_BY_USER_SETTING;
1940 viaparinfo->lvds_setting_info->lcd_mode = viafb_lcd_mode;
1941 viaparinfo->lvds_setting_info2->display_method =
1942 viaparinfo->lvds_setting_info->display_method;
1943 viaparinfo->lvds_setting_info2->lcd_mode =
1944 viaparinfo->lvds_setting_info->lcd_mode;
1945}
1946
1947void viafb_update_device_setting(int hres, int vres,
1948 int bpp, int vmode_refresh, int flag)
1949{
1950 if (flag == 0) {
1951 viaparinfo->crt_setting_info->h_active = hres;
1952 viaparinfo->crt_setting_info->v_active = vres;
1953 viaparinfo->crt_setting_info->bpp = bpp;
1954 viaparinfo->crt_setting_info->refresh_rate =
1955 vmode_refresh;
1956
1957 viaparinfo->tmds_setting_info->h_active = hres;
1958 viaparinfo->tmds_setting_info->v_active = vres;
1959 viaparinfo->tmds_setting_info->bpp = bpp;
1960 viaparinfo->tmds_setting_info->refresh_rate =
1961 vmode_refresh;
1962
1963 viaparinfo->lvds_setting_info->h_active = hres;
1964 viaparinfo->lvds_setting_info->v_active = vres;
1965 viaparinfo->lvds_setting_info->bpp = bpp;
1966 viaparinfo->lvds_setting_info->refresh_rate =
1967 vmode_refresh;
1968 viaparinfo->lvds_setting_info2->h_active = hres;
1969 viaparinfo->lvds_setting_info2->v_active = vres;
1970 viaparinfo->lvds_setting_info2->bpp = bpp;
1971 viaparinfo->lvds_setting_info2->refresh_rate =
1972 vmode_refresh;
1973 } else {
1974
1975 if (viaparinfo->tmds_setting_info->iga_path == IGA2) {
1976 viaparinfo->tmds_setting_info->h_active = hres;
1977 viaparinfo->tmds_setting_info->v_active = vres;
1978 viaparinfo->tmds_setting_info->bpp = bpp;
1979 viaparinfo->tmds_setting_info->refresh_rate =
1980 vmode_refresh;
1981 }
1982
1983 if (viaparinfo->lvds_setting_info->iga_path == IGA2) {
1984 viaparinfo->lvds_setting_info->h_active = hres;
1985 viaparinfo->lvds_setting_info->v_active = vres;
1986 viaparinfo->lvds_setting_info->bpp = bpp;
1987 viaparinfo->lvds_setting_info->refresh_rate =
1988 vmode_refresh;
1989 }
1990 if (IGA2 == viaparinfo->lvds_setting_info2->iga_path) {
1991 viaparinfo->lvds_setting_info2->h_active = hres;
1992 viaparinfo->lvds_setting_info2->v_active = vres;
1993 viaparinfo->lvds_setting_info2->bpp = bpp;
1994 viaparinfo->lvds_setting_info2->refresh_rate =
1995 vmode_refresh;
1996 }
1997 }
1998}
1999
Harald Welte2d280f72009-09-22 16:47:37 -07002000static void init_gfx_chip_info(struct pci_dev *pdev,
2001 const struct pci_device_id *pdi)
Joseph Chand61e0bf2008-10-15 22:03:23 -07002002{
Joseph Chand61e0bf2008-10-15 22:03:23 -07002003 u8 tmp;
2004
Harald Welte2d280f72009-09-22 16:47:37 -07002005 viaparinfo->chip_info->gfx_chip_name = pdi->driver_data;
Joseph Chand61e0bf2008-10-15 22:03:23 -07002006
2007 /* Check revision of CLE266 Chip */
2008 if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266) {
2009 /* CR4F only define in CLE266.CX chip */
2010 tmp = viafb_read_reg(VIACR, CR4F);
2011 viafb_write_reg(CR4F, VIACR, 0x55);
2012 if (viafb_read_reg(VIACR, CR4F) != 0x55)
2013 viaparinfo->chip_info->gfx_chip_revision =
2014 CLE266_REVISION_AX;
2015 else
2016 viaparinfo->chip_info->gfx_chip_revision =
2017 CLE266_REVISION_CX;
2018 /* restore orignal CR4F value */
2019 viafb_write_reg(CR4F, VIACR, tmp);
2020 }
2021
2022 if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CX700) {
2023 tmp = viafb_read_reg(VIASR, SR43);
2024 DEBUG_MSG(KERN_INFO "SR43:%X\n", tmp);
2025 if (tmp & 0x02) {
2026 viaparinfo->chip_info->gfx_chip_revision =
2027 CX700_REVISION_700M2;
2028 } else if (tmp & 0x40) {
2029 viaparinfo->chip_info->gfx_chip_revision =
2030 CX700_REVISION_700M;
2031 } else {
2032 viaparinfo->chip_info->gfx_chip_revision =
2033 CX700_REVISION_700;
2034 }
2035 }
Joseph Chand61e0bf2008-10-15 22:03:23 -07002036}
2037
2038static void init_tmds_chip_info(void)
2039{
2040 viafb_tmds_trasmitter_identify();
2041
2042 if (INTERFACE_NONE == viaparinfo->chip_info->tmds_chip_info.
2043 output_interface) {
2044 switch (viaparinfo->chip_info->gfx_chip_name) {
2045 case UNICHROME_CX700:
2046 {
2047 /* we should check support by hardware layout.*/
2048 if ((viafb_display_hardware_layout ==
2049 HW_LAYOUT_DVI_ONLY)
2050 || (viafb_display_hardware_layout ==
2051 HW_LAYOUT_LCD_DVI)) {
2052 viaparinfo->chip_info->tmds_chip_info.
2053 output_interface = INTERFACE_TMDS;
2054 } else {
2055 viaparinfo->chip_info->tmds_chip_info.
2056 output_interface =
2057 INTERFACE_NONE;
2058 }
2059 break;
2060 }
2061 case UNICHROME_K8M890:
2062 case UNICHROME_P4M900:
2063 case UNICHROME_P4M890:
2064 /* TMDS on PCIE, we set DFPLOW as default. */
2065 viaparinfo->chip_info->tmds_chip_info.output_interface =
2066 INTERFACE_DFP_LOW;
2067 break;
2068 default:
2069 {
2070 /* set DVP1 default for DVI */
2071 viaparinfo->chip_info->tmds_chip_info
2072 .output_interface = INTERFACE_DVP1;
2073 }
2074 }
2075 }
2076
2077 DEBUG_MSG(KERN_INFO "TMDS Chip = %d\n",
2078 viaparinfo->chip_info->tmds_chip_info.tmds_chip_name);
2079 viaparinfo->tmds_setting_info->get_dvi_size_method =
2080 GET_DVI_SIZE_BY_VGA_BIOS;
2081 viafb_init_dvi_size();
2082}
2083
2084static void init_lvds_chip_info(void)
2085{
2086 if (viafb_lcd_panel_id > LCD_PANEL_ID_MAXIMUM)
2087 viaparinfo->lvds_setting_info->get_lcd_size_method =
2088 GET_LCD_SIZE_BY_VGA_BIOS;
2089 else
2090 viaparinfo->lvds_setting_info->get_lcd_size_method =
2091 GET_LCD_SIZE_BY_USER_SETTING;
2092
2093 viafb_lvds_trasmitter_identify();
2094 viafb_init_lcd_size();
2095 viafb_init_lvds_output_interface(&viaparinfo->chip_info->lvds_chip_info,
2096 viaparinfo->lvds_setting_info);
2097 if (viaparinfo->chip_info->lvds_chip_info2.lvds_chip_name) {
2098 viafb_init_lvds_output_interface(&viaparinfo->chip_info->
2099 lvds_chip_info2, viaparinfo->lvds_setting_info2);
2100 }
2101 /*If CX700,two singel LCD, we need to reassign
2102 LCD interface to different LVDS port */
2103 if ((UNICHROME_CX700 == viaparinfo->chip_info->gfx_chip_name)
2104 && (HW_LAYOUT_LCD1_LCD2 == viafb_display_hardware_layout)) {
2105 if ((INTEGRATED_LVDS == viaparinfo->chip_info->lvds_chip_info.
2106 lvds_chip_name) && (INTEGRATED_LVDS ==
2107 viaparinfo->chip_info->
2108 lvds_chip_info2.lvds_chip_name)) {
2109 viaparinfo->chip_info->lvds_chip_info.output_interface =
2110 INTERFACE_LVDS0;
2111 viaparinfo->chip_info->lvds_chip_info2.
2112 output_interface =
2113 INTERFACE_LVDS1;
2114 }
2115 }
2116
2117 DEBUG_MSG(KERN_INFO "LVDS Chip = %d\n",
2118 viaparinfo->chip_info->lvds_chip_info.lvds_chip_name);
2119 DEBUG_MSG(KERN_INFO "LVDS1 output_interface = %d\n",
2120 viaparinfo->chip_info->lvds_chip_info.output_interface);
2121 DEBUG_MSG(KERN_INFO "LVDS2 output_interface = %d\n",
2122 viaparinfo->chip_info->lvds_chip_info.output_interface);
2123}
2124
2125void viafb_init_dac(int set_iga)
2126{
2127 int i;
2128 u8 tmp;
2129
2130 if (set_iga == IGA1) {
2131 /* access Primary Display's LUT */
2132 viafb_write_reg_mask(SR1A, VIASR, 0x00, BIT0);
2133 /* turn off LCK */
2134 viafb_write_reg_mask(SR1B, VIASR, 0x00, BIT7 + BIT6);
2135 for (i = 0; i < 256; i++) {
2136 write_dac_reg(i, palLUT_table[i].red,
2137 palLUT_table[i].green,
2138 palLUT_table[i].blue);
2139 }
2140 /* turn on LCK */
2141 viafb_write_reg_mask(SR1B, VIASR, 0xC0, BIT7 + BIT6);
2142 } else {
2143 tmp = viafb_read_reg(VIACR, CR6A);
2144 /* access Secondary Display's LUT */
2145 viafb_write_reg_mask(CR6A, VIACR, 0x40, BIT6);
2146 viafb_write_reg_mask(SR1A, VIASR, 0x01, BIT0);
2147 for (i = 0; i < 256; i++) {
2148 write_dac_reg(i, palLUT_table[i].red,
2149 palLUT_table[i].green,
2150 palLUT_table[i].blue);
2151 }
2152 /* set IGA1 DAC for default */
2153 viafb_write_reg_mask(SR1A, VIASR, 0x00, BIT0);
2154 viafb_write_reg(CR6A, VIACR, tmp);
2155 }
2156}
2157
2158static void device_screen_off(void)
2159{
2160 /* turn off CRT screen (IGA1) */
2161 viafb_write_reg_mask(SR01, VIASR, 0x20, BIT5);
2162}
2163
2164static void device_screen_on(void)
2165{
2166 /* turn on CRT screen (IGA1) */
2167 viafb_write_reg_mask(SR01, VIASR, 0x00, BIT5);
2168}
2169
2170static void set_display_channel(void)
2171{
2172 /*If viafb_LCD2_ON, on cx700, internal lvds's information
2173 is keeped on lvds_setting_info2 */
2174 if (viafb_LCD2_ON &&
2175 viaparinfo->lvds_setting_info2->device_lcd_dualedge) {
2176 /* For dual channel LCD: */
2177 /* Set to Dual LVDS channel. */
2178 viafb_write_reg_mask(CRD2, VIACR, 0x20, BIT4 + BIT5);
2179 } else if (viafb_LCD_ON && viafb_DVI_ON) {
2180 /* For LCD+DFP: */
2181 /* Set to LVDS1 + TMDS channel. */
2182 viafb_write_reg_mask(CRD2, VIACR, 0x10, BIT4 + BIT5);
2183 } else if (viafb_DVI_ON) {
2184 /* Set to single TMDS channel. */
2185 viafb_write_reg_mask(CRD2, VIACR, 0x30, BIT4 + BIT5);
2186 } else if (viafb_LCD_ON) {
2187 if (viaparinfo->lvds_setting_info->device_lcd_dualedge) {
2188 /* For dual channel LCD: */
2189 /* Set to Dual LVDS channel. */
2190 viafb_write_reg_mask(CRD2, VIACR, 0x20, BIT4 + BIT5);
2191 } else {
2192 /* Set to LVDS0 + LVDS1 channel. */
2193 viafb_write_reg_mask(CRD2, VIACR, 0x00, BIT4 + BIT5);
2194 }
2195 }
2196}
2197
2198int viafb_setmode(int vmode_index, int hor_res, int ver_res, int video_bpp,
2199 int vmode_index1, int hor_res1, int ver_res1, int video_bpp1)
2200{
2201 int i, j;
2202 int port;
2203 u8 value, index, mask;
2204 struct VideoModeTable *vmode_tbl;
2205 struct crt_mode_table *crt_timing;
2206 struct VideoModeTable *vmode_tbl1 = NULL;
2207 struct crt_mode_table *crt_timing1 = NULL;
2208
2209 DEBUG_MSG(KERN_INFO "Set Mode!!\n");
2210 DEBUG_MSG(KERN_INFO
2211 "vmode_index=%d hor_res=%d ver_res=%d video_bpp=%d\n",
2212 vmode_index, hor_res, ver_res, video_bpp);
2213
2214 device_screen_off();
2215 vmode_tbl = &CLE266Modes[search_mode_setting(vmode_index)];
2216 crt_timing = vmode_tbl->crtc;
2217
2218 if (viafb_SAMM_ON == 1) {
2219 vmode_tbl1 = &CLE266Modes[search_mode_setting(vmode_index1)];
2220 crt_timing1 = vmode_tbl1->crtc;
2221 }
2222
2223 inb(VIAStatus);
2224 outb(0x00, VIAAR);
2225
2226 /* Write Common Setting for Video Mode */
2227 switch (viaparinfo->chip_info->gfx_chip_name) {
2228 case UNICHROME_CLE266:
2229 viafb_write_regx(CLE266_ModeXregs, NUM_TOTAL_CLE266_ModeXregs);
2230 break;
2231
2232 case UNICHROME_K400:
2233 viafb_write_regx(KM400_ModeXregs, NUM_TOTAL_KM400_ModeXregs);
2234 break;
2235
2236 case UNICHROME_K800:
2237 case UNICHROME_PM800:
2238 viafb_write_regx(CN400_ModeXregs, NUM_TOTAL_CN400_ModeXregs);
2239 break;
2240
2241 case UNICHROME_CN700:
2242 case UNICHROME_K8M890:
2243 case UNICHROME_P4M890:
2244 case UNICHROME_P4M900:
2245 viafb_write_regx(CN700_ModeXregs, NUM_TOTAL_CN700_ModeXregs);
2246 break;
2247
2248 case UNICHROME_CX700:
Joseph Chand61e0bf2008-10-15 22:03:23 -07002249 case UNICHROME_VX800:
Florian Tobias Schandinat0e3ca332009-09-22 16:47:10 -07002250 viafb_write_regx(CX700_ModeXregs, NUM_TOTAL_CX700_ModeXregs);
Joseph Chand61e0bf2008-10-15 22:03:23 -07002251 break;
Harald Welte0306ab12009-09-22 16:47:35 -07002252
2253 case UNICHROME_VX855:
2254 viafb_write_regx(VX855_ModeXregs, NUM_TOTAL_VX855_ModeXregs);
2255 break;
Joseph Chand61e0bf2008-10-15 22:03:23 -07002256 }
2257
2258 device_off();
2259
2260 /* Fill VPIT Parameters */
2261 /* Write Misc Register */
2262 outb(VPIT.Misc, VIAWMisc);
2263
2264 /* Write Sequencer */
2265 for (i = 1; i <= StdSR; i++) {
2266 outb(i, VIASR);
2267 outb(VPIT.SR[i - 1], VIASR + 1);
2268 }
2269
Florian Tobias Schandinat09cf1182009-09-22 16:47:14 -07002270 viafb_set_primary_address(0);
2271 viafb_set_secondary_address(viafb_SAMM_ON ? viafb_second_offset : 0);
Joseph Chand61e0bf2008-10-15 22:03:23 -07002272 viafb_set_iga_path();
2273
2274 /* Write CRTC */
2275 viafb_fill_crtc_timing(crt_timing, vmode_index, video_bpp / 8, IGA1);
2276
2277 /* Write Graphic Controller */
2278 for (i = 0; i < StdGR; i++) {
2279 outb(i, VIAGR);
2280 outb(VPIT.GR[i], VIAGR + 1);
2281 }
2282
2283 /* Write Attribute Controller */
2284 for (i = 0; i < StdAR; i++) {
2285 inb(VIAStatus);
2286 outb(i, VIAAR);
2287 outb(VPIT.AR[i], VIAAR);
2288 }
2289
2290 inb(VIAStatus);
2291 outb(0x20, VIAAR);
2292
2293 /* Update Patch Register */
2294
2295 if ((viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266)
2296 || (viaparinfo->chip_info->gfx_chip_name == UNICHROME_K400)) {
2297 for (i = 0; i < NUM_TOTAL_PATCH_MODE; i++) {
2298 if (res_patch_table[i].mode_index == vmode_index) {
2299 for (j = 0;
2300 j < res_patch_table[i].table_length; j++) {
2301 index =
2302 res_patch_table[i].
2303 io_reg_table[j].index;
2304 port =
2305 res_patch_table[i].
2306 io_reg_table[j].port;
2307 value =
2308 res_patch_table[i].
2309 io_reg_table[j].value;
2310 mask =
2311 res_patch_table[i].
2312 io_reg_table[j].mask;
2313 viafb_write_reg_mask(index, port, value,
2314 mask);
2315 }
2316 }
2317 }
2318 }
2319
2320 if (viafb_SAMM_ON == 1) {
2321 if ((viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266)
2322 || (viaparinfo->chip_info->gfx_chip_name ==
2323 UNICHROME_K400)) {
2324 for (i = 0; i < NUM_TOTAL_PATCH_MODE; i++) {
2325 if (res_patch_table[i].mode_index ==
2326 vmode_index1) {
2327 for (j = 0;
2328 j <
2329 res_patch_table[i].
2330 table_length; j++) {
2331 index =
2332 res_patch_table[i].
2333 io_reg_table[j].index;
2334 port =
2335 res_patch_table[i].
2336 io_reg_table[j].port;
2337 value =
2338 res_patch_table[i].
2339 io_reg_table[j].value;
2340 mask =
2341 res_patch_table[i].
2342 io_reg_table[j].mask;
2343 viafb_write_reg_mask(index,
2344 port, value, mask);
2345 }
2346 }
2347 }
2348 }
2349 }
2350
Florian Tobias Schandinat2d6e8852009-09-22 16:47:29 -07002351 viafb_set_primary_pitch(viafbinfo->fix.line_length);
2352 viafb_set_secondary_pitch(viafb_dual_fb ? viafbinfo1->fix.line_length
2353 : viafbinfo->fix.line_length);
Joseph Chand61e0bf2008-10-15 22:03:23 -07002354 /* Update Refresh Rate Setting */
2355
2356 /* Clear On Screen */
2357
2358 /* CRT set mode */
2359 if (viafb_CRT_ON) {
2360 if (viafb_SAMM_ON && (viaparinfo->crt_setting_info->iga_path ==
2361 IGA2)) {
2362 viafb_fill_crtc_timing(crt_timing1, vmode_index1,
2363 video_bpp1 / 8,
2364 viaparinfo->crt_setting_info->iga_path);
2365 } else {
2366 viafb_fill_crtc_timing(crt_timing, vmode_index,
2367 video_bpp / 8,
2368 viaparinfo->crt_setting_info->iga_path);
2369 }
2370
2371 set_crt_output_path(viaparinfo->crt_setting_info->iga_path);
2372
2373 /* Patch if set_hres is not 8 alignment (1366) to viafb_setmode
2374 to 8 alignment (1368),there is several pixels (2 pixels)
2375 on right side of screen. */
2376 if (hor_res % 8) {
2377 viafb_unlock_crt();
2378 viafb_write_reg(CR02, VIACR,
2379 viafb_read_reg(VIACR, CR02) - 1);
2380 viafb_lock_crt();
2381 }
2382 }
2383
2384 if (viafb_DVI_ON) {
2385 if (viafb_SAMM_ON &&
2386 (viaparinfo->tmds_setting_info->iga_path == IGA2)) {
2387 viafb_dvi_set_mode(viafb_get_mode_index
2388 (viaparinfo->tmds_setting_info->h_active,
2389 viaparinfo->tmds_setting_info->
Florian Tobias Schandinat52159442009-08-06 15:07:34 -07002390 v_active),
Joseph Chand61e0bf2008-10-15 22:03:23 -07002391 video_bpp1, viaparinfo->
2392 tmds_setting_info->iga_path);
2393 } else {
2394 viafb_dvi_set_mode(viafb_get_mode_index
2395 (viaparinfo->tmds_setting_info->h_active,
2396 viaparinfo->
Florian Tobias Schandinat52159442009-08-06 15:07:34 -07002397 tmds_setting_info->v_active),
Joseph Chand61e0bf2008-10-15 22:03:23 -07002398 video_bpp, viaparinfo->
2399 tmds_setting_info->iga_path);
2400 }
2401 }
2402
2403 if (viafb_LCD_ON) {
2404 if (viafb_SAMM_ON &&
2405 (viaparinfo->lvds_setting_info->iga_path == IGA2)) {
2406 viaparinfo->lvds_setting_info->bpp = video_bpp1;
2407 viafb_lcd_set_mode(crt_timing1, viaparinfo->
2408 lvds_setting_info,
2409 &viaparinfo->chip_info->lvds_chip_info);
2410 } else {
2411 /* IGA1 doesn't have LCD scaling, so set it center. */
2412 if (viaparinfo->lvds_setting_info->iga_path == IGA1) {
2413 viaparinfo->lvds_setting_info->display_method =
2414 LCD_CENTERING;
2415 }
2416 viaparinfo->lvds_setting_info->bpp = video_bpp;
2417 viafb_lcd_set_mode(crt_timing, viaparinfo->
2418 lvds_setting_info,
2419 &viaparinfo->chip_info->lvds_chip_info);
2420 }
2421 }
2422 if (viafb_LCD2_ON) {
2423 if (viafb_SAMM_ON &&
2424 (viaparinfo->lvds_setting_info2->iga_path == IGA2)) {
2425 viaparinfo->lvds_setting_info2->bpp = video_bpp1;
2426 viafb_lcd_set_mode(crt_timing1, viaparinfo->
2427 lvds_setting_info2,
2428 &viaparinfo->chip_info->lvds_chip_info2);
2429 } else {
2430 /* IGA1 doesn't have LCD scaling, so set it center. */
2431 if (viaparinfo->lvds_setting_info2->iga_path == IGA1) {
2432 viaparinfo->lvds_setting_info2->display_method =
2433 LCD_CENTERING;
2434 }
2435 viaparinfo->lvds_setting_info2->bpp = video_bpp;
2436 viafb_lcd_set_mode(crt_timing, viaparinfo->
2437 lvds_setting_info2,
2438 &viaparinfo->chip_info->lvds_chip_info2);
2439 }
2440 }
2441
2442 if ((viaparinfo->chip_info->gfx_chip_name == UNICHROME_CX700)
2443 && (viafb_LCD_ON || viafb_DVI_ON))
2444 set_display_channel();
2445
2446 /* If set mode normally, save resolution information for hot-plug . */
2447 if (!viafb_hotplug) {
2448 viafb_hotplug_Xres = hor_res;
2449 viafb_hotplug_Yres = ver_res;
2450 viafb_hotplug_bpp = video_bpp;
2451 viafb_hotplug_refresh = viafb_refresh;
2452
2453 if (viafb_DVI_ON)
2454 viafb_DeviceStatus = DVI_Device;
2455 else
2456 viafb_DeviceStatus = CRT_Device;
2457 }
2458 device_on();
2459
2460 if (viafb_SAMM_ON == 1)
2461 viafb_write_reg_mask(CR6A, VIACR, 0xC0, BIT6 + BIT7);
2462
2463 device_screen_on();
2464 return 1;
2465}
2466
2467int viafb_get_pixclock(int hres, int vres, int vmode_refresh)
2468{
2469 int i;
2470
2471 for (i = 0; i < NUM_TOTAL_RES_MAP_REFRESH; i++) {
2472 if ((hres == res_map_refresh_tbl[i].hres)
2473 && (vres == res_map_refresh_tbl[i].vres)
2474 && (vmode_refresh == res_map_refresh_tbl[i].vmode_refresh))
2475 return res_map_refresh_tbl[i].pixclock;
2476 }
2477 return RES_640X480_60HZ_PIXCLOCK;
2478
2479}
2480
2481int viafb_get_refresh(int hres, int vres, u32 long_refresh)
2482{
2483#define REFRESH_TOLERANCE 3
2484 int i, nearest = -1, diff = REFRESH_TOLERANCE;
2485 for (i = 0; i < NUM_TOTAL_RES_MAP_REFRESH; i++) {
2486 if ((hres == res_map_refresh_tbl[i].hres)
2487 && (vres == res_map_refresh_tbl[i].vres)
2488 && (diff > (abs(long_refresh -
2489 res_map_refresh_tbl[i].vmode_refresh)))) {
2490 diff = abs(long_refresh - res_map_refresh_tbl[i].
2491 vmode_refresh);
2492 nearest = i;
2493 }
2494 }
2495#undef REFRESH_TOLERANCE
2496 if (nearest > 0)
2497 return res_map_refresh_tbl[nearest].vmode_refresh;
2498 return 60;
2499}
2500
2501static void device_off(void)
2502{
2503 viafb_crt_disable();
2504 viafb_dvi_disable();
2505 viafb_lcd_disable();
2506}
2507
2508static void device_on(void)
2509{
2510 if (viafb_CRT_ON == 1)
2511 viafb_crt_enable();
2512 if (viafb_DVI_ON == 1)
2513 viafb_dvi_enable();
2514 if (viafb_LCD_ON == 1)
2515 viafb_lcd_enable();
2516}
2517
2518void viafb_crt_disable(void)
2519{
2520 viafb_write_reg_mask(CR36, VIACR, BIT5 + BIT4, BIT5 + BIT4);
2521}
2522
2523void viafb_crt_enable(void)
2524{
2525 viafb_write_reg_mask(CR36, VIACR, 0x0, BIT5 + BIT4);
2526}
2527
Joseph Chand61e0bf2008-10-15 22:03:23 -07002528static void enable_second_display_channel(void)
2529{
2530 /* to enable second display channel. */
2531 viafb_write_reg_mask(CR6A, VIACR, 0x00, BIT6);
2532 viafb_write_reg_mask(CR6A, VIACR, BIT7, BIT7);
2533 viafb_write_reg_mask(CR6A, VIACR, BIT6, BIT6);
2534}
2535
2536static void disable_second_display_channel(void)
2537{
2538 /* to disable second display channel. */
2539 viafb_write_reg_mask(CR6A, VIACR, 0x00, BIT6);
2540 viafb_write_reg_mask(CR6A, VIACR, 0x00, BIT7);
2541 viafb_write_reg_mask(CR6A, VIACR, BIT6, BIT6);
2542}
2543
Harald Welte2d280f72009-09-22 16:47:37 -07002544int viafb_get_fb_size_from_pci(void)
Joseph Chand61e0bf2008-10-15 22:03:23 -07002545{
2546 unsigned long configid, deviceid, FBSize = 0;
2547 int VideoMemSize;
2548 int DeviceFound = false;
2549
2550 for (configid = 0x80000000; configid < 0x80010800; configid += 0x100) {
2551 outl(configid, (unsigned long)0xCF8);
2552 deviceid = (inl((unsigned long)0xCFC) >> 16) & 0xffff;
2553
2554 switch (deviceid) {
2555 case CLE266:
2556 case KM400:
2557 outl(configid + 0xE0, (unsigned long)0xCF8);
2558 FBSize = inl((unsigned long)0xCFC);
2559 DeviceFound = true; /* Found device id */
2560 break;
2561
2562 case CN400_FUNCTION3:
2563 case CN700_FUNCTION3:
2564 case CX700_FUNCTION3:
2565 case KM800_FUNCTION3:
2566 case KM890_FUNCTION3:
2567 case P4M890_FUNCTION3:
2568 case P4M900_FUNCTION3:
2569 case VX800_FUNCTION3:
Harald Welte0306ab12009-09-22 16:47:35 -07002570 case VX855_FUNCTION3:
Joseph Chand61e0bf2008-10-15 22:03:23 -07002571 /*case CN750_FUNCTION3: */
2572 outl(configid + 0xA0, (unsigned long)0xCF8);
2573 FBSize = inl((unsigned long)0xCFC);
2574 DeviceFound = true; /* Found device id */
2575 break;
2576
2577 default:
2578 break;
2579 }
2580
2581 if (DeviceFound)
2582 break;
2583 }
2584
2585 DEBUG_MSG(KERN_INFO "Device ID = %lx\n", deviceid);
2586
2587 FBSize = FBSize & 0x00007000;
2588 DEBUG_MSG(KERN_INFO "FB Size = %x\n", FBSize);
2589
2590 if (viaparinfo->chip_info->gfx_chip_name < UNICHROME_CX700) {
2591 switch (FBSize) {
2592 case 0x00004000:
2593 VideoMemSize = (16 << 20); /*16M */
2594 break;
2595
2596 case 0x00005000:
2597 VideoMemSize = (32 << 20); /*32M */
2598 break;
2599
2600 case 0x00006000:
2601 VideoMemSize = (64 << 20); /*64M */
2602 break;
2603
2604 default:
2605 VideoMemSize = (32 << 20); /*32M */
2606 break;
2607 }
2608 } else {
2609 switch (FBSize) {
2610 case 0x00001000:
2611 VideoMemSize = (8 << 20); /*8M */
2612 break;
2613
2614 case 0x00002000:
2615 VideoMemSize = (16 << 20); /*16M */
2616 break;
2617
2618 case 0x00003000:
2619 VideoMemSize = (32 << 20); /*32M */
2620 break;
2621
2622 case 0x00004000:
2623 VideoMemSize = (64 << 20); /*64M */
2624 break;
2625
2626 case 0x00005000:
2627 VideoMemSize = (128 << 20); /*128M */
2628 break;
2629
2630 case 0x00006000:
2631 VideoMemSize = (256 << 20); /*256M */
2632 break;
2633
Harald Welte0306ab12009-09-22 16:47:35 -07002634 case 0x00007000: /* Only on VX855/875 */
2635 VideoMemSize = (512 << 20); /*512M */
2636 break;
2637
Joseph Chand61e0bf2008-10-15 22:03:23 -07002638 default:
2639 VideoMemSize = (32 << 20); /*32M */
2640 break;
2641 }
2642 }
2643
2644 return VideoMemSize;
2645}
2646
2647void viafb_set_dpa_gfx(int output_interface, struct GFX_DPA_SETTING\
2648 *p_gfx_dpa_setting)
2649{
2650 switch (output_interface) {
2651 case INTERFACE_DVP0:
2652 {
2653 /* DVP0 Clock Polarity and Adjust: */
2654 viafb_write_reg_mask(CR96, VIACR,
2655 p_gfx_dpa_setting->DVP0, 0x0F);
2656
2657 /* DVP0 Clock and Data Pads Driving: */
2658 viafb_write_reg_mask(SR1E, VIASR,
2659 p_gfx_dpa_setting->DVP0ClockDri_S, BIT2);
2660 viafb_write_reg_mask(SR2A, VIASR,
2661 p_gfx_dpa_setting->DVP0ClockDri_S1,
2662 BIT4);
2663 viafb_write_reg_mask(SR1B, VIASR,
2664 p_gfx_dpa_setting->DVP0DataDri_S, BIT1);
2665 viafb_write_reg_mask(SR2A, VIASR,
2666 p_gfx_dpa_setting->DVP0DataDri_S1, BIT5);
2667 break;
2668 }
2669
2670 case INTERFACE_DVP1:
2671 {
2672 /* DVP1 Clock Polarity and Adjust: */
2673 viafb_write_reg_mask(CR9B, VIACR,
2674 p_gfx_dpa_setting->DVP1, 0x0F);
2675
2676 /* DVP1 Clock and Data Pads Driving: */
2677 viafb_write_reg_mask(SR65, VIASR,
2678 p_gfx_dpa_setting->DVP1Driving, 0x0F);
2679 break;
2680 }
2681
2682 case INTERFACE_DFP_HIGH:
2683 {
2684 viafb_write_reg_mask(CR97, VIACR,
2685 p_gfx_dpa_setting->DFPHigh, 0x0F);
2686 break;
2687 }
2688
2689 case INTERFACE_DFP_LOW:
2690 {
2691 viafb_write_reg_mask(CR99, VIACR,
2692 p_gfx_dpa_setting->DFPLow, 0x0F);
2693 break;
2694 }
2695
2696 case INTERFACE_DFP:
2697 {
2698 viafb_write_reg_mask(CR97, VIACR,
2699 p_gfx_dpa_setting->DFPHigh, 0x0F);
2700 viafb_write_reg_mask(CR99, VIACR,
2701 p_gfx_dpa_setting->DFPLow, 0x0F);
2702 break;
2703 }
2704 }
2705}
2706
Joseph Chand61e0bf2008-10-15 22:03:23 -07002707/*According var's xres, yres fill var's other timing information*/
2708void viafb_fill_var_timing_info(struct fb_var_screeninfo *var, int refresh,
2709 int mode_index)
2710{
2711 struct VideoModeTable *vmode_tbl = NULL;
2712 struct crt_mode_table *crt_timing = NULL;
2713 struct display_timing crt_reg;
2714 int i = 0, index = 0;
2715 vmode_tbl = &CLE266Modes[search_mode_setting(mode_index)];
2716 crt_timing = vmode_tbl->crtc;
2717 for (i = 0; i < vmode_tbl->mode_array; i++) {
2718 index = i;
2719 if (crt_timing[i].refresh_rate == refresh)
2720 break;
2721 }
2722
2723 crt_reg = crt_timing[index].crtc;
2724 switch (var->bits_per_pixel) {
2725 case 8:
2726 var->red.offset = 0;
2727 var->green.offset = 0;
2728 var->blue.offset = 0;
2729 var->red.length = 6;
2730 var->green.length = 6;
2731 var->blue.length = 6;
2732 break;
2733 case 16:
2734 var->red.offset = 11;
2735 var->green.offset = 5;
2736 var->blue.offset = 0;
2737 var->red.length = 5;
2738 var->green.length = 6;
2739 var->blue.length = 5;
2740 break;
2741 case 32:
2742 var->red.offset = 16;
2743 var->green.offset = 8;
2744 var->blue.offset = 0;
2745 var->red.length = 8;
2746 var->green.length = 8;
2747 var->blue.length = 8;
2748 break;
2749 default:
2750 /* never happed, put here to keep consistent */
2751 break;
2752 }
2753
2754 var->pixclock = viafb_get_pixclock(var->xres, var->yres, refresh);
2755 var->left_margin =
2756 crt_reg.hor_total - (crt_reg.hor_sync_start + crt_reg.hor_sync_end);
2757 var->right_margin = crt_reg.hor_sync_start - crt_reg.hor_addr;
2758 var->hsync_len = crt_reg.hor_sync_end;
2759 var->upper_margin =
2760 crt_reg.ver_total - (crt_reg.ver_sync_start + crt_reg.ver_sync_end);
2761 var->lower_margin = crt_reg.ver_sync_start - crt_reg.ver_addr;
2762 var->vsync_len = crt_reg.ver_sync_end;
2763}