blob: ef9b969aac3d5655a7e0425e5a622dfd613af7f8 [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>
24#include <linux/vmalloc.h>
25#include <linux/vt_kern.h>
26#include <linux/capability.h>
27#include <linux/fs.h>
28#include <linux/types.h>
29#include <linux/proc_fs.h>
apatard@mandriva.comd7636e02010-05-19 10:44:14 +020030
Kenji Toyamaa12c27c2011-04-26 12:13:43 +080031#include <linux/io.h>
apatard@mandriva.comd7636e02010-05-19 10:44:14 +020032#ifdef CONFIG_MTRR
33#include <asm/mtrr.h>
34#endif
35
36#include "XGIfb.h"
37#include "vgatypes.h"
38#include "XGI_main.h"
Aaro Koskinend542af52011-04-18 22:14:06 +030039#include "vb_init.h"
apatard@mandriva.comd7636e02010-05-19 10:44:14 +020040#include "vb_util.h"
Aaro Koskinend542af52011-04-18 22:14:06 +030041#include "vb_setmode.h"
apatard@mandriva.comd7636e02010-05-19 10:44:14 +020042
apatard@mandriva.comd7636e02010-05-19 10:44:14 +020043#define Index_CR_GPIO_Reg1 0x48
apatard@mandriva.comd7636e02010-05-19 10:44:14 +020044#define Index_CR_GPIO_Reg3 0x4a
45
46#define GPIOG_EN (1<<6)
apatard@mandriva.comd7636e02010-05-19 10:44:14 +020047#define GPIOG_READ (1<<1)
apatard@mandriva.comd7636e02010-05-19 10:44:14 +020048
Aaro Koskinen0f07d942011-02-17 23:29:13 +020049#define XGIFB_ROM_SIZE 65536
50
Aaro Koskinendfbdf802011-08-29 23:14:25 +030051static char *mode;
Aaro Koskinenc3228302011-08-29 23:14:32 +030052static int vesa = -1;
Aaro Koskinen7548a832011-10-11 21:47:17 +030053static unsigned int refresh_rate;
Aaro Koskinendfbdf802011-08-29 23:14:25 +030054
apatard@mandriva.comd7636e02010-05-19 10:44:14 +020055/* -------------------- Macro definitions ---------------------------- */
56
57#undef XGIFBDEBUG
58
59#ifdef XGIFBDEBUG
60#define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt, __FUNCTION__ , ## args)
61#else
62#define DPRINTK(fmt, args...)
63#endif
64
65#ifdef XGIFBDEBUG
66static void dumpVGAReg(void)
67{
Prashant P. Shahb654f872010-09-06 17:34:26 +053068 u8 i, reg;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +020069
Aaro Koskinenb6e2dc32011-04-18 22:13:59 +030070 xgifb_reg_set(XGISR, 0x05, 0x86);
Prashant P. Shahb654f872010-09-06 17:34:26 +053071 /*
Aaro Koskinenb6e2dc32011-04-18 22:13:59 +030072 xgifb_reg_set(XGISR, 0x08, 0x4f);
73 xgifb_reg_set(XGISR, 0x0f, 0x20);
74 xgifb_reg_set(XGISR, 0x11, 0x4f);
75 xgifb_reg_set(XGISR, 0x13, 0x45);
76 xgifb_reg_set(XGISR, 0x14, 0x51);
77 xgifb_reg_set(XGISR, 0x1e, 0x41);
78 xgifb_reg_set(XGISR, 0x1f, 0x0);
79 xgifb_reg_set(XGISR, 0x20, 0xa1);
80 xgifb_reg_set(XGISR, 0x22, 0xfb);
81 xgifb_reg_set(XGISR, 0x26, 0x22);
82 xgifb_reg_set(XGISR, 0x3e, 0x07);
Prashant P. Shahb654f872010-09-06 17:34:26 +053083 */
apatard@mandriva.comd7636e02010-05-19 10:44:14 +020084
Aaro Koskinenb6e2dc32011-04-18 22:13:59 +030085 /* xgifb_reg_set(XGICR, 0x19, 0x00); */
86 /* xgifb_reg_set(XGICR, 0x1a, 0x3C); */
87 /* xgifb_reg_set(XGICR, 0x22, 0xff); */
88 /* xgifb_reg_set(XGICR, 0x3D, 0x10); */
apatard@mandriva.comd7636e02010-05-19 10:44:14 +020089
Aaro Koskinenb6e2dc32011-04-18 22:13:59 +030090 /* xgifb_reg_set(XGICR, 0x4a, 0xf3); */
apatard@mandriva.comd7636e02010-05-19 10:44:14 +020091
Aaro Koskinenb6e2dc32011-04-18 22:13:59 +030092 /* xgifb_reg_set(XGICR, 0x57, 0x0); */
93 /* xgifb_reg_set(XGICR, 0x7a, 0x2c); */
apatard@mandriva.comd7636e02010-05-19 10:44:14 +020094
Aaro Koskinenb6e2dc32011-04-18 22:13:59 +030095 /* xgifb_reg_set(XGICR, 0x82, 0xcc); */
96 /* xgifb_reg_set(XGICR, 0x8c, 0x0); */
Prashant P. Shahb654f872010-09-06 17:34:26 +053097 /*
Aaro Koskinenb6e2dc32011-04-18 22:13:59 +030098 xgifb_reg_set(XGICR, 0x99, 0x1);
99 xgifb_reg_set(XGICR, 0x41, 0x40);
Prashant P. Shahb654f872010-09-06 17:34:26 +0530100 */
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200101
Prashant P. Shahb654f872010-09-06 17:34:26 +0530102 for (i = 0; i < 0x4f; i++) {
Aaro Koskinen7e119b72011-04-18 22:13:58 +0300103 reg = xgifb_reg_get(XGISR, i);
Prashant P. Shahb654f872010-09-06 17:34:26 +0530104 printk("\no 3c4 %x", i);
105 printk("\ni 3c5 => %x", reg);
106 }
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200107
Prashant P. Shahb654f872010-09-06 17:34:26 +0530108 for (i = 0; i < 0xF0; i++) {
Aaro Koskinen7e119b72011-04-18 22:13:58 +0300109 reg = xgifb_reg_get(XGICR, i);
Prashant P. Shahb654f872010-09-06 17:34:26 +0530110 printk("\no 3d4 %x", i);
111 printk("\ni 3d5 => %x", reg);
112 }
113 /*
Aaro Koskinenb6e2dc32011-04-18 22:13:59 +0300114 xgifb_reg_set(XGIPART1,0x2F,1);
Prashant P. Shahb654f872010-09-06 17:34:26 +0530115 for (i=1; i < 0x50; i++) {
Aaro Koskinen7e119b72011-04-18 22:13:58 +0300116 reg = xgifb_reg_get(XGIPART1, i);
Prashant P. Shahb654f872010-09-06 17:34:26 +0530117 printk("\no d004 %x", i);
118 printk("\ni d005 => %x", reg);
119 }
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200120
Prashant P. Shahb654f872010-09-06 17:34:26 +0530121 for (i=0; i < 0x50; i++) {
Aaro Koskinen7e119b72011-04-18 22:13:58 +0300122 reg = xgifb_reg_get(XGIPART2, i);
Prashant P. Shahb654f872010-09-06 17:34:26 +0530123 printk("\no d010 %x", i);
124 printk("\ni d011 => %x", reg);
125 }
126 for (i=0; i < 0x50; i++) {
Aaro Koskinen7e119b72011-04-18 22:13:58 +0300127 reg = xgifb_reg_get(XGIPART3, i);
Prashant P. Shahb654f872010-09-06 17:34:26 +0530128 printk("\no d012 %x",i);
129 printk("\ni d013 => %x",reg);
130 }
131 for (i=0; i < 0x50; i++) {
Aaro Koskinen7e119b72011-04-18 22:13:58 +0300132 reg = xgifb_reg_get(XGIPART4, i);
Prashant P. Shahb654f872010-09-06 17:34:26 +0530133 printk("\no d014 %x",i);
134 printk("\ni d015 => %x",reg);
135 }
136 */
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200137}
138#else
Prashant P. Shahb654f872010-09-06 17:34:26 +0530139static inline void dumpVGAReg(void)
140{
141}
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200142#endif
143
144/* data for XGI components */
Aaro Koskinenab886ff2011-10-11 21:47:18 +0300145struct xgifb_video_info xgi_video_info;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200146
147#if 1
148#define DEBUGPRN(x)
149#else
150#define DEBUGPRN(x) printk(KERN_INFO x "\n");
151#endif
152
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200153/* --------------- Hardware Access Routines -------------------------- */
154
Prashant P. Shahb654f872010-09-06 17:34:26 +0530155static int XGIfb_mode_rate_to_dclock(struct vb_device_info *XGI_Pr,
156 struct xgi_hw_device_info *HwDeviceExtension,
157 unsigned char modeno, unsigned char rateindex)
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200158{
Prashant P. Shahb654f872010-09-06 17:34:26 +0530159 unsigned short ModeNo = modeno;
160 unsigned short ModeIdIndex = 0, ClockIndex = 0;
161 unsigned short RefreshRateTableIndex = 0;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200162
Prashant P. Shahb654f872010-09-06 17:34:26 +0530163 /* unsigned long temp = 0; */
164 int Clock;
165 XGI_Pr->ROMAddr = HwDeviceExtension->pjVirtualRomBase;
166 InitTo330Pointer(HwDeviceExtension->jChipType, XGI_Pr);
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200167
Prashant P. Shahb654f872010-09-06 17:34:26 +0530168 RefreshRateTableIndex = XGI_GetRatePtrCRT2(HwDeviceExtension, ModeNo,
169 ModeIdIndex, XGI_Pr);
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200170
Prashant P. Shahb654f872010-09-06 17:34:26 +0530171 /*
172 temp = XGI_SearchModeID(ModeNo , &ModeIdIndex, XGI_Pr) ;
173 if (!temp) {
174 printk(KERN_ERR "Could not find mode %x\n", ModeNo);
175 return 65000;
176 }
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200177
Prashant P. Shahb654f872010-09-06 17:34:26 +0530178 RefreshRateTableIndex = XGI_Pr->EModeIDTable[ModeIdIndex].REFindex;
179 RefreshRateTableIndex += (rateindex - 1);
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200180
Prashant P. Shahb654f872010-09-06 17:34:26 +0530181 */
182 ClockIndex = XGI_Pr->RefIndex[RefreshRateTableIndex].Ext_CRTVCLK;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200183
Prashant P. Shahb654f872010-09-06 17:34:26 +0530184 Clock = XGI_Pr->VCLKData[ClockIndex].CLOCK * 1000;
185
186 return Clock;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200187}
188
Prashant P. Shahb654f872010-09-06 17:34:26 +0530189static int XGIfb_mode_rate_to_ddata(struct vb_device_info *XGI_Pr,
190 struct xgi_hw_device_info *HwDeviceExtension,
191 unsigned char modeno, unsigned char rateindex,
192 u32 *left_margin, u32 *right_margin, u32 *upper_margin,
193 u32 *lower_margin, u32 *hsync_len, u32 *vsync_len, u32 *sync,
194 u32 *vmode)
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200195{
Prashant P. Shahb654f872010-09-06 17:34:26 +0530196 unsigned short ModeNo = modeno;
197 unsigned short ModeIdIndex = 0, index = 0;
198 unsigned short RefreshRateTableIndex = 0;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200199
Prashant P. Shahb654f872010-09-06 17:34:26 +0530200 unsigned short VRE, VBE, VRS, VBS, VDE, VT;
201 unsigned short HRE, HBE, HRS, HBS, HDE, HT;
202 unsigned char sr_data, cr_data, cr_data2;
203 unsigned long cr_data3;
204 int A, B, C, D, E, F, temp, j;
205 XGI_Pr->ROMAddr = HwDeviceExtension->pjVirtualRomBase;
206 InitTo330Pointer(HwDeviceExtension->jChipType, XGI_Pr);
207 RefreshRateTableIndex = XGI_GetRatePtrCRT2(HwDeviceExtension, ModeNo,
208 ModeIdIndex, XGI_Pr);
209 /*
210 temp = XGI_SearchModeID(ModeNo, &ModeIdIndex, XGI_Pr);
211 if (!temp)
212 return 0;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200213
Prashant P. Shahb654f872010-09-06 17:34:26 +0530214 RefreshRateTableIndex = XGI_Pr->EModeIDTable[ModeIdIndex].REFindex;
215 RefreshRateTableIndex += (rateindex - 1);
216 */
217 index = XGI_Pr->RefIndex[RefreshRateTableIndex].Ext_CRT1CRTC;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200218
Prashant P. Shahb654f872010-09-06 17:34:26 +0530219 sr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[5];
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200220
Prashant P. Shahb654f872010-09-06 17:34:26 +0530221 cr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[0];
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200222
Prashant P. Shahb654f872010-09-06 17:34:26 +0530223 /* Horizontal total */
224 HT = (cr_data & 0xff) | ((unsigned short) (sr_data & 0x03) << 8);
225 A = HT + 5;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200226
Prashant P. Shahb654f872010-09-06 17:34:26 +0530227 /*
228 cr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[1];
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200229
Prashant P. Shahb654f872010-09-06 17:34:26 +0530230 Horizontal display enable end
231 HDE = (cr_data & 0xff) | ((unsigned short) (sr_data & 0x0C) << 6);
232 */
233 HDE = (XGI_Pr->RefIndex[RefreshRateTableIndex].XRes >> 3) - 1;
234 E = HDE + 1;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200235
Prashant P. Shahb654f872010-09-06 17:34:26 +0530236 cr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[3];
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200237
Prashant P. Shahb654f872010-09-06 17:34:26 +0530238 /* Horizontal retrace (=sync) start */
239 HRS = (cr_data & 0xff) | ((unsigned short) (sr_data & 0xC0) << 2);
240 F = HRS - E - 3;
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[1];
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200243
Prashant P. Shahb654f872010-09-06 17:34:26 +0530244 /* Horizontal blank start */
245 HBS = (cr_data & 0xff) | ((unsigned short) (sr_data & 0x30) << 4);
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200246
Prashant P. Shahb654f872010-09-06 17:34:26 +0530247 sr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[6];
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200248
Prashant P. Shahb654f872010-09-06 17:34:26 +0530249 cr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[2];
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200250
Prashant P. Shahb654f872010-09-06 17:34:26 +0530251 cr_data2 = XGI_Pr->XGINEWUB_CRT1Table[index].CR[4];
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200252
Prashant P. Shahb654f872010-09-06 17:34:26 +0530253 /* Horizontal blank end */
254 HBE = (cr_data & 0x1f) | ((unsigned short) (cr_data2 & 0x80) >> 2)
255 | ((unsigned short) (sr_data & 0x03) << 6);
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200256
Prashant P. Shahb654f872010-09-06 17:34:26 +0530257 /* Horizontal retrace (=sync) end */
258 HRE = (cr_data2 & 0x1f) | ((sr_data & 0x04) << 3);
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200259
Prashant P. Shahb654f872010-09-06 17:34:26 +0530260 temp = HBE - ((E - 1) & 255);
261 B = (temp > 0) ? temp : (temp + 256);
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200262
Prashant P. Shahb654f872010-09-06 17:34:26 +0530263 temp = HRE - ((E + F + 3) & 63);
264 C = (temp > 0) ? temp : (temp + 64);
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200265
Prashant P. Shahb654f872010-09-06 17:34:26 +0530266 D = B - F - C;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200267
Prashant P. Shahb654f872010-09-06 17:34:26 +0530268 *left_margin = D * 8;
269 *right_margin = F * 8;
270 *hsync_len = C * 8;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200271
Prashant P. Shahb654f872010-09-06 17:34:26 +0530272 sr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[14];
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200273
Prashant P. Shahb654f872010-09-06 17:34:26 +0530274 cr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[8];
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200275
Prashant P. Shahb654f872010-09-06 17:34:26 +0530276 cr_data2 = XGI_Pr->XGINEWUB_CRT1Table[index].CR[9];
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200277
Prashant P. Shahb654f872010-09-06 17:34:26 +0530278 /* Vertical total */
279 VT = (cr_data & 0xFF) | ((unsigned short) (cr_data2 & 0x01) << 8)
280 | ((unsigned short) (cr_data2 & 0x20) << 4)
281 | ((unsigned short) (sr_data & 0x01) << 10);
282 A = VT + 2;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200283
Prashant P. Shahb654f872010-09-06 17:34:26 +0530284 /* cr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[10]; */
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200285
Prashant P. Shahb654f872010-09-06 17:34:26 +0530286 /* Vertical display enable end */
287 /*
288 VDE = (cr_data & 0xff) |
289 ((unsigned short) (cr_data2 & 0x02) << 7) |
290 ((unsigned short) (cr_data2 & 0x40) << 3) |
291 ((unsigned short) (sr_data & 0x02) << 9);
292 */
293 VDE = XGI_Pr->RefIndex[RefreshRateTableIndex].YRes - 1;
294 E = VDE + 1;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200295
Prashant P. Shahb654f872010-09-06 17:34:26 +0530296 cr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[10];
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200297
Prashant P. Shahb654f872010-09-06 17:34:26 +0530298 /* Vertical retrace (=sync) start */
299 VRS = (cr_data & 0xff) | ((unsigned short) (cr_data2 & 0x04) << 6)
300 | ((unsigned short) (cr_data2 & 0x80) << 2)
301 | ((unsigned short) (sr_data & 0x08) << 7);
302 F = VRS + 1 - E;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200303
Prashant P. Shahb654f872010-09-06 17:34:26 +0530304 cr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[12];
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200305
Prashant P. Shahb654f872010-09-06 17:34:26 +0530306 cr_data3 = (XGI_Pr->XGINEWUB_CRT1Table[index].CR[14] & 0x80) << 5;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200307
Prashant P. Shahb654f872010-09-06 17:34:26 +0530308 /* Vertical blank start */
309 VBS = (cr_data & 0xff) | ((unsigned short) (cr_data2 & 0x08) << 5)
310 | ((unsigned short) (cr_data3 & 0x20) << 4)
311 | ((unsigned short) (sr_data & 0x04) << 8);
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[13];
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200314
Prashant P. Shahb654f872010-09-06 17:34:26 +0530315 /* Vertical blank end */
316 VBE = (cr_data & 0xff) | ((unsigned short) (sr_data & 0x10) << 4);
317 temp = VBE - ((E - 1) & 511);
318 B = (temp > 0) ? temp : (temp + 512);
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200319
Prashant P. Shahb654f872010-09-06 17:34:26 +0530320 cr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[11];
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200321
Prashant P. Shahb654f872010-09-06 17:34:26 +0530322 /* Vertical retrace (=sync) end */
323 VRE = (cr_data & 0x0f) | ((sr_data & 0x20) >> 1);
324 temp = VRE - ((E + F - 1) & 31);
325 C = (temp > 0) ? temp : (temp + 32);
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200326
Prashant P. Shahb654f872010-09-06 17:34:26 +0530327 D = B - F - C;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200328
Prashant P. Shahb654f872010-09-06 17:34:26 +0530329 *upper_margin = D;
330 *lower_margin = F;
331 *vsync_len = C;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200332
Prashant P. Shahb654f872010-09-06 17:34:26 +0530333 if (XGI_Pr->RefIndex[RefreshRateTableIndex].Ext_InfoFlag & 0x8000)
334 *sync &= ~FB_SYNC_VERT_HIGH_ACT;
335 else
336 *sync |= FB_SYNC_VERT_HIGH_ACT;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200337
Prashant P. Shahb654f872010-09-06 17:34:26 +0530338 if (XGI_Pr->RefIndex[RefreshRateTableIndex].Ext_InfoFlag & 0x4000)
339 *sync &= ~FB_SYNC_HOR_HIGH_ACT;
340 else
341 *sync |= FB_SYNC_HOR_HIGH_ACT;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200342
Prashant P. Shahb654f872010-09-06 17:34:26 +0530343 *vmode = FB_VMODE_NONINTERLACED;
344 if (XGI_Pr->RefIndex[RefreshRateTableIndex].Ext_InfoFlag & 0x0080)
345 *vmode = FB_VMODE_INTERLACED;
346 else {
347 j = 0;
348 while (XGI_Pr->EModeIDTable[j].Ext_ModeID != 0xff) {
Kenji Toyamaa12c27c2011-04-26 12:13:43 +0800349 if (XGI_Pr->EModeIDTable[j].Ext_ModeID ==
350 XGI_Pr->RefIndex[RefreshRateTableIndex].ModeID) {
351 if (XGI_Pr->EModeIDTable[j].Ext_ModeFlag &
352 DoubleScanMode) {
Prashant P. Shahb654f872010-09-06 17:34:26 +0530353 *vmode = FB_VMODE_DOUBLE;
354 }
355 break;
356 }
357 j++;
358 }
359 }
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200360
Prashant P. Shahb654f872010-09-06 17:34:26 +0530361 return 1;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200362}
363
Randy Dunlap89229672010-08-10 08:46:44 -0700364static void XGIRegInit(struct vb_device_info *XGI_Pr, unsigned long BaseAddr)
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200365{
Prashant P. Shahb654f872010-09-06 17:34:26 +0530366 XGI_Pr->RelIO = BaseAddr;
367 XGI_Pr->P3c4 = BaseAddr + 0x14;
368 XGI_Pr->P3d4 = BaseAddr + 0x24;
369 XGI_Pr->P3c0 = BaseAddr + 0x10;
370 XGI_Pr->P3ce = BaseAddr + 0x1e;
371 XGI_Pr->P3c2 = BaseAddr + 0x12;
372 XGI_Pr->P3ca = BaseAddr + 0x1a;
373 XGI_Pr->P3c6 = BaseAddr + 0x16;
374 XGI_Pr->P3c7 = BaseAddr + 0x17;
375 XGI_Pr->P3c8 = BaseAddr + 0x18;
376 XGI_Pr->P3c9 = BaseAddr + 0x19;
377 XGI_Pr->P3da = BaseAddr + 0x2A;
Kenji Toyamaa12c27c2011-04-26 12:13:43 +0800378 /* Digital video interface registers (LCD) */
379 XGI_Pr->Part1Port = BaseAddr + XGI_CRT2_PORT_04;
380 /* 301 TV Encoder registers */
381 XGI_Pr->Part2Port = BaseAddr + XGI_CRT2_PORT_10;
382 /* 301 Macrovision registers */
383 XGI_Pr->Part3Port = BaseAddr + XGI_CRT2_PORT_12;
384 /* 301 VGA2 (and LCD) registers */
385 XGI_Pr->Part4Port = BaseAddr + XGI_CRT2_PORT_14;
386 /* 301 palette address port registers */
387 XGI_Pr->Part5Port = BaseAddr + XGI_CRT2_PORT_14 + 2;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200388
389}
390
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200391/* ------------------ Internal helper routines ----------------- */
392
Aaro Koskinen8a94d1a2011-04-18 22:14:08 +0300393static int XGIfb_GetXG21DefaultLVDSModeIdx(void)
Aaro Koskinenc4fa7df2011-04-18 22:14:05 +0300394{
395
396 int found_mode = 0;
397 int XGIfb_mode_idx = 0;
398
399 found_mode = 0;
400 while ((XGIbios_mode[XGIfb_mode_idx].mode_no != 0)
401 && (XGIbios_mode[XGIfb_mode_idx].xres
402 <= XGI21_LCDCapList[0].LVDSHDE)) {
403 if ((XGIbios_mode[XGIfb_mode_idx].xres
404 == XGI21_LCDCapList[0].LVDSHDE)
405 && (XGIbios_mode[XGIfb_mode_idx].yres
406 == XGI21_LCDCapList[0].LVDSVDE)
407 && (XGIbios_mode[XGIfb_mode_idx].bpp == 8)) {
408 XGIfb_mode_no = XGIbios_mode[XGIfb_mode_idx].mode_no;
409 found_mode = 1;
410 break;
411 }
412 XGIfb_mode_idx++;
413 }
414 if (!found_mode)
Aaro Koskinende736db2011-08-29 23:14:29 +0300415 XGIfb_mode_idx = -1;
Aaro Koskinenc4fa7df2011-04-18 22:14:05 +0300416
417 return XGIfb_mode_idx;
418}
419
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200420static void XGIfb_search_mode(const char *name)
421{
422 int i = 0, j = 0, l;
423
Prashant P. Shahb654f872010-09-06 17:34:26 +0530424 while (XGIbios_mode[i].mode_no != 0) {
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200425 l = min(strlen(name), strlen(XGIbios_mode[i].name));
426 if (!strncmp(name, XGIbios_mode[i].name, l)) {
427 xgifb_mode_idx = i;
428 j = 1;
429 break;
430 }
431 i++;
432 }
Prashant P. Shahb654f872010-09-06 17:34:26 +0530433 if (!j)
434 printk(KERN_INFO "XGIfb: Invalid mode '%s'\n", name);
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200435}
436
437static void XGIfb_search_vesamode(unsigned int vesamode)
438{
439 int i = 0, j = 0;
440
Aaro Koskinenc3228302011-08-29 23:14:32 +0300441 if (vesamode == 0)
442 goto invalid;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200443
Prashant P. Shahb654f872010-09-06 17:34:26 +0530444 vesamode &= 0x1dff; /* Clean VESA mode number from other flags */
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200445
Prashant P. Shahb654f872010-09-06 17:34:26 +0530446 while (XGIbios_mode[i].mode_no != 0) {
Kenji Toyamaa12c27c2011-04-26 12:13:43 +0800447 if ((XGIbios_mode[i].vesa_mode_no_1 == vesamode) ||
448 (XGIbios_mode[i].vesa_mode_no_2 == vesamode)) {
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200449 xgifb_mode_idx = i;
450 j = 1;
451 break;
452 }
453 i++;
454 }
Aaro Koskinenc3228302011-08-29 23:14:32 +0300455
456invalid:
Prashant P. Shahb654f872010-09-06 17:34:26 +0530457 if (!j)
458 printk(KERN_INFO "XGIfb: Invalid VESA mode 0x%x'\n", vesamode);
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200459}
460
Randy Dunlap89229672010-08-10 08:46:44 -0700461static int XGIfb_GetXG21LVDSData(void)
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200462{
Prashant P. Shahb654f872010-09-06 17:34:26 +0530463 u8 tmp;
Aaro Koskinen863c02a2011-09-13 22:49:31 +0300464 void __iomem *data = xgi_video_info.mmio_vbase + 0x20000;
Prashant P. Shahb654f872010-09-06 17:34:26 +0530465 int i, j, k;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200466
Aaro Koskinen7e119b72011-04-18 22:13:58 +0300467 tmp = xgifb_reg_get(XGISR, 0x1e);
Aaro Koskinenb6e2dc32011-04-18 22:13:59 +0300468 xgifb_reg_set(XGISR, 0x1e, tmp | 4);
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200469
Aaro Koskinen863c02a2011-09-13 22:49:31 +0300470 if ((readb(data) == 0x55) &&
471 (readb(data + 1) == 0xAA) &&
472 (readb(data + 0x65) & 0x1)) {
473 i = readw(data + 0x316);
474 j = readb(data + i - 1);
Prashant P. Shahb654f872010-09-06 17:34:26 +0530475 if (j == 0xff)
476 j = 1;
477
478 k = 0;
479 do {
Aaro Koskinen863c02a2011-09-13 22:49:31 +0300480 XGI21_LCDCapList[k].LVDS_Capability = readw(data + i);
481 XGI21_LCDCapList[k].LVDSHT = readw(data + i + 2);
482 XGI21_LCDCapList[k].LVDSVT = readw(data + i + 4);
483 XGI21_LCDCapList[k].LVDSHDE = readw(data + i + 6);
484 XGI21_LCDCapList[k].LVDSVDE = readw(data + i + 8);
485 XGI21_LCDCapList[k].LVDSHFP = readw(data + i + 10);
486 XGI21_LCDCapList[k].LVDSVFP = readw(data + i + 12);
487 XGI21_LCDCapList[k].LVDSHSYNC = readw(data + i + 14);
488 XGI21_LCDCapList[k].LVDSVSYNC = readw(data + i + 16);
489 XGI21_LCDCapList[k].VCLKData1 = readb(data + i + 18);
490 XGI21_LCDCapList[k].VCLKData2 = readb(data + i + 19);
491 XGI21_LCDCapList[k].PSC_S1 = readb(data + i + 20);
492 XGI21_LCDCapList[k].PSC_S2 = readb(data + i + 21);
493 XGI21_LCDCapList[k].PSC_S3 = readb(data + i + 22);
494 XGI21_LCDCapList[k].PSC_S4 = readb(data + i + 23);
495 XGI21_LCDCapList[k].PSC_S5 = readb(data + i + 24);
Prashant P. Shahb654f872010-09-06 17:34:26 +0530496 i += 25;
497 j--;
498 k++;
499 } while ((j > 0) && (k < (sizeof(XGI21_LCDCapList)
500 / sizeof(struct XGI21_LVDSCapStruct))));
501 return 1;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200502 }
Prashant P. Shahb654f872010-09-06 17:34:26 +0530503 return 0;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200504}
505
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200506static int XGIfb_validate_mode(int myindex)
507{
Prashant P. Shahb654f872010-09-06 17:34:26 +0530508 u16 xres, yres;
Aaro Koskinenc62f2e42011-10-11 21:47:15 +0300509 struct xgi_hw_device_info *hw_info = &xgi_video_info.hw_info;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200510
Prashant P. Shahb654f872010-09-06 17:34:26 +0530511 if (xgi_video_info.chip == XG21) {
512 if ((xgi_video_info.disp_state & DISPTYPE_DISP2)
513 == DISPTYPE_LCD) {
514 xres = XGI21_LCDCapList[0].LVDSHDE;
515 yres = XGI21_LCDCapList[0].LVDSVDE;
516 if (XGIbios_mode[myindex].xres > xres)
517 return -1;
518 if (XGIbios_mode[myindex].yres > yres)
519 return -1;
Kenji Toyamaa12c27c2011-04-26 12:13:43 +0800520 if ((XGIbios_mode[myindex].xres < xres) &&
521 (XGIbios_mode[myindex].yres < yres)) {
Prashant P. Shahb654f872010-09-06 17:34:26 +0530522 if (XGIbios_mode[myindex].bpp > 8)
523 return -1;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200524 }
Prashant P. Shahb654f872010-09-06 17:34:26 +0530525
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200526 }
Prashant P. Shahb654f872010-09-06 17:34:26 +0530527 return myindex;
528
529 }
530
531 /* FIXME: for now, all is valid on XG27 */
532 if (xgi_video_info.chip == XG27)
533 return myindex;
534
535 if (!(XGIbios_mode[myindex].chipset & MD_XGI315))
536 return -1;
537
538 switch (xgi_video_info.disp_state & DISPTYPE_DISP2) {
539 case DISPTYPE_LCD:
Aaro Koskinenc62f2e42011-10-11 21:47:15 +0300540 switch (hw_info->ulCRT2LCDType) {
Prashant P. Shahb654f872010-09-06 17:34:26 +0530541 case LCD_640x480:
542 xres = 640;
543 yres = 480;
544 break;
545 case LCD_800x600:
546 xres = 800;
547 yres = 600;
548 break;
549 case LCD_1024x600:
550 xres = 1024;
551 yres = 600;
552 break;
553 case LCD_1024x768:
554 xres = 1024;
555 yres = 768;
556 break;
557 case LCD_1152x768:
558 xres = 1152;
559 yres = 768;
560 break;
561 case LCD_1280x960:
562 xres = 1280;
563 yres = 960;
564 break;
565 case LCD_1280x768:
566 xres = 1280;
567 yres = 768;
568 break;
569 case LCD_1280x1024:
570 xres = 1280;
571 yres = 1024;
572 break;
573 case LCD_1400x1050:
574 xres = 1400;
575 yres = 1050;
576 break;
577 case LCD_1600x1200:
578 xres = 1600;
579 yres = 1200;
580 break;
581 /* case LCD_320x480: */ /* TW: FSTN */
582 /*
583 xres = 320;
584 yres = 480;
585 break;
586 */
587 default:
588 xres = 0;
589 yres = 0;
590 break;
591 }
592 if (XGIbios_mode[myindex].xres > xres)
593 return -1;
594 if (XGIbios_mode[myindex].yres > yres)
595 return -1;
Aaro Koskinenc62f2e42011-10-11 21:47:15 +0300596 if ((hw_info->ulExternalChip == 0x01) || /* LVDS */
597 (hw_info->ulExternalChip == 0x05)) { /* LVDS+Chrontel */
Prashant P. Shahb654f872010-09-06 17:34:26 +0530598 switch (XGIbios_mode[myindex].xres) {
599 case 512:
600 if (XGIbios_mode[myindex].yres != 512)
601 return -1;
Aaro Koskinenc62f2e42011-10-11 21:47:15 +0300602 if (hw_info->ulCRT2LCDType == LCD_1024x600)
Prashant P. Shahb654f872010-09-06 17:34:26 +0530603 return -1;
604 break;
605 case 640:
606 if ((XGIbios_mode[myindex].yres != 400)
607 && (XGIbios_mode[myindex].yres
608 != 480))
609 return -1;
610 break;
611 case 800:
612 if (XGIbios_mode[myindex].yres != 600)
613 return -1;
614 break;
615 case 1024:
Kenji Toyamaa12c27c2011-04-26 12:13:43 +0800616 if ((XGIbios_mode[myindex].yres != 600) &&
617 (XGIbios_mode[myindex].yres != 768))
Prashant P. Shahb654f872010-09-06 17:34:26 +0530618 return -1;
Kenji Toyamaa12c27c2011-04-26 12:13:43 +0800619 if ((XGIbios_mode[myindex].yres == 600) &&
Aaro Koskinenc62f2e42011-10-11 21:47:15 +0300620 (hw_info->ulCRT2LCDType != LCD_1024x600))
Prashant P. Shahb654f872010-09-06 17:34:26 +0530621 return -1;
622 break;
623 case 1152:
624 if ((XGIbios_mode[myindex].yres) != 768)
625 return -1;
Aaro Koskinenc62f2e42011-10-11 21:47:15 +0300626 if (hw_info->ulCRT2LCDType != LCD_1152x768)
Prashant P. Shahb654f872010-09-06 17:34:26 +0530627 return -1;
628 break;
629 case 1280:
Kenji Toyamaa12c27c2011-04-26 12:13:43 +0800630 if ((XGIbios_mode[myindex].yres != 768) &&
631 (XGIbios_mode[myindex].yres != 1024))
Prashant P. Shahb654f872010-09-06 17:34:26 +0530632 return -1;
Kenji Toyamaa12c27c2011-04-26 12:13:43 +0800633 if ((XGIbios_mode[myindex].yres == 768) &&
Aaro Koskinenc62f2e42011-10-11 21:47:15 +0300634 (hw_info->ulCRT2LCDType != LCD_1280x768))
Prashant P. Shahb654f872010-09-06 17:34:26 +0530635 return -1;
636 break;
637 case 1400:
638 if (XGIbios_mode[myindex].yres != 1050)
639 return -1;
640 break;
641 case 1600:
642 if (XGIbios_mode[myindex].yres != 1200)
643 return -1;
644 break;
645 default:
646 return -1;
647 }
648 } else {
649 switch (XGIbios_mode[myindex].xres) {
650 case 512:
651 if (XGIbios_mode[myindex].yres != 512)
652 return -1;
653 break;
654 case 640:
Kenji Toyamaa12c27c2011-04-26 12:13:43 +0800655 if ((XGIbios_mode[myindex].yres != 400) &&
656 (XGIbios_mode[myindex].yres != 480))
Prashant P. Shahb654f872010-09-06 17:34:26 +0530657 return -1;
658 break;
659 case 800:
660 if (XGIbios_mode[myindex].yres != 600)
661 return -1;
662 break;
663 case 1024:
664 if (XGIbios_mode[myindex].yres != 768)
665 return -1;
666 break;
667 case 1280:
Kenji Toyamaa12c27c2011-04-26 12:13:43 +0800668 if ((XGIbios_mode[myindex].yres != 960) &&
669 (XGIbios_mode[myindex].yres != 1024))
Prashant P. Shahb654f872010-09-06 17:34:26 +0530670 return -1;
671 if (XGIbios_mode[myindex].yres == 960) {
Aaro Koskinenc62f2e42011-10-11 21:47:15 +0300672 if (hw_info->ulCRT2LCDType ==
Kenji Toyamaa12c27c2011-04-26 12:13:43 +0800673 LCD_1400x1050)
Prashant P. Shahb654f872010-09-06 17:34:26 +0530674 return -1;
675 }
676 break;
677 case 1400:
678 if (XGIbios_mode[myindex].yres != 1050)
679 return -1;
680 break;
681 case 1600:
682 if (XGIbios_mode[myindex].yres != 1200)
683 return -1;
684 break;
685 default:
686 return -1;
687 }
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200688 }
689 break;
Prashant P. Shahb654f872010-09-06 17:34:26 +0530690 case DISPTYPE_TV:
691 switch (XGIbios_mode[myindex].xres) {
692 case 512:
693 case 640:
694 case 800:
695 break;
696 case 720:
697 if (xgi_video_info.TV_type == TVMODE_NTSC) {
698 if (XGIbios_mode[myindex].yres != 480)
699 return -1;
700 } else if (xgi_video_info.TV_type == TVMODE_PAL) {
701 if (XGIbios_mode[myindex].yres != 576)
702 return -1;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200703 }
Prashant P. Shahb654f872010-09-06 17:34:26 +0530704 /* TW: LVDS/CHRONTEL does not support 720 */
Kenji Toyamaa12c27c2011-04-26 12:13:43 +0800705 if (xgi_video_info.hasVB == HASVB_LVDS_CHRONTEL ||
706 xgi_video_info.hasVB == HASVB_CHRONTEL) {
Prashant P. Shahb654f872010-09-06 17:34:26 +0530707 return -1;
708 }
709 break;
710 case 1024:
711 if (xgi_video_info.TV_type == TVMODE_NTSC) {
712 if (XGIbios_mode[myindex].bpp == 32)
713 return -1;
714 }
Prashant P. Shahb654f872010-09-06 17:34:26 +0530715 break;
716 default:
717 return -1;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200718 }
719 break;
Prashant P. Shahb654f872010-09-06 17:34:26 +0530720 case DISPTYPE_CRT2:
721 if (XGIbios_mode[myindex].xres > 1280)
722 return -1;
723 break;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200724 }
Prashant P. Shahb654f872010-09-06 17:34:26 +0530725 return myindex;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200726
727}
728
729static void XGIfb_search_crt2type(const char *name)
730{
731 int i = 0;
732
Prashant P. Shahb654f872010-09-06 17:34:26 +0530733 if (name == NULL)
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200734 return;
735
Prashant P. Shahb654f872010-09-06 17:34:26 +0530736 while (XGI_crt2type[i].type_no != -1) {
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200737 if (!strcmp(name, XGI_crt2type[i].name)) {
738 XGIfb_crt2type = XGI_crt2type[i].type_no;
739 XGIfb_tvplug = XGI_crt2type[i].tvplug_no;
740 break;
741 }
742 i++;
743 }
Prashant P. Shahb654f872010-09-06 17:34:26 +0530744 if (XGIfb_crt2type < 0)
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200745 printk(KERN_INFO "XGIfb: Invalid CRT2 type: %s\n", name);
746}
747
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200748static u8 XGIfb_search_refresh_rate(unsigned int rate)
749{
750 u16 xres, yres;
751 int i = 0;
752
753 xres = XGIbios_mode[xgifb_mode_idx].xres;
754 yres = XGIbios_mode[xgifb_mode_idx].yres;
755
756 XGIfb_rate_idx = 0;
757 while ((XGIfb_vrate[i].idx != 0) && (XGIfb_vrate[i].xres <= xres)) {
Kenji Toyamaa12c27c2011-04-26 12:13:43 +0800758 if ((XGIfb_vrate[i].xres == xres) &&
759 (XGIfb_vrate[i].yres == yres)) {
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200760 if (XGIfb_vrate[i].refresh == rate) {
761 XGIfb_rate_idx = XGIfb_vrate[i].idx;
762 break;
763 } else if (XGIfb_vrate[i].refresh > rate) {
764 if ((XGIfb_vrate[i].refresh - rate) <= 3) {
765 DPRINTK("XGIfb: Adjusting rate from %d up to %d\n",
Kenji Toyamaa12c27c2011-04-26 12:13:43 +0800766 rate, XGIfb_vrate[i].refresh);
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200767 XGIfb_rate_idx = XGIfb_vrate[i].idx;
Kenji Toyamaa12c27c2011-04-26 12:13:43 +0800768 xgi_video_info.refresh_rate =
769 XGIfb_vrate[i].refresh;
Prashant P. Shahb654f872010-09-06 17:34:26 +0530770 } else if (((rate - XGIfb_vrate[i - 1].refresh)
771 <= 2) && (XGIfb_vrate[i].idx
772 != 1)) {
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200773 DPRINTK("XGIfb: Adjusting rate from %d down to %d\n",
Kenji Toyamaa12c27c2011-04-26 12:13:43 +0800774 rate, XGIfb_vrate[i-1].refresh);
Prashant P. Shahb654f872010-09-06 17:34:26 +0530775 XGIfb_rate_idx = XGIfb_vrate[i - 1].idx;
Kenji Toyamaa12c27c2011-04-26 12:13:43 +0800776 xgi_video_info.refresh_rate =
777 XGIfb_vrate[i - 1].refresh;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200778 }
779 break;
Prashant P. Shahb654f872010-09-06 17:34:26 +0530780 } else if ((rate - XGIfb_vrate[i].refresh) <= 2) {
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200781 DPRINTK("XGIfb: Adjusting rate from %d down to %d\n",
Kenji Toyamaa12c27c2011-04-26 12:13:43 +0800782 rate, XGIfb_vrate[i].refresh);
Prashant P. Shahb654f872010-09-06 17:34:26 +0530783 XGIfb_rate_idx = XGIfb_vrate[i].idx;
784 break;
785 }
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200786 }
787 i++;
788 }
789 if (XGIfb_rate_idx > 0) {
790 return XGIfb_rate_idx;
791 } else {
Kenji Toyamaa12c27c2011-04-26 12:13:43 +0800792 printk(KERN_INFO "XGIfb: Unsupported rate %d for %dx%d\n",
793 rate, xres, yres);
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200794 return 0;
795 }
796}
797
798static void XGIfb_search_tvstd(const char *name)
799{
800 int i = 0;
801
Prashant P. Shahb654f872010-09-06 17:34:26 +0530802 if (name == NULL)
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200803 return;
804
805 while (XGI_tvtype[i].type_no != -1) {
806 if (!strcmp(name, XGI_tvtype[i].name)) {
807 XGIfb_tvmode = XGI_tvtype[i].type_no;
808 break;
809 }
810 i++;
811 }
812}
813
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200814/* ----------- FBDev related routines for all series ----------- */
815
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200816static void XGIfb_bpp_to_var(struct fb_var_screeninfo *var)
817{
Prashant P. Shahb654f872010-09-06 17:34:26 +0530818 switch (var->bits_per_pixel) {
819 case 8:
820 var->red.offset = var->green.offset = var->blue.offset = 0;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200821 var->red.length = var->green.length = var->blue.length = 6;
822 xgi_video_info.video_cmap_len = 256;
823 break;
Prashant P. Shahb654f872010-09-06 17:34:26 +0530824 case 16:
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200825 var->red.offset = 11;
826 var->red.length = 5;
827 var->green.offset = 5;
828 var->green.length = 6;
829 var->blue.offset = 0;
830 var->blue.length = 5;
831 var->transp.offset = 0;
832 var->transp.length = 0;
833 xgi_video_info.video_cmap_len = 16;
834 break;
Prashant P. Shahb654f872010-09-06 17:34:26 +0530835 case 32:
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200836 var->red.offset = 16;
837 var->red.length = 8;
838 var->green.offset = 8;
839 var->green.length = 8;
840 var->blue.offset = 0;
841 var->blue.length = 8;
842 var->transp.offset = 24;
843 var->transp.length = 8;
844 xgi_video_info.video_cmap_len = 16;
845 break;
846 }
847}
848
Aaro Koskinenc4fa7df2011-04-18 22:14:05 +0300849/* --------------------- SetMode routines ------------------------- */
850
851static void XGIfb_pre_setmode(void)
852{
853 u8 cr30 = 0, cr31 = 0;
854
855 cr31 = xgifb_reg_get(XGICR, 0x31);
856 cr31 &= ~0x60;
857
858 switch (xgi_video_info.disp_state & DISPTYPE_DISP2) {
859 case DISPTYPE_CRT2:
860 cr30 = (XGI_VB_OUTPUT_CRT2 | XGI_SIMULTANEOUS_VIEW_ENABLE);
861 cr31 |= XGI_DRIVER_MODE;
862 break;
863 case DISPTYPE_LCD:
864 cr30 = (XGI_VB_OUTPUT_LCD | XGI_SIMULTANEOUS_VIEW_ENABLE);
865 cr31 |= XGI_DRIVER_MODE;
866 break;
867 case DISPTYPE_TV:
868 if (xgi_video_info.TV_type == TVMODE_HIVISION)
869 cr30 = (XGI_VB_OUTPUT_HIVISION
870 | XGI_SIMULTANEOUS_VIEW_ENABLE);
871 else if (xgi_video_info.TV_plug == TVPLUG_SVIDEO)
872 cr30 = (XGI_VB_OUTPUT_SVIDEO
873 | XGI_SIMULTANEOUS_VIEW_ENABLE);
874 else if (xgi_video_info.TV_plug == TVPLUG_COMPOSITE)
875 cr30 = (XGI_VB_OUTPUT_COMPOSITE
876 | XGI_SIMULTANEOUS_VIEW_ENABLE);
877 else if (xgi_video_info.TV_plug == TVPLUG_SCART)
878 cr30 = (XGI_VB_OUTPUT_SCART
879 | XGI_SIMULTANEOUS_VIEW_ENABLE);
880 cr31 |= XGI_DRIVER_MODE;
881
882 if (XGIfb_tvmode == 1 || xgi_video_info.TV_type == TVMODE_PAL)
883 cr31 |= 0x01;
884 else
885 cr31 &= ~0x01;
886 break;
887 default: /* disable CRT2 */
888 cr30 = 0x00;
889 cr31 |= (XGI_DRIVER_MODE | XGI_VB_OUTPUT_DISABLE);
890 }
891
892 xgifb_reg_set(XGICR, IND_XGI_SCRATCH_REG_CR30, cr30);
893 xgifb_reg_set(XGICR, IND_XGI_SCRATCH_REG_CR31, cr31);
894 xgifb_reg_set(XGICR, IND_XGI_SCRATCH_REG_CR33, (XGIfb_rate_idx & 0x0F));
895}
896
897static void XGIfb_post_setmode(void)
898{
899 u8 reg;
900 unsigned char doit = 1;
901 /*
902 xgifb_reg_set(XGISR,IND_XGI_PASSWORD,XGI_PASSWORD);
903 xgifb_reg_set(XGICR, 0x13, 0x00);
904 xgifb_reg_and_or(XGISR,0x0E, 0xF0, 0x01);
905 *test*
906 */
907 if (xgi_video_info.video_bpp == 8) {
Kenji Toyamaa12c27c2011-04-26 12:13:43 +0800908 /* TW: We can't switch off CRT1 on LVDS/Chrontel
909 * in 8bpp Modes */
910 if ((xgi_video_info.hasVB == HASVB_LVDS) ||
911 (xgi_video_info.hasVB == HASVB_LVDS_CHRONTEL)) {
Aaro Koskinenc4fa7df2011-04-18 22:14:05 +0300912 doit = 0;
913 }
Kenji Toyamaa12c27c2011-04-26 12:13:43 +0800914 /* TW: We can't switch off CRT1 on 301B-DH
915 * in 8bpp Modes if using LCD */
Aaro Koskinenc4fa7df2011-04-18 22:14:05 +0300916 if (xgi_video_info.disp_state & DISPTYPE_LCD)
917 doit = 0;
918 }
919
920 /* TW: We can't switch off CRT1 if bridge is in slave mode */
921 if (xgi_video_info.hasVB != HASVB_NONE) {
922 reg = xgifb_reg_get(XGIPART1, 0x00);
923
924 if ((reg & 0x50) == 0x10)
925 doit = 0;
926
927 } else {
928 XGIfb_crt1off = 0;
929 }
930
931 reg = xgifb_reg_get(XGICR, 0x17);
932 if ((XGIfb_crt1off) && (doit))
933 reg &= ~0x80;
934 else
935 reg |= 0x80;
936 xgifb_reg_set(XGICR, 0x17, reg);
937
938 xgifb_reg_and(XGISR, IND_XGI_RAMDAC_CONTROL, ~0x04);
939
940 if ((xgi_video_info.disp_state & DISPTYPE_TV) && (xgi_video_info.hasVB
941 == HASVB_301)) {
942
943 reg = xgifb_reg_get(XGIPART4, 0x01);
944
945 if (reg < 0xB0) { /* Set filter for XGI301 */
Aaro Koskinenc4fa7df2011-04-18 22:14:05 +0300946 switch (xgi_video_info.video_width) {
947 case 320:
Kenji Toyamaa12c27c2011-04-26 12:13:43 +0800948 filter_tb = (xgi_video_info.TV_type ==
949 TVMODE_NTSC) ? 4 : 12;
Aaro Koskinenc4fa7df2011-04-18 22:14:05 +0300950 break;
951 case 640:
Kenji Toyamaa12c27c2011-04-26 12:13:43 +0800952 filter_tb = (xgi_video_info.TV_type ==
953 TVMODE_NTSC) ? 5 : 13;
Aaro Koskinenc4fa7df2011-04-18 22:14:05 +0300954 break;
955 case 720:
Kenji Toyamaa12c27c2011-04-26 12:13:43 +0800956 filter_tb = (xgi_video_info.TV_type ==
957 TVMODE_NTSC) ? 6 : 14;
Aaro Koskinenc4fa7df2011-04-18 22:14:05 +0300958 break;
959 case 800:
Kenji Toyamaa12c27c2011-04-26 12:13:43 +0800960 filter_tb = (xgi_video_info.TV_type ==
961 TVMODE_NTSC) ? 7 : 15;
Aaro Koskinenc4fa7df2011-04-18 22:14:05 +0300962 break;
963 default:
964 filter = -1;
965 break;
966 }
Aaro Koskinenc4fa7df2011-04-18 22:14:05 +0300967 xgifb_reg_or(XGIPART1, XGIfb_CRT2_write_enable, 0x01);
968
969 if (xgi_video_info.TV_type == TVMODE_NTSC) {
970
971 xgifb_reg_and(XGIPART2, 0x3a, 0x1f);
972
973 if (xgi_video_info.TV_plug == TVPLUG_SVIDEO) {
974
975 xgifb_reg_and(XGIPART2, 0x30, 0xdf);
976
977 } else if (xgi_video_info.TV_plug
978 == TVPLUG_COMPOSITE) {
979
980 xgifb_reg_or(XGIPART2, 0x30, 0x20);
981
982 switch (xgi_video_info.video_width) {
983 case 640:
Kenji Toyamaa12c27c2011-04-26 12:13:43 +0800984 xgifb_reg_set(XGIPART2,
985 0x35,
986 0xEB);
987 xgifb_reg_set(XGIPART2,
988 0x36,
989 0x04);
990 xgifb_reg_set(XGIPART2,
991 0x37,
992 0x25);
993 xgifb_reg_set(XGIPART2,
994 0x38,
995 0x18);
Aaro Koskinenc4fa7df2011-04-18 22:14:05 +0300996 break;
997 case 720:
Kenji Toyamaa12c27c2011-04-26 12:13:43 +0800998 xgifb_reg_set(XGIPART2,
999 0x35,
1000 0xEE);
1001 xgifb_reg_set(XGIPART2,
1002 0x36,
1003 0x0C);
1004 xgifb_reg_set(XGIPART2,
1005 0x37,
1006 0x22);
1007 xgifb_reg_set(XGIPART2,
1008 0x38,
1009 0x08);
Aaro Koskinenc4fa7df2011-04-18 22:14:05 +03001010 break;
1011 case 800:
Kenji Toyamaa12c27c2011-04-26 12:13:43 +08001012 xgifb_reg_set(XGIPART2,
1013 0x35,
1014 0xEB);
1015 xgifb_reg_set(XGIPART2,
1016 0x36,
1017 0x15);
1018 xgifb_reg_set(XGIPART2,
1019 0x37,
1020 0x25);
1021 xgifb_reg_set(XGIPART2,
1022 0x38,
1023 0xF6);
Aaro Koskinenc4fa7df2011-04-18 22:14:05 +03001024 break;
1025 }
1026 }
1027
1028 } else if (xgi_video_info.TV_type == TVMODE_PAL) {
1029
1030 xgifb_reg_and(XGIPART2, 0x3A, 0x1F);
1031
1032 if (xgi_video_info.TV_plug == TVPLUG_SVIDEO) {
1033
1034 xgifb_reg_and(XGIPART2, 0x30, 0xDF);
1035
1036 } else if (xgi_video_info.TV_plug
1037 == TVPLUG_COMPOSITE) {
1038
1039 xgifb_reg_or(XGIPART2, 0x30, 0x20);
1040
1041 switch (xgi_video_info.video_width) {
1042 case 640:
Kenji Toyamaa12c27c2011-04-26 12:13:43 +08001043 xgifb_reg_set(XGIPART2,
1044 0x35,
1045 0xF1);
1046 xgifb_reg_set(XGIPART2,
1047 0x36,
1048 0xF7);
1049 xgifb_reg_set(XGIPART2,
1050 0x37,
1051 0x1F);
1052 xgifb_reg_set(XGIPART2,
1053 0x38,
1054 0x32);
Aaro Koskinenc4fa7df2011-04-18 22:14:05 +03001055 break;
1056 case 720:
Kenji Toyamaa12c27c2011-04-26 12:13:43 +08001057 xgifb_reg_set(XGIPART2,
1058 0x35,
1059 0xF3);
1060 xgifb_reg_set(XGIPART2,
1061 0x36,
1062 0x00);
1063 xgifb_reg_set(XGIPART2,
1064 0x37,
1065 0x1D);
1066 xgifb_reg_set(XGIPART2,
1067 0x38,
1068 0x20);
Aaro Koskinenc4fa7df2011-04-18 22:14:05 +03001069 break;
1070 case 800:
Kenji Toyamaa12c27c2011-04-26 12:13:43 +08001071 xgifb_reg_set(XGIPART2,
1072 0x35,
1073 0xFC);
1074 xgifb_reg_set(XGIPART2,
1075 0x36,
1076 0xFB);
1077 xgifb_reg_set(XGIPART2,
1078 0x37,
1079 0x14);
1080 xgifb_reg_set(XGIPART2,
1081 0x38,
1082 0x2A);
Aaro Koskinenc4fa7df2011-04-18 22:14:05 +03001083 break;
1084 }
1085 }
1086 }
1087
1088 if ((filter >= 0) && (filter <= 7)) {
Kenji Toyamaa12c27c2011-04-26 12:13:43 +08001089 DPRINTK("FilterTable[%d]-%d: %02x %02x %02x %02x\n",
1090 filter_tb, filter,
1091 XGI_TV_filter[filter_tb].
1092 filter[filter][0],
1093 XGI_TV_filter[filter_tb].
1094 filter[filter][1],
1095 XGI_TV_filter[filter_tb].
1096 filter[filter][2],
1097 XGI_TV_filter[filter_tb].
1098 filter[filter][3]
Aaro Koskinenc4fa7df2011-04-18 22:14:05 +03001099 );
1100 xgifb_reg_set(
Kenji Toyamaa12c27c2011-04-26 12:13:43 +08001101 XGIPART2,
1102 0x35,
1103 (XGI_TV_filter[filter_tb].
1104 filter[filter][0]));
Aaro Koskinenc4fa7df2011-04-18 22:14:05 +03001105 xgifb_reg_set(
Kenji Toyamaa12c27c2011-04-26 12:13:43 +08001106 XGIPART2,
1107 0x36,
1108 (XGI_TV_filter[filter_tb].
1109 filter[filter][1]));
Aaro Koskinenc4fa7df2011-04-18 22:14:05 +03001110 xgifb_reg_set(
Kenji Toyamaa12c27c2011-04-26 12:13:43 +08001111 XGIPART2,
1112 0x37,
1113 (XGI_TV_filter[filter_tb].
1114 filter[filter][2]));
Aaro Koskinenc4fa7df2011-04-18 22:14:05 +03001115 xgifb_reg_set(
Kenji Toyamaa12c27c2011-04-26 12:13:43 +08001116 XGIPART2,
1117 0x38,
1118 (XGI_TV_filter[filter_tb].
1119 filter[filter][3]));
Aaro Koskinenc4fa7df2011-04-18 22:14:05 +03001120 }
Aaro Koskinenc4fa7df2011-04-18 22:14:05 +03001121 }
Aaro Koskinenc4fa7df2011-04-18 22:14:05 +03001122 }
Aaro Koskinenc4fa7df2011-04-18 22:14:05 +03001123}
1124
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001125static int XGIfb_do_set_var(struct fb_var_screeninfo *var, int isactive,
Prashant P. Shahb654f872010-09-06 17:34:26 +05301126 struct fb_info *info)
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001127{
Aaro Koskinenc62f2e42011-10-11 21:47:15 +03001128 struct xgi_hw_device_info *hw_info = &xgi_video_info.hw_info;
Prashant P. Shahb654f872010-09-06 17:34:26 +05301129 unsigned int htotal = var->left_margin + var->xres + var->right_margin
1130 + var->hsync_len;
1131 unsigned int vtotal = var->upper_margin + var->yres + var->lower_margin
1132 + var->vsync_len;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001133#if defined(__powerpc__)
1134 u8 sr_data, cr_data;
1135#endif
1136 unsigned int drate = 0, hrate = 0;
1137 int found_mode = 0;
1138 int old_mode;
Prashant P. Shahb654f872010-09-06 17:34:26 +05301139 /* unsigned char reg, reg1; */
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001140
1141 DEBUGPRN("Inside do_set_var");
Prashant P. Shahb654f872010-09-06 17:34:26 +05301142 /* 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 +02001143
Prashant P. Shahb654f872010-09-06 17:34:26 +05301144 info->var.xres_virtual = var->xres_virtual;
1145 info->var.yres_virtual = var->yres_virtual;
1146 info->var.bits_per_pixel = var->bits_per_pixel;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001147
1148 if ((var->vmode & FB_VMODE_MASK) == FB_VMODE_NONINTERLACED)
1149 vtotal <<= 1;
1150 else if ((var->vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE)
1151 vtotal <<= 2;
Prashant P. Shahb654f872010-09-06 17:34:26 +05301152 else if ((var->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) {
1153 /* vtotal <<= 1; */
1154 /* var->yres <<= 1; */
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001155 }
1156
Prashant P. Shahb654f872010-09-06 17:34:26 +05301157 if (!htotal || !vtotal) {
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001158 DPRINTK("XGIfb: Invalid 'var' information\n");
1159 return -EINVAL;
Prashant P. Shahb654f872010-09-06 17:34:26 +05301160 } printk(KERN_DEBUG "XGIfb: var->pixclock=%d, htotal=%d, vtotal=%d\n",
1161 var->pixclock, htotal, vtotal);
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001162
Prashant P. Shahb654f872010-09-06 17:34:26 +05301163 if (var->pixclock && htotal && vtotal) {
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001164 drate = 1000000000 / var->pixclock;
1165 hrate = (drate * 1000) / htotal;
Prashant P. Shahb654f872010-09-06 17:34:26 +05301166 xgi_video_info.refresh_rate = (unsigned int) (hrate * 2
1167 / vtotal);
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001168 } else {
1169 xgi_video_info.refresh_rate = 60;
1170 }
1171
1172 printk(KERN_DEBUG "XGIfb: Change mode to %dx%dx%d-%dHz\n",
Kenji Toyamaa12c27c2011-04-26 12:13:43 +08001173 var->xres,
1174 var->yres,
1175 var->bits_per_pixel,
1176 xgi_video_info.refresh_rate);
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001177
1178 old_mode = xgifb_mode_idx;
1179 xgifb_mode_idx = 0;
1180
Prashant P. Shahb654f872010-09-06 17:34:26 +05301181 while ((XGIbios_mode[xgifb_mode_idx].mode_no != 0)
1182 && (XGIbios_mode[xgifb_mode_idx].xres <= var->xres)) {
1183 if ((XGIbios_mode[xgifb_mode_idx].xres == var->xres)
1184 && (XGIbios_mode[xgifb_mode_idx].yres
1185 == var->yres)
1186 && (XGIbios_mode[xgifb_mode_idx].bpp
1187 == var->bits_per_pixel)) {
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001188 XGIfb_mode_no = XGIbios_mode[xgifb_mode_idx].mode_no;
1189 found_mode = 1;
1190 break;
1191 }
1192 xgifb_mode_idx++;
1193 }
1194
Prashant P. Shahb654f872010-09-06 17:34:26 +05301195 if (found_mode)
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001196 xgifb_mode_idx = XGIfb_validate_mode(xgifb_mode_idx);
1197 else
1198 xgifb_mode_idx = -1;
1199
Prashant P. Shahb654f872010-09-06 17:34:26 +05301200 if (xgifb_mode_idx < 0) {
Kenji Toyamaa12c27c2011-04-26 12:13:43 +08001201 printk(KERN_ERR "XGIfb: Mode %dx%dx%d not supported\n",
1202 var->xres, var->yres, var->bits_per_pixel);
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001203 xgifb_mode_idx = old_mode;
1204 return -EINVAL;
1205 }
1206
Prashant P. Shahb654f872010-09-06 17:34:26 +05301207 if (XGIfb_search_refresh_rate(xgi_video_info.refresh_rate) == 0) {
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001208 XGIfb_rate_idx = XGIbios_mode[xgifb_mode_idx].rate_idx;
1209 xgi_video_info.refresh_rate = 60;
1210 }
1211
Prashant P. Shahb654f872010-09-06 17:34:26 +05301212 if (isactive) {
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001213
1214 XGIfb_pre_setmode();
Aaro Koskinenc62f2e42011-10-11 21:47:15 +03001215 if (XGISetModeNew(hw_info, XGIfb_mode_no) == 0) {
Kenji Toyamaa12c27c2011-04-26 12:13:43 +08001216 printk(KERN_ERR "XGIfb: Setting mode[0x%x] failed\n",
1217 XGIfb_mode_no);
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001218 return -EINVAL;
1219 }
Prashant P. Shahb654f872010-09-06 17:34:26 +05301220 info->fix.line_length = ((info->var.xres_virtual
1221 * info->var.bits_per_pixel) >> 6);
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001222
Aaro Koskinenb6e2dc32011-04-18 22:13:59 +03001223 xgifb_reg_set(XGISR, IND_XGI_PASSWORD, XGI_PASSWORD);
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001224
Aaro Koskinenb6e2dc32011-04-18 22:13:59 +03001225 xgifb_reg_set(XGICR, 0x13, (info->fix.line_length & 0x00ff));
Kenji Toyamaa12c27c2011-04-26 12:13:43 +08001226 xgifb_reg_set(XGISR,
1227 0x0E,
1228 (info->fix.line_length & 0xff00) >> 8);
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001229
1230 XGIfb_post_setmode();
1231
Prashant P. Shahb654f872010-09-06 17:34:26 +05301232 DPRINTK("XGIfb: Set new mode: %dx%dx%d-%d\n",
1233 XGIbios_mode[xgifb_mode_idx].xres,
1234 XGIbios_mode[xgifb_mode_idx].yres,
1235 XGIbios_mode[xgifb_mode_idx].bpp,
1236 xgi_video_info.refresh_rate);
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001237
1238 xgi_video_info.video_bpp = XGIbios_mode[xgifb_mode_idx].bpp;
1239 xgi_video_info.video_vwidth = info->var.xres_virtual;
1240 xgi_video_info.video_width = XGIbios_mode[xgifb_mode_idx].xres;
1241 xgi_video_info.video_vheight = info->var.yres_virtual;
1242 xgi_video_info.video_height = XGIbios_mode[xgifb_mode_idx].yres;
1243 xgi_video_info.org_x = xgi_video_info.org_y = 0;
Prashant P. Shahb654f872010-09-06 17:34:26 +05301244 xgi_video_info.video_linelength = info->var.xres_virtual
1245 * (xgi_video_info.video_bpp >> 3);
Prashant P. Shahb654f872010-09-06 17:34:26 +05301246 switch (xgi_video_info.video_bpp) {
1247 case 8:
1248 xgi_video_info.DstColor = 0x0000;
1249 xgi_video_info.XGI310_AccelDepth = 0x00000000;
1250 xgi_video_info.video_cmap_len = 256;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001251#if defined(__powerpc__)
Aaro Koskinen7e119b72011-04-18 22:13:58 +03001252 cr_data = xgifb_reg_get(XGICR, 0x4D);
Aaro Koskinenb6e2dc32011-04-18 22:13:59 +03001253 xgifb_reg_set(XGICR, 0x4D, (cr_data & 0xE0));
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001254#endif
Prashant P. Shahb654f872010-09-06 17:34:26 +05301255 break;
1256 case 16:
1257 xgi_video_info.DstColor = 0x8000;
1258 xgi_video_info.XGI310_AccelDepth = 0x00010000;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001259#if defined(__powerpc__)
Aaro Koskinen7e119b72011-04-18 22:13:58 +03001260 cr_data = xgifb_reg_get(XGICR, 0x4D);
Aaro Koskinenb6e2dc32011-04-18 22:13:59 +03001261 xgifb_reg_set(XGICR, 0x4D, ((cr_data & 0xE0) | 0x0B));
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001262#endif
Prashant P. Shahb654f872010-09-06 17:34:26 +05301263 xgi_video_info.video_cmap_len = 16;
1264 break;
1265 case 32:
1266 xgi_video_info.DstColor = 0xC000;
1267 xgi_video_info.XGI310_AccelDepth = 0x00020000;
1268 xgi_video_info.video_cmap_len = 16;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001269#if defined(__powerpc__)
Aaro Koskinen7e119b72011-04-18 22:13:58 +03001270 cr_data = xgifb_reg_get(XGICR, 0x4D);
Aaro Koskinenb6e2dc32011-04-18 22:13:59 +03001271 xgifb_reg_set(XGICR, 0x4D, ((cr_data & 0xE0) | 0x15));
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001272#endif
Prashant P. Shahb654f872010-09-06 17:34:26 +05301273 break;
1274 default:
1275 xgi_video_info.video_cmap_len = 16;
Kenji Toyamaa12c27c2011-04-26 12:13:43 +08001276 printk(KERN_ERR "XGIfb: Unsupported depth %d",
1277 xgi_video_info.video_bpp);
Prashant P. Shahb654f872010-09-06 17:34:26 +05301278 break;
1279 }
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001280 }
1281 XGIfb_bpp_to_var(var); /*update ARGB info*/
1282 DEBUGPRN("End of do_set_var");
1283
1284 dumpVGAReg();
1285 return 0;
1286}
1287
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001288static int XGIfb_pan_var(struct fb_var_screeninfo *var)
1289{
1290 unsigned int base;
1291
Prashant P. Shahb654f872010-09-06 17:34:26 +05301292 /* printk("Inside pan_var"); */
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001293
1294 if (var->xoffset > (var->xres_virtual - var->xres)) {
Prashant P. Shahb654f872010-09-06 17:34:26 +05301295 /* printk("Pan: xo: %d xv %d xr %d\n",
1296 var->xoffset, var->xres_virtual, var->xres); */
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001297 return -EINVAL;
1298 }
Prashant P. Shahb654f872010-09-06 17:34:26 +05301299 if (var->yoffset > (var->yres_virtual - var->yres)) {
1300 /* printk("Pan: yo: %d yv %d yr %d\n",
1301 var->yoffset, var->yres_virtual, var->yres); */
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001302 return -EINVAL;
1303 }
Prashant P. Shahb654f872010-09-06 17:34:26 +05301304 base = var->yoffset * var->xres_virtual + var->xoffset;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001305
Prashant P. Shahb654f872010-09-06 17:34:26 +05301306 /* calculate base bpp dep. */
1307 switch (var->bits_per_pixel) {
1308 case 16:
1309 base >>= 1;
1310 break;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001311 case 32:
Prashant P. Shahb654f872010-09-06 17:34:26 +05301312 break;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001313 case 8:
Prashant P. Shahb654f872010-09-06 17:34:26 +05301314 default:
1315 base >>= 2;
1316 break;
1317 }
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001318
Aaro Koskinenb6e2dc32011-04-18 22:13:59 +03001319 xgifb_reg_set(XGISR, IND_XGI_PASSWORD, XGI_PASSWORD);
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001320
Aaro Koskinenb6e2dc32011-04-18 22:13:59 +03001321 xgifb_reg_set(XGICR, 0x0D, base & 0xFF);
1322 xgifb_reg_set(XGICR, 0x0C, (base >> 8) & 0xFF);
1323 xgifb_reg_set(XGISR, 0x0D, (base >> 16) & 0xFF);
1324 xgifb_reg_set(XGISR, 0x37, (base >> 24) & 0x03);
Aaro Koskinen65283d42011-04-18 22:14:02 +03001325 xgifb_reg_and_or(XGISR, 0x37, 0xDF, (base >> 21) & 0x04);
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001326
Prashant P. Shahb654f872010-09-06 17:34:26 +05301327 if (xgi_video_info.disp_state & DISPTYPE_DISP2) {
Aaro Koskinene67f4d42011-04-18 22:14:00 +03001328 xgifb_reg_or(XGIPART1, XGIfb_CRT2_write_enable, 0x01);
Aaro Koskinenb6e2dc32011-04-18 22:13:59 +03001329 xgifb_reg_set(XGIPART1, 0x06, (base & 0xFF));
1330 xgifb_reg_set(XGIPART1, 0x05, ((base >> 8) & 0xFF));
1331 xgifb_reg_set(XGIPART1, 0x04, ((base >> 16) & 0xFF));
Kenji Toyamaa12c27c2011-04-26 12:13:43 +08001332 xgifb_reg_and_or(XGIPART1,
1333 0x02,
1334 0x7F,
1335 ((base >> 24) & 0x01) << 7);
Prashant P. Shahb654f872010-09-06 17:34:26 +05301336 }
1337 /* printk("End of pan_var"); */
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001338 return 0;
1339}
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001340
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001341static int XGIfb_open(struct fb_info *info, int user)
1342{
Prashant P. Shahb654f872010-09-06 17:34:26 +05301343 return 0;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001344}
1345
1346static int XGIfb_release(struct fb_info *info, int user)
1347{
Prashant P. Shahb654f872010-09-06 17:34:26 +05301348 return 0;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001349}
1350
1351static int XGIfb_get_cmap_len(const struct fb_var_screeninfo *var)
1352{
1353 int rc = 16;
1354
Prashant P. Shahb654f872010-09-06 17:34:26 +05301355 switch (var->bits_per_pixel) {
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001356 case 8:
1357 rc = 256;
1358 break;
1359 case 16:
1360 rc = 16;
1361 break;
1362 case 32:
1363 rc = 16;
1364 break;
1365 }
1366 return rc;
1367}
1368
Prashant P. Shahb654f872010-09-06 17:34:26 +05301369static int XGIfb_setcolreg(unsigned regno, unsigned red, unsigned green,
1370 unsigned blue, unsigned transp, struct fb_info *info)
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001371{
1372 if (regno >= XGIfb_get_cmap_len(&info->var))
1373 return 1;
1374
1375 switch (info->var.bits_per_pixel) {
1376 case 8:
Aaro Koskinene3d5ceb2011-04-18 22:13:57 +03001377 outb(regno, XGIDACA);
1378 outb((red >> 10), XGIDACD);
1379 outb((green >> 10), XGIDACD);
1380 outb((blue >> 10), XGIDACD);
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001381 if (xgi_video_info.disp_state & DISPTYPE_DISP2) {
Aaro Koskinene3d5ceb2011-04-18 22:13:57 +03001382 outb(regno, XGIDAC2A);
1383 outb((red >> 8), XGIDAC2D);
1384 outb((green >> 8), XGIDAC2D);
1385 outb((blue >> 8), XGIDAC2D);
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001386 }
1387 break;
1388 case 16:
Prashant P. Shahb654f872010-09-06 17:34:26 +05301389 ((u32 *) (info->pseudo_palette))[regno] = ((red & 0xf800))
1390 | ((green & 0xfc00) >> 5) | ((blue & 0xf800)
1391 >> 11);
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001392 break;
1393 case 32:
1394 red >>= 8;
1395 green >>= 8;
1396 blue >>= 8;
Prashant P. Shahb654f872010-09-06 17:34:26 +05301397 ((u32 *) (info->pseudo_palette))[regno] = (red << 16) | (green
1398 << 8) | (blue);
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001399 break;
1400 }
1401 return 0;
1402}
1403
Aaro Koskinenc4fa7df2011-04-18 22:14:05 +03001404/* ----------- FBDev related routines for all series ---------- */
1405
1406static int XGIfb_get_fix(struct fb_fix_screeninfo *fix, int con,
1407 struct fb_info *info)
1408{
1409 DEBUGPRN("inside get_fix");
1410 memset(fix, 0, sizeof(struct fb_fix_screeninfo));
1411
Aaro Koskinenc4fa7df2011-04-18 22:14:05 +03001412 fix->smem_start = xgi_video_info.video_base;
1413
1414 fix->smem_len = xgi_video_info.video_size;
1415
Aaro Koskinende351ba2011-08-19 22:40:27 +03001416 fix->type = FB_TYPE_PACKED_PIXELS;
Aaro Koskinenc4fa7df2011-04-18 22:14:05 +03001417 fix->type_aux = 0;
1418 if (xgi_video_info.video_bpp == 8)
1419 fix->visual = FB_VISUAL_PSEUDOCOLOR;
1420 else
1421 fix->visual = FB_VISUAL_DIRECTCOLOR;
1422 fix->xpanstep = 0;
Aaro Koskinenc4fa7df2011-04-18 22:14:05 +03001423 if (XGIfb_ypan)
1424 fix->ypanstep = 1;
Aaro Koskinenc4fa7df2011-04-18 22:14:05 +03001425 fix->ywrapstep = 0;
1426 fix->line_length = xgi_video_info.video_linelength;
1427 fix->mmio_start = xgi_video_info.mmio_base;
1428 fix->mmio_len = xgi_video_info.mmio_size;
1429 fix->accel = FB_ACCEL_XGI_XABRE;
1430
1431 DEBUGPRN("end of get_fix");
1432 return 0;
1433}
1434
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001435static int XGIfb_set_par(struct fb_info *info)
1436{
1437 int err;
1438
Prashant P. Shahb654f872010-09-06 17:34:26 +05301439 /* printk("XGIfb: inside set_par\n"); */
1440 err = XGIfb_do_set_var(&info->var, 1, info);
1441 if (err)
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001442 return err;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001443 XGIfb_get_fix(&info->fix, -1, info);
Prashant P. Shahb654f872010-09-06 17:34:26 +05301444 /* printk("XGIfb: end of set_par\n"); */
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001445 return 0;
1446}
1447
Prashant P. Shahb654f872010-09-06 17:34:26 +05301448static int XGIfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001449{
Prashant P. Shahb654f872010-09-06 17:34:26 +05301450 unsigned int htotal = var->left_margin + var->xres + var->right_margin
1451 + var->hsync_len;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001452 unsigned int vtotal = 0;
1453 unsigned int drate = 0, hrate = 0;
1454 int found_mode = 0;
1455 int refresh_rate, search_idx;
1456
1457 DEBUGPRN("Inside check_var");
1458
Prashant P. Shahb654f872010-09-06 17:34:26 +05301459 if ((var->vmode & FB_VMODE_MASK) == FB_VMODE_NONINTERLACED) {
1460 vtotal = var->upper_margin + var->yres + var->lower_margin
1461 + var->vsync_len;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001462 vtotal <<= 1;
Prashant P. Shahb654f872010-09-06 17:34:26 +05301463 } else if ((var->vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE) {
1464 vtotal = var->upper_margin + var->yres + var->lower_margin
1465 + var->vsync_len;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001466 vtotal <<= 2;
Prashant P. Shahb654f872010-09-06 17:34:26 +05301467 } else if ((var->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) {
1468 vtotal = var->upper_margin + (var->yres / 2)
1469 + var->lower_margin + var->vsync_len;
1470 } else
1471 vtotal = var->upper_margin + var->yres + var->lower_margin
1472 + var->vsync_len;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001473
Prashant P. Shahb654f872010-09-06 17:34:26 +05301474 if (!(htotal) || !(vtotal))
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001475 XGIFAIL("XGIfb: no valid timing data");
Prashant P. Shahb654f872010-09-06 17:34:26 +05301476
1477 if (var->pixclock && htotal && vtotal) {
1478 drate = 1000000000 / var->pixclock;
1479 hrate = (drate * 1000) / htotal;
Kenji Toyamaa12c27c2011-04-26 12:13:43 +08001480 xgi_video_info.refresh_rate =
1481 (unsigned int) (hrate * 2 / vtotal);
Prashant P. Shahb654f872010-09-06 17:34:26 +05301482 printk(KERN_DEBUG
1483 "%s: pixclock = %d ,htotal=%d, vtotal=%d\n"
1484 "%s: drate=%d, hrate=%d, refresh_rate=%d\n",
1485 __func__, var->pixclock, htotal, vtotal,
1486 __func__, drate, hrate, xgi_video_info.refresh_rate);
1487 } else {
1488 xgi_video_info.refresh_rate = 60;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001489 }
1490
Prashant P. Shahb654f872010-09-06 17:34:26 +05301491 /*
1492 if ((var->pixclock) && (htotal)) {
1493 drate = 1E12 / var->pixclock;
1494 hrate = drate / htotal;
1495 refresh_rate = (unsigned int) (hrate / vtotal * 2 + 0.5);
1496 } else {
1497 refresh_rate = 60;
1498 }
1499 */
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001500 /* TW: Calculation wrong for 1024x600 - force it to 60Hz */
Prashant P. Shahb654f872010-09-06 17:34:26 +05301501 if ((var->xres == 1024) && (var->yres == 600))
1502 refresh_rate = 60;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001503
1504 search_idx = 0;
Prashant P. Shahb654f872010-09-06 17:34:26 +05301505 while ((XGIbios_mode[search_idx].mode_no != 0) &&
1506 (XGIbios_mode[search_idx].xres <= var->xres)) {
1507 if ((XGIbios_mode[search_idx].xres == var->xres) &&
1508 (XGIbios_mode[search_idx].yres == var->yres) &&
1509 (XGIbios_mode[search_idx].bpp == var->bits_per_pixel)) {
1510 if (XGIfb_validate_mode(search_idx) > 0) {
1511 found_mode = 1;
1512 break;
1513 }
1514 }
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001515 search_idx++;
1516 }
1517
Prashant P. Shahb654f872010-09-06 17:34:26 +05301518 if (!found_mode) {
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001519
1520 printk(KERN_ERR "XGIfb: %dx%dx%d is no valid mode\n",
1521 var->xres, var->yres, var->bits_per_pixel);
Prashant P. Shahb654f872010-09-06 17:34:26 +05301522 search_idx = 0;
1523 while (XGIbios_mode[search_idx].mode_no != 0) {
Prashant P. Shahb654f872010-09-06 17:34:26 +05301524 if ((var->xres <= XGIbios_mode[search_idx].xres) &&
Kenji Toyamaa12c27c2011-04-26 12:13:43 +08001525 (var->yres <= XGIbios_mode[search_idx].yres) &&
1526 (var->bits_per_pixel ==
1527 XGIbios_mode[search_idx].bpp)) {
Prashant P. Shahb654f872010-09-06 17:34:26 +05301528 if (XGIfb_validate_mode(search_idx) > 0) {
1529 found_mode = 1;
1530 break;
1531 }
1532 }
1533 search_idx++;
1534 }
1535 if (found_mode) {
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001536 var->xres = XGIbios_mode[search_idx].xres;
Prashant P. Shahb654f872010-09-06 17:34:26 +05301537 var->yres = XGIbios_mode[search_idx].yres;
1538 printk(KERN_DEBUG "XGIfb: Adapted to mode %dx%dx%d\n",
1539 var->xres, var->yres, var->bits_per_pixel);
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001540
1541 } else {
Prashant P. Shahb654f872010-09-06 17:34:26 +05301542 printk(KERN_ERR "XGIfb: Failed to find similar mode to %dx%dx%d\n",
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001543 var->xres, var->yres, var->bits_per_pixel);
Prashant P. Shahb654f872010-09-06 17:34:26 +05301544 return -EINVAL;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001545 }
1546 }
1547
1548 /* TW: TODO: Check the refresh rate */
1549
1550 /* Adapt RGB settings */
1551 XGIfb_bpp_to_var(var);
1552
1553 /* Sanity check for offsets */
1554 if (var->xoffset < 0)
1555 var->xoffset = 0;
1556 if (var->yoffset < 0)
1557 var->yoffset = 0;
1558
Prashant P. Shahb654f872010-09-06 17:34:26 +05301559 if (!XGIfb_ypan) {
1560 if (var->xres != var->xres_virtual)
1561 var->xres_virtual = var->xres;
1562 if (var->yres != var->yres_virtual)
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001563 var->yres_virtual = var->yres;
Prashant P. Shahb654f872010-09-06 17:34:26 +05301564 } /* else { */
1565 /* TW: Now patch yres_virtual if we use panning */
1566 /* May I do this? */
Kenji Toyamaa12c27c2011-04-26 12:13:43 +08001567 /* var->yres_virtual = xgi_video_info.heapstart /
1568 (var->xres * (var->bits_per_pixel >> 3)); */
Prashant P. Shahb654f872010-09-06 17:34:26 +05301569 /* if (var->yres_virtual <= var->yres) { */
1570 /* TW: Paranoia check */
1571 /* var->yres_virtual = var->yres; */
1572 /* } */
1573 /* } */
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001574
1575 /* Truncate offsets to maximum if too high */
1576 if (var->xoffset > var->xres_virtual - var->xres)
1577 var->xoffset = var->xres_virtual - var->xres - 1;
1578
1579 if (var->yoffset > var->yres_virtual - var->yres)
1580 var->yoffset = var->yres_virtual - var->yres - 1;
1581
1582 /* Set everything else to 0 */
1583 var->red.msb_right =
Prashant P. Shahb654f872010-09-06 17:34:26 +05301584 var->green.msb_right =
1585 var->blue.msb_right =
1586 var->transp.offset = var->transp.length = var->transp.msb_right = 0;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001587
1588 DEBUGPRN("end of check_var");
1589 return 0;
1590}
1591
Prashant P. Shahb654f872010-09-06 17:34:26 +05301592static int XGIfb_pan_display(struct fb_var_screeninfo *var,
1593 struct fb_info *info)
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001594{
1595 int err;
1596
Prashant P. Shahb654f872010-09-06 17:34:26 +05301597 /* printk("\nInside pan_display:\n"); */
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001598
1599 if (var->xoffset > (var->xres_virtual - var->xres))
1600 return -EINVAL;
1601 if (var->yoffset > (var->yres_virtual - var->yres))
1602 return -EINVAL;
1603
1604 if (var->vmode & FB_VMODE_YWRAP) {
Prashant P. Shahb654f872010-09-06 17:34:26 +05301605 if (var->yoffset < 0 || var->yoffset >= info->var.yres_virtual
1606 || var->xoffset)
1607 return -EINVAL;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001608 } else {
Prashant P. Shahb654f872010-09-06 17:34:26 +05301609 if (var->xoffset + info->var.xres > info->var.xres_virtual
1610 || var->yoffset + info->var.yres
1611 > info->var.yres_virtual)
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001612 return -EINVAL;
1613 }
Prashant P. Shahb654f872010-09-06 17:34:26 +05301614 err = XGIfb_pan_var(var);
1615 if (err < 0)
1616 return err;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001617
1618 info->var.xoffset = var->xoffset;
1619 info->var.yoffset = var->yoffset;
1620 if (var->vmode & FB_VMODE_YWRAP)
1621 info->var.vmode |= FB_VMODE_YWRAP;
1622 else
1623 info->var.vmode &= ~FB_VMODE_YWRAP;
1624
Prashant P. Shahb654f872010-09-06 17:34:26 +05301625 /* printk("End of pan_display\n"); */
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001626 return 0;
1627}
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001628
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001629static int XGIfb_blank(int blank, struct fb_info *info)
1630{
1631 u8 reg;
1632
Aaro Koskinen7e119b72011-04-18 22:13:58 +03001633 reg = xgifb_reg_get(XGICR, 0x17);
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001634
Prashant P. Shahb654f872010-09-06 17:34:26 +05301635 if (blank > 0)
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001636 reg &= 0x7f;
1637 else
1638 reg |= 0x80;
1639
Aaro Koskinenb6e2dc32011-04-18 22:13:59 +03001640 xgifb_reg_set(XGICR, 0x17, reg);
1641 xgifb_reg_set(XGISR, 0x00, 0x01); /* Synchronous Reset */
1642 xgifb_reg_set(XGISR, 0x00, 0x03); /* End Reset */
Prashant P. Shahb654f872010-09-06 17:34:26 +05301643 return 0;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001644}
1645
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001646static struct fb_ops XGIfb_ops = {
Prashant P. Shahb654f872010-09-06 17:34:26 +05301647 .owner = THIS_MODULE,
1648 .fb_open = XGIfb_open,
1649 .fb_release = XGIfb_release,
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001650 .fb_check_var = XGIfb_check_var,
Prashant P. Shahb654f872010-09-06 17:34:26 +05301651 .fb_set_par = XGIfb_set_par,
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001652 .fb_setcolreg = XGIfb_setcolreg,
Prashant P. Shahb654f872010-09-06 17:34:26 +05301653 .fb_pan_display = XGIfb_pan_display,
Prashant P. Shahb654f872010-09-06 17:34:26 +05301654 .fb_blank = XGIfb_blank,
Aaro Koskinen1b402962011-02-28 20:59:22 +02001655 .fb_fillrect = cfb_fillrect,
Aaro Koskinen85c3c562011-02-28 20:59:21 +02001656 .fb_copyarea = cfb_copyarea,
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001657 .fb_imageblit = cfb_imageblit,
Prashant P. Shahb654f872010-09-06 17:34:26 +05301658 /* .fb_mmap = XGIfb_mmap, */
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001659};
1660
1661/* ---------------- Chip generation dependent routines ---------------- */
1662
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001663/* for XGI 315/550/650/740/330 */
1664
1665static int XGIfb_get_dram_size(void)
1666{
1667
Prashant P. Shahb654f872010-09-06 17:34:26 +05301668 u8 ChannelNum, tmp;
1669 u8 reg = 0;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001670
1671 /* xorg driver sets 32MB * 1 channel */
1672 if (xgi_video_info.chip == XG27)
Aaro Koskinenb6e2dc32011-04-18 22:13:59 +03001673 xgifb_reg_set(XGISR, IND_XGI_DRAM_SIZE, 0x51);
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001674
Aaro Koskinen7e119b72011-04-18 22:13:58 +03001675 reg = xgifb_reg_get(XGISR, IND_XGI_DRAM_SIZE);
Prashant P. Shahb654f872010-09-06 17:34:26 +05301676 switch ((reg & XGI_DRAM_SIZE_MASK) >> 4) {
1677 case XGI_DRAM_SIZE_1MB:
1678 xgi_video_info.video_size = 0x100000;
1679 break;
1680 case XGI_DRAM_SIZE_2MB:
1681 xgi_video_info.video_size = 0x200000;
1682 break;
1683 case XGI_DRAM_SIZE_4MB:
1684 xgi_video_info.video_size = 0x400000;
1685 break;
1686 case XGI_DRAM_SIZE_8MB:
1687 xgi_video_info.video_size = 0x800000;
1688 break;
1689 case XGI_DRAM_SIZE_16MB:
1690 xgi_video_info.video_size = 0x1000000;
1691 break;
1692 case XGI_DRAM_SIZE_32MB:
1693 xgi_video_info.video_size = 0x2000000;
1694 break;
1695 case XGI_DRAM_SIZE_64MB:
1696 xgi_video_info.video_size = 0x4000000;
1697 break;
1698 case XGI_DRAM_SIZE_128MB:
1699 xgi_video_info.video_size = 0x8000000;
1700 break;
1701 case XGI_DRAM_SIZE_256MB:
1702 xgi_video_info.video_size = 0x10000000;
1703 break;
1704 default:
1705 return -1;
1706 }
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001707
Prashant P. Shahb654f872010-09-06 17:34:26 +05301708 tmp = (reg & 0x0c) >> 2;
1709 switch (xgi_video_info.chip) {
1710 case XG20:
1711 case XG21:
1712 case XG27:
1713 ChannelNum = 1;
1714 break;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001715
Prashant P. Shahb654f872010-09-06 17:34:26 +05301716 case XG42:
1717 if (reg & 0x04)
1718 ChannelNum = 2;
1719 else
1720 ChannelNum = 1;
1721 break;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001722
Prashant P. Shahb654f872010-09-06 17:34:26 +05301723 case XG45:
1724 if (tmp == 1)
1725 ChannelNum = 2;
1726 else if (tmp == 2)
1727 ChannelNum = 3;
1728 else if (tmp == 3)
1729 ChannelNum = 4;
1730 else
1731 ChannelNum = 1;
1732 break;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001733
Prashant P. Shahb654f872010-09-06 17:34:26 +05301734 case XG40:
1735 default:
1736 if (tmp == 2)
1737 ChannelNum = 2;
1738 else if (tmp == 3)
1739 ChannelNum = 3;
1740 else
1741 ChannelNum = 1;
1742 break;
1743 }
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001744
Prashant P. Shahb654f872010-09-06 17:34:26 +05301745 xgi_video_info.video_size = xgi_video_info.video_size * ChannelNum;
1746 /* PLiad fixed for benchmarking and fb set */
1747 /* xgi_video_info.video_size = 0x200000; */ /* 1024x768x16 */
1748 /* xgi_video_info.video_size = 0x1000000; */ /* benchmark */
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001749
Kenji Toyamaa12c27c2011-04-26 12:13:43 +08001750 printk("XGIfb: SR14=%x DramSzie %x ChannelNum %x\n",
1751 reg,
1752 xgi_video_info.video_size, ChannelNum);
Prashant P. Shahb654f872010-09-06 17:34:26 +05301753 return 0;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001754
1755}
1756
1757static void XGIfb_detect_VB(void)
1758{
Prashant P. Shahb654f872010-09-06 17:34:26 +05301759 u8 cr32, temp = 0;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001760
1761 xgi_video_info.TV_plug = xgi_video_info.TV_type = 0;
1762
Prashant P. Shahb654f872010-09-06 17:34:26 +05301763 switch (xgi_video_info.hasVB) {
1764 case HASVB_LVDS_CHRONTEL:
1765 case HASVB_CHRONTEL:
1766 break;
1767 case HASVB_301:
1768 case HASVB_302:
1769 /* XGI_Sense30x(); */ /* Yi-Lin TV Sense? */
1770 break;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001771 }
1772
Aaro Koskinen7e119b72011-04-18 22:13:58 +03001773 cr32 = xgifb_reg_get(XGICR, IND_XGI_SCRATCH_REG_CR32);
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001774
1775 if ((cr32 & XGI_CRT1) && !XGIfb_crt1off)
1776 XGIfb_crt1off = 0;
1777 else {
1778 if (cr32 & 0x5F)
1779 XGIfb_crt1off = 1;
1780 else
1781 XGIfb_crt1off = 0;
1782 }
1783
1784 if (XGIfb_crt2type != -1)
1785 /* TW: Override with option */
1786 xgi_video_info.disp_state = XGIfb_crt2type;
1787 else if (cr32 & XGI_VB_TV)
1788 xgi_video_info.disp_state = DISPTYPE_TV;
1789 else if (cr32 & XGI_VB_LCD)
1790 xgi_video_info.disp_state = DISPTYPE_LCD;
1791 else if (cr32 & XGI_VB_CRT2)
1792 xgi_video_info.disp_state = DISPTYPE_CRT2;
1793 else
1794 xgi_video_info.disp_state = 0;
1795
Prashant P. Shahb654f872010-09-06 17:34:26 +05301796 if (XGIfb_tvplug != -1)
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001797 /* PR/TW: Override with option */
Prashant P. Shahb654f872010-09-06 17:34:26 +05301798 xgi_video_info.TV_plug = XGIfb_tvplug;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001799 else if (cr32 & XGI_VB_HIVISION) {
1800 xgi_video_info.TV_type = TVMODE_HIVISION;
1801 xgi_video_info.TV_plug = TVPLUG_SVIDEO;
Prashant P. Shahb654f872010-09-06 17:34:26 +05301802 } else if (cr32 & XGI_VB_SVIDEO)
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001803 xgi_video_info.TV_plug = TVPLUG_SVIDEO;
1804 else if (cr32 & XGI_VB_COMPOSITE)
1805 xgi_video_info.TV_plug = TVPLUG_COMPOSITE;
1806 else if (cr32 & XGI_VB_SCART)
1807 xgi_video_info.TV_plug = TVPLUG_SCART;
1808
Prashant P. Shahb654f872010-09-06 17:34:26 +05301809 if (xgi_video_info.TV_type == 0) {
Aaro Koskinen7e119b72011-04-18 22:13:58 +03001810 temp = xgifb_reg_get(XGICR, 0x38);
Aaro Koskinenebe78462011-03-13 12:26:08 +02001811 if (temp & 0x10)
1812 xgi_video_info.TV_type = TVMODE_PAL;
1813 else
1814 xgi_video_info.TV_type = TVMODE_NTSC;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001815 }
1816
1817 /* TW: Copy forceCRT1 option to CRT1off if option is given */
Prashant P. Shahb654f872010-09-06 17:34:26 +05301818 if (XGIfb_forcecrt1 != -1) {
1819 if (XGIfb_forcecrt1)
1820 XGIfb_crt1off = 0;
1821 else
1822 XGIfb_crt1off = 1;
1823 }
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001824}
1825
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001826static int XGIfb_has_VB(void)
1827{
1828 u8 vb_chipid;
1829
Aaro Koskinen7e119b72011-04-18 22:13:58 +03001830 vb_chipid = xgifb_reg_get(XGIPART4, 0x00);
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001831 switch (vb_chipid) {
Prashant P. Shahb654f872010-09-06 17:34:26 +05301832 case 0x01:
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001833 xgi_video_info.hasVB = HASVB_301;
1834 break;
Prashant P. Shahb654f872010-09-06 17:34:26 +05301835 case 0x02:
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001836 xgi_video_info.hasVB = HASVB_302;
1837 break;
Prashant P. Shahb654f872010-09-06 17:34:26 +05301838 default:
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001839 xgi_video_info.hasVB = HASVB_NONE;
Bill Pembertondda08c52010-06-17 13:10:42 -04001840 return 0;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001841 }
Bill Pembertondda08c52010-06-17 13:10:42 -04001842 return 1;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001843}
1844
Aaro Koskinenc4fa7df2011-04-18 22:14:05 +03001845static void XGIfb_get_VB_type(void)
1846{
1847 u8 reg;
1848
1849 if (!XGIfb_has_VB()) {
1850 reg = xgifb_reg_get(XGICR, IND_XGI_SCRATCH_REG_CR37);
1851 switch ((reg & XGI_EXTERNAL_CHIP_MASK) >> 1) {
1852 case XGI310_EXTERNAL_CHIP_LVDS:
1853 xgi_video_info.hasVB = HASVB_LVDS;
1854 break;
1855 case XGI310_EXTERNAL_CHIP_LVDS_CHRONTEL:
1856 xgi_video_info.hasVB = HASVB_LVDS_CHRONTEL;
1857 break;
1858 default:
1859 break;
1860 }
1861 }
1862}
1863
Aaro Koskinend27c6bc2011-08-29 23:14:23 +03001864static int __init xgifb_optval(char *fullopt, int validx)
1865{
1866 unsigned long lres;
1867
1868 if (kstrtoul(fullopt + validx, 0, &lres) < 0 || lres > INT_MAX) {
1869 pr_err("xgifb: invalid value for option: %s\n", fullopt);
1870 return 0;
1871 }
1872 return lres;
1873}
1874
Ruslan Pisarev032abf72011-07-21 11:59:11 +03001875static int __init XGIfb_setup(char *options)
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001876{
1877 char *this_opt;
1878
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001879 if (!options || !*options)
1880 return 0;
1881
Aaro Koskinen79bea042011-08-29 23:14:21 +03001882 pr_info("xgifb: options: %s\n", options);
1883
Prashant P. Shahb654f872010-09-06 17:34:26 +05301884 while ((this_opt = strsep(&options, ",")) != NULL) {
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001885
Prashant P. Shahb654f872010-09-06 17:34:26 +05301886 if (!*this_opt)
1887 continue;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001888
1889 if (!strncmp(this_opt, "mode:", 5)) {
Aaro Koskinendfbdf802011-08-29 23:14:25 +03001890 mode = this_opt + 5;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001891 } else if (!strncmp(this_opt, "vesa:", 5)) {
Aaro Koskinendfbdf802011-08-29 23:14:25 +03001892 vesa = xgifb_optval(this_opt, 5);
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001893 } else if (!strncmp(this_opt, "vrate:", 6)) {
Aaro Koskinen7548a832011-10-11 21:47:17 +03001894 refresh_rate = xgifb_optval(this_opt, 6);
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001895 } else if (!strncmp(this_opt, "rate:", 5)) {
Aaro Koskinen7548a832011-10-11 21:47:17 +03001896 refresh_rate = xgifb_optval(this_opt, 5);
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001897 } else if (!strncmp(this_opt, "crt1off", 7)) {
1898 XGIfb_crt1off = 1;
1899 } else if (!strncmp(this_opt, "filter:", 7)) {
Aaro Koskinend27c6bc2011-08-29 23:14:23 +03001900 filter = xgifb_optval(this_opt, 7);
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001901 } else if (!strncmp(this_opt, "forcecrt2type:", 14)) {
1902 XGIfb_search_crt2type(this_opt + 14);
1903 } else if (!strncmp(this_opt, "forcecrt1:", 10)) {
Aaro Koskinend27c6bc2011-08-29 23:14:23 +03001904 XGIfb_forcecrt1 = xgifb_optval(this_opt, 10);
Prashant P. Shahb654f872010-09-06 17:34:26 +05301905 } else if (!strncmp(this_opt, "tvmode:", 7)) {
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001906 XGIfb_search_tvstd(this_opt + 7);
Prashant P. Shahb654f872010-09-06 17:34:26 +05301907 } else if (!strncmp(this_opt, "tvstandard:", 11)) {
1908 XGIfb_search_tvstd(this_opt + 7);
Prashant P. Shahb654f872010-09-06 17:34:26 +05301909 } else if (!strncmp(this_opt, "dstn", 4)) {
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001910 enable_dstn = 1;
1911 /* TW: DSTN overrules forcecrt2type */
1912 XGIfb_crt2type = DISPTYPE_LCD;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001913 } else if (!strncmp(this_opt, "noypan", 6)) {
Prashant P. Shahb654f872010-09-06 17:34:26 +05301914 XGIfb_ypan = 0;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001915 } else if (!strncmp(this_opt, "userom:", 7)) {
Aaro Koskinend27c6bc2011-08-29 23:14:23 +03001916 XGIfb_userom = xgifb_optval(this_opt, 7);
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001917 } else {
Aaro Koskinendfbdf802011-08-29 23:14:25 +03001918 mode = this_opt;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001919 }
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001920 }
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001921 return 0;
1922}
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001923
Aaro Koskinen0f07d942011-02-17 23:29:13 +02001924static unsigned char *xgifb_copy_rom(struct pci_dev *dev)
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001925{
Aaro Koskinen0f07d942011-02-17 23:29:13 +02001926 void __iomem *rom_address;
1927 unsigned char *rom_copy;
1928 size_t rom_size;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001929
Aaro Koskinen0f07d942011-02-17 23:29:13 +02001930 rom_address = pci_map_rom(dev, &rom_size);
1931 if (rom_address == NULL)
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001932 return NULL;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001933
Aaro Koskinen0f07d942011-02-17 23:29:13 +02001934 rom_copy = vzalloc(XGIFB_ROM_SIZE);
1935 if (rom_copy == NULL)
1936 goto done;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001937
Aaro Koskinen0f07d942011-02-17 23:29:13 +02001938 rom_size = min_t(size_t, rom_size, XGIFB_ROM_SIZE);
1939 memcpy_fromio(rom_copy, rom_address, rom_size);
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001940
Aaro Koskinen0f07d942011-02-17 23:29:13 +02001941done:
1942 pci_unmap_rom(dev, rom_address);
1943 return rom_copy;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001944}
1945
Randy Dunlap89229672010-08-10 08:46:44 -07001946static int __devinit xgifb_probe(struct pci_dev *pdev,
Prashant P. Shahb654f872010-09-06 17:34:26 +05301947 const struct pci_device_id *ent)
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001948{
Prashant P. Shahb654f872010-09-06 17:34:26 +05301949 u8 reg, reg1;
1950 u8 CR48, CR38;
Aaro Koskinenbb292232011-02-17 23:29:11 +02001951 int ret;
Aaro Koskinen009adf2d2011-08-29 23:14:24 +03001952 bool xgi21_drvlcdcaplist = false;
Aaro Koskinen19c1e882011-10-11 21:47:14 +03001953 struct fb_info *fb_info;
Aaro Koskinenc62f2e42011-10-11 21:47:15 +03001954 struct xgi_hw_device_info *hw_info = &xgi_video_info.hw_info;
Aaro Koskinenbb292232011-02-17 23:29:11 +02001955
Aaro Koskinenc62f2e42011-10-11 21:47:15 +03001956 memset(hw_info, 0, sizeof(struct xgi_hw_device_info));
Prashant P. Shahb654f872010-09-06 17:34:26 +05301957 fb_info = framebuffer_alloc(sizeof(struct fb_info), &pdev->dev);
1958 if (!fb_info)
1959 return -ENOMEM;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001960
Aaro Koskinen19c1e882011-10-11 21:47:14 +03001961 xgi_video_info.fb_info = fb_info;
Prashant P. Shahb654f872010-09-06 17:34:26 +05301962 xgi_video_info.chip_id = pdev->device;
Kenji Toyamaa12c27c2011-04-26 12:13:43 +08001963 pci_read_config_byte(pdev,
1964 PCI_REVISION_ID,
1965 &xgi_video_info.revision_id);
Aaro Koskinenc62f2e42011-10-11 21:47:15 +03001966 hw_info->jChipRevision = xgi_video_info.revision_id;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001967
Prashant P. Shahb654f872010-09-06 17:34:26 +05301968 xgi_video_info.pcibus = pdev->bus->number;
1969 xgi_video_info.pcislot = PCI_SLOT(pdev->devfn);
1970 xgi_video_info.pcifunc = PCI_FUNC(pdev->devfn);
1971 xgi_video_info.subsysvendor = pdev->subsystem_vendor;
1972 xgi_video_info.subsysdevice = pdev->subsystem_device;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001973
Prashant P. Shahb654f872010-09-06 17:34:26 +05301974 xgi_video_info.video_base = pci_resource_start(pdev, 0);
1975 xgi_video_info.mmio_base = pci_resource_start(pdev, 1);
Aaro Koskinen1b3909e2011-02-17 23:29:17 +02001976 xgi_video_info.mmio_size = pci_resource_len(pdev, 1);
Prashant P. Shahb654f872010-09-06 17:34:26 +05301977 xgi_video_info.vga_base = pci_resource_start(pdev, 2) + 0x30;
Aaro Koskinenc62f2e42011-10-11 21:47:15 +03001978 hw_info->pjIOAddress = (unsigned char *)xgi_video_info.vga_base;
Prashant P. Shahb654f872010-09-06 17:34:26 +05301979 /* XGI_Pr.RelIO = ioremap(pci_resource_start(pdev, 2), 128) + 0x30; */
1980 printk("XGIfb: Relocate IO address: %lx [%08lx]\n",
Kenji Toyamaa12c27c2011-04-26 12:13:43 +08001981 (unsigned long)pci_resource_start(pdev, 2), XGI_Pr.RelIO);
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001982
Aaro Koskinenbb292232011-02-17 23:29:11 +02001983 if (pci_enable_device(pdev)) {
1984 ret = -EIO;
1985 goto error;
1986 }
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001987
Aaro Koskinenc62f2e42011-10-11 21:47:15 +03001988 XGIRegInit(&XGI_Pr, (unsigned long)hw_info->pjIOAddress);
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001989
Aaro Koskinenb6e2dc32011-04-18 22:13:59 +03001990 xgifb_reg_set(XGISR, IND_XGI_PASSWORD, XGI_PASSWORD);
Aaro Koskinen7e119b72011-04-18 22:13:58 +03001991 reg1 = xgifb_reg_get(XGISR, IND_XGI_PASSWORD);
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001992
Prashant P. Shahb654f872010-09-06 17:34:26 +05301993 if (reg1 != 0xa1) { /*I/O error */
1994 printk("\nXGIfb: I/O error!!!");
Aaro Koskinenbb292232011-02-17 23:29:11 +02001995 ret = -EIO;
1996 goto error;
Prashant P. Shahb654f872010-09-06 17:34:26 +05301997 }
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001998
1999 switch (xgi_video_info.chip_id) {
Prashant P. Shahb654f872010-09-06 17:34:26 +05302000 case PCI_DEVICE_ID_XG_20:
Aaro Koskinene67f4d42011-04-18 22:14:00 +03002001 xgifb_reg_or(XGICR, Index_CR_GPIO_Reg3, GPIOG_EN);
Aaro Koskinen7e119b72011-04-18 22:13:58 +03002002 CR48 = xgifb_reg_get(XGICR, Index_CR_GPIO_Reg1);
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02002003 if (CR48&GPIOG_READ)
2004 xgi_video_info.chip = XG21;
2005 else
Prashant P. Shahb654f872010-09-06 17:34:26 +05302006 xgi_video_info.chip = XG20;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02002007 XGIfb_CRT2_write_enable = IND_XGI_CRT2_WRITE_ENABLE_315;
2008 break;
Prashant P. Shahb654f872010-09-06 17:34:26 +05302009 case PCI_DEVICE_ID_XG_40:
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02002010 xgi_video_info.chip = XG40;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02002011 XGIfb_CRT2_write_enable = IND_XGI_CRT2_WRITE_ENABLE_315;
2012 break;
Prashant P. Shahb654f872010-09-06 17:34:26 +05302013 case PCI_DEVICE_ID_XG_41:
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02002014 xgi_video_info.chip = XG41;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02002015 XGIfb_CRT2_write_enable = IND_XGI_CRT2_WRITE_ENABLE_315;
2016 break;
Prashant P. Shahb654f872010-09-06 17:34:26 +05302017 case PCI_DEVICE_ID_XG_42:
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02002018 xgi_video_info.chip = XG42;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02002019 XGIfb_CRT2_write_enable = IND_XGI_CRT2_WRITE_ENABLE_315;
2020 break;
Prashant P. Shahb654f872010-09-06 17:34:26 +05302021 case PCI_DEVICE_ID_XG_27:
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02002022 xgi_video_info.chip = XG27;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02002023 XGIfb_CRT2_write_enable = IND_XGI_CRT2_WRITE_ENABLE_315;
2024 break;
Prashant P. Shahb654f872010-09-06 17:34:26 +05302025 default:
Aaro Koskinenbb292232011-02-17 23:29:11 +02002026 ret = -ENODEV;
2027 goto error;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02002028 }
2029
Prashant P. Shahb654f872010-09-06 17:34:26 +05302030 printk("XGIfb:chipid = %x\n", xgi_video_info.chip);
Aaro Koskinenc62f2e42011-10-11 21:47:15 +03002031 hw_info->jChipType = xgi_video_info.chip;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02002032
Prashant P. Shahb654f872010-09-06 17:34:26 +05302033 if ((xgi_video_info.chip == XG21) || (XGIfb_userom)) {
Aaro Koskinenc62f2e42011-10-11 21:47:15 +03002034 hw_info->pjVirtualRomBase = xgifb_copy_rom(pdev);
2035 if (hw_info->pjVirtualRomBase)
Kenji Toyamaa12c27c2011-04-26 12:13:43 +08002036 printk(KERN_INFO "XGIfb: Video ROM found and mapped to %p\n",
Aaro Koskinenc62f2e42011-10-11 21:47:15 +03002037 hw_info->pjVirtualRomBase);
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02002038 else
2039 printk(KERN_INFO "XGIfb: Video ROM not found\n");
Prashant P. Shahb654f872010-09-06 17:34:26 +05302040 } else {
Aaro Koskinenc62f2e42011-10-11 21:47:15 +03002041 hw_info->pjVirtualRomBase = NULL;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02002042 printk(KERN_INFO "XGIfb: Video ROM usage disabled\n");
Prashant P. Shahb654f872010-09-06 17:34:26 +05302043 }
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02002044
Prashant P. Shahb654f872010-09-06 17:34:26 +05302045 if (XGIfb_get_dram_size()) {
Prashant P. Shahb654f872010-09-06 17:34:26 +05302046 printk(KERN_INFO "XGIfb: Fatal error: Unable to determine RAM size.\n");
Aaro Koskinenbb292232011-02-17 23:29:11 +02002047 ret = -ENODEV;
2048 goto error;
Prashant P. Shahb654f872010-09-06 17:34:26 +05302049 }
2050
Aaro Koskinene1521a12011-08-19 22:40:26 +03002051 /* Enable PCI_LINEAR_ADDRESSING and MMIO_ENABLE */
2052 xgifb_reg_or(XGISR,
2053 IND_XGI_PCI_ADDRESS_SET,
2054 (XGI_PCI_ADDR_ENABLE | XGI_MEM_MAP_IO_ENABLE));
2055 /* Enable 2D accelerator engine */
2056 xgifb_reg_or(XGISR, IND_XGI_MODULE_ENABLE, XGI_ENABLE_2D);
Prashant P. Shahb654f872010-09-06 17:34:26 +05302057
Aaro Koskinenc62f2e42011-10-11 21:47:15 +03002058 hw_info->ulVideoMemorySize = xgi_video_info.video_size;
Prashant P. Shahb654f872010-09-06 17:34:26 +05302059
Kenji Toyamaa12c27c2011-04-26 12:13:43 +08002060 if (!request_mem_region(xgi_video_info.video_base,
2061 xgi_video_info.video_size,
2062 "XGIfb FB")) {
2063 printk("unable request memory size %x",
2064 xgi_video_info.video_size);
Prashant P. Shahb654f872010-09-06 17:34:26 +05302065 printk(KERN_ERR "XGIfb: Fatal error: Unable to reserve frame buffer memory\n");
2066 printk(KERN_ERR "XGIfb: Is there another framebuffer driver active?\n");
Aaro Koskinenbb292232011-02-17 23:29:11 +02002067 ret = -ENODEV;
2068 goto error;
Prashant P. Shahb654f872010-09-06 17:34:26 +05302069 }
2070
Aaro Koskinen1b3909e2011-02-17 23:29:17 +02002071 if (!request_mem_region(xgi_video_info.mmio_base,
2072 xgi_video_info.mmio_size,
2073 "XGIfb MMIO")) {
Prashant P. Shahb654f872010-09-06 17:34:26 +05302074 printk(KERN_ERR "XGIfb: Fatal error: Unable to reserve MMIO region\n");
Aaro Koskinenbb292232011-02-17 23:29:11 +02002075 ret = -ENODEV;
Aaro Koskinen5c0ef2a2011-02-17 23:29:15 +02002076 goto error_0;
Prashant P. Shahb654f872010-09-06 17:34:26 +05302077 }
2078
Aaro Koskinenc62f2e42011-10-11 21:47:15 +03002079 xgi_video_info.video_vbase = hw_info->pjVideoMemoryAddress =
Prashant P. Shahb654f872010-09-06 17:34:26 +05302080 ioremap(xgi_video_info.video_base, xgi_video_info.video_size);
Aaro Koskinen1b3909e2011-02-17 23:29:17 +02002081 xgi_video_info.mmio_vbase = ioremap(xgi_video_info.mmio_base,
2082 xgi_video_info.mmio_size);
Prashant P. Shahb654f872010-09-06 17:34:26 +05302083
2084 printk(KERN_INFO "XGIfb: Framebuffer at 0x%lx, mapped to 0x%p, size %dk\n",
Kenji Toyamaa12c27c2011-04-26 12:13:43 +08002085 xgi_video_info.video_base,
2086 xgi_video_info.video_vbase,
2087 xgi_video_info.video_size / 1024);
Prashant P. Shahb654f872010-09-06 17:34:26 +05302088
2089 printk(KERN_INFO "XGIfb: MMIO at 0x%lx, mapped to 0x%p, size %ldk\n",
Aaro Koskinen1b3909e2011-02-17 23:29:17 +02002090 xgi_video_info.mmio_base, xgi_video_info.mmio_vbase,
2091 xgi_video_info.mmio_size / 1024);
Prashant P. Shahb654f872010-09-06 17:34:26 +05302092 printk("XGIfb: XGIInitNew() ...");
Aaro Koskinen6048d7612011-10-11 21:47:16 +03002093 pci_set_drvdata(pdev, &xgi_video_info);
2094 if (XGIInitNew(pdev))
Prashant P. Shahb654f872010-09-06 17:34:26 +05302095 printk("OK\n");
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02002096 else
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02002097 printk("Fail\n");
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02002098
Prashant P. Shahb654f872010-09-06 17:34:26 +05302099 xgi_video_info.mtrr = (unsigned int) 0;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02002100
Aaro Koskinene1521a12011-08-19 22:40:26 +03002101 xgi_video_info.hasVB = HASVB_NONE;
2102 if ((xgi_video_info.chip == XG20) ||
2103 (xgi_video_info.chip == XG27)) {
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02002104 xgi_video_info.hasVB = HASVB_NONE;
Aaro Koskinene1521a12011-08-19 22:40:26 +03002105 } else if (xgi_video_info.chip == XG21) {
2106 CR38 = xgifb_reg_get(XGICR, 0x38);
2107 if ((CR38&0xE0) == 0xC0) {
2108 xgi_video_info.disp_state = DISPTYPE_LCD;
Aaro Koskinen009adf2d2011-08-29 23:14:24 +03002109 if (!XGIfb_GetXG21LVDSData())
2110 xgi21_drvlcdcaplist = true;
Aaro Koskinene1521a12011-08-19 22:40:26 +03002111 } else if ((CR38&0xE0) == 0x60) {
2112 xgi_video_info.hasVB = HASVB_CHRONTEL;
Prashant P. Shahb654f872010-09-06 17:34:26 +05302113 } else {
Aaro Koskinene1521a12011-08-19 22:40:26 +03002114 xgi_video_info.hasVB = HASVB_NONE;
Prashant P. Shahb654f872010-09-06 17:34:26 +05302115 }
Aaro Koskinene1521a12011-08-19 22:40:26 +03002116 } else {
2117 XGIfb_get_VB_type();
2118 }
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02002119
Aaro Koskinenc62f2e42011-10-11 21:47:15 +03002120 hw_info->ujVBChipID = VB_CHIP_UNKNOWN;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02002121
Aaro Koskinenc62f2e42011-10-11 21:47:15 +03002122 hw_info->ulExternalChip = 0;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02002123
Aaro Koskinene1521a12011-08-19 22:40:26 +03002124 switch (xgi_video_info.hasVB) {
2125 case HASVB_301:
2126 reg = xgifb_reg_get(XGIPART4, 0x01);
2127 if (reg >= 0xE0) {
Aaro Koskinenc62f2e42011-10-11 21:47:15 +03002128 hw_info->ujVBChipID = VB_CHIP_302LV;
Aaro Koskinene1521a12011-08-19 22:40:26 +03002129 printk(KERN_INFO "XGIfb: XGI302LV bridge detected (revision 0x%02x)\n", reg);
2130 } else if (reg >= 0xD0) {
Aaro Koskinenc62f2e42011-10-11 21:47:15 +03002131 hw_info->ujVBChipID = VB_CHIP_301LV;
Aaro Koskinene1521a12011-08-19 22:40:26 +03002132 printk(KERN_INFO "XGIfb: XGI301LV bridge detected (revision 0x%02x)\n", reg);
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02002133 }
Aaro Koskinene1521a12011-08-19 22:40:26 +03002134 /* else if (reg >= 0xB0) {
Aaro Koskinenc62f2e42011-10-11 21:47:15 +03002135 hw_info->ujVBChipID = VB_CHIP_301B;
Aaro Koskinene1521a12011-08-19 22:40:26 +03002136 reg1 = xgifb_reg_get(XGIPART4, 0x23);
2137 printk("XGIfb: XGI301B bridge detected\n");
2138 } */
2139 else {
Aaro Koskinenc62f2e42011-10-11 21:47:15 +03002140 hw_info->ujVBChipID = VB_CHIP_301;
Aaro Koskinene1521a12011-08-19 22:40:26 +03002141 printk("XGIfb: XGI301 bridge detected\n");
2142 }
2143 break;
2144 case HASVB_302:
2145 reg = xgifb_reg_get(XGIPART4, 0x01);
2146 if (reg >= 0xE0) {
Aaro Koskinenc62f2e42011-10-11 21:47:15 +03002147 hw_info->ujVBChipID = VB_CHIP_302LV;
Aaro Koskinene1521a12011-08-19 22:40:26 +03002148 printk(KERN_INFO "XGIfb: XGI302LV bridge detected (revision 0x%02x)\n", reg);
2149 } else if (reg >= 0xD0) {
Aaro Koskinenc62f2e42011-10-11 21:47:15 +03002150 hw_info->ujVBChipID = VB_CHIP_301LV;
Aaro Koskinene1521a12011-08-19 22:40:26 +03002151 printk(KERN_INFO "XGIfb: XGI302LV bridge detected (revision 0x%02x)\n", reg);
2152 } else if (reg >= 0xB0) {
2153 reg1 = xgifb_reg_get(XGIPART4, 0x23);
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02002154
Aaro Koskinenc62f2e42011-10-11 21:47:15 +03002155 hw_info->ujVBChipID = VB_CHIP_302B;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02002156
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02002157 } else {
Aaro Koskinenc62f2e42011-10-11 21:47:15 +03002158 hw_info->ujVBChipID = VB_CHIP_302;
Aaro Koskinene1521a12011-08-19 22:40:26 +03002159 printk(KERN_INFO "XGIfb: XGI302 bridge detected\n");
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02002160 }
Aaro Koskinene1521a12011-08-19 22:40:26 +03002161 break;
2162 case HASVB_LVDS:
Aaro Koskinenc62f2e42011-10-11 21:47:15 +03002163 hw_info->ulExternalChip = 0x1;
Aaro Koskinene1521a12011-08-19 22:40:26 +03002164 printk(KERN_INFO "XGIfb: LVDS transmitter detected\n");
2165 break;
2166 case HASVB_TRUMPION:
Aaro Koskinenc62f2e42011-10-11 21:47:15 +03002167 hw_info->ulExternalChip = 0x2;
Aaro Koskinene1521a12011-08-19 22:40:26 +03002168 printk(KERN_INFO "XGIfb: Trumpion Zurac LVDS scaler detected\n");
2169 break;
2170 case HASVB_CHRONTEL:
Aaro Koskinenc62f2e42011-10-11 21:47:15 +03002171 hw_info->ulExternalChip = 0x4;
Aaro Koskinene1521a12011-08-19 22:40:26 +03002172 printk(KERN_INFO "XGIfb: Chrontel TV encoder detected\n");
2173 break;
2174 case HASVB_LVDS_CHRONTEL:
Aaro Koskinenc62f2e42011-10-11 21:47:15 +03002175 hw_info->ulExternalChip = 0x5;
Aaro Koskinene1521a12011-08-19 22:40:26 +03002176 printk(KERN_INFO "XGIfb: LVDS transmitter and Chrontel TV encoder detected\n");
2177 break;
2178 default:
2179 printk(KERN_INFO "XGIfb: No or unknown bridge type detected\n");
2180 break;
2181 }
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02002182
Aaro Koskinene1521a12011-08-19 22:40:26 +03002183 if (xgi_video_info.hasVB != HASVB_NONE)
2184 XGIfb_detect_VB();
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02002185
Aaro Koskinene1521a12011-08-19 22:40:26 +03002186 if (xgi_video_info.disp_state & DISPTYPE_DISP2) {
2187 if (XGIfb_crt1off)
2188 xgi_video_info.disp_state |= DISPMODE_SINGLE;
2189 else
2190 xgi_video_info.disp_state |= (DISPMODE_MIRROR |
2191 DISPTYPE_CRT1);
2192 } else {
2193 xgi_video_info.disp_state = DISPMODE_SINGLE |
2194 DISPTYPE_CRT1;
2195 }
2196
2197 if (xgi_video_info.disp_state & DISPTYPE_LCD) {
2198 if (!enable_dstn) {
2199 reg = xgifb_reg_get(XGICR, IND_XGI_LCD_PANEL);
2200 reg &= 0x0f;
Aaro Koskinenc62f2e42011-10-11 21:47:15 +03002201 hw_info->ulCRT2LCDType = XGI310paneltype[reg];
Aaro Koskinene1521a12011-08-19 22:40:26 +03002202
2203 } else {
2204 /* TW: FSTN/DSTN */
Aaro Koskinenc62f2e42011-10-11 21:47:15 +03002205 hw_info->ulCRT2LCDType = LCD_320x480;
Aaro Koskinene1521a12011-08-19 22:40:26 +03002206 }
2207 }
2208
Aaro Koskinenc62f2e42011-10-11 21:47:15 +03002209 if ((hw_info->ujVBChipID == VB_CHIP_302B) ||
2210 (hw_info->ujVBChipID == VB_CHIP_301LV) ||
2211 (hw_info->ujVBChipID == VB_CHIP_302LV)) {
Aaro Koskinene1521a12011-08-19 22:40:26 +03002212 int tmp;
2213 tmp = xgifb_reg_get(XGICR, 0x34);
2214 if (tmp <= 0x13) {
2215 /* Currently on LCDA?
2216 *(Some BIOSes leave CR38) */
2217 tmp = xgifb_reg_get(XGICR, 0x38);
2218 if ((tmp & 0x03) == 0x03) {
2219 /* XGI_Pr.XGI_UseLCDA = 1; */
Prashant P. Shahb654f872010-09-06 17:34:26 +05302220 } else {
Kenji Toyamaa12c27c2011-04-26 12:13:43 +08002221 /* Currently on LCDA?
Aaro Koskinene1521a12011-08-19 22:40:26 +03002222 *(Some newer BIOSes set D0 in CR35) */
2223 tmp = xgifb_reg_get(XGICR, 0x35);
2224 if (tmp & 0x01) {
Prashant P. Shahb654f872010-09-06 17:34:26 +05302225 /* XGI_Pr.XGI_UseLCDA = 1; */
2226 } else {
Aaro Koskinene1521a12011-08-19 22:40:26 +03002227 tmp = xgifb_reg_get(XGICR,
2228 0x30);
2229 if (tmp & 0x20) {
2230 tmp = xgifb_reg_get(
2231 XGIPART1, 0x13);
2232 if (tmp & 0x04) {
2233 /* XGI_Pr.XGI_UseLCDA = 1; */
Prashant P. Shahb654f872010-09-06 17:34:26 +05302234 }
2235 }
2236 }
2237 }
Prashant P. Shahb654f872010-09-06 17:34:26 +05302238 }
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02002239
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02002240 }
2241
Aaro Koskinendfbdf802011-08-29 23:14:25 +03002242 if (mode)
2243 XGIfb_search_mode(mode);
2244 else if (vesa != -1)
2245 XGIfb_search_vesamode(vesa);
2246
Aaro Koskinene1521a12011-08-19 22:40:26 +03002247 if (xgifb_mode_idx >= 0)
2248 xgifb_mode_idx = XGIfb_validate_mode(xgifb_mode_idx);
2249
2250 if (xgifb_mode_idx < 0) {
Aaro Koskinenc8bec1f2011-08-29 23:14:30 +03002251 if ((xgi_video_info.disp_state & DISPTYPE_DISP2) ==
2252 DISPTYPE_LCD &&
2253 xgi_video_info.chip == XG21)
2254 xgifb_mode_idx = XGIfb_GetXG21DefaultLVDSModeIdx();
2255 else
Aaro Koskinene1521a12011-08-19 22:40:26 +03002256 xgifb_mode_idx = DEFAULT_MODE;
Aaro Koskinene1521a12011-08-19 22:40:26 +03002257 }
2258
Aaro Koskinende736db2011-08-29 23:14:29 +03002259 if (xgifb_mode_idx < 0) {
2260 dev_err(&pdev->dev, "no supported video mode found\n");
2261 goto error_1;
2262 }
2263
Aaro Koskinen009adf2d2011-08-29 23:14:24 +03002264 if (xgi21_drvlcdcaplist) {
2265 int m;
2266
2267 for (m = 0; m < ARRAY_SIZE(XGI21_LCDCapList); m++)
2268 if ((XGI21_LCDCapList[m].LVDSHDE ==
2269 XGIbios_mode[xgifb_mode_idx].xres) &&
2270 (XGI21_LCDCapList[m].LVDSVDE ==
2271 XGIbios_mode[xgifb_mode_idx].yres)) {
2272 xgifb_reg_set(XGI_Pr.P3d4, 0x36, m);
2273 break;
2274 }
2275 }
2276
Aaro Koskinene1521a12011-08-19 22:40:26 +03002277 XGIfb_mode_no = XGIbios_mode[xgifb_mode_idx].mode_no;
2278
2279 /* yilin set default refresh rate */
Aaro Koskinen7548a832011-10-11 21:47:17 +03002280 xgi_video_info.refresh_rate = refresh_rate;
Aaro Koskinene1521a12011-08-19 22:40:26 +03002281 if (xgi_video_info.refresh_rate == 0)
2282 xgi_video_info.refresh_rate = 60;
2283 if (XGIfb_search_refresh_rate(
2284 xgi_video_info.refresh_rate) == 0) {
2285 XGIfb_rate_idx = XGIbios_mode[xgifb_mode_idx].rate_idx;
2286 xgi_video_info.refresh_rate = 60;
2287 }
2288
2289 xgi_video_info.video_bpp = XGIbios_mode[xgifb_mode_idx].bpp;
2290 xgi_video_info.video_vwidth =
2291 xgi_video_info.video_width =
2292 XGIbios_mode[xgifb_mode_idx].xres;
2293 xgi_video_info.video_vheight =
2294 xgi_video_info.video_height =
2295 XGIbios_mode[xgifb_mode_idx].yres;
2296 xgi_video_info.org_x = xgi_video_info.org_y = 0;
2297 xgi_video_info.video_linelength =
2298 xgi_video_info.video_width *
2299 (xgi_video_info.video_bpp >> 3);
2300 switch (xgi_video_info.video_bpp) {
2301 case 8:
2302 xgi_video_info.DstColor = 0x0000;
2303 xgi_video_info.XGI310_AccelDepth = 0x00000000;
2304 xgi_video_info.video_cmap_len = 256;
2305 break;
2306 case 16:
2307 xgi_video_info.DstColor = 0x8000;
2308 xgi_video_info.XGI310_AccelDepth = 0x00010000;
2309 xgi_video_info.video_cmap_len = 16;
2310 break;
2311 case 32:
2312 xgi_video_info.DstColor = 0xC000;
2313 xgi_video_info.XGI310_AccelDepth = 0x00020000;
2314 xgi_video_info.video_cmap_len = 16;
2315 break;
2316 default:
2317 xgi_video_info.video_cmap_len = 16;
2318 printk(KERN_INFO "XGIfb: Unsupported depth %d",
2319 xgi_video_info.video_bpp);
2320 break;
2321 }
2322
2323 printk(KERN_INFO "XGIfb: Default mode is %dx%dx%d (%dHz)\n",
2324 xgi_video_info.video_width,
2325 xgi_video_info.video_height,
2326 xgi_video_info.video_bpp,
2327 xgi_video_info.refresh_rate);
2328
2329 default_var.xres =
2330 default_var.xres_virtual =
2331 xgi_video_info.video_width;
2332 default_var.yres =
2333 default_var.yres_virtual =
2334 xgi_video_info.video_height;
2335 default_var.bits_per_pixel = xgi_video_info.video_bpp;
2336
2337 XGIfb_bpp_to_var(&default_var);
2338
2339 default_var.pixclock = (u32) (1000000000 /
Aaro Koskinenc62f2e42011-10-11 21:47:15 +03002340 XGIfb_mode_rate_to_dclock(&XGI_Pr, hw_info,
Aaro Koskinene1521a12011-08-19 22:40:26 +03002341 XGIfb_mode_no, XGIfb_rate_idx));
2342
Aaro Koskinenc62f2e42011-10-11 21:47:15 +03002343 if (XGIfb_mode_rate_to_ddata(&XGI_Pr, hw_info,
Aaro Koskinene1521a12011-08-19 22:40:26 +03002344 XGIfb_mode_no, XGIfb_rate_idx,
2345 &default_var.left_margin, &default_var.right_margin,
2346 &default_var.upper_margin, &default_var.lower_margin,
2347 &default_var.hsync_len, &default_var.vsync_len,
2348 &default_var.sync, &default_var.vmode)) {
2349
2350 if ((default_var.vmode & FB_VMODE_MASK) ==
2351 FB_VMODE_INTERLACED) {
2352 default_var.yres <<= 1;
2353 default_var.yres_virtual <<= 1;
2354 } else if ((default_var.vmode & FB_VMODE_MASK) ==
2355 FB_VMODE_DOUBLE) {
2356 default_var.pixclock >>= 1;
2357 default_var.yres >>= 1;
2358 default_var.yres_virtual >>= 1;
2359 }
2360
2361 }
2362
2363 fb_info->flags = FBINFO_FLAG_DEFAULT;
2364 fb_info->var = default_var;
2365 fb_info->fix = XGIfb_fix;
2366 fb_info->par = &xgi_video_info;
2367 fb_info->screen_base = xgi_video_info.video_vbase;
2368 fb_info->fbops = &XGIfb_ops;
2369 XGIfb_get_fix(&fb_info->fix, -1, fb_info);
2370 fb_info->pseudo_palette = pseudo_palette;
2371
2372 fb_alloc_cmap(&fb_info->cmap, 256 , 0);
2373
2374#ifdef CONFIG_MTRR
Aaro Koskinen7c1387e2011-09-11 00:29:55 +03002375 xgi_video_info.mtrr = mtrr_add(xgi_video_info.video_base,
2376 xgi_video_info.video_size, MTRR_TYPE_WRCOMB, 1);
Aaro Koskinen15ebe6c2011-09-11 00:29:54 +03002377 if (xgi_video_info.mtrr >= 0)
2378 dev_info(&pdev->dev, "added MTRR\n");
Aaro Koskinene1521a12011-08-19 22:40:26 +03002379#endif
2380
2381 if (register_framebuffer(fb_info) < 0) {
2382 ret = -EINVAL;
Aaro Koskinen30284742011-09-11 00:29:53 +03002383 goto error_mtrr;
Aaro Koskinene1521a12011-08-19 22:40:26 +03002384 }
2385
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02002386 dumpVGAReg();
2387
2388 return 0;
Aaro Koskinenbb292232011-02-17 23:29:11 +02002389
Aaro Koskinen30284742011-09-11 00:29:53 +03002390error_mtrr:
2391#ifdef CONFIG_MTRR
2392 if (xgi_video_info.mtrr >= 0)
2393 mtrr_del(xgi_video_info.mtrr, xgi_video_info.video_base,
2394 xgi_video_info.video_size);
2395#endif /* CONFIG_MTRR */
Aaro Koskinen5c0ef2a2011-02-17 23:29:15 +02002396error_1:
2397 iounmap(xgi_video_info.mmio_vbase);
2398 iounmap(xgi_video_info.video_vbase);
Aaro Koskinen1b3909e2011-02-17 23:29:17 +02002399 release_mem_region(xgi_video_info.mmio_base, xgi_video_info.mmio_size);
Aaro Koskinen5c0ef2a2011-02-17 23:29:15 +02002400error_0:
2401 release_mem_region(xgi_video_info.video_base,
2402 xgi_video_info.video_size);
Aaro Koskinenbb292232011-02-17 23:29:11 +02002403error:
Aaro Koskinenc62f2e42011-10-11 21:47:15 +03002404 vfree(hw_info->pjVirtualRomBase);
Aaro Koskinenbb292232011-02-17 23:29:11 +02002405 framebuffer_release(fb_info);
2406 return ret;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02002407}
2408
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02002409/*****************************************************/
2410/* PCI DEVICE HANDLING */
2411/*****************************************************/
2412
2413static void __devexit xgifb_remove(struct pci_dev *pdev)
2414{
Aaro Koskinenab886ff2011-10-11 21:47:18 +03002415 struct xgifb_video_info *xgifb_info = pci_get_drvdata(pdev);
Aaro Koskinen19c1e882011-10-11 21:47:14 +03002416 struct fb_info *fb_info = xgifb_info->fb_info;
Aaro Koskinen54301b52011-10-11 21:47:13 +03002417
Prashant P. Shahb654f872010-09-06 17:34:26 +05302418 unregister_framebuffer(fb_info);
Aaro Koskinen30284742011-09-11 00:29:53 +03002419#ifdef CONFIG_MTRR
Aaro Koskinen54301b52011-10-11 21:47:13 +03002420 if (xgifb_info->mtrr >= 0)
2421 mtrr_del(xgifb_info->mtrr, xgifb_info->video_base,
2422 xgifb_info->video_size);
Aaro Koskinen30284742011-09-11 00:29:53 +03002423#endif /* CONFIG_MTRR */
Aaro Koskinen54301b52011-10-11 21:47:13 +03002424 iounmap(xgifb_info->mmio_vbase);
2425 iounmap(xgifb_info->video_vbase);
2426 release_mem_region(xgifb_info->mmio_base, xgifb_info->mmio_size);
2427 release_mem_region(xgifb_info->video_base, xgifb_info->video_size);
Aaro Koskinenc62f2e42011-10-11 21:47:15 +03002428 vfree(xgifb_info->hw_info.pjVirtualRomBase);
Prashant P. Shahb654f872010-09-06 17:34:26 +05302429 framebuffer_release(fb_info);
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02002430 pci_set_drvdata(pdev, NULL);
Aaro Koskinen45dcfaf2011-02-17 23:29:16 +02002431}
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02002432
2433static struct pci_driver xgifb_driver = {
Prashant P. Shahb654f872010-09-06 17:34:26 +05302434 .name = "xgifb",
2435 .id_table = xgifb_pci_table,
2436 .probe = xgifb_probe,
2437 .remove = __devexit_p(xgifb_remove)
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02002438};
2439
Ruslan Pisarev032abf72011-07-21 11:59:11 +03002440static int __init xgifb_init(void)
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02002441{
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02002442 char *option = NULL;
2443
2444 if (fb_get_options("xgifb", &option))
2445 return -ENODEV;
2446 XGIfb_setup(option);
Javier Martinez Canillas328f55b2010-09-08 00:07:57 -04002447
Prashant P. Shahb654f872010-09-06 17:34:26 +05302448 return pci_register_driver(&xgifb_driver);
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02002449}
2450
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02002451module_init(xgifb_init);
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02002452
2453/*****************************************************/
2454/* MODULE */
2455/*****************************************************/
2456
2457#ifdef MODULE
2458
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02002459MODULE_DESCRIPTION("Z7 Z9 Z9S Z11 framebuffer device driver");
2460MODULE_LICENSE("GPL");
2461MODULE_AUTHOR("XGITECH , Others");
2462
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02002463module_param(mode, charp, 0);
2464module_param(vesa, int, 0);
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02002465module_param(filter, int, 0);
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02002466
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02002467MODULE_PARM_DESC(mode,
Aaro Koskinen47c92d52011-08-29 23:14:33 +03002468 "\nSelects the desired default display mode in the format XxYxDepth,\n"
2469 "eg. 1024x768x16.\n");
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02002470
2471MODULE_PARM_DESC(vesa,
Aaro Koskinen47c92d52011-08-29 23:14:33 +03002472 "\nSelects the desired default display mode by VESA mode number, eg.\n"
2473 "0x117.\n");
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02002474
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02002475MODULE_PARM_DESC(filter,
Prashant P. Shahb654f872010-09-06 17:34:26 +05302476 "\nSelects TV flicker filter type (only for systems with a SiS301 video bridge).\n"
2477 "(Possible values 0-7, default: [no filter])\n");
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02002478
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02002479static void __exit xgifb_remove_module(void)
2480{
2481 pci_unregister_driver(&xgifb_driver);
2482 printk(KERN_DEBUG "xgifb: Module unloaded\n");
2483}
2484
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02002485module_exit(xgifb_remove_module);
2486
Prashant P. Shahb654f872010-09-06 17:34:26 +05302487#endif /* /MODULE */