blob: ff7a144044c8644147a890a464bab38e042adced [file] [log] [blame]
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001/*
2 * XG20, XG21, XG40, XG42 frame buffer device
3 * for Linux kernels 2.5.x, 2.6.x
4 * Base on TW's sis fbdev code.
5 */
6
Prashant P. Shahb654f872010-09-06 17:34:26 +05307/* #include <linux/config.h> */
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02008#include <linux/module.h>
9#include <linux/moduleparam.h>
10#include <linux/kernel.h>
11#include <linux/spinlock.h>
12#include <linux/errno.h>
13#include <linux/string.h>
14#include <linux/mm.h>
15#include <linux/tty.h>
16#include <linux/slab.h>
17#include <linux/delay.h>
18#include <linux/fb.h>
19#include <linux/console.h>
20#include <linux/selection.h>
21#include <linux/ioport.h>
22#include <linux/init.h>
23#include <linux/pci.h>
apatard@mandriva.comd7636e02010-05-19 10:44:14 +020024#include <linux/vt_kern.h>
25#include <linux/capability.h>
26#include <linux/fs.h>
27#include <linux/types.h>
28#include <linux/proc_fs.h>
apatard@mandriva.comd7636e02010-05-19 10:44:14 +020029
Kenji Toyamaa12c27c2011-04-26 12:13:43 +080030#include <linux/io.h>
apatard@mandriva.comd7636e02010-05-19 10:44:14 +020031#ifdef CONFIG_MTRR
32#include <asm/mtrr.h>
33#endif
34
35#include "XGIfb.h"
36#include "vgatypes.h"
37#include "XGI_main.h"
Aaro Koskinend542af52011-04-18 22:14:06 +030038#include "vb_init.h"
apatard@mandriva.comd7636e02010-05-19 10:44:14 +020039#include "vb_util.h"
Aaro Koskinend542af52011-04-18 22:14:06 +030040#include "vb_setmode.h"
apatard@mandriva.comd7636e02010-05-19 10:44:14 +020041
apatard@mandriva.comd7636e02010-05-19 10:44:14 +020042#define Index_CR_GPIO_Reg1 0x48
apatard@mandriva.comd7636e02010-05-19 10:44:14 +020043#define Index_CR_GPIO_Reg3 0x4a
44
45#define GPIOG_EN (1<<6)
apatard@mandriva.comd7636e02010-05-19 10:44:14 +020046#define GPIOG_READ (1<<1)
apatard@mandriva.comd7636e02010-05-19 10:44:14 +020047
Aaro Koskinen2d2c8802011-12-06 00:10:49 +020048static char *forcecrt2type;
Aaro Koskinendfbdf802011-08-29 23:14:25 +030049static char *mode;
Aaro Koskinenc3228302011-08-29 23:14:32 +030050static int vesa = -1;
Aaro Koskinen7548a832011-10-11 21:47:17 +030051static unsigned int refresh_rate;
Aaro Koskinendfbdf802011-08-29 23:14:25 +030052
apatard@mandriva.comd7636e02010-05-19 10:44:14 +020053/* -------------------- Macro definitions ---------------------------- */
54
55#undef XGIFBDEBUG
56
57#ifdef XGIFBDEBUG
58#define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt, __FUNCTION__ , ## args)
59#else
60#define DPRINTK(fmt, args...)
61#endif
62
63#ifdef XGIFBDEBUG
64static void dumpVGAReg(void)
65{
Prashant P. Shahb654f872010-09-06 17:34:26 +053066 u8 i, reg;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +020067
Aaro Koskinenb6e2dc32011-04-18 22:13:59 +030068 xgifb_reg_set(XGISR, 0x05, 0x86);
Prashant P. Shahb654f872010-09-06 17:34:26 +053069 /*
Aaro Koskinenb6e2dc32011-04-18 22:13:59 +030070 xgifb_reg_set(XGISR, 0x08, 0x4f);
71 xgifb_reg_set(XGISR, 0x0f, 0x20);
72 xgifb_reg_set(XGISR, 0x11, 0x4f);
73 xgifb_reg_set(XGISR, 0x13, 0x45);
74 xgifb_reg_set(XGISR, 0x14, 0x51);
75 xgifb_reg_set(XGISR, 0x1e, 0x41);
76 xgifb_reg_set(XGISR, 0x1f, 0x0);
77 xgifb_reg_set(XGISR, 0x20, 0xa1);
78 xgifb_reg_set(XGISR, 0x22, 0xfb);
79 xgifb_reg_set(XGISR, 0x26, 0x22);
80 xgifb_reg_set(XGISR, 0x3e, 0x07);
Prashant P. Shahb654f872010-09-06 17:34:26 +053081 */
apatard@mandriva.comd7636e02010-05-19 10:44:14 +020082
Aaro Koskinenb6e2dc32011-04-18 22:13:59 +030083 /* xgifb_reg_set(XGICR, 0x19, 0x00); */
84 /* xgifb_reg_set(XGICR, 0x1a, 0x3C); */
85 /* xgifb_reg_set(XGICR, 0x22, 0xff); */
86 /* xgifb_reg_set(XGICR, 0x3D, 0x10); */
apatard@mandriva.comd7636e02010-05-19 10:44:14 +020087
Aaro Koskinenb6e2dc32011-04-18 22:13:59 +030088 /* xgifb_reg_set(XGICR, 0x4a, 0xf3); */
apatard@mandriva.comd7636e02010-05-19 10:44:14 +020089
Aaro Koskinenb6e2dc32011-04-18 22:13:59 +030090 /* xgifb_reg_set(XGICR, 0x57, 0x0); */
91 /* xgifb_reg_set(XGICR, 0x7a, 0x2c); */
apatard@mandriva.comd7636e02010-05-19 10:44:14 +020092
Aaro Koskinenb6e2dc32011-04-18 22:13:59 +030093 /* xgifb_reg_set(XGICR, 0x82, 0xcc); */
94 /* xgifb_reg_set(XGICR, 0x8c, 0x0); */
Prashant P. Shahb654f872010-09-06 17:34:26 +053095 /*
Aaro Koskinenb6e2dc32011-04-18 22:13:59 +030096 xgifb_reg_set(XGICR, 0x99, 0x1);
97 xgifb_reg_set(XGICR, 0x41, 0x40);
Prashant P. Shahb654f872010-09-06 17:34:26 +053098 */
apatard@mandriva.comd7636e02010-05-19 10:44:14 +020099
Prashant P. Shahb654f872010-09-06 17:34:26 +0530100 for (i = 0; i < 0x4f; i++) {
Aaro Koskinen7e119b72011-04-18 22:13:58 +0300101 reg = xgifb_reg_get(XGISR, i);
Prashant P. Shahb654f872010-09-06 17:34:26 +0530102 printk("\no 3c4 %x", i);
103 printk("\ni 3c5 => %x", reg);
104 }
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200105
Prashant P. Shahb654f872010-09-06 17:34:26 +0530106 for (i = 0; i < 0xF0; i++) {
Aaro Koskinen7e119b72011-04-18 22:13:58 +0300107 reg = xgifb_reg_get(XGICR, i);
Prashant P. Shahb654f872010-09-06 17:34:26 +0530108 printk("\no 3d4 %x", i);
109 printk("\ni 3d5 => %x", reg);
110 }
111 /*
Aaro Koskinenb6e2dc32011-04-18 22:13:59 +0300112 xgifb_reg_set(XGIPART1,0x2F,1);
Prashant P. Shahb654f872010-09-06 17:34:26 +0530113 for (i=1; i < 0x50; i++) {
Aaro Koskinen7e119b72011-04-18 22:13:58 +0300114 reg = xgifb_reg_get(XGIPART1, i);
Prashant P. Shahb654f872010-09-06 17:34:26 +0530115 printk("\no d004 %x", i);
116 printk("\ni d005 => %x", reg);
117 }
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200118
Prashant P. Shahb654f872010-09-06 17:34:26 +0530119 for (i=0; i < 0x50; i++) {
Aaro Koskinen7e119b72011-04-18 22:13:58 +0300120 reg = xgifb_reg_get(XGIPART2, i);
Prashant P. Shahb654f872010-09-06 17:34:26 +0530121 printk("\no d010 %x", i);
122 printk("\ni d011 => %x", reg);
123 }
124 for (i=0; i < 0x50; i++) {
Aaro Koskinen7e119b72011-04-18 22:13:58 +0300125 reg = xgifb_reg_get(XGIPART3, i);
Prashant P. Shahb654f872010-09-06 17:34:26 +0530126 printk("\no d012 %x",i);
127 printk("\ni d013 => %x",reg);
128 }
129 for (i=0; i < 0x50; i++) {
Aaro Koskinen7e119b72011-04-18 22:13:58 +0300130 reg = xgifb_reg_get(XGIPART4, i);
Prashant P. Shahb654f872010-09-06 17:34:26 +0530131 printk("\no d014 %x",i);
132 printk("\ni d015 => %x",reg);
133 }
134 */
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200135}
136#else
Prashant P. Shahb654f872010-09-06 17:34:26 +0530137static inline void dumpVGAReg(void)
138{
139}
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200140#endif
141
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200142#if 1
143#define DEBUGPRN(x)
144#else
145#define DEBUGPRN(x) printk(KERN_INFO x "\n");
146#endif
147
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200148/* --------------- Hardware Access Routines -------------------------- */
149
Prashant P. Shahb654f872010-09-06 17:34:26 +0530150static int XGIfb_mode_rate_to_dclock(struct vb_device_info *XGI_Pr,
151 struct xgi_hw_device_info *HwDeviceExtension,
152 unsigned char modeno, unsigned char rateindex)
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200153{
Prashant P. Shahb654f872010-09-06 17:34:26 +0530154 unsigned short ModeNo = modeno;
155 unsigned short ModeIdIndex = 0, ClockIndex = 0;
156 unsigned short RefreshRateTableIndex = 0;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200157
Prashant P. Shahb654f872010-09-06 17:34:26 +0530158 /* unsigned long temp = 0; */
159 int Clock;
Prashant P. Shahb654f872010-09-06 17:34:26 +0530160 InitTo330Pointer(HwDeviceExtension->jChipType, XGI_Pr);
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200161
Prashant P. Shahb654f872010-09-06 17:34:26 +0530162 RefreshRateTableIndex = XGI_GetRatePtrCRT2(HwDeviceExtension, ModeNo,
163 ModeIdIndex, XGI_Pr);
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200164
Prashant P. Shahb654f872010-09-06 17:34:26 +0530165 /*
166 temp = XGI_SearchModeID(ModeNo , &ModeIdIndex, XGI_Pr) ;
167 if (!temp) {
168 printk(KERN_ERR "Could not find mode %x\n", ModeNo);
169 return 65000;
170 }
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200171
Prashant P. Shahb654f872010-09-06 17:34:26 +0530172 RefreshRateTableIndex = XGI_Pr->EModeIDTable[ModeIdIndex].REFindex;
173 RefreshRateTableIndex += (rateindex - 1);
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200174
Prashant P. Shahb654f872010-09-06 17:34:26 +0530175 */
176 ClockIndex = XGI_Pr->RefIndex[RefreshRateTableIndex].Ext_CRTVCLK;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200177
Prashant P. Shahb654f872010-09-06 17:34:26 +0530178 Clock = XGI_Pr->VCLKData[ClockIndex].CLOCK * 1000;
179
180 return Clock;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200181}
182
Prashant P. Shahb654f872010-09-06 17:34:26 +0530183static int XGIfb_mode_rate_to_ddata(struct vb_device_info *XGI_Pr,
184 struct xgi_hw_device_info *HwDeviceExtension,
185 unsigned char modeno, unsigned char rateindex,
186 u32 *left_margin, u32 *right_margin, u32 *upper_margin,
187 u32 *lower_margin, u32 *hsync_len, u32 *vsync_len, u32 *sync,
188 u32 *vmode)
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200189{
Prashant P. Shahb654f872010-09-06 17:34:26 +0530190 unsigned short ModeNo = modeno;
191 unsigned short ModeIdIndex = 0, index = 0;
192 unsigned short RefreshRateTableIndex = 0;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200193
Prashant P. Shahb654f872010-09-06 17:34:26 +0530194 unsigned short VRE, VBE, VRS, VBS, VDE, VT;
195 unsigned short HRE, HBE, HRS, HBS, HDE, HT;
196 unsigned char sr_data, cr_data, cr_data2;
197 unsigned long cr_data3;
198 int A, B, C, D, E, F, temp, j;
Prashant P. Shahb654f872010-09-06 17:34:26 +0530199 InitTo330Pointer(HwDeviceExtension->jChipType, XGI_Pr);
200 RefreshRateTableIndex = XGI_GetRatePtrCRT2(HwDeviceExtension, ModeNo,
201 ModeIdIndex, XGI_Pr);
202 /*
203 temp = XGI_SearchModeID(ModeNo, &ModeIdIndex, XGI_Pr);
204 if (!temp)
205 return 0;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200206
Prashant P. Shahb654f872010-09-06 17:34:26 +0530207 RefreshRateTableIndex = XGI_Pr->EModeIDTable[ModeIdIndex].REFindex;
208 RefreshRateTableIndex += (rateindex - 1);
209 */
210 index = XGI_Pr->RefIndex[RefreshRateTableIndex].Ext_CRT1CRTC;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200211
Prashant P. Shahb654f872010-09-06 17:34:26 +0530212 sr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[5];
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200213
Prashant P. Shahb654f872010-09-06 17:34:26 +0530214 cr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[0];
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200215
Prashant P. Shahb654f872010-09-06 17:34:26 +0530216 /* Horizontal total */
217 HT = (cr_data & 0xff) | ((unsigned short) (sr_data & 0x03) << 8);
218 A = HT + 5;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200219
Prashant P. Shahb654f872010-09-06 17:34:26 +0530220 /*
221 cr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[1];
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200222
Prashant P. Shahb654f872010-09-06 17:34:26 +0530223 Horizontal display enable end
224 HDE = (cr_data & 0xff) | ((unsigned short) (sr_data & 0x0C) << 6);
225 */
226 HDE = (XGI_Pr->RefIndex[RefreshRateTableIndex].XRes >> 3) - 1;
227 E = HDE + 1;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200228
Prashant P. Shahb654f872010-09-06 17:34:26 +0530229 cr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[3];
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200230
Prashant P. Shahb654f872010-09-06 17:34:26 +0530231 /* Horizontal retrace (=sync) start */
232 HRS = (cr_data & 0xff) | ((unsigned short) (sr_data & 0xC0) << 2);
233 F = HRS - E - 3;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200234
Prashant P. Shahb654f872010-09-06 17:34:26 +0530235 cr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[1];
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200236
Prashant P. Shahb654f872010-09-06 17:34:26 +0530237 /* Horizontal blank start */
238 HBS = (cr_data & 0xff) | ((unsigned short) (sr_data & 0x30) << 4);
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200239
Prashant P. Shahb654f872010-09-06 17:34:26 +0530240 sr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[6];
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200241
Prashant P. Shahb654f872010-09-06 17:34:26 +0530242 cr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[2];
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200243
Prashant P. Shahb654f872010-09-06 17:34:26 +0530244 cr_data2 = XGI_Pr->XGINEWUB_CRT1Table[index].CR[4];
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200245
Prashant P. Shahb654f872010-09-06 17:34:26 +0530246 /* Horizontal blank end */
247 HBE = (cr_data & 0x1f) | ((unsigned short) (cr_data2 & 0x80) >> 2)
248 | ((unsigned short) (sr_data & 0x03) << 6);
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200249
Prashant P. Shahb654f872010-09-06 17:34:26 +0530250 /* Horizontal retrace (=sync) end */
251 HRE = (cr_data2 & 0x1f) | ((sr_data & 0x04) << 3);
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200252
Prashant P. Shahb654f872010-09-06 17:34:26 +0530253 temp = HBE - ((E - 1) & 255);
254 B = (temp > 0) ? temp : (temp + 256);
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200255
Prashant P. Shahb654f872010-09-06 17:34:26 +0530256 temp = HRE - ((E + F + 3) & 63);
257 C = (temp > 0) ? temp : (temp + 64);
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200258
Prashant P. Shahb654f872010-09-06 17:34:26 +0530259 D = B - F - C;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200260
Prashant P. Shahb654f872010-09-06 17:34:26 +0530261 *left_margin = D * 8;
262 *right_margin = F * 8;
263 *hsync_len = C * 8;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200264
Prashant P. Shahb654f872010-09-06 17:34:26 +0530265 sr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[14];
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200266
Prashant P. Shahb654f872010-09-06 17:34:26 +0530267 cr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[8];
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200268
Prashant P. Shahb654f872010-09-06 17:34:26 +0530269 cr_data2 = XGI_Pr->XGINEWUB_CRT1Table[index].CR[9];
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200270
Prashant P. Shahb654f872010-09-06 17:34:26 +0530271 /* Vertical total */
272 VT = (cr_data & 0xFF) | ((unsigned short) (cr_data2 & 0x01) << 8)
273 | ((unsigned short) (cr_data2 & 0x20) << 4)
274 | ((unsigned short) (sr_data & 0x01) << 10);
275 A = VT + 2;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200276
Prashant P. Shahb654f872010-09-06 17:34:26 +0530277 /* cr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[10]; */
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200278
Prashant P. Shahb654f872010-09-06 17:34:26 +0530279 /* Vertical display enable end */
280 /*
281 VDE = (cr_data & 0xff) |
282 ((unsigned short) (cr_data2 & 0x02) << 7) |
283 ((unsigned short) (cr_data2 & 0x40) << 3) |
284 ((unsigned short) (sr_data & 0x02) << 9);
285 */
286 VDE = XGI_Pr->RefIndex[RefreshRateTableIndex].YRes - 1;
287 E = VDE + 1;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200288
Prashant P. Shahb654f872010-09-06 17:34:26 +0530289 cr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[10];
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200290
Prashant P. Shahb654f872010-09-06 17:34:26 +0530291 /* Vertical retrace (=sync) start */
292 VRS = (cr_data & 0xff) | ((unsigned short) (cr_data2 & 0x04) << 6)
293 | ((unsigned short) (cr_data2 & 0x80) << 2)
294 | ((unsigned short) (sr_data & 0x08) << 7);
295 F = VRS + 1 - E;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200296
Prashant P. Shahb654f872010-09-06 17:34:26 +0530297 cr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[12];
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200298
Prashant P. Shahb654f872010-09-06 17:34:26 +0530299 cr_data3 = (XGI_Pr->XGINEWUB_CRT1Table[index].CR[14] & 0x80) << 5;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200300
Prashant P. Shahb654f872010-09-06 17:34:26 +0530301 /* Vertical blank start */
302 VBS = (cr_data & 0xff) | ((unsigned short) (cr_data2 & 0x08) << 5)
303 | ((unsigned short) (cr_data3 & 0x20) << 4)
304 | ((unsigned short) (sr_data & 0x04) << 8);
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200305
Prashant P. Shahb654f872010-09-06 17:34:26 +0530306 cr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[13];
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200307
Prashant P. Shahb654f872010-09-06 17:34:26 +0530308 /* Vertical blank end */
309 VBE = (cr_data & 0xff) | ((unsigned short) (sr_data & 0x10) << 4);
310 temp = VBE - ((E - 1) & 511);
311 B = (temp > 0) ? temp : (temp + 512);
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200312
Prashant P. Shahb654f872010-09-06 17:34:26 +0530313 cr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[11];
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200314
Prashant P. Shahb654f872010-09-06 17:34:26 +0530315 /* Vertical retrace (=sync) end */
316 VRE = (cr_data & 0x0f) | ((sr_data & 0x20) >> 1);
317 temp = VRE - ((E + F - 1) & 31);
318 C = (temp > 0) ? temp : (temp + 32);
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200319
Prashant P. Shahb654f872010-09-06 17:34:26 +0530320 D = B - F - C;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200321
Prashant P. Shahb654f872010-09-06 17:34:26 +0530322 *upper_margin = D;
323 *lower_margin = F;
324 *vsync_len = C;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200325
Prashant P. Shahb654f872010-09-06 17:34:26 +0530326 if (XGI_Pr->RefIndex[RefreshRateTableIndex].Ext_InfoFlag & 0x8000)
327 *sync &= ~FB_SYNC_VERT_HIGH_ACT;
328 else
329 *sync |= FB_SYNC_VERT_HIGH_ACT;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200330
Prashant P. Shahb654f872010-09-06 17:34:26 +0530331 if (XGI_Pr->RefIndex[RefreshRateTableIndex].Ext_InfoFlag & 0x4000)
332 *sync &= ~FB_SYNC_HOR_HIGH_ACT;
333 else
334 *sync |= FB_SYNC_HOR_HIGH_ACT;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200335
Prashant P. Shahb654f872010-09-06 17:34:26 +0530336 *vmode = FB_VMODE_NONINTERLACED;
337 if (XGI_Pr->RefIndex[RefreshRateTableIndex].Ext_InfoFlag & 0x0080)
338 *vmode = FB_VMODE_INTERLACED;
339 else {
340 j = 0;
341 while (XGI_Pr->EModeIDTable[j].Ext_ModeID != 0xff) {
Kenji Toyamaa12c27c2011-04-26 12:13:43 +0800342 if (XGI_Pr->EModeIDTable[j].Ext_ModeID ==
343 XGI_Pr->RefIndex[RefreshRateTableIndex].ModeID) {
344 if (XGI_Pr->EModeIDTable[j].Ext_ModeFlag &
345 DoubleScanMode) {
Prashant P. Shahb654f872010-09-06 17:34:26 +0530346 *vmode = FB_VMODE_DOUBLE;
347 }
348 break;
349 }
350 j++;
351 }
352 }
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200353
Prashant P. Shahb654f872010-09-06 17:34:26 +0530354 return 1;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200355}
356
Randy Dunlap89229672010-08-10 08:46:44 -0700357static void XGIRegInit(struct vb_device_info *XGI_Pr, unsigned long BaseAddr)
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200358{
Prashant P. Shahb654f872010-09-06 17:34:26 +0530359 XGI_Pr->RelIO = BaseAddr;
360 XGI_Pr->P3c4 = BaseAddr + 0x14;
361 XGI_Pr->P3d4 = BaseAddr + 0x24;
362 XGI_Pr->P3c0 = BaseAddr + 0x10;
363 XGI_Pr->P3ce = BaseAddr + 0x1e;
364 XGI_Pr->P3c2 = BaseAddr + 0x12;
365 XGI_Pr->P3ca = BaseAddr + 0x1a;
366 XGI_Pr->P3c6 = BaseAddr + 0x16;
367 XGI_Pr->P3c7 = BaseAddr + 0x17;
368 XGI_Pr->P3c8 = BaseAddr + 0x18;
369 XGI_Pr->P3c9 = BaseAddr + 0x19;
370 XGI_Pr->P3da = BaseAddr + 0x2A;
Kenji Toyamaa12c27c2011-04-26 12:13:43 +0800371 /* Digital video interface registers (LCD) */
372 XGI_Pr->Part1Port = BaseAddr + XGI_CRT2_PORT_04;
373 /* 301 TV Encoder registers */
374 XGI_Pr->Part2Port = BaseAddr + XGI_CRT2_PORT_10;
375 /* 301 Macrovision registers */
376 XGI_Pr->Part3Port = BaseAddr + XGI_CRT2_PORT_12;
377 /* 301 VGA2 (and LCD) registers */
378 XGI_Pr->Part4Port = BaseAddr + XGI_CRT2_PORT_14;
379 /* 301 palette address port registers */
380 XGI_Pr->Part5Port = BaseAddr + XGI_CRT2_PORT_14 + 2;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200381
382}
383
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200384/* ------------------ Internal helper routines ----------------- */
385
Aaro Koskinenfab04b92011-12-06 00:10:45 +0200386static int XGIfb_GetXG21DefaultLVDSModeIdx(struct xgifb_video_info *xgifb_info)
Aaro Koskinenc4fa7df2011-04-18 22:14:05 +0300387{
388
389 int found_mode = 0;
390 int XGIfb_mode_idx = 0;
391
392 found_mode = 0;
393 while ((XGIbios_mode[XGIfb_mode_idx].mode_no != 0)
394 && (XGIbios_mode[XGIfb_mode_idx].xres
Aaro Koskinenfab04b92011-12-06 00:10:45 +0200395 <= xgifb_info->lvds_data.LVDSHDE)) {
Aaro Koskinenc4fa7df2011-04-18 22:14:05 +0300396 if ((XGIbios_mode[XGIfb_mode_idx].xres
Aaro Koskinenfab04b92011-12-06 00:10:45 +0200397 == xgifb_info->lvds_data.LVDSHDE)
Aaro Koskinenc4fa7df2011-04-18 22:14:05 +0300398 && (XGIbios_mode[XGIfb_mode_idx].yres
Aaro Koskinenfab04b92011-12-06 00:10:45 +0200399 == xgifb_info->lvds_data.LVDSVDE)
Aaro Koskinenc4fa7df2011-04-18 22:14:05 +0300400 && (XGIbios_mode[XGIfb_mode_idx].bpp == 8)) {
Aaro Koskinenc4fa7df2011-04-18 22:14:05 +0300401 found_mode = 1;
402 break;
403 }
404 XGIfb_mode_idx++;
405 }
406 if (!found_mode)
Aaro Koskinende736db2011-08-29 23:14:29 +0300407 XGIfb_mode_idx = -1;
Aaro Koskinenc4fa7df2011-04-18 22:14:05 +0300408
409 return XGIfb_mode_idx;
410}
411
Aaro Koskinenccf265a2011-10-11 21:47:22 +0300412static void XGIfb_search_mode(struct xgifb_video_info *xgifb_info,
413 const char *name)
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200414{
415 int i = 0, j = 0, l;
416
Prashant P. Shahb654f872010-09-06 17:34:26 +0530417 while (XGIbios_mode[i].mode_no != 0) {
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200418 l = min(strlen(name), strlen(XGIbios_mode[i].name));
419 if (!strncmp(name, XGIbios_mode[i].name, l)) {
Aaro Koskinenccf265a2011-10-11 21:47:22 +0300420 xgifb_info->mode_idx = i;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200421 j = 1;
422 break;
423 }
424 i++;
425 }
Prashant P. Shahb654f872010-09-06 17:34:26 +0530426 if (!j)
427 printk(KERN_INFO "XGIfb: Invalid mode '%s'\n", name);
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200428}
429
Aaro Koskinenccf265a2011-10-11 21:47:22 +0300430static void XGIfb_search_vesamode(struct xgifb_video_info *xgifb_info,
431 unsigned int vesamode)
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200432{
433 int i = 0, j = 0;
434
Aaro Koskinenc3228302011-08-29 23:14:32 +0300435 if (vesamode == 0)
436 goto invalid;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200437
Prashant P. Shahb654f872010-09-06 17:34:26 +0530438 vesamode &= 0x1dff; /* Clean VESA mode number from other flags */
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200439
Prashant P. Shahb654f872010-09-06 17:34:26 +0530440 while (XGIbios_mode[i].mode_no != 0) {
Kenji Toyamaa12c27c2011-04-26 12:13:43 +0800441 if ((XGIbios_mode[i].vesa_mode_no_1 == vesamode) ||
442 (XGIbios_mode[i].vesa_mode_no_2 == vesamode)) {
Aaro Koskinenccf265a2011-10-11 21:47:22 +0300443 xgifb_info->mode_idx = i;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200444 j = 1;
445 break;
446 }
447 i++;
448 }
Aaro Koskinenc3228302011-08-29 23:14:32 +0300449
450invalid:
Prashant P. Shahb654f872010-09-06 17:34:26 +0530451 if (!j)
452 printk(KERN_INFO "XGIfb: Invalid VESA mode 0x%x'\n", vesamode);
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200453}
454
Aaro Koskinenfd26d422011-10-11 21:47:19 +0300455static int XGIfb_validate_mode(struct xgifb_video_info *xgifb_info, int myindex)
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200456{
Prashant P. Shahb654f872010-09-06 17:34:26 +0530457 u16 xres, yres;
Aaro Koskinenfd26d422011-10-11 21:47:19 +0300458 struct xgi_hw_device_info *hw_info = &xgifb_info->hw_info;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200459
Aaro Koskinenfd26d422011-10-11 21:47:19 +0300460 if (xgifb_info->chip == XG21) {
Aaro Koskinen289ea522011-10-11 21:47:37 +0300461 if (xgifb_info->display2 == XGIFB_DISP_LCD) {
Aaro Koskinenfab04b92011-12-06 00:10:45 +0200462 xres = xgifb_info->lvds_data.LVDSHDE;
463 yres = xgifb_info->lvds_data.LVDSVDE;
Prashant P. Shahb654f872010-09-06 17:34:26 +0530464 if (XGIbios_mode[myindex].xres > xres)
465 return -1;
466 if (XGIbios_mode[myindex].yres > yres)
467 return -1;
Kenji Toyamaa12c27c2011-04-26 12:13:43 +0800468 if ((XGIbios_mode[myindex].xres < xres) &&
469 (XGIbios_mode[myindex].yres < yres)) {
Prashant P. Shahb654f872010-09-06 17:34:26 +0530470 if (XGIbios_mode[myindex].bpp > 8)
471 return -1;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200472 }
Prashant P. Shahb654f872010-09-06 17:34:26 +0530473
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200474 }
Prashant P. Shahb654f872010-09-06 17:34:26 +0530475 return myindex;
476
477 }
478
479 /* FIXME: for now, all is valid on XG27 */
Aaro Koskinenfd26d422011-10-11 21:47:19 +0300480 if (xgifb_info->chip == XG27)
Prashant P. Shahb654f872010-09-06 17:34:26 +0530481 return myindex;
482
483 if (!(XGIbios_mode[myindex].chipset & MD_XGI315))
484 return -1;
485
Aaro Koskinen289ea522011-10-11 21:47:37 +0300486 switch (xgifb_info->display2) {
487 case XGIFB_DISP_LCD:
Aaro Koskinenc62f2e42011-10-11 21:47:15 +0300488 switch (hw_info->ulCRT2LCDType) {
Prashant P. Shahb654f872010-09-06 17:34:26 +0530489 case LCD_640x480:
490 xres = 640;
491 yres = 480;
492 break;
493 case LCD_800x600:
494 xres = 800;
495 yres = 600;
496 break;
497 case LCD_1024x600:
498 xres = 1024;
499 yres = 600;
500 break;
501 case LCD_1024x768:
502 xres = 1024;
503 yres = 768;
504 break;
505 case LCD_1152x768:
506 xres = 1152;
507 yres = 768;
508 break;
509 case LCD_1280x960:
510 xres = 1280;
511 yres = 960;
512 break;
513 case LCD_1280x768:
514 xres = 1280;
515 yres = 768;
516 break;
517 case LCD_1280x1024:
518 xres = 1280;
519 yres = 1024;
520 break;
521 case LCD_1400x1050:
522 xres = 1400;
523 yres = 1050;
524 break;
525 case LCD_1600x1200:
526 xres = 1600;
527 yres = 1200;
528 break;
Prashant P. Shahb654f872010-09-06 17:34:26 +0530529 default:
530 xres = 0;
531 yres = 0;
532 break;
533 }
534 if (XGIbios_mode[myindex].xres > xres)
535 return -1;
536 if (XGIbios_mode[myindex].yres > yres)
537 return -1;
Aaro Koskinenc62f2e42011-10-11 21:47:15 +0300538 if ((hw_info->ulExternalChip == 0x01) || /* LVDS */
539 (hw_info->ulExternalChip == 0x05)) { /* LVDS+Chrontel */
Prashant P. Shahb654f872010-09-06 17:34:26 +0530540 switch (XGIbios_mode[myindex].xres) {
541 case 512:
542 if (XGIbios_mode[myindex].yres != 512)
543 return -1;
Aaro Koskinenc62f2e42011-10-11 21:47:15 +0300544 if (hw_info->ulCRT2LCDType == LCD_1024x600)
Prashant P. Shahb654f872010-09-06 17:34:26 +0530545 return -1;
546 break;
547 case 640:
548 if ((XGIbios_mode[myindex].yres != 400)
549 && (XGIbios_mode[myindex].yres
550 != 480))
551 return -1;
552 break;
553 case 800:
554 if (XGIbios_mode[myindex].yres != 600)
555 return -1;
556 break;
557 case 1024:
Kenji Toyamaa12c27c2011-04-26 12:13:43 +0800558 if ((XGIbios_mode[myindex].yres != 600) &&
559 (XGIbios_mode[myindex].yres != 768))
Prashant P. Shahb654f872010-09-06 17:34:26 +0530560 return -1;
Kenji Toyamaa12c27c2011-04-26 12:13:43 +0800561 if ((XGIbios_mode[myindex].yres == 600) &&
Aaro Koskinenc62f2e42011-10-11 21:47:15 +0300562 (hw_info->ulCRT2LCDType != LCD_1024x600))
Prashant P. Shahb654f872010-09-06 17:34:26 +0530563 return -1;
564 break;
565 case 1152:
566 if ((XGIbios_mode[myindex].yres) != 768)
567 return -1;
Aaro Koskinenc62f2e42011-10-11 21:47:15 +0300568 if (hw_info->ulCRT2LCDType != LCD_1152x768)
Prashant P. Shahb654f872010-09-06 17:34:26 +0530569 return -1;
570 break;
571 case 1280:
Kenji Toyamaa12c27c2011-04-26 12:13:43 +0800572 if ((XGIbios_mode[myindex].yres != 768) &&
573 (XGIbios_mode[myindex].yres != 1024))
Prashant P. Shahb654f872010-09-06 17:34:26 +0530574 return -1;
Kenji Toyamaa12c27c2011-04-26 12:13:43 +0800575 if ((XGIbios_mode[myindex].yres == 768) &&
Aaro Koskinenc62f2e42011-10-11 21:47:15 +0300576 (hw_info->ulCRT2LCDType != LCD_1280x768))
Prashant P. Shahb654f872010-09-06 17:34:26 +0530577 return -1;
578 break;
579 case 1400:
580 if (XGIbios_mode[myindex].yres != 1050)
581 return -1;
582 break;
583 case 1600:
584 if (XGIbios_mode[myindex].yres != 1200)
585 return -1;
586 break;
587 default:
588 return -1;
589 }
590 } else {
591 switch (XGIbios_mode[myindex].xres) {
592 case 512:
593 if (XGIbios_mode[myindex].yres != 512)
594 return -1;
595 break;
596 case 640:
Kenji Toyamaa12c27c2011-04-26 12:13:43 +0800597 if ((XGIbios_mode[myindex].yres != 400) &&
598 (XGIbios_mode[myindex].yres != 480))
Prashant P. Shahb654f872010-09-06 17:34:26 +0530599 return -1;
600 break;
601 case 800:
602 if (XGIbios_mode[myindex].yres != 600)
603 return -1;
604 break;
605 case 1024:
606 if (XGIbios_mode[myindex].yres != 768)
607 return -1;
608 break;
609 case 1280:
Kenji Toyamaa12c27c2011-04-26 12:13:43 +0800610 if ((XGIbios_mode[myindex].yres != 960) &&
611 (XGIbios_mode[myindex].yres != 1024))
Prashant P. Shahb654f872010-09-06 17:34:26 +0530612 return -1;
613 if (XGIbios_mode[myindex].yres == 960) {
Aaro Koskinenc62f2e42011-10-11 21:47:15 +0300614 if (hw_info->ulCRT2LCDType ==
Kenji Toyamaa12c27c2011-04-26 12:13:43 +0800615 LCD_1400x1050)
Prashant P. Shahb654f872010-09-06 17:34:26 +0530616 return -1;
617 }
618 break;
619 case 1400:
620 if (XGIbios_mode[myindex].yres != 1050)
621 return -1;
622 break;
623 case 1600:
624 if (XGIbios_mode[myindex].yres != 1200)
625 return -1;
626 break;
627 default:
628 return -1;
629 }
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200630 }
631 break;
Aaro Koskinen289ea522011-10-11 21:47:37 +0300632 case XGIFB_DISP_TV:
Prashant P. Shahb654f872010-09-06 17:34:26 +0530633 switch (XGIbios_mode[myindex].xres) {
634 case 512:
635 case 640:
636 case 800:
637 break;
638 case 720:
Aaro Koskinenfd26d422011-10-11 21:47:19 +0300639 if (xgifb_info->TV_type == TVMODE_NTSC) {
Prashant P. Shahb654f872010-09-06 17:34:26 +0530640 if (XGIbios_mode[myindex].yres != 480)
641 return -1;
Aaro Koskinenfd26d422011-10-11 21:47:19 +0300642 } else if (xgifb_info->TV_type == TVMODE_PAL) {
Prashant P. Shahb654f872010-09-06 17:34:26 +0530643 if (XGIbios_mode[myindex].yres != 576)
644 return -1;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200645 }
Prashant P. Shahb654f872010-09-06 17:34:26 +0530646 /* TW: LVDS/CHRONTEL does not support 720 */
Aaro Koskinenfd26d422011-10-11 21:47:19 +0300647 if (xgifb_info->hasVB == HASVB_LVDS_CHRONTEL ||
648 xgifb_info->hasVB == HASVB_CHRONTEL) {
Prashant P. Shahb654f872010-09-06 17:34:26 +0530649 return -1;
650 }
651 break;
652 case 1024:
Aaro Koskinenfd26d422011-10-11 21:47:19 +0300653 if (xgifb_info->TV_type == TVMODE_NTSC) {
Prashant P. Shahb654f872010-09-06 17:34:26 +0530654 if (XGIbios_mode[myindex].bpp == 32)
655 return -1;
656 }
Prashant P. Shahb654f872010-09-06 17:34:26 +0530657 break;
658 default:
659 return -1;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200660 }
661 break;
Aaro Koskinen289ea522011-10-11 21:47:37 +0300662 case XGIFB_DISP_CRT:
Prashant P. Shahb654f872010-09-06 17:34:26 +0530663 if (XGIbios_mode[myindex].xres > 1280)
664 return -1;
665 break;
Aaro Koskinen289ea522011-10-11 21:47:37 +0300666 case XGIFB_DISP_NONE:
667 break;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200668 }
Prashant P. Shahb654f872010-09-06 17:34:26 +0530669 return myindex;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200670
671}
672
673static void XGIfb_search_crt2type(const char *name)
674{
675 int i = 0;
676
Prashant P. Shahb654f872010-09-06 17:34:26 +0530677 if (name == NULL)
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200678 return;
679
Prashant P. Shahb654f872010-09-06 17:34:26 +0530680 while (XGI_crt2type[i].type_no != -1) {
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200681 if (!strcmp(name, XGI_crt2type[i].name)) {
682 XGIfb_crt2type = XGI_crt2type[i].type_no;
683 XGIfb_tvplug = XGI_crt2type[i].tvplug_no;
684 break;
685 }
686 i++;
687 }
Prashant P. Shahb654f872010-09-06 17:34:26 +0530688 if (XGIfb_crt2type < 0)
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200689 printk(KERN_INFO "XGIfb: Invalid CRT2 type: %s\n", name);
690}
691
Aaro Koskinenfd26d422011-10-11 21:47:19 +0300692static u8 XGIfb_search_refresh_rate(struct xgifb_video_info *xgifb_info,
693 unsigned int rate)
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200694{
695 u16 xres, yres;
696 int i = 0;
697
Aaro Koskinenccf265a2011-10-11 21:47:22 +0300698 xres = XGIbios_mode[xgifb_info->mode_idx].xres;
699 yres = XGIbios_mode[xgifb_info->mode_idx].yres;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200700
Aaro Koskinen5aa55d92011-10-11 21:47:23 +0300701 xgifb_info->rate_idx = 0;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200702 while ((XGIfb_vrate[i].idx != 0) && (XGIfb_vrate[i].xres <= xres)) {
Kenji Toyamaa12c27c2011-04-26 12:13:43 +0800703 if ((XGIfb_vrate[i].xres == xres) &&
704 (XGIfb_vrate[i].yres == yres)) {
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200705 if (XGIfb_vrate[i].refresh == rate) {
Aaro Koskinen5aa55d92011-10-11 21:47:23 +0300706 xgifb_info->rate_idx = XGIfb_vrate[i].idx;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200707 break;
708 } else if (XGIfb_vrate[i].refresh > rate) {
709 if ((XGIfb_vrate[i].refresh - rate) <= 3) {
710 DPRINTK("XGIfb: Adjusting rate from %d up to %d\n",
Kenji Toyamaa12c27c2011-04-26 12:13:43 +0800711 rate, XGIfb_vrate[i].refresh);
Aaro Koskinen5aa55d92011-10-11 21:47:23 +0300712 xgifb_info->rate_idx =
713 XGIfb_vrate[i].idx;
Aaro Koskinenfd26d422011-10-11 21:47:19 +0300714 xgifb_info->refresh_rate =
Kenji Toyamaa12c27c2011-04-26 12:13:43 +0800715 XGIfb_vrate[i].refresh;
Prashant P. Shahb654f872010-09-06 17:34:26 +0530716 } else if (((rate - XGIfb_vrate[i - 1].refresh)
717 <= 2) && (XGIfb_vrate[i].idx
718 != 1)) {
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200719 DPRINTK("XGIfb: Adjusting rate from %d down to %d\n",
Kenji Toyamaa12c27c2011-04-26 12:13:43 +0800720 rate, XGIfb_vrate[i-1].refresh);
Aaro Koskinen5aa55d92011-10-11 21:47:23 +0300721 xgifb_info->rate_idx =
722 XGIfb_vrate[i - 1].idx;
Aaro Koskinenfd26d422011-10-11 21:47:19 +0300723 xgifb_info->refresh_rate =
Kenji Toyamaa12c27c2011-04-26 12:13:43 +0800724 XGIfb_vrate[i - 1].refresh;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200725 }
726 break;
Prashant P. Shahb654f872010-09-06 17:34:26 +0530727 } else if ((rate - XGIfb_vrate[i].refresh) <= 2) {
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200728 DPRINTK("XGIfb: Adjusting rate from %d down to %d\n",
Kenji Toyamaa12c27c2011-04-26 12:13:43 +0800729 rate, XGIfb_vrate[i].refresh);
Aaro Koskinen5aa55d92011-10-11 21:47:23 +0300730 xgifb_info->rate_idx = XGIfb_vrate[i].idx;
Prashant P. Shahb654f872010-09-06 17:34:26 +0530731 break;
732 }
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200733 }
734 i++;
735 }
Aaro Koskinen5aa55d92011-10-11 21:47:23 +0300736 if (xgifb_info->rate_idx > 0) {
737 return xgifb_info->rate_idx;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200738 } else {
Kenji Toyamaa12c27c2011-04-26 12:13:43 +0800739 printk(KERN_INFO "XGIfb: Unsupported rate %d for %dx%d\n",
740 rate, xres, yres);
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200741 return 0;
742 }
743}
744
745static void XGIfb_search_tvstd(const char *name)
746{
747 int i = 0;
748
Prashant P. Shahb654f872010-09-06 17:34:26 +0530749 if (name == NULL)
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200750 return;
751
752 while (XGI_tvtype[i].type_no != -1) {
753 if (!strcmp(name, XGI_tvtype[i].name)) {
754 XGIfb_tvmode = XGI_tvtype[i].type_no;
755 break;
756 }
757 i++;
758 }
759}
760
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200761/* ----------- FBDev related routines for all series ----------- */
762
Aaro Koskinenfd26d422011-10-11 21:47:19 +0300763static void XGIfb_bpp_to_var(struct xgifb_video_info *xgifb_info,
764 struct fb_var_screeninfo *var)
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200765{
Prashant P. Shahb654f872010-09-06 17:34:26 +0530766 switch (var->bits_per_pixel) {
767 case 8:
768 var->red.offset = var->green.offset = var->blue.offset = 0;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200769 var->red.length = var->green.length = var->blue.length = 6;
Aaro Koskinenfd26d422011-10-11 21:47:19 +0300770 xgifb_info->video_cmap_len = 256;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200771 break;
Prashant P. Shahb654f872010-09-06 17:34:26 +0530772 case 16:
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200773 var->red.offset = 11;
774 var->red.length = 5;
775 var->green.offset = 5;
776 var->green.length = 6;
777 var->blue.offset = 0;
778 var->blue.length = 5;
779 var->transp.offset = 0;
780 var->transp.length = 0;
Aaro Koskinenfd26d422011-10-11 21:47:19 +0300781 xgifb_info->video_cmap_len = 16;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200782 break;
Prashant P. Shahb654f872010-09-06 17:34:26 +0530783 case 32:
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200784 var->red.offset = 16;
785 var->red.length = 8;
786 var->green.offset = 8;
787 var->green.length = 8;
788 var->blue.offset = 0;
789 var->blue.length = 8;
790 var->transp.offset = 24;
791 var->transp.length = 8;
Aaro Koskinenfd26d422011-10-11 21:47:19 +0300792 xgifb_info->video_cmap_len = 16;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200793 break;
794 }
795}
796
Aaro Koskinenc4fa7df2011-04-18 22:14:05 +0300797/* --------------------- SetMode routines ------------------------- */
798
Aaro Koskinenfd26d422011-10-11 21:47:19 +0300799static void XGIfb_pre_setmode(struct xgifb_video_info *xgifb_info)
Aaro Koskinenc4fa7df2011-04-18 22:14:05 +0300800{
801 u8 cr30 = 0, cr31 = 0;
802
803 cr31 = xgifb_reg_get(XGICR, 0x31);
804 cr31 &= ~0x60;
805
Aaro Koskinen289ea522011-10-11 21:47:37 +0300806 switch (xgifb_info->display2) {
807 case XGIFB_DISP_CRT:
Peter Huewefc39dcb2012-01-15 19:22:12 +0100808 cr30 = (SIS_VB_OUTPUT_CRT2 | SIS_SIMULTANEOUS_VIEW_ENABLE);
809 cr31 |= SIS_DRIVER_MODE;
Aaro Koskinenc4fa7df2011-04-18 22:14:05 +0300810 break;
Aaro Koskinen289ea522011-10-11 21:47:37 +0300811 case XGIFB_DISP_LCD:
Peter Huewefc39dcb2012-01-15 19:22:12 +0100812 cr30 = (SIS_VB_OUTPUT_LCD | SIS_SIMULTANEOUS_VIEW_ENABLE);
813 cr31 |= SIS_DRIVER_MODE;
Aaro Koskinenc4fa7df2011-04-18 22:14:05 +0300814 break;
Aaro Koskinen289ea522011-10-11 21:47:37 +0300815 case XGIFB_DISP_TV:
Aaro Koskinenfd26d422011-10-11 21:47:19 +0300816 if (xgifb_info->TV_type == TVMODE_HIVISION)
Peter Huewefc39dcb2012-01-15 19:22:12 +0100817 cr30 = (SIS_VB_OUTPUT_HIVISION
818 | SIS_SIMULTANEOUS_VIEW_ENABLE);
Aaro Koskinenfd26d422011-10-11 21:47:19 +0300819 else if (xgifb_info->TV_plug == TVPLUG_SVIDEO)
Peter Huewefc39dcb2012-01-15 19:22:12 +0100820 cr30 = (SIS_VB_OUTPUT_SVIDEO
821 | SIS_SIMULTANEOUS_VIEW_ENABLE);
Aaro Koskinenfd26d422011-10-11 21:47:19 +0300822 else if (xgifb_info->TV_plug == TVPLUG_COMPOSITE)
Peter Huewefc39dcb2012-01-15 19:22:12 +0100823 cr30 = (SIS_VB_OUTPUT_COMPOSITE
824 | SIS_SIMULTANEOUS_VIEW_ENABLE);
Aaro Koskinenfd26d422011-10-11 21:47:19 +0300825 else if (xgifb_info->TV_plug == TVPLUG_SCART)
Peter Huewefc39dcb2012-01-15 19:22:12 +0100826 cr30 = (SIS_VB_OUTPUT_SCART
827 | SIS_SIMULTANEOUS_VIEW_ENABLE);
828 cr31 |= SIS_DRIVER_MODE;
Aaro Koskinenc4fa7df2011-04-18 22:14:05 +0300829
Aaro Koskinenfd26d422011-10-11 21:47:19 +0300830 if (XGIfb_tvmode == 1 || xgifb_info->TV_type == TVMODE_PAL)
Aaro Koskinenc4fa7df2011-04-18 22:14:05 +0300831 cr31 |= 0x01;
832 else
833 cr31 &= ~0x01;
834 break;
835 default: /* disable CRT2 */
836 cr30 = 0x00;
Peter Huewefc39dcb2012-01-15 19:22:12 +0100837 cr31 |= (SIS_DRIVER_MODE | SIS_VB_OUTPUT_DISABLE);
Aaro Koskinenc4fa7df2011-04-18 22:14:05 +0300838 }
839
840 xgifb_reg_set(XGICR, IND_XGI_SCRATCH_REG_CR30, cr30);
841 xgifb_reg_set(XGICR, IND_XGI_SCRATCH_REG_CR31, cr31);
Aaro Koskinen5aa55d92011-10-11 21:47:23 +0300842 xgifb_reg_set(XGICR, IND_XGI_SCRATCH_REG_CR33,
843 (xgifb_info->rate_idx & 0x0F));
Aaro Koskinenc4fa7df2011-04-18 22:14:05 +0300844}
845
Aaro Koskinenfd26d422011-10-11 21:47:19 +0300846static void XGIfb_post_setmode(struct xgifb_video_info *xgifb_info)
Aaro Koskinenc4fa7df2011-04-18 22:14:05 +0300847{
848 u8 reg;
849 unsigned char doit = 1;
850 /*
Peter Huewefc39dcb2012-01-15 19:22:12 +0100851 xgifb_reg_set(XGISR,IND_SIS_PASSWORD,SIS_PASSWORD);
Aaro Koskinenc4fa7df2011-04-18 22:14:05 +0300852 xgifb_reg_set(XGICR, 0x13, 0x00);
853 xgifb_reg_and_or(XGISR,0x0E, 0xF0, 0x01);
854 *test*
855 */
Aaro Koskinenfd26d422011-10-11 21:47:19 +0300856 if (xgifb_info->video_bpp == 8) {
Kenji Toyamaa12c27c2011-04-26 12:13:43 +0800857 /* TW: We can't switch off CRT1 on LVDS/Chrontel
858 * in 8bpp Modes */
Aaro Koskinenfd26d422011-10-11 21:47:19 +0300859 if ((xgifb_info->hasVB == HASVB_LVDS) ||
860 (xgifb_info->hasVB == HASVB_LVDS_CHRONTEL)) {
Aaro Koskinenc4fa7df2011-04-18 22:14:05 +0300861 doit = 0;
862 }
Kenji Toyamaa12c27c2011-04-26 12:13:43 +0800863 /* TW: We can't switch off CRT1 on 301B-DH
864 * in 8bpp Modes if using LCD */
Aaro Koskinen289ea522011-10-11 21:47:37 +0300865 if (xgifb_info->display2 == XGIFB_DISP_LCD)
Aaro Koskinenc4fa7df2011-04-18 22:14:05 +0300866 doit = 0;
867 }
868
869 /* TW: We can't switch off CRT1 if bridge is in slave mode */
Aaro Koskinenfd26d422011-10-11 21:47:19 +0300870 if (xgifb_info->hasVB != HASVB_NONE) {
Aaro Koskinenc4fa7df2011-04-18 22:14:05 +0300871 reg = xgifb_reg_get(XGIPART1, 0x00);
872
873 if ((reg & 0x50) == 0x10)
874 doit = 0;
875
876 } else {
877 XGIfb_crt1off = 0;
878 }
879
880 reg = xgifb_reg_get(XGICR, 0x17);
881 if ((XGIfb_crt1off) && (doit))
882 reg &= ~0x80;
883 else
884 reg |= 0x80;
885 xgifb_reg_set(XGICR, 0x17, reg);
886
Peter Huewefc39dcb2012-01-15 19:22:12 +0100887 xgifb_reg_and(XGISR, IND_SIS_RAMDAC_CONTROL, ~0x04);
Aaro Koskinenc4fa7df2011-04-18 22:14:05 +0300888
Aaro Koskinen289ea522011-10-11 21:47:37 +0300889 if (xgifb_info->display2 == XGIFB_DISP_TV &&
890 xgifb_info->hasVB == HASVB_301) {
Aaro Koskinenc4fa7df2011-04-18 22:14:05 +0300891
892 reg = xgifb_reg_get(XGIPART4, 0x01);
893
894 if (reg < 0xB0) { /* Set filter for XGI301 */
Aaro Koskinen84a6c462011-10-11 21:47:28 +0300895 int filter_tb;
896
Aaro Koskinenfd26d422011-10-11 21:47:19 +0300897 switch (xgifb_info->video_width) {
Aaro Koskinenc4fa7df2011-04-18 22:14:05 +0300898 case 320:
Aaro Koskinenfd26d422011-10-11 21:47:19 +0300899 filter_tb = (xgifb_info->TV_type ==
Kenji Toyamaa12c27c2011-04-26 12:13:43 +0800900 TVMODE_NTSC) ? 4 : 12;
Aaro Koskinenc4fa7df2011-04-18 22:14:05 +0300901 break;
902 case 640:
Aaro Koskinenfd26d422011-10-11 21:47:19 +0300903 filter_tb = (xgifb_info->TV_type ==
Kenji Toyamaa12c27c2011-04-26 12:13:43 +0800904 TVMODE_NTSC) ? 5 : 13;
Aaro Koskinenc4fa7df2011-04-18 22:14:05 +0300905 break;
906 case 720:
Aaro Koskinenfd26d422011-10-11 21:47:19 +0300907 filter_tb = (xgifb_info->TV_type ==
Kenji Toyamaa12c27c2011-04-26 12:13:43 +0800908 TVMODE_NTSC) ? 6 : 14;
Aaro Koskinenc4fa7df2011-04-18 22:14:05 +0300909 break;
910 case 800:
Aaro Koskinenfd26d422011-10-11 21:47:19 +0300911 filter_tb = (xgifb_info->TV_type ==
Kenji Toyamaa12c27c2011-04-26 12:13:43 +0800912 TVMODE_NTSC) ? 7 : 15;
Aaro Koskinenc4fa7df2011-04-18 22:14:05 +0300913 break;
914 default:
Aaro Koskinen84a6c462011-10-11 21:47:28 +0300915 filter_tb = 0;
Aaro Koskinenc4fa7df2011-04-18 22:14:05 +0300916 filter = -1;
917 break;
918 }
Aaro Koskinen39f10bf2011-10-11 21:47:25 +0300919 xgifb_reg_or(XGIPART1,
Peter Huewefc39dcb2012-01-15 19:22:12 +0100920 SIS_CRT2_WENABLE_315,
Aaro Koskinen39f10bf2011-10-11 21:47:25 +0300921 0x01);
Aaro Koskinenc4fa7df2011-04-18 22:14:05 +0300922
Aaro Koskinenfd26d422011-10-11 21:47:19 +0300923 if (xgifb_info->TV_type == TVMODE_NTSC) {
Aaro Koskinenc4fa7df2011-04-18 22:14:05 +0300924
925 xgifb_reg_and(XGIPART2, 0x3a, 0x1f);
926
Aaro Koskinenfd26d422011-10-11 21:47:19 +0300927 if (xgifb_info->TV_plug == TVPLUG_SVIDEO) {
Aaro Koskinenc4fa7df2011-04-18 22:14:05 +0300928
929 xgifb_reg_and(XGIPART2, 0x30, 0xdf);
930
Aaro Koskinenfd26d422011-10-11 21:47:19 +0300931 } else if (xgifb_info->TV_plug
Aaro Koskinenc4fa7df2011-04-18 22:14:05 +0300932 == TVPLUG_COMPOSITE) {
933
934 xgifb_reg_or(XGIPART2, 0x30, 0x20);
935
Aaro Koskinenfd26d422011-10-11 21:47:19 +0300936 switch (xgifb_info->video_width) {
Aaro Koskinenc4fa7df2011-04-18 22:14:05 +0300937 case 640:
Kenji Toyamaa12c27c2011-04-26 12:13:43 +0800938 xgifb_reg_set(XGIPART2,
939 0x35,
940 0xEB);
941 xgifb_reg_set(XGIPART2,
942 0x36,
943 0x04);
944 xgifb_reg_set(XGIPART2,
945 0x37,
946 0x25);
947 xgifb_reg_set(XGIPART2,
948 0x38,
949 0x18);
Aaro Koskinenc4fa7df2011-04-18 22:14:05 +0300950 break;
951 case 720:
Kenji Toyamaa12c27c2011-04-26 12:13:43 +0800952 xgifb_reg_set(XGIPART2,
953 0x35,
954 0xEE);
955 xgifb_reg_set(XGIPART2,
956 0x36,
957 0x0C);
958 xgifb_reg_set(XGIPART2,
959 0x37,
960 0x22);
961 xgifb_reg_set(XGIPART2,
962 0x38,
963 0x08);
Aaro Koskinenc4fa7df2011-04-18 22:14:05 +0300964 break;
965 case 800:
Kenji Toyamaa12c27c2011-04-26 12:13:43 +0800966 xgifb_reg_set(XGIPART2,
967 0x35,
968 0xEB);
969 xgifb_reg_set(XGIPART2,
970 0x36,
971 0x15);
972 xgifb_reg_set(XGIPART2,
973 0x37,
974 0x25);
975 xgifb_reg_set(XGIPART2,
976 0x38,
977 0xF6);
Aaro Koskinenc4fa7df2011-04-18 22:14:05 +0300978 break;
979 }
980 }
981
Aaro Koskinenfd26d422011-10-11 21:47:19 +0300982 } else if (xgifb_info->TV_type == TVMODE_PAL) {
Aaro Koskinenc4fa7df2011-04-18 22:14:05 +0300983
984 xgifb_reg_and(XGIPART2, 0x3A, 0x1F);
985
Aaro Koskinenfd26d422011-10-11 21:47:19 +0300986 if (xgifb_info->TV_plug == TVPLUG_SVIDEO) {
Aaro Koskinenc4fa7df2011-04-18 22:14:05 +0300987
988 xgifb_reg_and(XGIPART2, 0x30, 0xDF);
989
Aaro Koskinenfd26d422011-10-11 21:47:19 +0300990 } else if (xgifb_info->TV_plug
Aaro Koskinenc4fa7df2011-04-18 22:14:05 +0300991 == TVPLUG_COMPOSITE) {
992
993 xgifb_reg_or(XGIPART2, 0x30, 0x20);
994
Aaro Koskinenfd26d422011-10-11 21:47:19 +0300995 switch (xgifb_info->video_width) {
Aaro Koskinenc4fa7df2011-04-18 22:14:05 +0300996 case 640:
Kenji Toyamaa12c27c2011-04-26 12:13:43 +0800997 xgifb_reg_set(XGIPART2,
998 0x35,
999 0xF1);
1000 xgifb_reg_set(XGIPART2,
1001 0x36,
1002 0xF7);
1003 xgifb_reg_set(XGIPART2,
1004 0x37,
1005 0x1F);
1006 xgifb_reg_set(XGIPART2,
1007 0x38,
1008 0x32);
Aaro Koskinenc4fa7df2011-04-18 22:14:05 +03001009 break;
1010 case 720:
Kenji Toyamaa12c27c2011-04-26 12:13:43 +08001011 xgifb_reg_set(XGIPART2,
1012 0x35,
1013 0xF3);
1014 xgifb_reg_set(XGIPART2,
1015 0x36,
1016 0x00);
1017 xgifb_reg_set(XGIPART2,
1018 0x37,
1019 0x1D);
1020 xgifb_reg_set(XGIPART2,
1021 0x38,
1022 0x20);
Aaro Koskinenc4fa7df2011-04-18 22:14:05 +03001023 break;
1024 case 800:
Kenji Toyamaa12c27c2011-04-26 12:13:43 +08001025 xgifb_reg_set(XGIPART2,
1026 0x35,
1027 0xFC);
1028 xgifb_reg_set(XGIPART2,
1029 0x36,
1030 0xFB);
1031 xgifb_reg_set(XGIPART2,
1032 0x37,
1033 0x14);
1034 xgifb_reg_set(XGIPART2,
1035 0x38,
1036 0x2A);
Aaro Koskinenc4fa7df2011-04-18 22:14:05 +03001037 break;
1038 }
1039 }
1040 }
1041
1042 if ((filter >= 0) && (filter <= 7)) {
Kenji Toyamaa12c27c2011-04-26 12:13:43 +08001043 DPRINTK("FilterTable[%d]-%d: %02x %02x %02x %02x\n",
1044 filter_tb, filter,
1045 XGI_TV_filter[filter_tb].
1046 filter[filter][0],
1047 XGI_TV_filter[filter_tb].
1048 filter[filter][1],
1049 XGI_TV_filter[filter_tb].
1050 filter[filter][2],
1051 XGI_TV_filter[filter_tb].
1052 filter[filter][3]
Aaro Koskinenc4fa7df2011-04-18 22:14:05 +03001053 );
1054 xgifb_reg_set(
Kenji Toyamaa12c27c2011-04-26 12:13:43 +08001055 XGIPART2,
1056 0x35,
1057 (XGI_TV_filter[filter_tb].
1058 filter[filter][0]));
Aaro Koskinenc4fa7df2011-04-18 22:14:05 +03001059 xgifb_reg_set(
Kenji Toyamaa12c27c2011-04-26 12:13:43 +08001060 XGIPART2,
1061 0x36,
1062 (XGI_TV_filter[filter_tb].
1063 filter[filter][1]));
Aaro Koskinenc4fa7df2011-04-18 22:14:05 +03001064 xgifb_reg_set(
Kenji Toyamaa12c27c2011-04-26 12:13:43 +08001065 XGIPART2,
1066 0x37,
1067 (XGI_TV_filter[filter_tb].
1068 filter[filter][2]));
Aaro Koskinenc4fa7df2011-04-18 22:14:05 +03001069 xgifb_reg_set(
Kenji Toyamaa12c27c2011-04-26 12:13:43 +08001070 XGIPART2,
1071 0x38,
1072 (XGI_TV_filter[filter_tb].
1073 filter[filter][3]));
Aaro Koskinenc4fa7df2011-04-18 22:14:05 +03001074 }
Aaro Koskinenc4fa7df2011-04-18 22:14:05 +03001075 }
Aaro Koskinenc4fa7df2011-04-18 22:14:05 +03001076 }
Aaro Koskinenc4fa7df2011-04-18 22:14:05 +03001077}
1078
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001079static int XGIfb_do_set_var(struct fb_var_screeninfo *var, int isactive,
Prashant P. Shahb654f872010-09-06 17:34:26 +05301080 struct fb_info *info)
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001081{
Aaro Koskinenfd26d422011-10-11 21:47:19 +03001082 struct xgifb_video_info *xgifb_info = info->par;
1083 struct xgi_hw_device_info *hw_info = &xgifb_info->hw_info;
Prashant P. Shahb654f872010-09-06 17:34:26 +05301084 unsigned int htotal = var->left_margin + var->xres + var->right_margin
1085 + var->hsync_len;
1086 unsigned int vtotal = var->upper_margin + var->yres + var->lower_margin
1087 + var->vsync_len;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001088#if defined(__powerpc__)
1089 u8 sr_data, cr_data;
1090#endif
1091 unsigned int drate = 0, hrate = 0;
1092 int found_mode = 0;
1093 int old_mode;
Prashant P. Shahb654f872010-09-06 17:34:26 +05301094 /* unsigned char reg, reg1; */
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001095
1096 DEBUGPRN("Inside do_set_var");
Prashant P. Shahb654f872010-09-06 17:34:26 +05301097 /* printk(KERN_DEBUG "XGIfb:var->yres=%d, var->upper_margin=%d, var->lower_margin=%d, var->vsync_len=%d\n", var->yres, var->upper_margin, var->lower_margin, var->vsync_len); */
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001098
Prashant P. Shahb654f872010-09-06 17:34:26 +05301099 info->var.xres_virtual = var->xres_virtual;
1100 info->var.yres_virtual = var->yres_virtual;
1101 info->var.bits_per_pixel = var->bits_per_pixel;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001102
1103 if ((var->vmode & FB_VMODE_MASK) == FB_VMODE_NONINTERLACED)
1104 vtotal <<= 1;
1105 else if ((var->vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE)
1106 vtotal <<= 2;
Prashant P. Shahb654f872010-09-06 17:34:26 +05301107 else if ((var->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) {
1108 /* vtotal <<= 1; */
1109 /* var->yres <<= 1; */
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001110 }
1111
Prashant P. Shahb654f872010-09-06 17:34:26 +05301112 if (!htotal || !vtotal) {
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001113 DPRINTK("XGIfb: Invalid 'var' information\n");
1114 return -EINVAL;
Prashant P. Shahb654f872010-09-06 17:34:26 +05301115 } printk(KERN_DEBUG "XGIfb: var->pixclock=%d, htotal=%d, vtotal=%d\n",
1116 var->pixclock, htotal, vtotal);
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001117
Prashant P. Shahb654f872010-09-06 17:34:26 +05301118 if (var->pixclock && htotal && vtotal) {
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001119 drate = 1000000000 / var->pixclock;
1120 hrate = (drate * 1000) / htotal;
Aaro Koskinenfd26d422011-10-11 21:47:19 +03001121 xgifb_info->refresh_rate = (unsigned int) (hrate * 2
Prashant P. Shahb654f872010-09-06 17:34:26 +05301122 / vtotal);
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001123 } else {
Aaro Koskinenfd26d422011-10-11 21:47:19 +03001124 xgifb_info->refresh_rate = 60;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001125 }
1126
1127 printk(KERN_DEBUG "XGIfb: Change mode to %dx%dx%d-%dHz\n",
Kenji Toyamaa12c27c2011-04-26 12:13:43 +08001128 var->xres,
1129 var->yres,
1130 var->bits_per_pixel,
Aaro Koskinenfd26d422011-10-11 21:47:19 +03001131 xgifb_info->refresh_rate);
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001132
Aaro Koskinenccf265a2011-10-11 21:47:22 +03001133 old_mode = xgifb_info->mode_idx;
1134 xgifb_info->mode_idx = 0;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001135
Aaro Koskinenccf265a2011-10-11 21:47:22 +03001136 while ((XGIbios_mode[xgifb_info->mode_idx].mode_no != 0) &&
1137 (XGIbios_mode[xgifb_info->mode_idx].xres <= var->xres)) {
1138 if ((XGIbios_mode[xgifb_info->mode_idx].xres == var->xres) &&
1139 (XGIbios_mode[xgifb_info->mode_idx].yres == var->yres) &&
1140 (XGIbios_mode[xgifb_info->mode_idx].bpp
Prashant P. Shahb654f872010-09-06 17:34:26 +05301141 == var->bits_per_pixel)) {
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001142 found_mode = 1;
1143 break;
1144 }
Aaro Koskinenccf265a2011-10-11 21:47:22 +03001145 xgifb_info->mode_idx++;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001146 }
1147
Prashant P. Shahb654f872010-09-06 17:34:26 +05301148 if (found_mode)
Aaro Koskinenccf265a2011-10-11 21:47:22 +03001149 xgifb_info->mode_idx = XGIfb_validate_mode(xgifb_info,
1150 xgifb_info->mode_idx);
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001151 else
Aaro Koskinenccf265a2011-10-11 21:47:22 +03001152 xgifb_info->mode_idx = -1;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001153
Aaro Koskinenccf265a2011-10-11 21:47:22 +03001154 if (xgifb_info->mode_idx < 0) {
Kenji Toyamaa12c27c2011-04-26 12:13:43 +08001155 printk(KERN_ERR "XGIfb: Mode %dx%dx%d not supported\n",
1156 var->xres, var->yres, var->bits_per_pixel);
Aaro Koskinenccf265a2011-10-11 21:47:22 +03001157 xgifb_info->mode_idx = old_mode;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001158 return -EINVAL;
1159 }
1160
Aaro Koskinenfd26d422011-10-11 21:47:19 +03001161 if (XGIfb_search_refresh_rate(xgifb_info,
1162 xgifb_info->refresh_rate) == 0) {
Aaro Koskinen5aa55d92011-10-11 21:47:23 +03001163 xgifb_info->rate_idx =
1164 XGIbios_mode[xgifb_info->mode_idx].rate_idx;
Aaro Koskinenfd26d422011-10-11 21:47:19 +03001165 xgifb_info->refresh_rate = 60;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001166 }
1167
Prashant P. Shahb654f872010-09-06 17:34:26 +05301168 if (isactive) {
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001169
Aaro Koskinenfd26d422011-10-11 21:47:19 +03001170 XGIfb_pre_setmode(xgifb_info);
Aaro Koskinenfab04b92011-12-06 00:10:45 +02001171 if (XGISetModeNew(xgifb_info, hw_info,
Aaro Koskinenccf265a2011-10-11 21:47:22 +03001172 XGIbios_mode[xgifb_info->mode_idx].mode_no)
1173 == 0) {
Kenji Toyamaa12c27c2011-04-26 12:13:43 +08001174 printk(KERN_ERR "XGIfb: Setting mode[0x%x] failed\n",
Aaro Koskinenccf265a2011-10-11 21:47:22 +03001175 XGIbios_mode[xgifb_info->mode_idx].mode_no);
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001176 return -EINVAL;
1177 }
Prashant P. Shahb654f872010-09-06 17:34:26 +05301178 info->fix.line_length = ((info->var.xres_virtual
1179 * info->var.bits_per_pixel) >> 6);
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001180
Peter Huewefc39dcb2012-01-15 19:22:12 +01001181 xgifb_reg_set(XGISR, IND_SIS_PASSWORD, SIS_PASSWORD);
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001182
Aaro Koskinenb6e2dc32011-04-18 22:13:59 +03001183 xgifb_reg_set(XGICR, 0x13, (info->fix.line_length & 0x00ff));
Kenji Toyamaa12c27c2011-04-26 12:13:43 +08001184 xgifb_reg_set(XGISR,
1185 0x0E,
1186 (info->fix.line_length & 0xff00) >> 8);
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001187
Aaro Koskinenfd26d422011-10-11 21:47:19 +03001188 XGIfb_post_setmode(xgifb_info);
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001189
Prashant P. Shahb654f872010-09-06 17:34:26 +05301190 DPRINTK("XGIfb: Set new mode: %dx%dx%d-%d\n",
Aaro Koskinenccf265a2011-10-11 21:47:22 +03001191 XGIbios_mode[xgifb_info->mode_idx].xres,
1192 XGIbios_mode[xgifb_info->mode_idx].yres,
1193 XGIbios_mode[xgifb_info->mode_idx].bpp,
Aaro Koskinenfd26d422011-10-11 21:47:19 +03001194 xgifb_info->refresh_rate);
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001195
Aaro Koskinenccf265a2011-10-11 21:47:22 +03001196 xgifb_info->video_bpp = XGIbios_mode[xgifb_info->mode_idx].bpp;
Aaro Koskinenfd26d422011-10-11 21:47:19 +03001197 xgifb_info->video_vwidth = info->var.xres_virtual;
Aaro Koskinenccf265a2011-10-11 21:47:22 +03001198 xgifb_info->video_width =
1199 XGIbios_mode[xgifb_info->mode_idx].xres;
Aaro Koskinenfd26d422011-10-11 21:47:19 +03001200 xgifb_info->video_vheight = info->var.yres_virtual;
Aaro Koskinenccf265a2011-10-11 21:47:22 +03001201 xgifb_info->video_height =
1202 XGIbios_mode[xgifb_info->mode_idx].yres;
Aaro Koskinenfd26d422011-10-11 21:47:19 +03001203 xgifb_info->org_x = xgifb_info->org_y = 0;
1204 xgifb_info->video_linelength = info->var.xres_virtual
1205 * (xgifb_info->video_bpp >> 3);
1206 switch (xgifb_info->video_bpp) {
Prashant P. Shahb654f872010-09-06 17:34:26 +05301207 case 8:
Aaro Koskinenfd26d422011-10-11 21:47:19 +03001208 xgifb_info->DstColor = 0x0000;
1209 xgifb_info->XGI310_AccelDepth = 0x00000000;
1210 xgifb_info->video_cmap_len = 256;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001211#if defined(__powerpc__)
Aaro Koskinen7e119b72011-04-18 22:13:58 +03001212 cr_data = xgifb_reg_get(XGICR, 0x4D);
Aaro Koskinenb6e2dc32011-04-18 22:13:59 +03001213 xgifb_reg_set(XGICR, 0x4D, (cr_data & 0xE0));
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001214#endif
Prashant P. Shahb654f872010-09-06 17:34:26 +05301215 break;
1216 case 16:
Aaro Koskinenfd26d422011-10-11 21:47:19 +03001217 xgifb_info->DstColor = 0x8000;
1218 xgifb_info->XGI310_AccelDepth = 0x00010000;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001219#if defined(__powerpc__)
Aaro Koskinen7e119b72011-04-18 22:13:58 +03001220 cr_data = xgifb_reg_get(XGICR, 0x4D);
Aaro Koskinenb6e2dc32011-04-18 22:13:59 +03001221 xgifb_reg_set(XGICR, 0x4D, ((cr_data & 0xE0) | 0x0B));
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001222#endif
Aaro Koskinenfd26d422011-10-11 21:47:19 +03001223 xgifb_info->video_cmap_len = 16;
Prashant P. Shahb654f872010-09-06 17:34:26 +05301224 break;
1225 case 32:
Aaro Koskinenfd26d422011-10-11 21:47:19 +03001226 xgifb_info->DstColor = 0xC000;
1227 xgifb_info->XGI310_AccelDepth = 0x00020000;
1228 xgifb_info->video_cmap_len = 16;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001229#if defined(__powerpc__)
Aaro Koskinen7e119b72011-04-18 22:13:58 +03001230 cr_data = xgifb_reg_get(XGICR, 0x4D);
Aaro Koskinenb6e2dc32011-04-18 22:13:59 +03001231 xgifb_reg_set(XGICR, 0x4D, ((cr_data & 0xE0) | 0x15));
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001232#endif
Prashant P. Shahb654f872010-09-06 17:34:26 +05301233 break;
1234 default:
Aaro Koskinenfd26d422011-10-11 21:47:19 +03001235 xgifb_info->video_cmap_len = 16;
Kenji Toyamaa12c27c2011-04-26 12:13:43 +08001236 printk(KERN_ERR "XGIfb: Unsupported depth %d",
Aaro Koskinenfd26d422011-10-11 21:47:19 +03001237 xgifb_info->video_bpp);
Prashant P. Shahb654f872010-09-06 17:34:26 +05301238 break;
1239 }
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001240 }
Aaro Koskinenfd26d422011-10-11 21:47:19 +03001241 XGIfb_bpp_to_var(xgifb_info, var); /*update ARGB info*/
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001242 DEBUGPRN("End of do_set_var");
1243
1244 dumpVGAReg();
1245 return 0;
1246}
1247
Laurent Pinchart0d5c6ca2011-05-25 11:34:52 +02001248static int XGIfb_pan_var(struct fb_var_screeninfo *var, struct fb_info *info)
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001249{
Linus Torvaldsacff9872011-10-30 15:30:01 -07001250 struct xgifb_video_info *xgifb_info = info->par;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001251 unsigned int base;
1252
Prashant P. Shahb654f872010-09-06 17:34:26 +05301253 /* printk("Inside pan_var"); */
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001254
Laurent Pinchart0d5c6ca2011-05-25 11:34:52 +02001255 base = var->yoffset * info->var.xres_virtual + var->xoffset;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001256
Prashant P. Shahb654f872010-09-06 17:34:26 +05301257 /* calculate base bpp dep. */
Laurent Pinchart0d5c6ca2011-05-25 11:34:52 +02001258 switch (info->var.bits_per_pixel) {
Prashant P. Shahb654f872010-09-06 17:34:26 +05301259 case 16:
1260 base >>= 1;
1261 break;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001262 case 32:
Prashant P. Shahb654f872010-09-06 17:34:26 +05301263 break;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001264 case 8:
Prashant P. Shahb654f872010-09-06 17:34:26 +05301265 default:
1266 base >>= 2;
1267 break;
1268 }
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001269
Peter Huewefc39dcb2012-01-15 19:22:12 +01001270 xgifb_reg_set(XGISR, IND_SIS_PASSWORD, SIS_PASSWORD);
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001271
Aaro Koskinenb6e2dc32011-04-18 22:13:59 +03001272 xgifb_reg_set(XGICR, 0x0D, base & 0xFF);
1273 xgifb_reg_set(XGICR, 0x0C, (base >> 8) & 0xFF);
1274 xgifb_reg_set(XGISR, 0x0D, (base >> 16) & 0xFF);
1275 xgifb_reg_set(XGISR, 0x37, (base >> 24) & 0x03);
Aaro Koskinen65283d42011-04-18 22:14:02 +03001276 xgifb_reg_and_or(XGISR, 0x37, 0xDF, (base >> 21) & 0x04);
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001277
Aaro Koskinen289ea522011-10-11 21:47:37 +03001278 if (xgifb_info->display2 != XGIFB_DISP_NONE) {
Peter Huewefc39dcb2012-01-15 19:22:12 +01001279 xgifb_reg_or(XGIPART1, SIS_CRT2_WENABLE_315, 0x01);
Aaro Koskinenb6e2dc32011-04-18 22:13:59 +03001280 xgifb_reg_set(XGIPART1, 0x06, (base & 0xFF));
1281 xgifb_reg_set(XGIPART1, 0x05, ((base >> 8) & 0xFF));
1282 xgifb_reg_set(XGIPART1, 0x04, ((base >> 16) & 0xFF));
Kenji Toyamaa12c27c2011-04-26 12:13:43 +08001283 xgifb_reg_and_or(XGIPART1,
1284 0x02,
1285 0x7F,
1286 ((base >> 24) & 0x01) << 7);
Prashant P. Shahb654f872010-09-06 17:34:26 +05301287 }
1288 /* printk("End of pan_var"); */
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001289 return 0;
1290}
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001291
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001292static int XGIfb_open(struct fb_info *info, int user)
1293{
Prashant P. Shahb654f872010-09-06 17:34:26 +05301294 return 0;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001295}
1296
1297static int XGIfb_release(struct fb_info *info, int user)
1298{
Prashant P. Shahb654f872010-09-06 17:34:26 +05301299 return 0;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001300}
1301
1302static int XGIfb_get_cmap_len(const struct fb_var_screeninfo *var)
1303{
1304 int rc = 16;
1305
Prashant P. Shahb654f872010-09-06 17:34:26 +05301306 switch (var->bits_per_pixel) {
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001307 case 8:
1308 rc = 256;
1309 break;
1310 case 16:
1311 rc = 16;
1312 break;
1313 case 32:
1314 rc = 16;
1315 break;
1316 }
1317 return rc;
1318}
1319
Prashant P. Shahb654f872010-09-06 17:34:26 +05301320static int XGIfb_setcolreg(unsigned regno, unsigned red, unsigned green,
1321 unsigned blue, unsigned transp, struct fb_info *info)
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001322{
Aaro Koskinenfd26d422011-10-11 21:47:19 +03001323 struct xgifb_video_info *xgifb_info = info->par;
1324
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001325 if (regno >= XGIfb_get_cmap_len(&info->var))
1326 return 1;
1327
1328 switch (info->var.bits_per_pixel) {
1329 case 8:
Aaro Koskinene3d5ceb2011-04-18 22:13:57 +03001330 outb(regno, XGIDACA);
1331 outb((red >> 10), XGIDACD);
1332 outb((green >> 10), XGIDACD);
1333 outb((blue >> 10), XGIDACD);
Aaro Koskinen289ea522011-10-11 21:47:37 +03001334 if (xgifb_info->display2 != XGIFB_DISP_NONE) {
Aaro Koskinene3d5ceb2011-04-18 22:13:57 +03001335 outb(regno, XGIDAC2A);
1336 outb((red >> 8), XGIDAC2D);
1337 outb((green >> 8), XGIDAC2D);
1338 outb((blue >> 8), XGIDAC2D);
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001339 }
1340 break;
1341 case 16:
Prashant P. Shahb654f872010-09-06 17:34:26 +05301342 ((u32 *) (info->pseudo_palette))[regno] = ((red & 0xf800))
1343 | ((green & 0xfc00) >> 5) | ((blue & 0xf800)
1344 >> 11);
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001345 break;
1346 case 32:
1347 red >>= 8;
1348 green >>= 8;
1349 blue >>= 8;
Prashant P. Shahb654f872010-09-06 17:34:26 +05301350 ((u32 *) (info->pseudo_palette))[regno] = (red << 16) | (green
1351 << 8) | (blue);
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001352 break;
1353 }
1354 return 0;
1355}
1356
Aaro Koskinenc4fa7df2011-04-18 22:14:05 +03001357/* ----------- FBDev related routines for all series ---------- */
1358
1359static int XGIfb_get_fix(struct fb_fix_screeninfo *fix, int con,
1360 struct fb_info *info)
1361{
Aaro Koskinenfd26d422011-10-11 21:47:19 +03001362 struct xgifb_video_info *xgifb_info = info->par;
1363
Aaro Koskinenc4fa7df2011-04-18 22:14:05 +03001364 DEBUGPRN("inside get_fix");
1365 memset(fix, 0, sizeof(struct fb_fix_screeninfo));
1366
Aaro Koskinenfd26d422011-10-11 21:47:19 +03001367 fix->smem_start = xgifb_info->video_base;
Aaro Koskinenc4fa7df2011-04-18 22:14:05 +03001368
Aaro Koskinenfd26d422011-10-11 21:47:19 +03001369 fix->smem_len = xgifb_info->video_size;
Aaro Koskinenc4fa7df2011-04-18 22:14:05 +03001370
Aaro Koskinende351ba2011-08-19 22:40:27 +03001371 fix->type = FB_TYPE_PACKED_PIXELS;
Aaro Koskinenc4fa7df2011-04-18 22:14:05 +03001372 fix->type_aux = 0;
Aaro Koskinenfd26d422011-10-11 21:47:19 +03001373 if (xgifb_info->video_bpp == 8)
Aaro Koskinenc4fa7df2011-04-18 22:14:05 +03001374 fix->visual = FB_VISUAL_PSEUDOCOLOR;
1375 else
1376 fix->visual = FB_VISUAL_DIRECTCOLOR;
1377 fix->xpanstep = 0;
Aaro Koskinenc4fa7df2011-04-18 22:14:05 +03001378 if (XGIfb_ypan)
1379 fix->ypanstep = 1;
Aaro Koskinenc4fa7df2011-04-18 22:14:05 +03001380 fix->ywrapstep = 0;
Aaro Koskinenfd26d422011-10-11 21:47:19 +03001381 fix->line_length = xgifb_info->video_linelength;
1382 fix->mmio_start = xgifb_info->mmio_base;
1383 fix->mmio_len = xgifb_info->mmio_size;
Peter Huewefc39dcb2012-01-15 19:22:12 +01001384 fix->accel = FB_ACCEL_SIS_XABRE;
Aaro Koskinenc4fa7df2011-04-18 22:14:05 +03001385
1386 DEBUGPRN("end of get_fix");
1387 return 0;
1388}
1389
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001390static int XGIfb_set_par(struct fb_info *info)
1391{
1392 int err;
1393
Prashant P. Shahb654f872010-09-06 17:34:26 +05301394 /* printk("XGIfb: inside set_par\n"); */
1395 err = XGIfb_do_set_var(&info->var, 1, info);
1396 if (err)
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001397 return err;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001398 XGIfb_get_fix(&info->fix, -1, info);
Prashant P. Shahb654f872010-09-06 17:34:26 +05301399 /* printk("XGIfb: end of set_par\n"); */
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001400 return 0;
1401}
1402
Prashant P. Shahb654f872010-09-06 17:34:26 +05301403static int XGIfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001404{
Aaro Koskinenfd26d422011-10-11 21:47:19 +03001405 struct xgifb_video_info *xgifb_info = info->par;
Prashant P. Shahb654f872010-09-06 17:34:26 +05301406 unsigned int htotal = var->left_margin + var->xres + var->right_margin
1407 + var->hsync_len;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001408 unsigned int vtotal = 0;
1409 unsigned int drate = 0, hrate = 0;
1410 int found_mode = 0;
1411 int refresh_rate, search_idx;
1412
1413 DEBUGPRN("Inside check_var");
1414
Prashant P. Shahb654f872010-09-06 17:34:26 +05301415 if ((var->vmode & FB_VMODE_MASK) == FB_VMODE_NONINTERLACED) {
1416 vtotal = var->upper_margin + var->yres + var->lower_margin
1417 + var->vsync_len;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001418 vtotal <<= 1;
Prashant P. Shahb654f872010-09-06 17:34:26 +05301419 } else if ((var->vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE) {
1420 vtotal = var->upper_margin + var->yres + var->lower_margin
1421 + var->vsync_len;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001422 vtotal <<= 2;
Prashant P. Shahb654f872010-09-06 17:34:26 +05301423 } else if ((var->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) {
1424 vtotal = var->upper_margin + (var->yres / 2)
1425 + var->lower_margin + var->vsync_len;
1426 } else
1427 vtotal = var->upper_margin + var->yres + var->lower_margin
1428 + var->vsync_len;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001429
Prashant P. Shahb654f872010-09-06 17:34:26 +05301430 if (!(htotal) || !(vtotal))
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001431 XGIFAIL("XGIfb: no valid timing data");
Prashant P. Shahb654f872010-09-06 17:34:26 +05301432
1433 if (var->pixclock && htotal && vtotal) {
1434 drate = 1000000000 / var->pixclock;
1435 hrate = (drate * 1000) / htotal;
Aaro Koskinenfd26d422011-10-11 21:47:19 +03001436 xgifb_info->refresh_rate =
Kenji Toyamaa12c27c2011-04-26 12:13:43 +08001437 (unsigned int) (hrate * 2 / vtotal);
Prashant P. Shahb654f872010-09-06 17:34:26 +05301438 printk(KERN_DEBUG
1439 "%s: pixclock = %d ,htotal=%d, vtotal=%d\n"
1440 "%s: drate=%d, hrate=%d, refresh_rate=%d\n",
1441 __func__, var->pixclock, htotal, vtotal,
Aaro Koskinenfd26d422011-10-11 21:47:19 +03001442 __func__, drate, hrate, xgifb_info->refresh_rate);
Prashant P. Shahb654f872010-09-06 17:34:26 +05301443 } else {
Aaro Koskinenfd26d422011-10-11 21:47:19 +03001444 xgifb_info->refresh_rate = 60;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001445 }
1446
Prashant P. Shahb654f872010-09-06 17:34:26 +05301447 /*
1448 if ((var->pixclock) && (htotal)) {
1449 drate = 1E12 / var->pixclock;
1450 hrate = drate / htotal;
1451 refresh_rate = (unsigned int) (hrate / vtotal * 2 + 0.5);
1452 } else {
1453 refresh_rate = 60;
1454 }
1455 */
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001456 /* TW: Calculation wrong for 1024x600 - force it to 60Hz */
Prashant P. Shahb654f872010-09-06 17:34:26 +05301457 if ((var->xres == 1024) && (var->yres == 600))
1458 refresh_rate = 60;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001459
1460 search_idx = 0;
Prashant P. Shahb654f872010-09-06 17:34:26 +05301461 while ((XGIbios_mode[search_idx].mode_no != 0) &&
1462 (XGIbios_mode[search_idx].xres <= var->xres)) {
1463 if ((XGIbios_mode[search_idx].xres == var->xres) &&
1464 (XGIbios_mode[search_idx].yres == var->yres) &&
1465 (XGIbios_mode[search_idx].bpp == var->bits_per_pixel)) {
Aaro Koskinenfd26d422011-10-11 21:47:19 +03001466 if (XGIfb_validate_mode(xgifb_info, search_idx) > 0) {
Prashant P. Shahb654f872010-09-06 17:34:26 +05301467 found_mode = 1;
1468 break;
1469 }
1470 }
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001471 search_idx++;
1472 }
1473
Prashant P. Shahb654f872010-09-06 17:34:26 +05301474 if (!found_mode) {
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001475
1476 printk(KERN_ERR "XGIfb: %dx%dx%d is no valid mode\n",
1477 var->xres, var->yres, var->bits_per_pixel);
Prashant P. Shahb654f872010-09-06 17:34:26 +05301478 search_idx = 0;
1479 while (XGIbios_mode[search_idx].mode_no != 0) {
Prashant P. Shahb654f872010-09-06 17:34:26 +05301480 if ((var->xres <= XGIbios_mode[search_idx].xres) &&
Kenji Toyamaa12c27c2011-04-26 12:13:43 +08001481 (var->yres <= XGIbios_mode[search_idx].yres) &&
1482 (var->bits_per_pixel ==
1483 XGIbios_mode[search_idx].bpp)) {
Aaro Koskinenfd26d422011-10-11 21:47:19 +03001484 if (XGIfb_validate_mode(xgifb_info,
1485 search_idx) > 0) {
Prashant P. Shahb654f872010-09-06 17:34:26 +05301486 found_mode = 1;
1487 break;
1488 }
1489 }
1490 search_idx++;
1491 }
1492 if (found_mode) {
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001493 var->xres = XGIbios_mode[search_idx].xres;
Prashant P. Shahb654f872010-09-06 17:34:26 +05301494 var->yres = XGIbios_mode[search_idx].yres;
1495 printk(KERN_DEBUG "XGIfb: Adapted to mode %dx%dx%d\n",
1496 var->xres, var->yres, var->bits_per_pixel);
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001497
1498 } else {
Prashant P. Shahb654f872010-09-06 17:34:26 +05301499 printk(KERN_ERR "XGIfb: Failed to find similar mode to %dx%dx%d\n",
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001500 var->xres, var->yres, var->bits_per_pixel);
Prashant P. Shahb654f872010-09-06 17:34:26 +05301501 return -EINVAL;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001502 }
1503 }
1504
1505 /* TW: TODO: Check the refresh rate */
1506
1507 /* Adapt RGB settings */
Aaro Koskinenfd26d422011-10-11 21:47:19 +03001508 XGIfb_bpp_to_var(xgifb_info, var);
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001509
1510 /* Sanity check for offsets */
1511 if (var->xoffset < 0)
1512 var->xoffset = 0;
1513 if (var->yoffset < 0)
1514 var->yoffset = 0;
1515
Prashant P. Shahb654f872010-09-06 17:34:26 +05301516 if (!XGIfb_ypan) {
1517 if (var->xres != var->xres_virtual)
1518 var->xres_virtual = var->xres;
1519 if (var->yres != var->yres_virtual)
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001520 var->yres_virtual = var->yres;
Prashant P. Shahb654f872010-09-06 17:34:26 +05301521 } /* else { */
1522 /* TW: Now patch yres_virtual if we use panning */
1523 /* May I do this? */
Aaro Koskinenfd26d422011-10-11 21:47:19 +03001524 /* var->yres_virtual = xgifb_info->heapstart /
Kenji Toyamaa12c27c2011-04-26 12:13:43 +08001525 (var->xres * (var->bits_per_pixel >> 3)); */
Prashant P. Shahb654f872010-09-06 17:34:26 +05301526 /* if (var->yres_virtual <= var->yres) { */
1527 /* TW: Paranoia check */
1528 /* var->yres_virtual = var->yres; */
1529 /* } */
1530 /* } */
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001531
1532 /* Truncate offsets to maximum if too high */
1533 if (var->xoffset > var->xres_virtual - var->xres)
1534 var->xoffset = var->xres_virtual - var->xres - 1;
1535
1536 if (var->yoffset > var->yres_virtual - var->yres)
1537 var->yoffset = var->yres_virtual - var->yres - 1;
1538
1539 /* Set everything else to 0 */
1540 var->red.msb_right =
Prashant P. Shahb654f872010-09-06 17:34:26 +05301541 var->green.msb_right =
1542 var->blue.msb_right =
1543 var->transp.offset = var->transp.length = var->transp.msb_right = 0;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001544
1545 DEBUGPRN("end of check_var");
1546 return 0;
1547}
1548
Prashant P. Shahb654f872010-09-06 17:34:26 +05301549static int XGIfb_pan_display(struct fb_var_screeninfo *var,
1550 struct fb_info *info)
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001551{
1552 int err;
1553
Prashant P. Shahb654f872010-09-06 17:34:26 +05301554 /* printk("\nInside pan_display:\n"); */
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001555
Laurent Pinchart0d5c6ca2011-05-25 11:34:52 +02001556 if (var->xoffset > (info->var.xres_virtual - info->var.xres))
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001557 return -EINVAL;
Laurent Pinchart0d5c6ca2011-05-25 11:34:52 +02001558 if (var->yoffset > (info->var.yres_virtual - info->var.yres))
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001559 return -EINVAL;
1560
1561 if (var->vmode & FB_VMODE_YWRAP) {
Prashant P. Shahb654f872010-09-06 17:34:26 +05301562 if (var->yoffset < 0 || var->yoffset >= info->var.yres_virtual
1563 || var->xoffset)
1564 return -EINVAL;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001565 } else {
Prashant P. Shahb654f872010-09-06 17:34:26 +05301566 if (var->xoffset + info->var.xres > info->var.xres_virtual
1567 || var->yoffset + info->var.yres
1568 > info->var.yres_virtual)
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001569 return -EINVAL;
1570 }
Laurent Pinchart0d5c6ca2011-05-25 11:34:52 +02001571 err = XGIfb_pan_var(var, info);
Prashant P. Shahb654f872010-09-06 17:34:26 +05301572 if (err < 0)
1573 return err;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001574
1575 info->var.xoffset = var->xoffset;
1576 info->var.yoffset = var->yoffset;
1577 if (var->vmode & FB_VMODE_YWRAP)
1578 info->var.vmode |= FB_VMODE_YWRAP;
1579 else
1580 info->var.vmode &= ~FB_VMODE_YWRAP;
1581
Prashant P. Shahb654f872010-09-06 17:34:26 +05301582 /* printk("End of pan_display\n"); */
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001583 return 0;
1584}
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001585
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001586static int XGIfb_blank(int blank, struct fb_info *info)
1587{
Aaro Koskinenf2df8c02011-10-11 21:47:30 +03001588 struct xgifb_video_info *xgifb_info = info->par;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001589 u8 reg;
1590
Aaro Koskinen7e119b72011-04-18 22:13:58 +03001591 reg = xgifb_reg_get(XGICR, 0x17);
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001592
Prashant P. Shahb654f872010-09-06 17:34:26 +05301593 if (blank > 0)
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001594 reg &= 0x7f;
1595 else
1596 reg |= 0x80;
1597
Aaro Koskinenb6e2dc32011-04-18 22:13:59 +03001598 xgifb_reg_set(XGICR, 0x17, reg);
1599 xgifb_reg_set(XGISR, 0x00, 0x01); /* Synchronous Reset */
1600 xgifb_reg_set(XGISR, 0x00, 0x03); /* End Reset */
Prashant P. Shahb654f872010-09-06 17:34:26 +05301601 return 0;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001602}
1603
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001604static struct fb_ops XGIfb_ops = {
Prashant P. Shahb654f872010-09-06 17:34:26 +05301605 .owner = THIS_MODULE,
1606 .fb_open = XGIfb_open,
1607 .fb_release = XGIfb_release,
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001608 .fb_check_var = XGIfb_check_var,
Prashant P. Shahb654f872010-09-06 17:34:26 +05301609 .fb_set_par = XGIfb_set_par,
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001610 .fb_setcolreg = XGIfb_setcolreg,
Prashant P. Shahb654f872010-09-06 17:34:26 +05301611 .fb_pan_display = XGIfb_pan_display,
Prashant P. Shahb654f872010-09-06 17:34:26 +05301612 .fb_blank = XGIfb_blank,
Aaro Koskinen1b402962011-02-28 20:59:22 +02001613 .fb_fillrect = cfb_fillrect,
Aaro Koskinen85c3c562011-02-28 20:59:21 +02001614 .fb_copyarea = cfb_copyarea,
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001615 .fb_imageblit = cfb_imageblit,
Prashant P. Shahb654f872010-09-06 17:34:26 +05301616 /* .fb_mmap = XGIfb_mmap, */
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001617};
1618
1619/* ---------------- Chip generation dependent routines ---------------- */
1620
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001621/* for XGI 315/550/650/740/330 */
1622
Aaro Koskinenfd26d422011-10-11 21:47:19 +03001623static int XGIfb_get_dram_size(struct xgifb_video_info *xgifb_info)
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001624{
1625
Prashant P. Shahb654f872010-09-06 17:34:26 +05301626 u8 ChannelNum, tmp;
1627 u8 reg = 0;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001628
1629 /* xorg driver sets 32MB * 1 channel */
Aaro Koskinenfd26d422011-10-11 21:47:19 +03001630 if (xgifb_info->chip == XG27)
Peter Huewefc39dcb2012-01-15 19:22:12 +01001631 xgifb_reg_set(XGISR, IND_SIS_DRAM_SIZE, 0x51);
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001632
Peter Huewefc39dcb2012-01-15 19:22:12 +01001633 reg = xgifb_reg_get(XGISR, IND_SIS_DRAM_SIZE);
Prashant P. Shahb654f872010-09-06 17:34:26 +05301634 switch ((reg & XGI_DRAM_SIZE_MASK) >> 4) {
1635 case XGI_DRAM_SIZE_1MB:
Aaro Koskinenfd26d422011-10-11 21:47:19 +03001636 xgifb_info->video_size = 0x100000;
Prashant P. Shahb654f872010-09-06 17:34:26 +05301637 break;
1638 case XGI_DRAM_SIZE_2MB:
Aaro Koskinenfd26d422011-10-11 21:47:19 +03001639 xgifb_info->video_size = 0x200000;
Prashant P. Shahb654f872010-09-06 17:34:26 +05301640 break;
1641 case XGI_DRAM_SIZE_4MB:
Aaro Koskinenfd26d422011-10-11 21:47:19 +03001642 xgifb_info->video_size = 0x400000;
Prashant P. Shahb654f872010-09-06 17:34:26 +05301643 break;
1644 case XGI_DRAM_SIZE_8MB:
Aaro Koskinenfd26d422011-10-11 21:47:19 +03001645 xgifb_info->video_size = 0x800000;
Prashant P. Shahb654f872010-09-06 17:34:26 +05301646 break;
1647 case XGI_DRAM_SIZE_16MB:
Aaro Koskinenfd26d422011-10-11 21:47:19 +03001648 xgifb_info->video_size = 0x1000000;
Prashant P. Shahb654f872010-09-06 17:34:26 +05301649 break;
1650 case XGI_DRAM_SIZE_32MB:
Aaro Koskinenfd26d422011-10-11 21:47:19 +03001651 xgifb_info->video_size = 0x2000000;
Prashant P. Shahb654f872010-09-06 17:34:26 +05301652 break;
1653 case XGI_DRAM_SIZE_64MB:
Aaro Koskinenfd26d422011-10-11 21:47:19 +03001654 xgifb_info->video_size = 0x4000000;
Prashant P. Shahb654f872010-09-06 17:34:26 +05301655 break;
1656 case XGI_DRAM_SIZE_128MB:
Aaro Koskinenfd26d422011-10-11 21:47:19 +03001657 xgifb_info->video_size = 0x8000000;
Prashant P. Shahb654f872010-09-06 17:34:26 +05301658 break;
1659 case XGI_DRAM_SIZE_256MB:
Aaro Koskinenfd26d422011-10-11 21:47:19 +03001660 xgifb_info->video_size = 0x10000000;
Prashant P. Shahb654f872010-09-06 17:34:26 +05301661 break;
1662 default:
1663 return -1;
1664 }
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001665
Prashant P. Shahb654f872010-09-06 17:34:26 +05301666 tmp = (reg & 0x0c) >> 2;
Aaro Koskinenfd26d422011-10-11 21:47:19 +03001667 switch (xgifb_info->chip) {
Prashant P. Shahb654f872010-09-06 17:34:26 +05301668 case XG20:
1669 case XG21:
1670 case XG27:
1671 ChannelNum = 1;
1672 break;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001673
Prashant P. Shahb654f872010-09-06 17:34:26 +05301674 case XG42:
1675 if (reg & 0x04)
1676 ChannelNum = 2;
1677 else
1678 ChannelNum = 1;
1679 break;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001680
Prashant P. Shahb654f872010-09-06 17:34:26 +05301681 case XG45:
1682 if (tmp == 1)
1683 ChannelNum = 2;
1684 else if (tmp == 2)
1685 ChannelNum = 3;
1686 else if (tmp == 3)
1687 ChannelNum = 4;
1688 else
1689 ChannelNum = 1;
1690 break;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001691
Prashant P. Shahb654f872010-09-06 17:34:26 +05301692 case XG40:
1693 default:
1694 if (tmp == 2)
1695 ChannelNum = 2;
1696 else if (tmp == 3)
1697 ChannelNum = 3;
1698 else
1699 ChannelNum = 1;
1700 break;
1701 }
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001702
Aaro Koskinenfd26d422011-10-11 21:47:19 +03001703 xgifb_info->video_size = xgifb_info->video_size * ChannelNum;
Prashant P. Shahb654f872010-09-06 17:34:26 +05301704 /* PLiad fixed for benchmarking and fb set */
Aaro Koskinenfd26d422011-10-11 21:47:19 +03001705 /* xgifb_info->video_size = 0x200000; */ /* 1024x768x16 */
1706 /* xgifb_info->video_size = 0x1000000; */ /* benchmark */
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001707
Kenji Toyamaa12c27c2011-04-26 12:13:43 +08001708 printk("XGIfb: SR14=%x DramSzie %x ChannelNum %x\n",
1709 reg,
Aaro Koskinenfd26d422011-10-11 21:47:19 +03001710 xgifb_info->video_size, ChannelNum);
Prashant P. Shahb654f872010-09-06 17:34:26 +05301711 return 0;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001712
1713}
1714
Aaro Koskinenfd26d422011-10-11 21:47:19 +03001715static void XGIfb_detect_VB(struct xgifb_video_info *xgifb_info)
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001716{
Prashant P. Shahb654f872010-09-06 17:34:26 +05301717 u8 cr32, temp = 0;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001718
Aaro Koskinenfd26d422011-10-11 21:47:19 +03001719 xgifb_info->TV_plug = xgifb_info->TV_type = 0;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001720
Aaro Koskinenfd26d422011-10-11 21:47:19 +03001721 switch (xgifb_info->hasVB) {
Prashant P. Shahb654f872010-09-06 17:34:26 +05301722 case HASVB_LVDS_CHRONTEL:
1723 case HASVB_CHRONTEL:
1724 break;
1725 case HASVB_301:
1726 case HASVB_302:
1727 /* XGI_Sense30x(); */ /* Yi-Lin TV Sense? */
1728 break;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001729 }
1730
Aaro Koskinen7e119b72011-04-18 22:13:58 +03001731 cr32 = xgifb_reg_get(XGICR, IND_XGI_SCRATCH_REG_CR32);
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001732
Peter Huewefc39dcb2012-01-15 19:22:12 +01001733 if ((cr32 & SIS_CRT1) && !XGIfb_crt1off)
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001734 XGIfb_crt1off = 0;
1735 else {
1736 if (cr32 & 0x5F)
1737 XGIfb_crt1off = 1;
1738 else
1739 XGIfb_crt1off = 0;
1740 }
1741
Aaro Koskinen25aa75f2011-12-06 00:10:48 +02001742 if (!xgifb_info->display2_force) {
Peter Huewefc39dcb2012-01-15 19:22:12 +01001743 if (cr32 & SIS_VB_TV)
Aaro Koskinen25aa75f2011-12-06 00:10:48 +02001744 xgifb_info->display2 = XGIFB_DISP_TV;
Peter Huewefc39dcb2012-01-15 19:22:12 +01001745 else if (cr32 & SIS_VB_LCD)
Aaro Koskinen25aa75f2011-12-06 00:10:48 +02001746 xgifb_info->display2 = XGIFB_DISP_LCD;
Peter Huewefc39dcb2012-01-15 19:22:12 +01001747 else if (cr32 & SIS_VB_CRT2)
Aaro Koskinen25aa75f2011-12-06 00:10:48 +02001748 xgifb_info->display2 = XGIFB_DISP_CRT;
1749 else
1750 xgifb_info->display2 = XGIFB_DISP_NONE;
1751 }
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001752
Prashant P. Shahb654f872010-09-06 17:34:26 +05301753 if (XGIfb_tvplug != -1)
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001754 /* PR/TW: Override with option */
Aaro Koskinenfd26d422011-10-11 21:47:19 +03001755 xgifb_info->TV_plug = XGIfb_tvplug;
Peter Huewefc39dcb2012-01-15 19:22:12 +01001756 else if (cr32 & SIS_VB_HIVISION) {
Aaro Koskinenfd26d422011-10-11 21:47:19 +03001757 xgifb_info->TV_type = TVMODE_HIVISION;
1758 xgifb_info->TV_plug = TVPLUG_SVIDEO;
Peter Huewefc39dcb2012-01-15 19:22:12 +01001759 } else if (cr32 & SIS_VB_SVIDEO)
Aaro Koskinenfd26d422011-10-11 21:47:19 +03001760 xgifb_info->TV_plug = TVPLUG_SVIDEO;
Peter Huewefc39dcb2012-01-15 19:22:12 +01001761 else if (cr32 & SIS_VB_COMPOSITE)
Aaro Koskinenfd26d422011-10-11 21:47:19 +03001762 xgifb_info->TV_plug = TVPLUG_COMPOSITE;
Peter Huewefc39dcb2012-01-15 19:22:12 +01001763 else if (cr32 & SIS_VB_SCART)
Aaro Koskinenfd26d422011-10-11 21:47:19 +03001764 xgifb_info->TV_plug = TVPLUG_SCART;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001765
Aaro Koskinenfd26d422011-10-11 21:47:19 +03001766 if (xgifb_info->TV_type == 0) {
Aaro Koskinen7e119b72011-04-18 22:13:58 +03001767 temp = xgifb_reg_get(XGICR, 0x38);
Aaro Koskinenebe78462011-03-13 12:26:08 +02001768 if (temp & 0x10)
Aaro Koskinenfd26d422011-10-11 21:47:19 +03001769 xgifb_info->TV_type = TVMODE_PAL;
Aaro Koskinenebe78462011-03-13 12:26:08 +02001770 else
Aaro Koskinenfd26d422011-10-11 21:47:19 +03001771 xgifb_info->TV_type = TVMODE_NTSC;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001772 }
1773
1774 /* TW: Copy forceCRT1 option to CRT1off if option is given */
Prashant P. Shahb654f872010-09-06 17:34:26 +05301775 if (XGIfb_forcecrt1 != -1) {
1776 if (XGIfb_forcecrt1)
1777 XGIfb_crt1off = 0;
1778 else
1779 XGIfb_crt1off = 1;
1780 }
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001781}
1782
Aaro Koskinenfd26d422011-10-11 21:47:19 +03001783static int XGIfb_has_VB(struct xgifb_video_info *xgifb_info)
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001784{
1785 u8 vb_chipid;
1786
Aaro Koskinen7e119b72011-04-18 22:13:58 +03001787 vb_chipid = xgifb_reg_get(XGIPART4, 0x00);
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001788 switch (vb_chipid) {
Prashant P. Shahb654f872010-09-06 17:34:26 +05301789 case 0x01:
Aaro Koskinenfd26d422011-10-11 21:47:19 +03001790 xgifb_info->hasVB = HASVB_301;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001791 break;
Prashant P. Shahb654f872010-09-06 17:34:26 +05301792 case 0x02:
Aaro Koskinenfd26d422011-10-11 21:47:19 +03001793 xgifb_info->hasVB = HASVB_302;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001794 break;
Prashant P. Shahb654f872010-09-06 17:34:26 +05301795 default:
Aaro Koskinenfd26d422011-10-11 21:47:19 +03001796 xgifb_info->hasVB = HASVB_NONE;
Bill Pembertondda08c52010-06-17 13:10:42 -04001797 return 0;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001798 }
Bill Pembertondda08c52010-06-17 13:10:42 -04001799 return 1;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001800}
1801
Aaro Koskinenfd26d422011-10-11 21:47:19 +03001802static void XGIfb_get_VB_type(struct xgifb_video_info *xgifb_info)
Aaro Koskinenc4fa7df2011-04-18 22:14:05 +03001803{
1804 u8 reg;
1805
Aaro Koskinenfd26d422011-10-11 21:47:19 +03001806 if (!XGIfb_has_VB(xgifb_info)) {
Aaro Koskinenc4fa7df2011-04-18 22:14:05 +03001807 reg = xgifb_reg_get(XGICR, IND_XGI_SCRATCH_REG_CR37);
Peter Huewefc39dcb2012-01-15 19:22:12 +01001808 switch ((reg & SIS_EXTERNAL_CHIP_MASK) >> 1) {
1809 case SIS_EXTERNAL_CHIP_LVDS:
Aaro Koskinenfd26d422011-10-11 21:47:19 +03001810 xgifb_info->hasVB = HASVB_LVDS;
Aaro Koskinenc4fa7df2011-04-18 22:14:05 +03001811 break;
Peter Huewefc39dcb2012-01-15 19:22:12 +01001812 case SIS_EXTERNAL_CHIP_LVDS_CHRONTEL:
Aaro Koskinenfd26d422011-10-11 21:47:19 +03001813 xgifb_info->hasVB = HASVB_LVDS_CHRONTEL;
Aaro Koskinenc4fa7df2011-04-18 22:14:05 +03001814 break;
1815 default:
1816 break;
1817 }
1818 }
1819}
1820
Aaro Koskinend27c6bc2011-08-29 23:14:23 +03001821static int __init xgifb_optval(char *fullopt, int validx)
1822{
1823 unsigned long lres;
1824
1825 if (kstrtoul(fullopt + validx, 0, &lres) < 0 || lres > INT_MAX) {
1826 pr_err("xgifb: invalid value for option: %s\n", fullopt);
1827 return 0;
1828 }
1829 return lres;
1830}
1831
Ruslan Pisarev032abf72011-07-21 11:59:11 +03001832static int __init XGIfb_setup(char *options)
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001833{
1834 char *this_opt;
1835
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001836 if (!options || !*options)
1837 return 0;
1838
Aaro Koskinen79bea042011-08-29 23:14:21 +03001839 pr_info("xgifb: options: %s\n", options);
1840
Prashant P. Shahb654f872010-09-06 17:34:26 +05301841 while ((this_opt = strsep(&options, ",")) != NULL) {
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001842
Prashant P. Shahb654f872010-09-06 17:34:26 +05301843 if (!*this_opt)
1844 continue;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001845
1846 if (!strncmp(this_opt, "mode:", 5)) {
Aaro Koskinendfbdf802011-08-29 23:14:25 +03001847 mode = this_opt + 5;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001848 } else if (!strncmp(this_opt, "vesa:", 5)) {
Aaro Koskinendfbdf802011-08-29 23:14:25 +03001849 vesa = xgifb_optval(this_opt, 5);
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001850 } else if (!strncmp(this_opt, "vrate:", 6)) {
Aaro Koskinen7548a832011-10-11 21:47:17 +03001851 refresh_rate = xgifb_optval(this_opt, 6);
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001852 } else if (!strncmp(this_opt, "rate:", 5)) {
Aaro Koskinen7548a832011-10-11 21:47:17 +03001853 refresh_rate = xgifb_optval(this_opt, 5);
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001854 } else if (!strncmp(this_opt, "crt1off", 7)) {
1855 XGIfb_crt1off = 1;
1856 } else if (!strncmp(this_opt, "filter:", 7)) {
Aaro Koskinend27c6bc2011-08-29 23:14:23 +03001857 filter = xgifb_optval(this_opt, 7);
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001858 } else if (!strncmp(this_opt, "forcecrt2type:", 14)) {
1859 XGIfb_search_crt2type(this_opt + 14);
1860 } else if (!strncmp(this_opt, "forcecrt1:", 10)) {
Aaro Koskinend27c6bc2011-08-29 23:14:23 +03001861 XGIfb_forcecrt1 = xgifb_optval(this_opt, 10);
Prashant P. Shahb654f872010-09-06 17:34:26 +05301862 } else if (!strncmp(this_opt, "tvmode:", 7)) {
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001863 XGIfb_search_tvstd(this_opt + 7);
Prashant P. Shahb654f872010-09-06 17:34:26 +05301864 } else if (!strncmp(this_opt, "tvstandard:", 11)) {
1865 XGIfb_search_tvstd(this_opt + 7);
Prashant P. Shahb654f872010-09-06 17:34:26 +05301866 } else if (!strncmp(this_opt, "dstn", 4)) {
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001867 enable_dstn = 1;
1868 /* TW: DSTN overrules forcecrt2type */
Aaro Koskinen289ea522011-10-11 21:47:37 +03001869 XGIfb_crt2type = XGIFB_DISP_LCD;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001870 } else if (!strncmp(this_opt, "noypan", 6)) {
Prashant P. Shahb654f872010-09-06 17:34:26 +05301871 XGIfb_ypan = 0;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001872 } else {
Aaro Koskinendfbdf802011-08-29 23:14:25 +03001873 mode = this_opt;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001874 }
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001875 }
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001876 return 0;
1877}
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001878
Randy Dunlap89229672010-08-10 08:46:44 -07001879static int __devinit xgifb_probe(struct pci_dev *pdev,
Prashant P. Shahb654f872010-09-06 17:34:26 +05301880 const struct pci_device_id *ent)
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001881{
Prashant P. Shahb654f872010-09-06 17:34:26 +05301882 u8 reg, reg1;
1883 u8 CR48, CR38;
Aaro Koskinenbb292232011-02-17 23:29:11 +02001884 int ret;
Aaro Koskinen19c1e882011-10-11 21:47:14 +03001885 struct fb_info *fb_info;
Aaro Koskinenfcbdda92011-10-11 21:47:20 +03001886 struct xgifb_video_info *xgifb_info;
1887 struct xgi_hw_device_info *hw_info;
Aaro Koskinenbb292232011-02-17 23:29:11 +02001888
Aaro Koskinenfcbdda92011-10-11 21:47:20 +03001889 fb_info = framebuffer_alloc(sizeof(*xgifb_info), &pdev->dev);
Prashant P. Shahb654f872010-09-06 17:34:26 +05301890 if (!fb_info)
1891 return -ENOMEM;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001892
Aaro Koskinenfcbdda92011-10-11 21:47:20 +03001893 xgifb_info = fb_info->par;
1894 hw_info = &xgifb_info->hw_info;
Aaro Koskinenfd26d422011-10-11 21:47:19 +03001895 xgifb_info->fb_info = fb_info;
1896 xgifb_info->chip_id = pdev->device;
Kenji Toyamaa12c27c2011-04-26 12:13:43 +08001897 pci_read_config_byte(pdev,
1898 PCI_REVISION_ID,
Aaro Koskinenfd26d422011-10-11 21:47:19 +03001899 &xgifb_info->revision_id);
1900 hw_info->jChipRevision = xgifb_info->revision_id;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001901
Aaro Koskinenfd26d422011-10-11 21:47:19 +03001902 xgifb_info->pcibus = pdev->bus->number;
1903 xgifb_info->pcislot = PCI_SLOT(pdev->devfn);
1904 xgifb_info->pcifunc = PCI_FUNC(pdev->devfn);
1905 xgifb_info->subsysvendor = pdev->subsystem_vendor;
1906 xgifb_info->subsysdevice = pdev->subsystem_device;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001907
Aaro Koskinenfd26d422011-10-11 21:47:19 +03001908 xgifb_info->video_base = pci_resource_start(pdev, 0);
1909 xgifb_info->mmio_base = pci_resource_start(pdev, 1);
1910 xgifb_info->mmio_size = pci_resource_len(pdev, 1);
1911 xgifb_info->vga_base = pci_resource_start(pdev, 2) + 0x30;
1912 hw_info->pjIOAddress = (unsigned char *)xgifb_info->vga_base;
Prashant P. Shahb654f872010-09-06 17:34:26 +05301913 /* XGI_Pr.RelIO = ioremap(pci_resource_start(pdev, 2), 128) + 0x30; */
1914 printk("XGIfb: Relocate IO address: %lx [%08lx]\n",
Aaro Koskinenf2df8c02011-10-11 21:47:30 +03001915 (unsigned long)pci_resource_start(pdev, 2),
1916 xgifb_info->dev_info.RelIO);
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001917
Aaro Koskinenbb292232011-02-17 23:29:11 +02001918 if (pci_enable_device(pdev)) {
1919 ret = -EIO;
1920 goto error;
1921 }
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001922
Aaro Koskinen25aa75f2011-12-06 00:10:48 +02001923 if (XGIfb_crt2type != -1) {
1924 xgifb_info->display2 = XGIfb_crt2type;
1925 xgifb_info->display2_force = true;
1926 }
1927
Aaro Koskinenf2df8c02011-10-11 21:47:30 +03001928 XGIRegInit(&xgifb_info->dev_info, (unsigned long)hw_info->pjIOAddress);
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001929
Peter Huewefc39dcb2012-01-15 19:22:12 +01001930 xgifb_reg_set(XGISR, IND_SIS_PASSWORD, SIS_PASSWORD);
1931 reg1 = xgifb_reg_get(XGISR, IND_SIS_PASSWORD);
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001932
Prashant P. Shahb654f872010-09-06 17:34:26 +05301933 if (reg1 != 0xa1) { /*I/O error */
1934 printk("\nXGIfb: I/O error!!!");
Aaro Koskinenbb292232011-02-17 23:29:11 +02001935 ret = -EIO;
1936 goto error;
Prashant P. Shahb654f872010-09-06 17:34:26 +05301937 }
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001938
Aaro Koskinenfd26d422011-10-11 21:47:19 +03001939 switch (xgifb_info->chip_id) {
Peter Huewefc39dcb2012-01-15 19:22:12 +01001940 case PCI_DEVICE_ID_XGI_20:
Aaro Koskinene67f4d42011-04-18 22:14:00 +03001941 xgifb_reg_or(XGICR, Index_CR_GPIO_Reg3, GPIOG_EN);
Aaro Koskinen7e119b72011-04-18 22:13:58 +03001942 CR48 = xgifb_reg_get(XGICR, Index_CR_GPIO_Reg1);
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001943 if (CR48&GPIOG_READ)
Aaro Koskinenfd26d422011-10-11 21:47:19 +03001944 xgifb_info->chip = XG21;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001945 else
Aaro Koskinenfd26d422011-10-11 21:47:19 +03001946 xgifb_info->chip = XG20;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001947 break;
Peter Huewefc39dcb2012-01-15 19:22:12 +01001948 case PCI_DEVICE_ID_XGI_40:
Aaro Koskinenfd26d422011-10-11 21:47:19 +03001949 xgifb_info->chip = XG40;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001950 break;
Peter Huewefc39dcb2012-01-15 19:22:12 +01001951 case PCI_DEVICE_ID_XGI_41:
Aaro Koskinenfd26d422011-10-11 21:47:19 +03001952 xgifb_info->chip = XG41;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001953 break;
Peter Huewefc39dcb2012-01-15 19:22:12 +01001954 case PCI_DEVICE_ID_XGI_42:
Aaro Koskinenfd26d422011-10-11 21:47:19 +03001955 xgifb_info->chip = XG42;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001956 break;
Peter Huewefc39dcb2012-01-15 19:22:12 +01001957 case PCI_DEVICE_ID_XGI_27:
Aaro Koskinenfd26d422011-10-11 21:47:19 +03001958 xgifb_info->chip = XG27;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001959 break;
Prashant P. Shahb654f872010-09-06 17:34:26 +05301960 default:
Aaro Koskinenbb292232011-02-17 23:29:11 +02001961 ret = -ENODEV;
1962 goto error;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001963 }
1964
Aaro Koskinenfd26d422011-10-11 21:47:19 +03001965 printk("XGIfb:chipid = %x\n", xgifb_info->chip);
1966 hw_info->jChipType = xgifb_info->chip;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001967
Aaro Koskinenfd26d422011-10-11 21:47:19 +03001968 if (XGIfb_get_dram_size(xgifb_info)) {
Prashant P. Shahb654f872010-09-06 17:34:26 +05301969 printk(KERN_INFO "XGIfb: Fatal error: Unable to determine RAM size.\n");
Aaro Koskinenbb292232011-02-17 23:29:11 +02001970 ret = -ENODEV;
1971 goto error;
Prashant P. Shahb654f872010-09-06 17:34:26 +05301972 }
1973
Aaro Koskinene1521a12011-08-19 22:40:26 +03001974 /* Enable PCI_LINEAR_ADDRESSING and MMIO_ENABLE */
1975 xgifb_reg_or(XGISR,
Peter Huewefc39dcb2012-01-15 19:22:12 +01001976 IND_SIS_PCI_ADDRESS_SET,
1977 (SIS_PCI_ADDR_ENABLE | SIS_MEM_MAP_IO_ENABLE));
Aaro Koskinene1521a12011-08-19 22:40:26 +03001978 /* Enable 2D accelerator engine */
Peter Huewefc39dcb2012-01-15 19:22:12 +01001979 xgifb_reg_or(XGISR, IND_SIS_MODULE_ENABLE, SIS_ENABLE_2D);
Prashant P. Shahb654f872010-09-06 17:34:26 +05301980
Aaro Koskinenfd26d422011-10-11 21:47:19 +03001981 hw_info->ulVideoMemorySize = xgifb_info->video_size;
Prashant P. Shahb654f872010-09-06 17:34:26 +05301982
Aaro Koskinenfd26d422011-10-11 21:47:19 +03001983 if (!request_mem_region(xgifb_info->video_base,
1984 xgifb_info->video_size,
Kenji Toyamaa12c27c2011-04-26 12:13:43 +08001985 "XGIfb FB")) {
1986 printk("unable request memory size %x",
Aaro Koskinenfd26d422011-10-11 21:47:19 +03001987 xgifb_info->video_size);
Prashant P. Shahb654f872010-09-06 17:34:26 +05301988 printk(KERN_ERR "XGIfb: Fatal error: Unable to reserve frame buffer memory\n");
1989 printk(KERN_ERR "XGIfb: Is there another framebuffer driver active?\n");
Aaro Koskinenbb292232011-02-17 23:29:11 +02001990 ret = -ENODEV;
1991 goto error;
Prashant P. Shahb654f872010-09-06 17:34:26 +05301992 }
1993
Aaro Koskinenfd26d422011-10-11 21:47:19 +03001994 if (!request_mem_region(xgifb_info->mmio_base,
1995 xgifb_info->mmio_size,
Aaro Koskinen1b3909e2011-02-17 23:29:17 +02001996 "XGIfb MMIO")) {
Prashant P. Shahb654f872010-09-06 17:34:26 +05301997 printk(KERN_ERR "XGIfb: Fatal error: Unable to reserve MMIO region\n");
Aaro Koskinenbb292232011-02-17 23:29:11 +02001998 ret = -ENODEV;
Aaro Koskinen5c0ef2a2011-02-17 23:29:15 +02001999 goto error_0;
Prashant P. Shahb654f872010-09-06 17:34:26 +05302000 }
2001
Aaro Koskinenfd26d422011-10-11 21:47:19 +03002002 xgifb_info->video_vbase = hw_info->pjVideoMemoryAddress =
2003 ioremap(xgifb_info->video_base, xgifb_info->video_size);
2004 xgifb_info->mmio_vbase = ioremap(xgifb_info->mmio_base,
2005 xgifb_info->mmio_size);
Prashant P. Shahb654f872010-09-06 17:34:26 +05302006
2007 printk(KERN_INFO "XGIfb: Framebuffer at 0x%lx, mapped to 0x%p, size %dk\n",
Aaro Koskinenfd26d422011-10-11 21:47:19 +03002008 xgifb_info->video_base,
2009 xgifb_info->video_vbase,
2010 xgifb_info->video_size / 1024);
Prashant P. Shahb654f872010-09-06 17:34:26 +05302011
2012 printk(KERN_INFO "XGIfb: MMIO at 0x%lx, mapped to 0x%p, size %ldk\n",
Aaro Koskinenfd26d422011-10-11 21:47:19 +03002013 xgifb_info->mmio_base, xgifb_info->mmio_vbase,
2014 xgifb_info->mmio_size / 1024);
Prashant P. Shahb654f872010-09-06 17:34:26 +05302015 printk("XGIfb: XGIInitNew() ...");
Aaro Koskinenfcbdda92011-10-11 21:47:20 +03002016 pci_set_drvdata(pdev, xgifb_info);
Aaro Koskinen6048d7612011-10-11 21:47:16 +03002017 if (XGIInitNew(pdev))
Prashant P. Shahb654f872010-09-06 17:34:26 +05302018 printk("OK\n");
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02002019 else
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02002020 printk("Fail\n");
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02002021
Aaro Koskinenfd26d422011-10-11 21:47:19 +03002022 xgifb_info->mtrr = (unsigned int) 0;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02002023
Aaro Koskinenfd26d422011-10-11 21:47:19 +03002024 xgifb_info->hasVB = HASVB_NONE;
2025 if ((xgifb_info->chip == XG20) ||
2026 (xgifb_info->chip == XG27)) {
2027 xgifb_info->hasVB = HASVB_NONE;
2028 } else if (xgifb_info->chip == XG21) {
Aaro Koskinene1521a12011-08-19 22:40:26 +03002029 CR38 = xgifb_reg_get(XGICR, 0x38);
2030 if ((CR38&0xE0) == 0xC0) {
Aaro Koskinen289ea522011-10-11 21:47:37 +03002031 xgifb_info->display2 = XGIFB_DISP_LCD;
Aaro Koskinene1521a12011-08-19 22:40:26 +03002032 } else if ((CR38&0xE0) == 0x60) {
Aaro Koskinenfd26d422011-10-11 21:47:19 +03002033 xgifb_info->hasVB = HASVB_CHRONTEL;
Prashant P. Shahb654f872010-09-06 17:34:26 +05302034 } else {
Aaro Koskinenfd26d422011-10-11 21:47:19 +03002035 xgifb_info->hasVB = HASVB_NONE;
Prashant P. Shahb654f872010-09-06 17:34:26 +05302036 }
Aaro Koskinene1521a12011-08-19 22:40:26 +03002037 } else {
Aaro Koskinenfd26d422011-10-11 21:47:19 +03002038 XGIfb_get_VB_type(xgifb_info);
Aaro Koskinene1521a12011-08-19 22:40:26 +03002039 }
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02002040
Aaro Koskinenc62f2e42011-10-11 21:47:15 +03002041 hw_info->ujVBChipID = VB_CHIP_UNKNOWN;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02002042
Aaro Koskinenc62f2e42011-10-11 21:47:15 +03002043 hw_info->ulExternalChip = 0;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02002044
Aaro Koskinenfd26d422011-10-11 21:47:19 +03002045 switch (xgifb_info->hasVB) {
Aaro Koskinene1521a12011-08-19 22:40:26 +03002046 case HASVB_301:
2047 reg = xgifb_reg_get(XGIPART4, 0x01);
2048 if (reg >= 0xE0) {
Aaro Koskinenc62f2e42011-10-11 21:47:15 +03002049 hw_info->ujVBChipID = VB_CHIP_302LV;
Aaro Koskinene1521a12011-08-19 22:40:26 +03002050 printk(KERN_INFO "XGIfb: XGI302LV bridge detected (revision 0x%02x)\n", reg);
2051 } else if (reg >= 0xD0) {
Aaro Koskinenc62f2e42011-10-11 21:47:15 +03002052 hw_info->ujVBChipID = VB_CHIP_301LV;
Aaro Koskinene1521a12011-08-19 22:40:26 +03002053 printk(KERN_INFO "XGIfb: XGI301LV bridge detected (revision 0x%02x)\n", reg);
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02002054 }
Aaro Koskinene1521a12011-08-19 22:40:26 +03002055 /* else if (reg >= 0xB0) {
Aaro Koskinenc62f2e42011-10-11 21:47:15 +03002056 hw_info->ujVBChipID = VB_CHIP_301B;
Aaro Koskinene1521a12011-08-19 22:40:26 +03002057 reg1 = xgifb_reg_get(XGIPART4, 0x23);
2058 printk("XGIfb: XGI301B bridge detected\n");
2059 } */
2060 else {
Aaro Koskinenc62f2e42011-10-11 21:47:15 +03002061 hw_info->ujVBChipID = VB_CHIP_301;
Aaro Koskinene1521a12011-08-19 22:40:26 +03002062 printk("XGIfb: XGI301 bridge detected\n");
2063 }
2064 break;
2065 case HASVB_302:
2066 reg = xgifb_reg_get(XGIPART4, 0x01);
2067 if (reg >= 0xE0) {
Aaro Koskinenc62f2e42011-10-11 21:47:15 +03002068 hw_info->ujVBChipID = VB_CHIP_302LV;
Aaro Koskinene1521a12011-08-19 22:40:26 +03002069 printk(KERN_INFO "XGIfb: XGI302LV bridge detected (revision 0x%02x)\n", reg);
2070 } else if (reg >= 0xD0) {
Aaro Koskinenc62f2e42011-10-11 21:47:15 +03002071 hw_info->ujVBChipID = VB_CHIP_301LV;
Aaro Koskinene1521a12011-08-19 22:40:26 +03002072 printk(KERN_INFO "XGIfb: XGI302LV bridge detected (revision 0x%02x)\n", reg);
2073 } else if (reg >= 0xB0) {
2074 reg1 = xgifb_reg_get(XGIPART4, 0x23);
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02002075
Aaro Koskinenc62f2e42011-10-11 21:47:15 +03002076 hw_info->ujVBChipID = VB_CHIP_302B;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02002077
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02002078 } else {
Aaro Koskinenc62f2e42011-10-11 21:47:15 +03002079 hw_info->ujVBChipID = VB_CHIP_302;
Aaro Koskinene1521a12011-08-19 22:40:26 +03002080 printk(KERN_INFO "XGIfb: XGI302 bridge detected\n");
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02002081 }
Aaro Koskinene1521a12011-08-19 22:40:26 +03002082 break;
2083 case HASVB_LVDS:
Aaro Koskinenc62f2e42011-10-11 21:47:15 +03002084 hw_info->ulExternalChip = 0x1;
Aaro Koskinene1521a12011-08-19 22:40:26 +03002085 printk(KERN_INFO "XGIfb: LVDS transmitter detected\n");
2086 break;
2087 case HASVB_TRUMPION:
Aaro Koskinenc62f2e42011-10-11 21:47:15 +03002088 hw_info->ulExternalChip = 0x2;
Aaro Koskinene1521a12011-08-19 22:40:26 +03002089 printk(KERN_INFO "XGIfb: Trumpion Zurac LVDS scaler detected\n");
2090 break;
2091 case HASVB_CHRONTEL:
Aaro Koskinenc62f2e42011-10-11 21:47:15 +03002092 hw_info->ulExternalChip = 0x4;
Aaro Koskinene1521a12011-08-19 22:40:26 +03002093 printk(KERN_INFO "XGIfb: Chrontel TV encoder detected\n");
2094 break;
2095 case HASVB_LVDS_CHRONTEL:
Aaro Koskinenc62f2e42011-10-11 21:47:15 +03002096 hw_info->ulExternalChip = 0x5;
Aaro Koskinene1521a12011-08-19 22:40:26 +03002097 printk(KERN_INFO "XGIfb: LVDS transmitter and Chrontel TV encoder detected\n");
2098 break;
2099 default:
2100 printk(KERN_INFO "XGIfb: No or unknown bridge type detected\n");
2101 break;
2102 }
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02002103
Aaro Koskinenfd26d422011-10-11 21:47:19 +03002104 if (xgifb_info->hasVB != HASVB_NONE)
2105 XGIfb_detect_VB(xgifb_info);
Aaro Koskinen25aa75f2011-12-06 00:10:48 +02002106 else if (xgifb_info->chip != XG21)
2107 xgifb_info->display2 = XGIFB_DISP_NONE;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02002108
Aaro Koskinen289ea522011-10-11 21:47:37 +03002109 if (xgifb_info->display2 == XGIFB_DISP_LCD) {
Aaro Koskinene1521a12011-08-19 22:40:26 +03002110 if (!enable_dstn) {
2111 reg = xgifb_reg_get(XGICR, IND_XGI_LCD_PANEL);
2112 reg &= 0x0f;
Aaro Koskinenc62f2e42011-10-11 21:47:15 +03002113 hw_info->ulCRT2LCDType = XGI310paneltype[reg];
Aaro Koskinene1521a12011-08-19 22:40:26 +03002114 }
2115 }
2116
Aaro Koskinenc62f2e42011-10-11 21:47:15 +03002117 if ((hw_info->ujVBChipID == VB_CHIP_302B) ||
2118 (hw_info->ujVBChipID == VB_CHIP_301LV) ||
2119 (hw_info->ujVBChipID == VB_CHIP_302LV)) {
Aaro Koskinene1521a12011-08-19 22:40:26 +03002120 int tmp;
2121 tmp = xgifb_reg_get(XGICR, 0x34);
2122 if (tmp <= 0x13) {
2123 /* Currently on LCDA?
2124 *(Some BIOSes leave CR38) */
2125 tmp = xgifb_reg_get(XGICR, 0x38);
2126 if ((tmp & 0x03) == 0x03) {
2127 /* XGI_Pr.XGI_UseLCDA = 1; */
Prashant P. Shahb654f872010-09-06 17:34:26 +05302128 } else {
Kenji Toyamaa12c27c2011-04-26 12:13:43 +08002129 /* Currently on LCDA?
Aaro Koskinene1521a12011-08-19 22:40:26 +03002130 *(Some newer BIOSes set D0 in CR35) */
2131 tmp = xgifb_reg_get(XGICR, 0x35);
2132 if (tmp & 0x01) {
Prashant P. Shahb654f872010-09-06 17:34:26 +05302133 /* XGI_Pr.XGI_UseLCDA = 1; */
2134 } else {
Aaro Koskinene1521a12011-08-19 22:40:26 +03002135 tmp = xgifb_reg_get(XGICR,
2136 0x30);
2137 if (tmp & 0x20) {
2138 tmp = xgifb_reg_get(
2139 XGIPART1, 0x13);
2140 if (tmp & 0x04) {
2141 /* XGI_Pr.XGI_UseLCDA = 1; */
Prashant P. Shahb654f872010-09-06 17:34:26 +05302142 }
2143 }
2144 }
2145 }
Prashant P. Shahb654f872010-09-06 17:34:26 +05302146 }
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02002147
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02002148 }
2149
Aaro Koskinenccf265a2011-10-11 21:47:22 +03002150 xgifb_info->mode_idx = -1;
2151
Aaro Koskinendfbdf802011-08-29 23:14:25 +03002152 if (mode)
Aaro Koskinenccf265a2011-10-11 21:47:22 +03002153 XGIfb_search_mode(xgifb_info, mode);
Aaro Koskinendfbdf802011-08-29 23:14:25 +03002154 else if (vesa != -1)
Aaro Koskinenccf265a2011-10-11 21:47:22 +03002155 XGIfb_search_vesamode(xgifb_info, vesa);
Aaro Koskinendfbdf802011-08-29 23:14:25 +03002156
Aaro Koskinenccf265a2011-10-11 21:47:22 +03002157 if (xgifb_info->mode_idx >= 0)
2158 xgifb_info->mode_idx =
2159 XGIfb_validate_mode(xgifb_info, xgifb_info->mode_idx);
Aaro Koskinene1521a12011-08-19 22:40:26 +03002160
Aaro Koskinenccf265a2011-10-11 21:47:22 +03002161 if (xgifb_info->mode_idx < 0) {
Aaro Koskinen289ea522011-10-11 21:47:37 +03002162 if (xgifb_info->display2 == XGIFB_DISP_LCD &&
Aaro Koskinenfd26d422011-10-11 21:47:19 +03002163 xgifb_info->chip == XG21)
Aaro Koskinenccf265a2011-10-11 21:47:22 +03002164 xgifb_info->mode_idx =
Aaro Koskinenfab04b92011-12-06 00:10:45 +02002165 XGIfb_GetXG21DefaultLVDSModeIdx(xgifb_info);
Aaro Koskinenc8bec1f2011-08-29 23:14:30 +03002166 else
Aaro Koskinenccf265a2011-10-11 21:47:22 +03002167 xgifb_info->mode_idx = DEFAULT_MODE;
Aaro Koskinene1521a12011-08-19 22:40:26 +03002168 }
2169
Aaro Koskinenccf265a2011-10-11 21:47:22 +03002170 if (xgifb_info->mode_idx < 0) {
Aaro Koskinende736db2011-08-29 23:14:29 +03002171 dev_err(&pdev->dev, "no supported video mode found\n");
2172 goto error_1;
2173 }
2174
Aaro Koskinene1521a12011-08-19 22:40:26 +03002175 /* yilin set default refresh rate */
Aaro Koskinenfd26d422011-10-11 21:47:19 +03002176 xgifb_info->refresh_rate = refresh_rate;
2177 if (xgifb_info->refresh_rate == 0)
2178 xgifb_info->refresh_rate = 60;
2179 if (XGIfb_search_refresh_rate(xgifb_info,
2180 xgifb_info->refresh_rate) == 0) {
Aaro Koskinen5aa55d92011-10-11 21:47:23 +03002181 xgifb_info->rate_idx =
2182 XGIbios_mode[xgifb_info->mode_idx].rate_idx;
Aaro Koskinenfd26d422011-10-11 21:47:19 +03002183 xgifb_info->refresh_rate = 60;
Aaro Koskinene1521a12011-08-19 22:40:26 +03002184 }
2185
Aaro Koskinenccf265a2011-10-11 21:47:22 +03002186 xgifb_info->video_bpp = XGIbios_mode[xgifb_info->mode_idx].bpp;
Aaro Koskinenfd26d422011-10-11 21:47:19 +03002187 xgifb_info->video_vwidth =
2188 xgifb_info->video_width =
Aaro Koskinenccf265a2011-10-11 21:47:22 +03002189 XGIbios_mode[xgifb_info->mode_idx].xres;
Aaro Koskinenfd26d422011-10-11 21:47:19 +03002190 xgifb_info->video_vheight =
2191 xgifb_info->video_height =
Aaro Koskinenccf265a2011-10-11 21:47:22 +03002192 XGIbios_mode[xgifb_info->mode_idx].yres;
Aaro Koskinenfd26d422011-10-11 21:47:19 +03002193 xgifb_info->org_x = xgifb_info->org_y = 0;
2194 xgifb_info->video_linelength =
2195 xgifb_info->video_width *
2196 (xgifb_info->video_bpp >> 3);
2197 switch (xgifb_info->video_bpp) {
Aaro Koskinene1521a12011-08-19 22:40:26 +03002198 case 8:
Aaro Koskinenfd26d422011-10-11 21:47:19 +03002199 xgifb_info->DstColor = 0x0000;
2200 xgifb_info->XGI310_AccelDepth = 0x00000000;
2201 xgifb_info->video_cmap_len = 256;
Aaro Koskinene1521a12011-08-19 22:40:26 +03002202 break;
2203 case 16:
Aaro Koskinenfd26d422011-10-11 21:47:19 +03002204 xgifb_info->DstColor = 0x8000;
2205 xgifb_info->XGI310_AccelDepth = 0x00010000;
2206 xgifb_info->video_cmap_len = 16;
Aaro Koskinene1521a12011-08-19 22:40:26 +03002207 break;
2208 case 32:
Aaro Koskinenfd26d422011-10-11 21:47:19 +03002209 xgifb_info->DstColor = 0xC000;
2210 xgifb_info->XGI310_AccelDepth = 0x00020000;
2211 xgifb_info->video_cmap_len = 16;
Aaro Koskinene1521a12011-08-19 22:40:26 +03002212 break;
2213 default:
Aaro Koskinenfd26d422011-10-11 21:47:19 +03002214 xgifb_info->video_cmap_len = 16;
Aaro Koskinene1521a12011-08-19 22:40:26 +03002215 printk(KERN_INFO "XGIfb: Unsupported depth %d",
Aaro Koskinenfd26d422011-10-11 21:47:19 +03002216 xgifb_info->video_bpp);
Aaro Koskinene1521a12011-08-19 22:40:26 +03002217 break;
2218 }
2219
2220 printk(KERN_INFO "XGIfb: Default mode is %dx%dx%d (%dHz)\n",
Aaro Koskinenfd26d422011-10-11 21:47:19 +03002221 xgifb_info->video_width,
2222 xgifb_info->video_height,
2223 xgifb_info->video_bpp,
2224 xgifb_info->refresh_rate);
Aaro Koskinene1521a12011-08-19 22:40:26 +03002225
Aaro Koskinene9865d42011-10-11 21:47:26 +03002226 fb_info->var.red.length = 8;
2227 fb_info->var.green.length = 8;
2228 fb_info->var.blue.length = 8;
2229 fb_info->var.activate = FB_ACTIVATE_NOW;
2230 fb_info->var.height = -1;
2231 fb_info->var.width = -1;
2232 fb_info->var.vmode = FB_VMODE_NONINTERLACED;
2233 fb_info->var.xres = xgifb_info->video_width;
2234 fb_info->var.xres_virtual = xgifb_info->video_width;
2235 fb_info->var.yres = xgifb_info->video_height;
2236 fb_info->var.yres_virtual = xgifb_info->video_height;
2237 fb_info->var.bits_per_pixel = xgifb_info->video_bpp;
Aaro Koskinene1521a12011-08-19 22:40:26 +03002238
Aaro Koskinene9865d42011-10-11 21:47:26 +03002239 XGIfb_bpp_to_var(xgifb_info, &fb_info->var);
Aaro Koskinene1521a12011-08-19 22:40:26 +03002240
Aaro Koskinene9865d42011-10-11 21:47:26 +03002241 fb_info->var.pixclock = (u32) (1000000000 /
Aaro Koskinenf2df8c02011-10-11 21:47:30 +03002242 XGIfb_mode_rate_to_dclock(&xgifb_info->dev_info,
2243 hw_info,
Aaro Koskinenccf265a2011-10-11 21:47:22 +03002244 XGIbios_mode[xgifb_info->mode_idx].mode_no,
Aaro Koskinen5aa55d92011-10-11 21:47:23 +03002245 xgifb_info->rate_idx));
Aaro Koskinene1521a12011-08-19 22:40:26 +03002246
Aaro Koskinenf2df8c02011-10-11 21:47:30 +03002247 if (XGIfb_mode_rate_to_ddata(&xgifb_info->dev_info, hw_info,
Aaro Koskinen5aa55d92011-10-11 21:47:23 +03002248 XGIbios_mode[xgifb_info->mode_idx].mode_no,
2249 xgifb_info->rate_idx,
Aaro Koskinene9865d42011-10-11 21:47:26 +03002250 &fb_info->var.left_margin,
2251 &fb_info->var.right_margin,
2252 &fb_info->var.upper_margin,
2253 &fb_info->var.lower_margin,
2254 &fb_info->var.hsync_len,
2255 &fb_info->var.vsync_len,
2256 &fb_info->var.sync,
2257 &fb_info->var.vmode)) {
Aaro Koskinene1521a12011-08-19 22:40:26 +03002258
Aaro Koskinene9865d42011-10-11 21:47:26 +03002259 if ((fb_info->var.vmode & FB_VMODE_MASK) ==
Aaro Koskinene1521a12011-08-19 22:40:26 +03002260 FB_VMODE_INTERLACED) {
Aaro Koskinene9865d42011-10-11 21:47:26 +03002261 fb_info->var.yres <<= 1;
2262 fb_info->var.yres_virtual <<= 1;
2263 } else if ((fb_info->var.vmode & FB_VMODE_MASK) ==
Aaro Koskinene1521a12011-08-19 22:40:26 +03002264 FB_VMODE_DOUBLE) {
Aaro Koskinene9865d42011-10-11 21:47:26 +03002265 fb_info->var.pixclock >>= 1;
2266 fb_info->var.yres >>= 1;
2267 fb_info->var.yres_virtual >>= 1;
Aaro Koskinene1521a12011-08-19 22:40:26 +03002268 }
2269
2270 }
2271
Aaro Koskinenc11d0ef2011-10-11 21:47:27 +03002272 strncpy(fb_info->fix.id, "XGI", sizeof(fb_info->fix.id) - 1);
2273 fb_info->fix.type = FB_TYPE_PACKED_PIXELS;
2274 fb_info->fix.xpanstep = 1;
2275 fb_info->fix.ypanstep = 1;
2276
Aaro Koskinene1521a12011-08-19 22:40:26 +03002277 fb_info->flags = FBINFO_FLAG_DEFAULT;
Aaro Koskinenfd26d422011-10-11 21:47:19 +03002278 fb_info->screen_base = xgifb_info->video_vbase;
Aaro Koskinene1521a12011-08-19 22:40:26 +03002279 fb_info->fbops = &XGIfb_ops;
2280 XGIfb_get_fix(&fb_info->fix, -1, fb_info);
Aaro Koskinen76cabaa2011-10-11 21:47:24 +03002281 fb_info->pseudo_palette = xgifb_info->pseudo_palette;
Aaro Koskinene1521a12011-08-19 22:40:26 +03002282
2283 fb_alloc_cmap(&fb_info->cmap, 256 , 0);
2284
2285#ifdef CONFIG_MTRR
Aaro Koskinenfd26d422011-10-11 21:47:19 +03002286 xgifb_info->mtrr = mtrr_add(xgifb_info->video_base,
2287 xgifb_info->video_size, MTRR_TYPE_WRCOMB, 1);
2288 if (xgifb_info->mtrr >= 0)
Aaro Koskinen15ebe6c2011-09-11 00:29:54 +03002289 dev_info(&pdev->dev, "added MTRR\n");
Aaro Koskinene1521a12011-08-19 22:40:26 +03002290#endif
2291
2292 if (register_framebuffer(fb_info) < 0) {
2293 ret = -EINVAL;
Aaro Koskinen30284742011-09-11 00:29:53 +03002294 goto error_mtrr;
Aaro Koskinene1521a12011-08-19 22:40:26 +03002295 }
2296
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02002297 dumpVGAReg();
2298
2299 return 0;
Aaro Koskinenbb292232011-02-17 23:29:11 +02002300
Aaro Koskinen30284742011-09-11 00:29:53 +03002301error_mtrr:
2302#ifdef CONFIG_MTRR
Aaro Koskinenfd26d422011-10-11 21:47:19 +03002303 if (xgifb_info->mtrr >= 0)
2304 mtrr_del(xgifb_info->mtrr, xgifb_info->video_base,
2305 xgifb_info->video_size);
Aaro Koskinen30284742011-09-11 00:29:53 +03002306#endif /* CONFIG_MTRR */
Aaro Koskinen5c0ef2a2011-02-17 23:29:15 +02002307error_1:
Aaro Koskinenfd26d422011-10-11 21:47:19 +03002308 iounmap(xgifb_info->mmio_vbase);
2309 iounmap(xgifb_info->video_vbase);
2310 release_mem_region(xgifb_info->mmio_base, xgifb_info->mmio_size);
Aaro Koskinen5c0ef2a2011-02-17 23:29:15 +02002311error_0:
Aaro Koskinenfd26d422011-10-11 21:47:19 +03002312 release_mem_region(xgifb_info->video_base, xgifb_info->video_size);
Aaro Koskinenbb292232011-02-17 23:29:11 +02002313error:
2314 framebuffer_release(fb_info);
2315 return ret;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02002316}
2317
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02002318/*****************************************************/
2319/* PCI DEVICE HANDLING */
2320/*****************************************************/
2321
2322static void __devexit xgifb_remove(struct pci_dev *pdev)
2323{
Aaro Koskinenab886ff2011-10-11 21:47:18 +03002324 struct xgifb_video_info *xgifb_info = pci_get_drvdata(pdev);
Aaro Koskinen19c1e882011-10-11 21:47:14 +03002325 struct fb_info *fb_info = xgifb_info->fb_info;
Aaro Koskinen54301b52011-10-11 21:47:13 +03002326
Prashant P. Shahb654f872010-09-06 17:34:26 +05302327 unregister_framebuffer(fb_info);
Aaro Koskinen30284742011-09-11 00:29:53 +03002328#ifdef CONFIG_MTRR
Aaro Koskinen54301b52011-10-11 21:47:13 +03002329 if (xgifb_info->mtrr >= 0)
2330 mtrr_del(xgifb_info->mtrr, xgifb_info->video_base,
2331 xgifb_info->video_size);
Aaro Koskinen30284742011-09-11 00:29:53 +03002332#endif /* CONFIG_MTRR */
Aaro Koskinen54301b52011-10-11 21:47:13 +03002333 iounmap(xgifb_info->mmio_vbase);
2334 iounmap(xgifb_info->video_vbase);
2335 release_mem_region(xgifb_info->mmio_base, xgifb_info->mmio_size);
2336 release_mem_region(xgifb_info->video_base, xgifb_info->video_size);
Prashant P. Shahb654f872010-09-06 17:34:26 +05302337 framebuffer_release(fb_info);
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02002338 pci_set_drvdata(pdev, NULL);
Aaro Koskinen45dcfaf2011-02-17 23:29:16 +02002339}
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02002340
2341static struct pci_driver xgifb_driver = {
Prashant P. Shahb654f872010-09-06 17:34:26 +05302342 .name = "xgifb",
2343 .id_table = xgifb_pci_table,
2344 .probe = xgifb_probe,
2345 .remove = __devexit_p(xgifb_remove)
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02002346};
2347
Ruslan Pisarev032abf72011-07-21 11:59:11 +03002348static int __init xgifb_init(void)
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02002349{
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02002350 char *option = NULL;
2351
Aaro Koskinen2d2c8802011-12-06 00:10:49 +02002352 if (forcecrt2type != NULL)
2353 XGIfb_search_crt2type(forcecrt2type);
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02002354 if (fb_get_options("xgifb", &option))
2355 return -ENODEV;
2356 XGIfb_setup(option);
Javier Martinez Canillas328f55b2010-09-08 00:07:57 -04002357
Prashant P. Shahb654f872010-09-06 17:34:26 +05302358 return pci_register_driver(&xgifb_driver);
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02002359}
2360
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02002361module_init(xgifb_init);
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02002362
2363/*****************************************************/
2364/* MODULE */
2365/*****************************************************/
2366
2367#ifdef MODULE
2368
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02002369MODULE_DESCRIPTION("Z7 Z9 Z9S Z11 framebuffer device driver");
2370MODULE_LICENSE("GPL");
2371MODULE_AUTHOR("XGITECH , Others");
2372
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02002373module_param(mode, charp, 0);
2374module_param(vesa, int, 0);
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02002375module_param(filter, int, 0);
Aaro Koskinen2d2c8802011-12-06 00:10:49 +02002376module_param(forcecrt2type, charp, 0);
2377
2378MODULE_PARM_DESC(forcecrt2type,
2379 "\nForce the second display output type. Possible values are NONE,\n"
2380 "LCD, TV, VGA, SVIDEO or COMPOSITE.\n");
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02002381
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02002382MODULE_PARM_DESC(mode,
Aaro Koskinen47c92d52011-08-29 23:14:33 +03002383 "\nSelects the desired default display mode in the format XxYxDepth,\n"
2384 "eg. 1024x768x16.\n");
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02002385
2386MODULE_PARM_DESC(vesa,
Aaro Koskinen47c92d52011-08-29 23:14:33 +03002387 "\nSelects the desired default display mode by VESA mode number, eg.\n"
2388 "0x117.\n");
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02002389
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02002390MODULE_PARM_DESC(filter,
Prashant P. Shahb654f872010-09-06 17:34:26 +05302391 "\nSelects TV flicker filter type (only for systems with a SiS301 video bridge).\n"
2392 "(Possible values 0-7, default: [no filter])\n");
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02002393
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02002394static void __exit xgifb_remove_module(void)
2395{
2396 pci_unregister_driver(&xgifb_driver);
2397 printk(KERN_DEBUG "xgifb: Module unloaded\n");
2398}
2399
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02002400module_exit(xgifb_remove_module);
2401
Prashant P. Shahb654f872010-09-06 17:34:26 +05302402#endif /* /MODULE */