blob: a45a497115edb7d17873f318b41225562993e0b9 [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
Sam Hansen96c66042012-01-22 00:48:25 -08007#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
8
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02009#include <linux/module.h>
apatard@mandriva.comd7636e02010-05-19 10:44:14 +020010
apatard@mandriva.comd7636e02010-05-19 10:44:14 +020011#ifdef CONFIG_MTRR
12#include <asm/mtrr.h>
13#endif
14
apatard@mandriva.comd7636e02010-05-19 10:44:14 +020015#include "XGI_main.h"
Aaro Koskinend542af52011-04-18 22:14:06 +030016#include "vb_init.h"
apatard@mandriva.comd7636e02010-05-19 10:44:14 +020017#include "vb_util.h"
Aaro Koskinend542af52011-04-18 22:14:06 +030018#include "vb_setmode.h"
apatard@mandriva.comd7636e02010-05-19 10:44:14 +020019
apatard@mandriva.comd7636e02010-05-19 10:44:14 +020020#define Index_CR_GPIO_Reg1 0x48
apatard@mandriva.comd7636e02010-05-19 10:44:14 +020021#define Index_CR_GPIO_Reg3 0x4a
22
23#define GPIOG_EN (1<<6)
apatard@mandriva.comd7636e02010-05-19 10:44:14 +020024#define GPIOG_READ (1<<1)
apatard@mandriva.comd7636e02010-05-19 10:44:14 +020025
Aaro Koskinen2d2c8802011-12-06 00:10:49 +020026static char *forcecrt2type;
Aaro Koskinendfbdf802011-08-29 23:14:25 +030027static char *mode;
Aaro Koskinenc3228302011-08-29 23:14:32 +030028static int vesa = -1;
Aaro Koskinen7548a832011-10-11 21:47:17 +030029static unsigned int refresh_rate;
Aaro Koskinendfbdf802011-08-29 23:14:25 +030030
apatard@mandriva.comd7636e02010-05-19 10:44:14 +020031/* -------------------- Macro definitions ---------------------------- */
32
Miguel Gómez96cd1f82012-06-18 13:12:02 +020033#ifdef DEBUG
apatard@mandriva.comd7636e02010-05-19 10:44:14 +020034static void dumpVGAReg(void)
35{
Prashant P. Shahb654f872010-09-06 17:34:26 +053036 u8 i, reg;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +020037
Aaro Koskinenb6e2dc32011-04-18 22:13:59 +030038 xgifb_reg_set(XGISR, 0x05, 0x86);
Prashant P. Shahb654f872010-09-06 17:34:26 +053039 /*
Aaro Koskinenb6e2dc32011-04-18 22:13:59 +030040 xgifb_reg_set(XGISR, 0x08, 0x4f);
41 xgifb_reg_set(XGISR, 0x0f, 0x20);
42 xgifb_reg_set(XGISR, 0x11, 0x4f);
43 xgifb_reg_set(XGISR, 0x13, 0x45);
44 xgifb_reg_set(XGISR, 0x14, 0x51);
45 xgifb_reg_set(XGISR, 0x1e, 0x41);
46 xgifb_reg_set(XGISR, 0x1f, 0x0);
47 xgifb_reg_set(XGISR, 0x20, 0xa1);
48 xgifb_reg_set(XGISR, 0x22, 0xfb);
49 xgifb_reg_set(XGISR, 0x26, 0x22);
50 xgifb_reg_set(XGISR, 0x3e, 0x07);
Prashant P. Shahb654f872010-09-06 17:34:26 +053051 */
apatard@mandriva.comd7636e02010-05-19 10:44:14 +020052
Aaro Koskinenb6e2dc32011-04-18 22:13:59 +030053 /* xgifb_reg_set(XGICR, 0x19, 0x00); */
54 /* xgifb_reg_set(XGICR, 0x1a, 0x3C); */
55 /* xgifb_reg_set(XGICR, 0x22, 0xff); */
56 /* xgifb_reg_set(XGICR, 0x3D, 0x10); */
apatard@mandriva.comd7636e02010-05-19 10:44:14 +020057
Aaro Koskinenb6e2dc32011-04-18 22:13:59 +030058 /* xgifb_reg_set(XGICR, 0x4a, 0xf3); */
apatard@mandriva.comd7636e02010-05-19 10:44:14 +020059
Aaro Koskinenb6e2dc32011-04-18 22:13:59 +030060 /* xgifb_reg_set(XGICR, 0x57, 0x0); */
61 /* xgifb_reg_set(XGICR, 0x7a, 0x2c); */
apatard@mandriva.comd7636e02010-05-19 10:44:14 +020062
Aaro Koskinenb6e2dc32011-04-18 22:13:59 +030063 /* xgifb_reg_set(XGICR, 0x82, 0xcc); */
64 /* xgifb_reg_set(XGICR, 0x8c, 0x0); */
Prashant P. Shahb654f872010-09-06 17:34:26 +053065 /*
Aaro Koskinenb6e2dc32011-04-18 22:13:59 +030066 xgifb_reg_set(XGICR, 0x99, 0x1);
67 xgifb_reg_set(XGICR, 0x41, 0x40);
Prashant P. Shahb654f872010-09-06 17:34:26 +053068 */
apatard@mandriva.comd7636e02010-05-19 10:44:14 +020069
Prashant P. Shahb654f872010-09-06 17:34:26 +053070 for (i = 0; i < 0x4f; i++) {
Aaro Koskinen7e119b72011-04-18 22:13:58 +030071 reg = xgifb_reg_get(XGISR, i);
Prashant P. Shahb654f872010-09-06 17:34:26 +053072 printk("\no 3c4 %x", i);
73 printk("\ni 3c5 => %x", reg);
74 }
apatard@mandriva.comd7636e02010-05-19 10:44:14 +020075
Prashant P. Shahb654f872010-09-06 17:34:26 +053076 for (i = 0; i < 0xF0; i++) {
Aaro Koskinen7e119b72011-04-18 22:13:58 +030077 reg = xgifb_reg_get(XGICR, i);
Prashant P. Shahb654f872010-09-06 17:34:26 +053078 printk("\no 3d4 %x", i);
79 printk("\ni 3d5 => %x", reg);
80 }
81 /*
Aaro Koskinenb6e2dc32011-04-18 22:13:59 +030082 xgifb_reg_set(XGIPART1,0x2F,1);
Prashant P. Shahb654f872010-09-06 17:34:26 +053083 for (i=1; i < 0x50; i++) {
Aaro Koskinen7e119b72011-04-18 22:13:58 +030084 reg = xgifb_reg_get(XGIPART1, i);
Prashant P. Shahb654f872010-09-06 17:34:26 +053085 printk("\no d004 %x", i);
86 printk("\ni d005 => %x", reg);
87 }
apatard@mandriva.comd7636e02010-05-19 10:44:14 +020088
Prashant P. Shahb654f872010-09-06 17:34:26 +053089 for (i=0; i < 0x50; i++) {
Aaro Koskinen7e119b72011-04-18 22:13:58 +030090 reg = xgifb_reg_get(XGIPART2, i);
Prashant P. Shahb654f872010-09-06 17:34:26 +053091 printk("\no d010 %x", i);
92 printk("\ni d011 => %x", reg);
93 }
94 for (i=0; i < 0x50; i++) {
Aaro Koskinen7e119b72011-04-18 22:13:58 +030095 reg = xgifb_reg_get(XGIPART3, i);
Prashant P. Shahb654f872010-09-06 17:34:26 +053096 printk("\no d012 %x",i);
97 printk("\ni d013 => %x",reg);
98 }
99 for (i=0; i < 0x50; i++) {
Aaro Koskinen7e119b72011-04-18 22:13:58 +0300100 reg = xgifb_reg_get(XGIPART4, i);
Prashant P. Shahb654f872010-09-06 17:34:26 +0530101 printk("\no d014 %x",i);
102 printk("\ni d015 => %x",reg);
103 }
104 */
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200105}
106#else
Prashant P. Shahb654f872010-09-06 17:34:26 +0530107static inline void dumpVGAReg(void)
108{
109}
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200110#endif
111
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200112/* --------------- Hardware Access Routines -------------------------- */
113
Prashant P. Shahb654f872010-09-06 17:34:26 +0530114static int XGIfb_mode_rate_to_dclock(struct vb_device_info *XGI_Pr,
115 struct xgi_hw_device_info *HwDeviceExtension,
116 unsigned char modeno, unsigned char rateindex)
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200117{
Prashant P. Shahb654f872010-09-06 17:34:26 +0530118 unsigned short ModeNo = modeno;
119 unsigned short ModeIdIndex = 0, ClockIndex = 0;
120 unsigned short RefreshRateTableIndex = 0;
Prashant P. Shahb654f872010-09-06 17:34:26 +0530121 int Clock;
Prashant P. Shahb654f872010-09-06 17:34:26 +0530122 InitTo330Pointer(HwDeviceExtension->jChipType, XGI_Pr);
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200123
Aaro Koskinenaca03bc2012-04-07 01:13:50 +0300124 XGI_SearchModeID(ModeNo, &ModeIdIndex, XGI_Pr);
125
Prashant P. Shahb654f872010-09-06 17:34:26 +0530126 RefreshRateTableIndex = XGI_GetRatePtrCRT2(HwDeviceExtension, ModeNo,
127 ModeIdIndex, XGI_Pr);
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200128
Prashant P. Shahb654f872010-09-06 17:34:26 +0530129 ClockIndex = XGI_Pr->RefIndex[RefreshRateTableIndex].Ext_CRTVCLK;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200130
Prashant P. Shahb654f872010-09-06 17:34:26 +0530131 Clock = XGI_Pr->VCLKData[ClockIndex].CLOCK * 1000;
132
133 return Clock;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200134}
135
Prashant P. Shahb654f872010-09-06 17:34:26 +0530136static int XGIfb_mode_rate_to_ddata(struct vb_device_info *XGI_Pr,
137 struct xgi_hw_device_info *HwDeviceExtension,
138 unsigned char modeno, unsigned char rateindex,
139 u32 *left_margin, u32 *right_margin, u32 *upper_margin,
140 u32 *lower_margin, u32 *hsync_len, u32 *vsync_len, u32 *sync,
141 u32 *vmode)
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200142{
Prashant P. Shahb654f872010-09-06 17:34:26 +0530143 unsigned short ModeNo = modeno;
Aaro Koskinen051ff1b2012-04-07 01:13:48 +0300144 unsigned short ModeIdIndex, index = 0;
Prashant P. Shahb654f872010-09-06 17:34:26 +0530145 unsigned short RefreshRateTableIndex = 0;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200146
Prashant P. Shahb654f872010-09-06 17:34:26 +0530147 unsigned short VRE, VBE, VRS, VBS, VDE, VT;
148 unsigned short HRE, HBE, HRS, HBS, HDE, HT;
149 unsigned char sr_data, cr_data, cr_data2;
150 unsigned long cr_data3;
151 int A, B, C, D, E, F, temp, j;
Prashant P. Shahb654f872010-09-06 17:34:26 +0530152 InitTo330Pointer(HwDeviceExtension->jChipType, XGI_Pr);
Aaro Koskinen051ff1b2012-04-07 01:13:48 +0300153 if (!XGI_SearchModeID(ModeNo, &ModeIdIndex, XGI_Pr))
154 return 0;
Prashant P. Shahb654f872010-09-06 17:34:26 +0530155 RefreshRateTableIndex = XGI_GetRatePtrCRT2(HwDeviceExtension, ModeNo,
156 ModeIdIndex, XGI_Pr);
Prashant P. Shahb654f872010-09-06 17:34:26 +0530157 index = XGI_Pr->RefIndex[RefreshRateTableIndex].Ext_CRT1CRTC;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200158
Prashant P. Shahb654f872010-09-06 17:34:26 +0530159 sr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[5];
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200160
Prashant P. Shahb654f872010-09-06 17:34:26 +0530161 cr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[0];
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200162
Prashant P. Shahb654f872010-09-06 17:34:26 +0530163 /* Horizontal total */
164 HT = (cr_data & 0xff) | ((unsigned short) (sr_data & 0x03) << 8);
165 A = HT + 5;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200166
Prashant P. Shahb654f872010-09-06 17:34:26 +0530167 HDE = (XGI_Pr->RefIndex[RefreshRateTableIndex].XRes >> 3) - 1;
168 E = HDE + 1;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200169
Prashant P. Shahb654f872010-09-06 17:34:26 +0530170 cr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[3];
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200171
Prashant P. Shahb654f872010-09-06 17:34:26 +0530172 /* Horizontal retrace (=sync) start */
173 HRS = (cr_data & 0xff) | ((unsigned short) (sr_data & 0xC0) << 2);
174 F = HRS - E - 3;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200175
Prashant P. Shahb654f872010-09-06 17:34:26 +0530176 cr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[1];
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200177
Prashant P. Shahb654f872010-09-06 17:34:26 +0530178 /* Horizontal blank start */
179 HBS = (cr_data & 0xff) | ((unsigned short) (sr_data & 0x30) << 4);
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200180
Prashant P. Shahb654f872010-09-06 17:34:26 +0530181 sr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[6];
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200182
Prashant P. Shahb654f872010-09-06 17:34:26 +0530183 cr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[2];
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200184
Prashant P. Shahb654f872010-09-06 17:34:26 +0530185 cr_data2 = XGI_Pr->XGINEWUB_CRT1Table[index].CR[4];
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200186
Prashant P. Shahb654f872010-09-06 17:34:26 +0530187 /* Horizontal blank end */
188 HBE = (cr_data & 0x1f) | ((unsigned short) (cr_data2 & 0x80) >> 2)
189 | ((unsigned short) (sr_data & 0x03) << 6);
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200190
Prashant P. Shahb654f872010-09-06 17:34:26 +0530191 /* Horizontal retrace (=sync) end */
192 HRE = (cr_data2 & 0x1f) | ((sr_data & 0x04) << 3);
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200193
Prashant P. Shahb654f872010-09-06 17:34:26 +0530194 temp = HBE - ((E - 1) & 255);
195 B = (temp > 0) ? temp : (temp + 256);
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200196
Prashant P. Shahb654f872010-09-06 17:34:26 +0530197 temp = HRE - ((E + F + 3) & 63);
198 C = (temp > 0) ? temp : (temp + 64);
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200199
Prashant P. Shahb654f872010-09-06 17:34:26 +0530200 D = B - F - C;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200201
Prashant P. Shahb654f872010-09-06 17:34:26 +0530202 *left_margin = D * 8;
203 *right_margin = F * 8;
204 *hsync_len = C * 8;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200205
Prashant P. Shahb654f872010-09-06 17:34:26 +0530206 sr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[14];
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200207
Prashant P. Shahb654f872010-09-06 17:34:26 +0530208 cr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[8];
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200209
Prashant P. Shahb654f872010-09-06 17:34:26 +0530210 cr_data2 = XGI_Pr->XGINEWUB_CRT1Table[index].CR[9];
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200211
Prashant P. Shahb654f872010-09-06 17:34:26 +0530212 /* Vertical total */
213 VT = (cr_data & 0xFF) | ((unsigned short) (cr_data2 & 0x01) << 8)
214 | ((unsigned short) (cr_data2 & 0x20) << 4)
215 | ((unsigned short) (sr_data & 0x01) << 10);
216 A = VT + 2;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200217
Prashant P. Shahb654f872010-09-06 17:34:26 +0530218 /* cr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[10]; */
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200219
Prashant P. Shahb654f872010-09-06 17:34:26 +0530220 /* Vertical display enable end */
221 /*
222 VDE = (cr_data & 0xff) |
223 ((unsigned short) (cr_data2 & 0x02) << 7) |
224 ((unsigned short) (cr_data2 & 0x40) << 3) |
225 ((unsigned short) (sr_data & 0x02) << 9);
226 */
227 VDE = XGI_Pr->RefIndex[RefreshRateTableIndex].YRes - 1;
228 E = VDE + 1;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200229
Prashant P. Shahb654f872010-09-06 17:34:26 +0530230 cr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[10];
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200231
Prashant P. Shahb654f872010-09-06 17:34:26 +0530232 /* Vertical retrace (=sync) start */
233 VRS = (cr_data & 0xff) | ((unsigned short) (cr_data2 & 0x04) << 6)
234 | ((unsigned short) (cr_data2 & 0x80) << 2)
235 | ((unsigned short) (sr_data & 0x08) << 7);
236 F = VRS + 1 - E;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200237
Prashant P. Shahb654f872010-09-06 17:34:26 +0530238 cr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[12];
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200239
Prashant P. Shahb654f872010-09-06 17:34:26 +0530240 cr_data3 = (XGI_Pr->XGINEWUB_CRT1Table[index].CR[14] & 0x80) << 5;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200241
Prashant P. Shahb654f872010-09-06 17:34:26 +0530242 /* Vertical blank start */
243 VBS = (cr_data & 0xff) | ((unsigned short) (cr_data2 & 0x08) << 5)
244 | ((unsigned short) (cr_data3 & 0x20) << 4)
245 | ((unsigned short) (sr_data & 0x04) << 8);
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200246
Prashant P. Shahb654f872010-09-06 17:34:26 +0530247 cr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[13];
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200248
Prashant P. Shahb654f872010-09-06 17:34:26 +0530249 /* Vertical blank end */
250 VBE = (cr_data & 0xff) | ((unsigned short) (sr_data & 0x10) << 4);
251 temp = VBE - ((E - 1) & 511);
252 B = (temp > 0) ? temp : (temp + 512);
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200253
Prashant P. Shahb654f872010-09-06 17:34:26 +0530254 cr_data = XGI_Pr->XGINEWUB_CRT1Table[index].CR[11];
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200255
Prashant P. Shahb654f872010-09-06 17:34:26 +0530256 /* Vertical retrace (=sync) end */
257 VRE = (cr_data & 0x0f) | ((sr_data & 0x20) >> 1);
258 temp = VRE - ((E + F - 1) & 31);
259 C = (temp > 0) ? temp : (temp + 32);
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200260
Prashant P. Shahb654f872010-09-06 17:34:26 +0530261 D = B - F - C;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200262
Prashant P. Shahb654f872010-09-06 17:34:26 +0530263 *upper_margin = D;
264 *lower_margin = F;
265 *vsync_len = C;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200266
Prashant P. Shahb654f872010-09-06 17:34:26 +0530267 if (XGI_Pr->RefIndex[RefreshRateTableIndex].Ext_InfoFlag & 0x8000)
268 *sync &= ~FB_SYNC_VERT_HIGH_ACT;
269 else
270 *sync |= FB_SYNC_VERT_HIGH_ACT;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200271
Prashant P. Shahb654f872010-09-06 17:34:26 +0530272 if (XGI_Pr->RefIndex[RefreshRateTableIndex].Ext_InfoFlag & 0x4000)
273 *sync &= ~FB_SYNC_HOR_HIGH_ACT;
274 else
275 *sync |= FB_SYNC_HOR_HIGH_ACT;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200276
Prashant P. Shahb654f872010-09-06 17:34:26 +0530277 *vmode = FB_VMODE_NONINTERLACED;
278 if (XGI_Pr->RefIndex[RefreshRateTableIndex].Ext_InfoFlag & 0x0080)
279 *vmode = FB_VMODE_INTERLACED;
280 else {
281 j = 0;
282 while (XGI_Pr->EModeIDTable[j].Ext_ModeID != 0xff) {
Kenji Toyamaa12c27c2011-04-26 12:13:43 +0800283 if (XGI_Pr->EModeIDTable[j].Ext_ModeID ==
284 XGI_Pr->RefIndex[RefreshRateTableIndex].ModeID) {
285 if (XGI_Pr->EModeIDTable[j].Ext_ModeFlag &
286 DoubleScanMode) {
Prashant P. Shahb654f872010-09-06 17:34:26 +0530287 *vmode = FB_VMODE_DOUBLE;
288 }
289 break;
290 }
291 j++;
292 }
293 }
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200294
Prashant P. Shahb654f872010-09-06 17:34:26 +0530295 return 1;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200296}
297
Randy Dunlap89229672010-08-10 08:46:44 -0700298static void XGIRegInit(struct vb_device_info *XGI_Pr, unsigned long BaseAddr)
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200299{
Prashant P. Shahb654f872010-09-06 17:34:26 +0530300 XGI_Pr->P3c4 = BaseAddr + 0x14;
301 XGI_Pr->P3d4 = BaseAddr + 0x24;
302 XGI_Pr->P3c0 = BaseAddr + 0x10;
303 XGI_Pr->P3ce = BaseAddr + 0x1e;
304 XGI_Pr->P3c2 = BaseAddr + 0x12;
305 XGI_Pr->P3ca = BaseAddr + 0x1a;
306 XGI_Pr->P3c6 = BaseAddr + 0x16;
307 XGI_Pr->P3c7 = BaseAddr + 0x17;
308 XGI_Pr->P3c8 = BaseAddr + 0x18;
309 XGI_Pr->P3c9 = BaseAddr + 0x19;
310 XGI_Pr->P3da = BaseAddr + 0x2A;
Kenji Toyamaa12c27c2011-04-26 12:13:43 +0800311 /* Digital video interface registers (LCD) */
Peter Huewe6896b942012-02-09 21:11:46 +0100312 XGI_Pr->Part1Port = BaseAddr + SIS_CRT2_PORT_04;
Kenji Toyamaa12c27c2011-04-26 12:13:43 +0800313 /* 301 TV Encoder registers */
Peter Huewe6896b942012-02-09 21:11:46 +0100314 XGI_Pr->Part2Port = BaseAddr + SIS_CRT2_PORT_10;
Kenji Toyamaa12c27c2011-04-26 12:13:43 +0800315 /* 301 Macrovision registers */
Peter Huewe6896b942012-02-09 21:11:46 +0100316 XGI_Pr->Part3Port = BaseAddr + SIS_CRT2_PORT_12;
Kenji Toyamaa12c27c2011-04-26 12:13:43 +0800317 /* 301 VGA2 (and LCD) registers */
Peter Huewe6896b942012-02-09 21:11:46 +0100318 XGI_Pr->Part4Port = BaseAddr + SIS_CRT2_PORT_14;
Kenji Toyamaa12c27c2011-04-26 12:13:43 +0800319 /* 301 palette address port registers */
Peter Huewe6896b942012-02-09 21:11:46 +0100320 XGI_Pr->Part5Port = BaseAddr + SIS_CRT2_PORT_14 + 2;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200321
322}
323
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200324/* ------------------ Internal helper routines ----------------- */
325
Aaro Koskinenfab04b92011-12-06 00:10:45 +0200326static int XGIfb_GetXG21DefaultLVDSModeIdx(struct xgifb_video_info *xgifb_info)
Aaro Koskinenc4fa7df2011-04-18 22:14:05 +0300327{
328
329 int found_mode = 0;
330 int XGIfb_mode_idx = 0;
331
332 found_mode = 0;
333 while ((XGIbios_mode[XGIfb_mode_idx].mode_no != 0)
334 && (XGIbios_mode[XGIfb_mode_idx].xres
Aaro Koskinenfab04b92011-12-06 00:10:45 +0200335 <= xgifb_info->lvds_data.LVDSHDE)) {
Aaro Koskinenc4fa7df2011-04-18 22:14:05 +0300336 if ((XGIbios_mode[XGIfb_mode_idx].xres
Aaro Koskinenfab04b92011-12-06 00:10:45 +0200337 == xgifb_info->lvds_data.LVDSHDE)
Aaro Koskinenc4fa7df2011-04-18 22:14:05 +0300338 && (XGIbios_mode[XGIfb_mode_idx].yres
Aaro Koskinenfab04b92011-12-06 00:10:45 +0200339 == xgifb_info->lvds_data.LVDSVDE)
Aaro Koskinenc4fa7df2011-04-18 22:14:05 +0300340 && (XGIbios_mode[XGIfb_mode_idx].bpp == 8)) {
Aaro Koskinenc4fa7df2011-04-18 22:14:05 +0300341 found_mode = 1;
342 break;
343 }
344 XGIfb_mode_idx++;
345 }
346 if (!found_mode)
Aaro Koskinende736db2011-08-29 23:14:29 +0300347 XGIfb_mode_idx = -1;
Aaro Koskinenc4fa7df2011-04-18 22:14:05 +0300348
349 return XGIfb_mode_idx;
350}
351
Aaro Koskinenccf265a2011-10-11 21:47:22 +0300352static void XGIfb_search_mode(struct xgifb_video_info *xgifb_info,
353 const char *name)
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200354{
Aaro Koskinenf9e5de02012-04-07 01:13:55 +0300355 unsigned int xres;
356 unsigned int yres;
357 unsigned int bpp;
358 int i;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200359
Aaro Koskinenf9e5de02012-04-07 01:13:55 +0300360 if (sscanf(name, "%ux%ux%u", &xres, &yres, &bpp) != 3)
361 goto invalid_mode;
362
363 if (bpp == 24)
364 bpp = 32; /* That's for people who mix up color and fb depth. */
365
366 for (i = 0; XGIbios_mode[i].mode_no != 0; i++)
367 if (XGIbios_mode[i].xres == xres &&
368 XGIbios_mode[i].yres == yres &&
369 XGIbios_mode[i].bpp == bpp) {
Aaro Koskinenccf265a2011-10-11 21:47:22 +0300370 xgifb_info->mode_idx = i;
Aaro Koskinenf9e5de02012-04-07 01:13:55 +0300371 return;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200372 }
Aaro Koskinenf9e5de02012-04-07 01:13:55 +0300373invalid_mode:
374 pr_info("Invalid mode '%s'\n", name);
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200375}
376
Aaro Koskinenccf265a2011-10-11 21:47:22 +0300377static void XGIfb_search_vesamode(struct xgifb_video_info *xgifb_info,
378 unsigned int vesamode)
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200379{
380 int i = 0, j = 0;
381
Aaro Koskinenc3228302011-08-29 23:14:32 +0300382 if (vesamode == 0)
383 goto invalid;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200384
Prashant P. Shahb654f872010-09-06 17:34:26 +0530385 vesamode &= 0x1dff; /* Clean VESA mode number from other flags */
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200386
Prashant P. Shahb654f872010-09-06 17:34:26 +0530387 while (XGIbios_mode[i].mode_no != 0) {
Kenji Toyamaa12c27c2011-04-26 12:13:43 +0800388 if ((XGIbios_mode[i].vesa_mode_no_1 == vesamode) ||
389 (XGIbios_mode[i].vesa_mode_no_2 == vesamode)) {
Aaro Koskinenccf265a2011-10-11 21:47:22 +0300390 xgifb_info->mode_idx = i;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200391 j = 1;
392 break;
393 }
394 i++;
395 }
Aaro Koskinenc3228302011-08-29 23:14:32 +0300396
397invalid:
Prashant P. Shahb654f872010-09-06 17:34:26 +0530398 if (!j)
Sam Hansen4a6b1512012-01-22 16:48:53 -0800399 pr_info("Invalid VESA mode 0x%x'\n", vesamode);
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200400}
401
Aaro Koskinenfd26d422011-10-11 21:47:19 +0300402static int XGIfb_validate_mode(struct xgifb_video_info *xgifb_info, int myindex)
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200403{
Prashant P. Shahb654f872010-09-06 17:34:26 +0530404 u16 xres, yres;
Aaro Koskinenfd26d422011-10-11 21:47:19 +0300405 struct xgi_hw_device_info *hw_info = &xgifb_info->hw_info;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200406
Aaro Koskinenfd26d422011-10-11 21:47:19 +0300407 if (xgifb_info->chip == XG21) {
Aaro Koskinen289ea522011-10-11 21:47:37 +0300408 if (xgifb_info->display2 == XGIFB_DISP_LCD) {
Aaro Koskinenfab04b92011-12-06 00:10:45 +0200409 xres = xgifb_info->lvds_data.LVDSHDE;
410 yres = xgifb_info->lvds_data.LVDSVDE;
Prashant P. Shahb654f872010-09-06 17:34:26 +0530411 if (XGIbios_mode[myindex].xres > xres)
412 return -1;
413 if (XGIbios_mode[myindex].yres > yres)
414 return -1;
Kenji Toyamaa12c27c2011-04-26 12:13:43 +0800415 if ((XGIbios_mode[myindex].xres < xres) &&
416 (XGIbios_mode[myindex].yres < yres)) {
Prashant P. Shahb654f872010-09-06 17:34:26 +0530417 if (XGIbios_mode[myindex].bpp > 8)
418 return -1;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200419 }
Prashant P. Shahb654f872010-09-06 17:34:26 +0530420
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200421 }
Prashant P. Shahb654f872010-09-06 17:34:26 +0530422 return myindex;
423
424 }
425
426 /* FIXME: for now, all is valid on XG27 */
Aaro Koskinenfd26d422011-10-11 21:47:19 +0300427 if (xgifb_info->chip == XG27)
Prashant P. Shahb654f872010-09-06 17:34:26 +0530428 return myindex;
429
430 if (!(XGIbios_mode[myindex].chipset & MD_XGI315))
431 return -1;
432
Aaro Koskinen289ea522011-10-11 21:47:37 +0300433 switch (xgifb_info->display2) {
434 case XGIFB_DISP_LCD:
Aaro Koskinenc62f2e42011-10-11 21:47:15 +0300435 switch (hw_info->ulCRT2LCDType) {
Prashant P. Shahb654f872010-09-06 17:34:26 +0530436 case LCD_640x480:
437 xres = 640;
438 yres = 480;
439 break;
440 case LCD_800x600:
441 xres = 800;
442 yres = 600;
443 break;
444 case LCD_1024x600:
445 xres = 1024;
446 yres = 600;
447 break;
448 case LCD_1024x768:
449 xres = 1024;
450 yres = 768;
451 break;
452 case LCD_1152x768:
453 xres = 1152;
454 yres = 768;
455 break;
456 case LCD_1280x960:
457 xres = 1280;
458 yres = 960;
459 break;
460 case LCD_1280x768:
461 xres = 1280;
462 yres = 768;
463 break;
464 case LCD_1280x1024:
465 xres = 1280;
466 yres = 1024;
467 break;
468 case LCD_1400x1050:
469 xres = 1400;
470 yres = 1050;
471 break;
472 case LCD_1600x1200:
473 xres = 1600;
474 yres = 1200;
475 break;
Prashant P. Shahb654f872010-09-06 17:34:26 +0530476 default:
477 xres = 0;
478 yres = 0;
479 break;
480 }
481 if (XGIbios_mode[myindex].xres > xres)
482 return -1;
483 if (XGIbios_mode[myindex].yres > yres)
484 return -1;
Aaro Koskinenc62f2e42011-10-11 21:47:15 +0300485 if ((hw_info->ulExternalChip == 0x01) || /* LVDS */
486 (hw_info->ulExternalChip == 0x05)) { /* LVDS+Chrontel */
Prashant P. Shahb654f872010-09-06 17:34:26 +0530487 switch (XGIbios_mode[myindex].xres) {
488 case 512:
489 if (XGIbios_mode[myindex].yres != 512)
490 return -1;
Aaro Koskinenc62f2e42011-10-11 21:47:15 +0300491 if (hw_info->ulCRT2LCDType == LCD_1024x600)
Prashant P. Shahb654f872010-09-06 17:34:26 +0530492 return -1;
493 break;
494 case 640:
495 if ((XGIbios_mode[myindex].yres != 400)
496 && (XGIbios_mode[myindex].yres
497 != 480))
498 return -1;
499 break;
500 case 800:
501 if (XGIbios_mode[myindex].yres != 600)
502 return -1;
503 break;
504 case 1024:
Kenji Toyamaa12c27c2011-04-26 12:13:43 +0800505 if ((XGIbios_mode[myindex].yres != 600) &&
506 (XGIbios_mode[myindex].yres != 768))
Prashant P. Shahb654f872010-09-06 17:34:26 +0530507 return -1;
Kenji Toyamaa12c27c2011-04-26 12:13:43 +0800508 if ((XGIbios_mode[myindex].yres == 600) &&
Aaro Koskinenc62f2e42011-10-11 21:47:15 +0300509 (hw_info->ulCRT2LCDType != LCD_1024x600))
Prashant P. Shahb654f872010-09-06 17:34:26 +0530510 return -1;
511 break;
512 case 1152:
513 if ((XGIbios_mode[myindex].yres) != 768)
514 return -1;
Aaro Koskinenc62f2e42011-10-11 21:47:15 +0300515 if (hw_info->ulCRT2LCDType != LCD_1152x768)
Prashant P. Shahb654f872010-09-06 17:34:26 +0530516 return -1;
517 break;
518 case 1280:
Kenji Toyamaa12c27c2011-04-26 12:13:43 +0800519 if ((XGIbios_mode[myindex].yres != 768) &&
520 (XGIbios_mode[myindex].yres != 1024))
Prashant P. Shahb654f872010-09-06 17:34:26 +0530521 return -1;
Kenji Toyamaa12c27c2011-04-26 12:13:43 +0800522 if ((XGIbios_mode[myindex].yres == 768) &&
Aaro Koskinenc62f2e42011-10-11 21:47:15 +0300523 (hw_info->ulCRT2LCDType != LCD_1280x768))
Prashant P. Shahb654f872010-09-06 17:34:26 +0530524 return -1;
525 break;
526 case 1400:
527 if (XGIbios_mode[myindex].yres != 1050)
528 return -1;
529 break;
530 case 1600:
531 if (XGIbios_mode[myindex].yres != 1200)
532 return -1;
533 break;
534 default:
535 return -1;
536 }
537 } else {
538 switch (XGIbios_mode[myindex].xres) {
539 case 512:
540 if (XGIbios_mode[myindex].yres != 512)
541 return -1;
542 break;
543 case 640:
Kenji Toyamaa12c27c2011-04-26 12:13:43 +0800544 if ((XGIbios_mode[myindex].yres != 400) &&
545 (XGIbios_mode[myindex].yres != 480))
Prashant P. Shahb654f872010-09-06 17:34:26 +0530546 return -1;
547 break;
548 case 800:
549 if (XGIbios_mode[myindex].yres != 600)
550 return -1;
551 break;
552 case 1024:
553 if (XGIbios_mode[myindex].yres != 768)
554 return -1;
555 break;
556 case 1280:
Kenji Toyamaa12c27c2011-04-26 12:13:43 +0800557 if ((XGIbios_mode[myindex].yres != 960) &&
558 (XGIbios_mode[myindex].yres != 1024))
Prashant P. Shahb654f872010-09-06 17:34:26 +0530559 return -1;
560 if (XGIbios_mode[myindex].yres == 960) {
Aaro Koskinenc62f2e42011-10-11 21:47:15 +0300561 if (hw_info->ulCRT2LCDType ==
Kenji Toyamaa12c27c2011-04-26 12:13:43 +0800562 LCD_1400x1050)
Prashant P. Shahb654f872010-09-06 17:34:26 +0530563 return -1;
564 }
565 break;
566 case 1400:
567 if (XGIbios_mode[myindex].yres != 1050)
568 return -1;
569 break;
570 case 1600:
571 if (XGIbios_mode[myindex].yres != 1200)
572 return -1;
573 break;
574 default:
575 return -1;
576 }
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200577 }
578 break;
Aaro Koskinen289ea522011-10-11 21:47:37 +0300579 case XGIFB_DISP_TV:
Prashant P. Shahb654f872010-09-06 17:34:26 +0530580 switch (XGIbios_mode[myindex].xres) {
581 case 512:
582 case 640:
583 case 800:
584 break;
585 case 720:
Aaro Koskinenfd26d422011-10-11 21:47:19 +0300586 if (xgifb_info->TV_type == TVMODE_NTSC) {
Prashant P. Shahb654f872010-09-06 17:34:26 +0530587 if (XGIbios_mode[myindex].yres != 480)
588 return -1;
Aaro Koskinenfd26d422011-10-11 21:47:19 +0300589 } else if (xgifb_info->TV_type == TVMODE_PAL) {
Prashant P. Shahb654f872010-09-06 17:34:26 +0530590 if (XGIbios_mode[myindex].yres != 576)
591 return -1;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200592 }
Prashant P. Shahb654f872010-09-06 17:34:26 +0530593 /* TW: LVDS/CHRONTEL does not support 720 */
Aaro Koskinenfd26d422011-10-11 21:47:19 +0300594 if (xgifb_info->hasVB == HASVB_LVDS_CHRONTEL ||
595 xgifb_info->hasVB == HASVB_CHRONTEL) {
Prashant P. Shahb654f872010-09-06 17:34:26 +0530596 return -1;
597 }
598 break;
599 case 1024:
Aaro Koskinenfd26d422011-10-11 21:47:19 +0300600 if (xgifb_info->TV_type == TVMODE_NTSC) {
Prashant P. Shahb654f872010-09-06 17:34:26 +0530601 if (XGIbios_mode[myindex].bpp == 32)
602 return -1;
603 }
Prashant P. Shahb654f872010-09-06 17:34:26 +0530604 break;
605 default:
606 return -1;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200607 }
608 break;
Aaro Koskinen289ea522011-10-11 21:47:37 +0300609 case XGIFB_DISP_CRT:
Prashant P. Shahb654f872010-09-06 17:34:26 +0530610 if (XGIbios_mode[myindex].xres > 1280)
611 return -1;
612 break;
Aaro Koskinen289ea522011-10-11 21:47:37 +0300613 case XGIFB_DISP_NONE:
614 break;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200615 }
Prashant P. Shahb654f872010-09-06 17:34:26 +0530616 return myindex;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200617
618}
619
620static void XGIfb_search_crt2type(const char *name)
621{
622 int i = 0;
623
Prashant P. Shahb654f872010-09-06 17:34:26 +0530624 if (name == NULL)
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200625 return;
626
Prashant P. Shahb654f872010-09-06 17:34:26 +0530627 while (XGI_crt2type[i].type_no != -1) {
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200628 if (!strcmp(name, XGI_crt2type[i].name)) {
629 XGIfb_crt2type = XGI_crt2type[i].type_no;
630 XGIfb_tvplug = XGI_crt2type[i].tvplug_no;
631 break;
632 }
633 i++;
634 }
Prashant P. Shahb654f872010-09-06 17:34:26 +0530635 if (XGIfb_crt2type < 0)
Sam Hansen4a6b1512012-01-22 16:48:53 -0800636 pr_info("Invalid CRT2 type: %s\n", name);
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200637}
638
Aaro Koskinenfd26d422011-10-11 21:47:19 +0300639static u8 XGIfb_search_refresh_rate(struct xgifb_video_info *xgifb_info,
640 unsigned int rate)
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200641{
642 u16 xres, yres;
643 int i = 0;
644
Aaro Koskinenccf265a2011-10-11 21:47:22 +0300645 xres = XGIbios_mode[xgifb_info->mode_idx].xres;
646 yres = XGIbios_mode[xgifb_info->mode_idx].yres;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200647
Aaro Koskinen5aa55d92011-10-11 21:47:23 +0300648 xgifb_info->rate_idx = 0;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200649 while ((XGIfb_vrate[i].idx != 0) && (XGIfb_vrate[i].xres <= xres)) {
Kenji Toyamaa12c27c2011-04-26 12:13:43 +0800650 if ((XGIfb_vrate[i].xres == xres) &&
651 (XGIfb_vrate[i].yres == yres)) {
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200652 if (XGIfb_vrate[i].refresh == rate) {
Aaro Koskinen5aa55d92011-10-11 21:47:23 +0300653 xgifb_info->rate_idx = XGIfb_vrate[i].idx;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200654 break;
655 } else if (XGIfb_vrate[i].refresh > rate) {
656 if ((XGIfb_vrate[i].refresh - rate) <= 3) {
Miguel Gómezd56b4c32012-06-18 13:12:01 +0200657 pr_debug("XGIfb: Adjusting rate from %d up to %d\n",
658 rate, XGIfb_vrate[i].refresh);
Aaro Koskinen5aa55d92011-10-11 21:47:23 +0300659 xgifb_info->rate_idx =
660 XGIfb_vrate[i].idx;
Aaro Koskinenfd26d422011-10-11 21:47:19 +0300661 xgifb_info->refresh_rate =
Kenji Toyamaa12c27c2011-04-26 12:13:43 +0800662 XGIfb_vrate[i].refresh;
Prashant P. Shahb654f872010-09-06 17:34:26 +0530663 } else if (((rate - XGIfb_vrate[i - 1].refresh)
664 <= 2) && (XGIfb_vrate[i].idx
665 != 1)) {
Miguel Gómezd56b4c32012-06-18 13:12:01 +0200666 pr_debug("XGIfb: Adjusting rate from %d down to %d\n",
667 rate, XGIfb_vrate[i-1].refresh);
Aaro Koskinen5aa55d92011-10-11 21:47:23 +0300668 xgifb_info->rate_idx =
669 XGIfb_vrate[i - 1].idx;
Aaro Koskinenfd26d422011-10-11 21:47:19 +0300670 xgifb_info->refresh_rate =
Kenji Toyamaa12c27c2011-04-26 12:13:43 +0800671 XGIfb_vrate[i - 1].refresh;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200672 }
673 break;
Prashant P. Shahb654f872010-09-06 17:34:26 +0530674 } else if ((rate - XGIfb_vrate[i].refresh) <= 2) {
Miguel Gómezd56b4c32012-06-18 13:12:01 +0200675 pr_debug("XGIfb: Adjusting rate from %d down to %d\n",
676 rate, XGIfb_vrate[i].refresh);
Aaro Koskinen5aa55d92011-10-11 21:47:23 +0300677 xgifb_info->rate_idx = XGIfb_vrate[i].idx;
Prashant P. Shahb654f872010-09-06 17:34:26 +0530678 break;
679 }
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200680 }
681 i++;
682 }
Aaro Koskinen5aa55d92011-10-11 21:47:23 +0300683 if (xgifb_info->rate_idx > 0) {
684 return xgifb_info->rate_idx;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200685 } else {
Sam Hansen4a6b1512012-01-22 16:48:53 -0800686 pr_info("Unsupported rate %d for %dx%d\n",
Kenji Toyamaa12c27c2011-04-26 12:13:43 +0800687 rate, xres, yres);
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200688 return 0;
689 }
690}
691
692static void XGIfb_search_tvstd(const char *name)
693{
694 int i = 0;
695
Prashant P. Shahb654f872010-09-06 17:34:26 +0530696 if (name == NULL)
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200697 return;
698
699 while (XGI_tvtype[i].type_no != -1) {
700 if (!strcmp(name, XGI_tvtype[i].name)) {
701 XGIfb_tvmode = XGI_tvtype[i].type_no;
702 break;
703 }
704 i++;
705 }
706}
707
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200708/* ----------- FBDev related routines for all series ----------- */
709
Aaro Koskinenfd26d422011-10-11 21:47:19 +0300710static void XGIfb_bpp_to_var(struct xgifb_video_info *xgifb_info,
711 struct fb_var_screeninfo *var)
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200712{
Prashant P. Shahb654f872010-09-06 17:34:26 +0530713 switch (var->bits_per_pixel) {
714 case 8:
715 var->red.offset = var->green.offset = var->blue.offset = 0;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200716 var->red.length = var->green.length = var->blue.length = 6;
Aaro Koskinenfd26d422011-10-11 21:47:19 +0300717 xgifb_info->video_cmap_len = 256;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200718 break;
Prashant P. Shahb654f872010-09-06 17:34:26 +0530719 case 16:
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200720 var->red.offset = 11;
721 var->red.length = 5;
722 var->green.offset = 5;
723 var->green.length = 6;
724 var->blue.offset = 0;
725 var->blue.length = 5;
726 var->transp.offset = 0;
727 var->transp.length = 0;
Aaro Koskinenfd26d422011-10-11 21:47:19 +0300728 xgifb_info->video_cmap_len = 16;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200729 break;
Prashant P. Shahb654f872010-09-06 17:34:26 +0530730 case 32:
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200731 var->red.offset = 16;
732 var->red.length = 8;
733 var->green.offset = 8;
734 var->green.length = 8;
735 var->blue.offset = 0;
736 var->blue.length = 8;
737 var->transp.offset = 24;
738 var->transp.length = 8;
Aaro Koskinenfd26d422011-10-11 21:47:19 +0300739 xgifb_info->video_cmap_len = 16;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +0200740 break;
741 }
742}
743
Aaro Koskinenc4fa7df2011-04-18 22:14:05 +0300744/* --------------------- SetMode routines ------------------------- */
745
Aaro Koskinenfd26d422011-10-11 21:47:19 +0300746static void XGIfb_pre_setmode(struct xgifb_video_info *xgifb_info)
Aaro Koskinenc4fa7df2011-04-18 22:14:05 +0300747{
748 u8 cr30 = 0, cr31 = 0;
749
750 cr31 = xgifb_reg_get(XGICR, 0x31);
751 cr31 &= ~0x60;
752
Aaro Koskinen289ea522011-10-11 21:47:37 +0300753 switch (xgifb_info->display2) {
754 case XGIFB_DISP_CRT:
Peter Huewefc39dcb2012-01-15 19:22:12 +0100755 cr30 = (SIS_VB_OUTPUT_CRT2 | SIS_SIMULTANEOUS_VIEW_ENABLE);
756 cr31 |= SIS_DRIVER_MODE;
Aaro Koskinenc4fa7df2011-04-18 22:14:05 +0300757 break;
Aaro Koskinen289ea522011-10-11 21:47:37 +0300758 case XGIFB_DISP_LCD:
Peter Huewefc39dcb2012-01-15 19:22:12 +0100759 cr30 = (SIS_VB_OUTPUT_LCD | SIS_SIMULTANEOUS_VIEW_ENABLE);
760 cr31 |= SIS_DRIVER_MODE;
Aaro Koskinenc4fa7df2011-04-18 22:14:05 +0300761 break;
Aaro Koskinen289ea522011-10-11 21:47:37 +0300762 case XGIFB_DISP_TV:
Aaro Koskinenfd26d422011-10-11 21:47:19 +0300763 if (xgifb_info->TV_type == TVMODE_HIVISION)
Peter Huewefc39dcb2012-01-15 19:22:12 +0100764 cr30 = (SIS_VB_OUTPUT_HIVISION
765 | SIS_SIMULTANEOUS_VIEW_ENABLE);
Aaro Koskinenfd26d422011-10-11 21:47:19 +0300766 else if (xgifb_info->TV_plug == TVPLUG_SVIDEO)
Peter Huewefc39dcb2012-01-15 19:22:12 +0100767 cr30 = (SIS_VB_OUTPUT_SVIDEO
768 | SIS_SIMULTANEOUS_VIEW_ENABLE);
Aaro Koskinenfd26d422011-10-11 21:47:19 +0300769 else if (xgifb_info->TV_plug == TVPLUG_COMPOSITE)
Peter Huewefc39dcb2012-01-15 19:22:12 +0100770 cr30 = (SIS_VB_OUTPUT_COMPOSITE
771 | SIS_SIMULTANEOUS_VIEW_ENABLE);
Aaro Koskinenfd26d422011-10-11 21:47:19 +0300772 else if (xgifb_info->TV_plug == TVPLUG_SCART)
Peter Huewefc39dcb2012-01-15 19:22:12 +0100773 cr30 = (SIS_VB_OUTPUT_SCART
774 | SIS_SIMULTANEOUS_VIEW_ENABLE);
775 cr31 |= SIS_DRIVER_MODE;
Aaro Koskinenc4fa7df2011-04-18 22:14:05 +0300776
Aaro Koskinenfd26d422011-10-11 21:47:19 +0300777 if (XGIfb_tvmode == 1 || xgifb_info->TV_type == TVMODE_PAL)
Aaro Koskinenc4fa7df2011-04-18 22:14:05 +0300778 cr31 |= 0x01;
779 else
780 cr31 &= ~0x01;
781 break;
782 default: /* disable CRT2 */
783 cr30 = 0x00;
Peter Huewefc39dcb2012-01-15 19:22:12 +0100784 cr31 |= (SIS_DRIVER_MODE | SIS_VB_OUTPUT_DISABLE);
Aaro Koskinenc4fa7df2011-04-18 22:14:05 +0300785 }
786
787 xgifb_reg_set(XGICR, IND_XGI_SCRATCH_REG_CR30, cr30);
788 xgifb_reg_set(XGICR, IND_XGI_SCRATCH_REG_CR31, cr31);
Aaro Koskinen5aa55d92011-10-11 21:47:23 +0300789 xgifb_reg_set(XGICR, IND_XGI_SCRATCH_REG_CR33,
790 (xgifb_info->rate_idx & 0x0F));
Aaro Koskinenc4fa7df2011-04-18 22:14:05 +0300791}
792
Aaro Koskinenfd26d422011-10-11 21:47:19 +0300793static void XGIfb_post_setmode(struct xgifb_video_info *xgifb_info)
Aaro Koskinenc4fa7df2011-04-18 22:14:05 +0300794{
795 u8 reg;
796 unsigned char doit = 1;
797 /*
Peter Huewefc39dcb2012-01-15 19:22:12 +0100798 xgifb_reg_set(XGISR,IND_SIS_PASSWORD,SIS_PASSWORD);
Aaro Koskinenc4fa7df2011-04-18 22:14:05 +0300799 xgifb_reg_set(XGICR, 0x13, 0x00);
800 xgifb_reg_and_or(XGISR,0x0E, 0xF0, 0x01);
801 *test*
802 */
Aaro Koskinenfd26d422011-10-11 21:47:19 +0300803 if (xgifb_info->video_bpp == 8) {
Kenji Toyamaa12c27c2011-04-26 12:13:43 +0800804 /* TW: We can't switch off CRT1 on LVDS/Chrontel
805 * in 8bpp Modes */
Aaro Koskinenfd26d422011-10-11 21:47:19 +0300806 if ((xgifb_info->hasVB == HASVB_LVDS) ||
807 (xgifb_info->hasVB == HASVB_LVDS_CHRONTEL)) {
Aaro Koskinenc4fa7df2011-04-18 22:14:05 +0300808 doit = 0;
809 }
Kenji Toyamaa12c27c2011-04-26 12:13:43 +0800810 /* TW: We can't switch off CRT1 on 301B-DH
811 * in 8bpp Modes if using LCD */
Aaro Koskinen289ea522011-10-11 21:47:37 +0300812 if (xgifb_info->display2 == XGIFB_DISP_LCD)
Aaro Koskinenc4fa7df2011-04-18 22:14:05 +0300813 doit = 0;
814 }
815
816 /* TW: We can't switch off CRT1 if bridge is in slave mode */
Aaro Koskinenfd26d422011-10-11 21:47:19 +0300817 if (xgifb_info->hasVB != HASVB_NONE) {
Aaro Koskinenc4fa7df2011-04-18 22:14:05 +0300818 reg = xgifb_reg_get(XGIPART1, 0x00);
819
820 if ((reg & 0x50) == 0x10)
821 doit = 0;
822
823 } else {
824 XGIfb_crt1off = 0;
825 }
826
827 reg = xgifb_reg_get(XGICR, 0x17);
828 if ((XGIfb_crt1off) && (doit))
829 reg &= ~0x80;
830 else
831 reg |= 0x80;
832 xgifb_reg_set(XGICR, 0x17, reg);
833
Peter Huewefc39dcb2012-01-15 19:22:12 +0100834 xgifb_reg_and(XGISR, IND_SIS_RAMDAC_CONTROL, ~0x04);
Aaro Koskinenc4fa7df2011-04-18 22:14:05 +0300835
Aaro Koskinen289ea522011-10-11 21:47:37 +0300836 if (xgifb_info->display2 == XGIFB_DISP_TV &&
837 xgifb_info->hasVB == HASVB_301) {
Aaro Koskinenc4fa7df2011-04-18 22:14:05 +0300838
839 reg = xgifb_reg_get(XGIPART4, 0x01);
840
841 if (reg < 0xB0) { /* Set filter for XGI301 */
Aaro Koskinen84a6c462011-10-11 21:47:28 +0300842 int filter_tb;
843
Aaro Koskinenfd26d422011-10-11 21:47:19 +0300844 switch (xgifb_info->video_width) {
Aaro Koskinenc4fa7df2011-04-18 22:14:05 +0300845 case 320:
Aaro Koskinenfd26d422011-10-11 21:47:19 +0300846 filter_tb = (xgifb_info->TV_type ==
Kenji Toyamaa12c27c2011-04-26 12:13:43 +0800847 TVMODE_NTSC) ? 4 : 12;
Aaro Koskinenc4fa7df2011-04-18 22:14:05 +0300848 break;
849 case 640:
Aaro Koskinenfd26d422011-10-11 21:47:19 +0300850 filter_tb = (xgifb_info->TV_type ==
Kenji Toyamaa12c27c2011-04-26 12:13:43 +0800851 TVMODE_NTSC) ? 5 : 13;
Aaro Koskinenc4fa7df2011-04-18 22:14:05 +0300852 break;
853 case 720:
Aaro Koskinenfd26d422011-10-11 21:47:19 +0300854 filter_tb = (xgifb_info->TV_type ==
Kenji Toyamaa12c27c2011-04-26 12:13:43 +0800855 TVMODE_NTSC) ? 6 : 14;
Aaro Koskinenc4fa7df2011-04-18 22:14:05 +0300856 break;
857 case 800:
Aaro Koskinenfd26d422011-10-11 21:47:19 +0300858 filter_tb = (xgifb_info->TV_type ==
Kenji Toyamaa12c27c2011-04-26 12:13:43 +0800859 TVMODE_NTSC) ? 7 : 15;
Aaro Koskinenc4fa7df2011-04-18 22:14:05 +0300860 break;
861 default:
Aaro Koskinen84a6c462011-10-11 21:47:28 +0300862 filter_tb = 0;
Aaro Koskinenc4fa7df2011-04-18 22:14:05 +0300863 filter = -1;
864 break;
865 }
Aaro Koskinen39f10bf2011-10-11 21:47:25 +0300866 xgifb_reg_or(XGIPART1,
Peter Huewefc39dcb2012-01-15 19:22:12 +0100867 SIS_CRT2_WENABLE_315,
Aaro Koskinen39f10bf2011-10-11 21:47:25 +0300868 0x01);
Aaro Koskinenc4fa7df2011-04-18 22:14:05 +0300869
Aaro Koskinenfd26d422011-10-11 21:47:19 +0300870 if (xgifb_info->TV_type == TVMODE_NTSC) {
Aaro Koskinenc4fa7df2011-04-18 22:14:05 +0300871
872 xgifb_reg_and(XGIPART2, 0x3a, 0x1f);
873
Aaro Koskinenfd26d422011-10-11 21:47:19 +0300874 if (xgifb_info->TV_plug == TVPLUG_SVIDEO) {
Aaro Koskinenc4fa7df2011-04-18 22:14:05 +0300875
876 xgifb_reg_and(XGIPART2, 0x30, 0xdf);
877
Aaro Koskinenfd26d422011-10-11 21:47:19 +0300878 } else if (xgifb_info->TV_plug
Aaro Koskinenc4fa7df2011-04-18 22:14:05 +0300879 == TVPLUG_COMPOSITE) {
880
881 xgifb_reg_or(XGIPART2, 0x30, 0x20);
882
Aaro Koskinenfd26d422011-10-11 21:47:19 +0300883 switch (xgifb_info->video_width) {
Aaro Koskinenc4fa7df2011-04-18 22:14:05 +0300884 case 640:
Kenji Toyamaa12c27c2011-04-26 12:13:43 +0800885 xgifb_reg_set(XGIPART2,
886 0x35,
887 0xEB);
888 xgifb_reg_set(XGIPART2,
889 0x36,
890 0x04);
891 xgifb_reg_set(XGIPART2,
892 0x37,
893 0x25);
894 xgifb_reg_set(XGIPART2,
895 0x38,
896 0x18);
Aaro Koskinenc4fa7df2011-04-18 22:14:05 +0300897 break;
898 case 720:
Kenji Toyamaa12c27c2011-04-26 12:13:43 +0800899 xgifb_reg_set(XGIPART2,
900 0x35,
901 0xEE);
902 xgifb_reg_set(XGIPART2,
903 0x36,
904 0x0C);
905 xgifb_reg_set(XGIPART2,
906 0x37,
907 0x22);
908 xgifb_reg_set(XGIPART2,
909 0x38,
910 0x08);
Aaro Koskinenc4fa7df2011-04-18 22:14:05 +0300911 break;
912 case 800:
Kenji Toyamaa12c27c2011-04-26 12:13:43 +0800913 xgifb_reg_set(XGIPART2,
914 0x35,
915 0xEB);
916 xgifb_reg_set(XGIPART2,
917 0x36,
918 0x15);
919 xgifb_reg_set(XGIPART2,
920 0x37,
921 0x25);
922 xgifb_reg_set(XGIPART2,
923 0x38,
924 0xF6);
Aaro Koskinenc4fa7df2011-04-18 22:14:05 +0300925 break;
926 }
927 }
928
Aaro Koskinenfd26d422011-10-11 21:47:19 +0300929 } else if (xgifb_info->TV_type == TVMODE_PAL) {
Aaro Koskinenc4fa7df2011-04-18 22:14:05 +0300930
931 xgifb_reg_and(XGIPART2, 0x3A, 0x1F);
932
Aaro Koskinenfd26d422011-10-11 21:47:19 +0300933 if (xgifb_info->TV_plug == TVPLUG_SVIDEO) {
Aaro Koskinenc4fa7df2011-04-18 22:14:05 +0300934
935 xgifb_reg_and(XGIPART2, 0x30, 0xDF);
936
Aaro Koskinenfd26d422011-10-11 21:47:19 +0300937 } else if (xgifb_info->TV_plug
Aaro Koskinenc4fa7df2011-04-18 22:14:05 +0300938 == TVPLUG_COMPOSITE) {
939
940 xgifb_reg_or(XGIPART2, 0x30, 0x20);
941
Aaro Koskinenfd26d422011-10-11 21:47:19 +0300942 switch (xgifb_info->video_width) {
Aaro Koskinenc4fa7df2011-04-18 22:14:05 +0300943 case 640:
Kenji Toyamaa12c27c2011-04-26 12:13:43 +0800944 xgifb_reg_set(XGIPART2,
945 0x35,
946 0xF1);
947 xgifb_reg_set(XGIPART2,
948 0x36,
949 0xF7);
950 xgifb_reg_set(XGIPART2,
951 0x37,
952 0x1F);
953 xgifb_reg_set(XGIPART2,
954 0x38,
955 0x32);
Aaro Koskinenc4fa7df2011-04-18 22:14:05 +0300956 break;
957 case 720:
Kenji Toyamaa12c27c2011-04-26 12:13:43 +0800958 xgifb_reg_set(XGIPART2,
959 0x35,
960 0xF3);
961 xgifb_reg_set(XGIPART2,
962 0x36,
963 0x00);
964 xgifb_reg_set(XGIPART2,
965 0x37,
966 0x1D);
967 xgifb_reg_set(XGIPART2,
968 0x38,
969 0x20);
Aaro Koskinenc4fa7df2011-04-18 22:14:05 +0300970 break;
971 case 800:
Kenji Toyamaa12c27c2011-04-26 12:13:43 +0800972 xgifb_reg_set(XGIPART2,
973 0x35,
974 0xFC);
975 xgifb_reg_set(XGIPART2,
976 0x36,
977 0xFB);
978 xgifb_reg_set(XGIPART2,
979 0x37,
980 0x14);
981 xgifb_reg_set(XGIPART2,
982 0x38,
983 0x2A);
Aaro Koskinenc4fa7df2011-04-18 22:14:05 +0300984 break;
985 }
986 }
987 }
988
989 if ((filter >= 0) && (filter <= 7)) {
Miguel Gómezd56b4c32012-06-18 13:12:01 +0200990 pr_debug("FilterTable[%d]-%d: %02x %02x %02x %02x\n",
991 filter_tb, filter,
992 XGI_TV_filter[filter_tb].
Kenji Toyamaa12c27c2011-04-26 12:13:43 +0800993 filter[filter][0],
Miguel Gómezd56b4c32012-06-18 13:12:01 +0200994 XGI_TV_filter[filter_tb].
Kenji Toyamaa12c27c2011-04-26 12:13:43 +0800995 filter[filter][1],
Miguel Gómezd56b4c32012-06-18 13:12:01 +0200996 XGI_TV_filter[filter_tb].
Kenji Toyamaa12c27c2011-04-26 12:13:43 +0800997 filter[filter][2],
Miguel Gómezd56b4c32012-06-18 13:12:01 +0200998 XGI_TV_filter[filter_tb].
Kenji Toyamaa12c27c2011-04-26 12:13:43 +0800999 filter[filter][3]
Aaro Koskinenc4fa7df2011-04-18 22:14:05 +03001000 );
1001 xgifb_reg_set(
Kenji Toyamaa12c27c2011-04-26 12:13:43 +08001002 XGIPART2,
1003 0x35,
1004 (XGI_TV_filter[filter_tb].
1005 filter[filter][0]));
Aaro Koskinenc4fa7df2011-04-18 22:14:05 +03001006 xgifb_reg_set(
Kenji Toyamaa12c27c2011-04-26 12:13:43 +08001007 XGIPART2,
1008 0x36,
1009 (XGI_TV_filter[filter_tb].
1010 filter[filter][1]));
Aaro Koskinenc4fa7df2011-04-18 22:14:05 +03001011 xgifb_reg_set(
Kenji Toyamaa12c27c2011-04-26 12:13:43 +08001012 XGIPART2,
1013 0x37,
1014 (XGI_TV_filter[filter_tb].
1015 filter[filter][2]));
Aaro Koskinenc4fa7df2011-04-18 22:14:05 +03001016 xgifb_reg_set(
Kenji Toyamaa12c27c2011-04-26 12:13:43 +08001017 XGIPART2,
1018 0x38,
1019 (XGI_TV_filter[filter_tb].
1020 filter[filter][3]));
Aaro Koskinenc4fa7df2011-04-18 22:14:05 +03001021 }
Aaro Koskinenc4fa7df2011-04-18 22:14:05 +03001022 }
Aaro Koskinenc4fa7df2011-04-18 22:14:05 +03001023 }
Aaro Koskinenc4fa7df2011-04-18 22:14:05 +03001024}
1025
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001026static int XGIfb_do_set_var(struct fb_var_screeninfo *var, int isactive,
Prashant P. Shahb654f872010-09-06 17:34:26 +05301027 struct fb_info *info)
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001028{
Aaro Koskinenfd26d422011-10-11 21:47:19 +03001029 struct xgifb_video_info *xgifb_info = info->par;
1030 struct xgi_hw_device_info *hw_info = &xgifb_info->hw_info;
Prashant P. Shahb654f872010-09-06 17:34:26 +05301031 unsigned int htotal = var->left_margin + var->xres + var->right_margin
1032 + var->hsync_len;
1033 unsigned int vtotal = var->upper_margin + var->yres + var->lower_margin
1034 + var->vsync_len;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001035#if defined(__powerpc__)
Dmitry Eremin-Solenikovef23b212012-03-19 21:50:11 +04001036 u8 cr_data;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001037#endif
1038 unsigned int drate = 0, hrate = 0;
1039 int found_mode = 0;
1040 int old_mode;
Prashant P. Shahb654f872010-09-06 17:34:26 +05301041 /* unsigned char reg, reg1; */
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001042
Prashant P. Shahb654f872010-09-06 17:34:26 +05301043 /* 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 +02001044
Prashant P. Shahb654f872010-09-06 17:34:26 +05301045 info->var.xres_virtual = var->xres_virtual;
1046 info->var.yres_virtual = var->yres_virtual;
1047 info->var.bits_per_pixel = var->bits_per_pixel;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001048
1049 if ((var->vmode & FB_VMODE_MASK) == FB_VMODE_NONINTERLACED)
1050 vtotal <<= 1;
1051 else if ((var->vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE)
1052 vtotal <<= 2;
Prashant P. Shahb654f872010-09-06 17:34:26 +05301053 else if ((var->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) {
1054 /* vtotal <<= 1; */
1055 /* var->yres <<= 1; */
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001056 }
1057
Prashant P. Shahb654f872010-09-06 17:34:26 +05301058 if (!htotal || !vtotal) {
Miguel Gómezd56b4c32012-06-18 13:12:01 +02001059 pr_debug("XGIfb: Invalid 'var' information\n");
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001060 return -EINVAL;
Sam Hansen4a6b1512012-01-22 16:48:53 -08001061 } pr_debug("var->pixclock=%d, htotal=%d, vtotal=%d\n",
Prashant P. Shahb654f872010-09-06 17:34:26 +05301062 var->pixclock, htotal, vtotal);
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001063
Prashant P. Shahb654f872010-09-06 17:34:26 +05301064 if (var->pixclock && htotal && vtotal) {
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001065 drate = 1000000000 / var->pixclock;
1066 hrate = (drate * 1000) / htotal;
Aaro Koskinenfd26d422011-10-11 21:47:19 +03001067 xgifb_info->refresh_rate = (unsigned int) (hrate * 2
Prashant P. Shahb654f872010-09-06 17:34:26 +05301068 / vtotal);
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001069 } else {
Aaro Koskinenfd26d422011-10-11 21:47:19 +03001070 xgifb_info->refresh_rate = 60;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001071 }
1072
Sam Hansen4a6b1512012-01-22 16:48:53 -08001073 pr_debug("Change mode to %dx%dx%d-%dHz\n",
Kenji Toyamaa12c27c2011-04-26 12:13:43 +08001074 var->xres,
1075 var->yres,
1076 var->bits_per_pixel,
Aaro Koskinenfd26d422011-10-11 21:47:19 +03001077 xgifb_info->refresh_rate);
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001078
Aaro Koskinenccf265a2011-10-11 21:47:22 +03001079 old_mode = xgifb_info->mode_idx;
1080 xgifb_info->mode_idx = 0;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001081
Aaro Koskinenccf265a2011-10-11 21:47:22 +03001082 while ((XGIbios_mode[xgifb_info->mode_idx].mode_no != 0) &&
1083 (XGIbios_mode[xgifb_info->mode_idx].xres <= var->xres)) {
1084 if ((XGIbios_mode[xgifb_info->mode_idx].xres == var->xres) &&
1085 (XGIbios_mode[xgifb_info->mode_idx].yres == var->yres) &&
1086 (XGIbios_mode[xgifb_info->mode_idx].bpp
Prashant P. Shahb654f872010-09-06 17:34:26 +05301087 == var->bits_per_pixel)) {
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001088 found_mode = 1;
1089 break;
1090 }
Aaro Koskinenccf265a2011-10-11 21:47:22 +03001091 xgifb_info->mode_idx++;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001092 }
1093
Prashant P. Shahb654f872010-09-06 17:34:26 +05301094 if (found_mode)
Aaro Koskinenccf265a2011-10-11 21:47:22 +03001095 xgifb_info->mode_idx = XGIfb_validate_mode(xgifb_info,
1096 xgifb_info->mode_idx);
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001097 else
Aaro Koskinenccf265a2011-10-11 21:47:22 +03001098 xgifb_info->mode_idx = -1;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001099
Aaro Koskinenccf265a2011-10-11 21:47:22 +03001100 if (xgifb_info->mode_idx < 0) {
Sam Hansen4a6b1512012-01-22 16:48:53 -08001101 pr_err("Mode %dx%dx%d not supported\n",
Kenji Toyamaa12c27c2011-04-26 12:13:43 +08001102 var->xres, var->yres, var->bits_per_pixel);
Aaro Koskinenccf265a2011-10-11 21:47:22 +03001103 xgifb_info->mode_idx = old_mode;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001104 return -EINVAL;
1105 }
1106
Aaro Koskinenfd26d422011-10-11 21:47:19 +03001107 if (XGIfb_search_refresh_rate(xgifb_info,
1108 xgifb_info->refresh_rate) == 0) {
Aaro Koskinenf47f12d2012-04-07 01:13:54 +03001109 xgifb_info->rate_idx = 1;
Aaro Koskinenfd26d422011-10-11 21:47:19 +03001110 xgifb_info->refresh_rate = 60;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001111 }
1112
Prashant P. Shahb654f872010-09-06 17:34:26 +05301113 if (isactive) {
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001114
Aaro Koskinenfd26d422011-10-11 21:47:19 +03001115 XGIfb_pre_setmode(xgifb_info);
Aaro Koskinenfab04b92011-12-06 00:10:45 +02001116 if (XGISetModeNew(xgifb_info, hw_info,
Aaro Koskinenccf265a2011-10-11 21:47:22 +03001117 XGIbios_mode[xgifb_info->mode_idx].mode_no)
1118 == 0) {
Sam Hansen4a6b1512012-01-22 16:48:53 -08001119 pr_err("Setting mode[0x%x] failed\n",
Aaro Koskinenccf265a2011-10-11 21:47:22 +03001120 XGIbios_mode[xgifb_info->mode_idx].mode_no);
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001121 return -EINVAL;
1122 }
Prashant P. Shahb654f872010-09-06 17:34:26 +05301123 info->fix.line_length = ((info->var.xres_virtual
1124 * info->var.bits_per_pixel) >> 6);
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001125
Peter Huewefc39dcb2012-01-15 19:22:12 +01001126 xgifb_reg_set(XGISR, IND_SIS_PASSWORD, SIS_PASSWORD);
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001127
Aaro Koskinenb6e2dc32011-04-18 22:13:59 +03001128 xgifb_reg_set(XGICR, 0x13, (info->fix.line_length & 0x00ff));
Kenji Toyamaa12c27c2011-04-26 12:13:43 +08001129 xgifb_reg_set(XGISR,
1130 0x0E,
1131 (info->fix.line_length & 0xff00) >> 8);
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001132
Aaro Koskinenfd26d422011-10-11 21:47:19 +03001133 XGIfb_post_setmode(xgifb_info);
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001134
Miguel Gómezd56b4c32012-06-18 13:12:01 +02001135 pr_debug("XGIfb: Set new mode: %dx%dx%d-%d\n",
1136 XGIbios_mode[xgifb_info->mode_idx].xres,
1137 XGIbios_mode[xgifb_info->mode_idx].yres,
1138 XGIbios_mode[xgifb_info->mode_idx].bpp,
1139 xgifb_info->refresh_rate);
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001140
Aaro Koskinenccf265a2011-10-11 21:47:22 +03001141 xgifb_info->video_bpp = XGIbios_mode[xgifb_info->mode_idx].bpp;
Aaro Koskinenfd26d422011-10-11 21:47:19 +03001142 xgifb_info->video_vwidth = info->var.xres_virtual;
Aaro Koskinenccf265a2011-10-11 21:47:22 +03001143 xgifb_info->video_width =
1144 XGIbios_mode[xgifb_info->mode_idx].xres;
Aaro Koskinenfd26d422011-10-11 21:47:19 +03001145 xgifb_info->video_vheight = info->var.yres_virtual;
Aaro Koskinenccf265a2011-10-11 21:47:22 +03001146 xgifb_info->video_height =
1147 XGIbios_mode[xgifb_info->mode_idx].yres;
Aaro Koskinenfd26d422011-10-11 21:47:19 +03001148 xgifb_info->org_x = xgifb_info->org_y = 0;
1149 xgifb_info->video_linelength = info->var.xres_virtual
1150 * (xgifb_info->video_bpp >> 3);
1151 switch (xgifb_info->video_bpp) {
Prashant P. Shahb654f872010-09-06 17:34:26 +05301152 case 8:
Aaro Koskinenfd26d422011-10-11 21:47:19 +03001153 xgifb_info->DstColor = 0x0000;
1154 xgifb_info->XGI310_AccelDepth = 0x00000000;
1155 xgifb_info->video_cmap_len = 256;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001156#if defined(__powerpc__)
Aaro Koskinen7e119b72011-04-18 22:13:58 +03001157 cr_data = xgifb_reg_get(XGICR, 0x4D);
Aaro Koskinenb6e2dc32011-04-18 22:13:59 +03001158 xgifb_reg_set(XGICR, 0x4D, (cr_data & 0xE0));
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001159#endif
Prashant P. Shahb654f872010-09-06 17:34:26 +05301160 break;
1161 case 16:
Aaro Koskinenfd26d422011-10-11 21:47:19 +03001162 xgifb_info->DstColor = 0x8000;
1163 xgifb_info->XGI310_AccelDepth = 0x00010000;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001164#if defined(__powerpc__)
Aaro Koskinen7e119b72011-04-18 22:13:58 +03001165 cr_data = xgifb_reg_get(XGICR, 0x4D);
Aaro Koskinenb6e2dc32011-04-18 22:13:59 +03001166 xgifb_reg_set(XGICR, 0x4D, ((cr_data & 0xE0) | 0x0B));
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001167#endif
Aaro Koskinenfd26d422011-10-11 21:47:19 +03001168 xgifb_info->video_cmap_len = 16;
Prashant P. Shahb654f872010-09-06 17:34:26 +05301169 break;
1170 case 32:
Aaro Koskinenfd26d422011-10-11 21:47:19 +03001171 xgifb_info->DstColor = 0xC000;
1172 xgifb_info->XGI310_AccelDepth = 0x00020000;
1173 xgifb_info->video_cmap_len = 16;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001174#if defined(__powerpc__)
Aaro Koskinen7e119b72011-04-18 22:13:58 +03001175 cr_data = xgifb_reg_get(XGICR, 0x4D);
Aaro Koskinenb6e2dc32011-04-18 22:13:59 +03001176 xgifb_reg_set(XGICR, 0x4D, ((cr_data & 0xE0) | 0x15));
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001177#endif
Prashant P. Shahb654f872010-09-06 17:34:26 +05301178 break;
1179 default:
Aaro Koskinenfd26d422011-10-11 21:47:19 +03001180 xgifb_info->video_cmap_len = 16;
Sam Hansen4a6b1512012-01-22 16:48:53 -08001181 pr_err("Unsupported depth %d",
Aaro Koskinenfd26d422011-10-11 21:47:19 +03001182 xgifb_info->video_bpp);
Prashant P. Shahb654f872010-09-06 17:34:26 +05301183 break;
1184 }
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001185 }
Aaro Koskinenfd26d422011-10-11 21:47:19 +03001186 XGIfb_bpp_to_var(xgifb_info, var); /*update ARGB info*/
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001187
1188 dumpVGAReg();
1189 return 0;
1190}
1191
Laurent Pinchart0d5c6ca2011-05-25 11:34:52 +02001192static int XGIfb_pan_var(struct fb_var_screeninfo *var, struct fb_info *info)
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001193{
Linus Torvaldsacff9872011-10-30 15:30:01 -07001194 struct xgifb_video_info *xgifb_info = info->par;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001195 unsigned int base;
1196
Prashant P. Shahb654f872010-09-06 17:34:26 +05301197 /* printk("Inside pan_var"); */
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001198
Laurent Pinchart0d5c6ca2011-05-25 11:34:52 +02001199 base = var->yoffset * info->var.xres_virtual + var->xoffset;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001200
Prashant P. Shahb654f872010-09-06 17:34:26 +05301201 /* calculate base bpp dep. */
Laurent Pinchart0d5c6ca2011-05-25 11:34:52 +02001202 switch (info->var.bits_per_pixel) {
Prashant P. Shahb654f872010-09-06 17:34:26 +05301203 case 16:
1204 base >>= 1;
1205 break;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001206 case 32:
Prashant P. Shahb654f872010-09-06 17:34:26 +05301207 break;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001208 case 8:
Prashant P. Shahb654f872010-09-06 17:34:26 +05301209 default:
1210 base >>= 2;
1211 break;
1212 }
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001213
Peter Huewefc39dcb2012-01-15 19:22:12 +01001214 xgifb_reg_set(XGISR, IND_SIS_PASSWORD, SIS_PASSWORD);
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001215
Aaro Koskinenb6e2dc32011-04-18 22:13:59 +03001216 xgifb_reg_set(XGICR, 0x0D, base & 0xFF);
1217 xgifb_reg_set(XGICR, 0x0C, (base >> 8) & 0xFF);
1218 xgifb_reg_set(XGISR, 0x0D, (base >> 16) & 0xFF);
1219 xgifb_reg_set(XGISR, 0x37, (base >> 24) & 0x03);
Aaro Koskinen65283d42011-04-18 22:14:02 +03001220 xgifb_reg_and_or(XGISR, 0x37, 0xDF, (base >> 21) & 0x04);
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001221
Aaro Koskinen289ea522011-10-11 21:47:37 +03001222 if (xgifb_info->display2 != XGIFB_DISP_NONE) {
Peter Huewefc39dcb2012-01-15 19:22:12 +01001223 xgifb_reg_or(XGIPART1, SIS_CRT2_WENABLE_315, 0x01);
Aaro Koskinenb6e2dc32011-04-18 22:13:59 +03001224 xgifb_reg_set(XGIPART1, 0x06, (base & 0xFF));
1225 xgifb_reg_set(XGIPART1, 0x05, ((base >> 8) & 0xFF));
1226 xgifb_reg_set(XGIPART1, 0x04, ((base >> 16) & 0xFF));
Kenji Toyamaa12c27c2011-04-26 12:13:43 +08001227 xgifb_reg_and_or(XGIPART1,
1228 0x02,
1229 0x7F,
1230 ((base >> 24) & 0x01) << 7);
Prashant P. Shahb654f872010-09-06 17:34:26 +05301231 }
1232 /* printk("End of pan_var"); */
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001233 return 0;
1234}
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001235
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001236static int XGIfb_open(struct fb_info *info, int user)
1237{
Prashant P. Shahb654f872010-09-06 17:34:26 +05301238 return 0;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001239}
1240
1241static int XGIfb_release(struct fb_info *info, int user)
1242{
Prashant P. Shahb654f872010-09-06 17:34:26 +05301243 return 0;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001244}
1245
1246static int XGIfb_get_cmap_len(const struct fb_var_screeninfo *var)
1247{
1248 int rc = 16;
1249
Prashant P. Shahb654f872010-09-06 17:34:26 +05301250 switch (var->bits_per_pixel) {
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001251 case 8:
1252 rc = 256;
1253 break;
1254 case 16:
1255 rc = 16;
1256 break;
1257 case 32:
1258 rc = 16;
1259 break;
1260 }
1261 return rc;
1262}
1263
Prashant P. Shahb654f872010-09-06 17:34:26 +05301264static int XGIfb_setcolreg(unsigned regno, unsigned red, unsigned green,
1265 unsigned blue, unsigned transp, struct fb_info *info)
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001266{
Aaro Koskinenfd26d422011-10-11 21:47:19 +03001267 struct xgifb_video_info *xgifb_info = info->par;
1268
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001269 if (regno >= XGIfb_get_cmap_len(&info->var))
1270 return 1;
1271
1272 switch (info->var.bits_per_pixel) {
1273 case 8:
Aaro Koskinene3d5ceb2011-04-18 22:13:57 +03001274 outb(regno, XGIDACA);
1275 outb((red >> 10), XGIDACD);
1276 outb((green >> 10), XGIDACD);
1277 outb((blue >> 10), XGIDACD);
Aaro Koskinen289ea522011-10-11 21:47:37 +03001278 if (xgifb_info->display2 != XGIFB_DISP_NONE) {
Aaro Koskinene3d5ceb2011-04-18 22:13:57 +03001279 outb(regno, XGIDAC2A);
1280 outb((red >> 8), XGIDAC2D);
1281 outb((green >> 8), XGIDAC2D);
1282 outb((blue >> 8), XGIDAC2D);
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001283 }
1284 break;
1285 case 16:
Prashant P. Shahb654f872010-09-06 17:34:26 +05301286 ((u32 *) (info->pseudo_palette))[regno] = ((red & 0xf800))
1287 | ((green & 0xfc00) >> 5) | ((blue & 0xf800)
1288 >> 11);
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001289 break;
1290 case 32:
1291 red >>= 8;
1292 green >>= 8;
1293 blue >>= 8;
Prashant P. Shahb654f872010-09-06 17:34:26 +05301294 ((u32 *) (info->pseudo_palette))[regno] = (red << 16) | (green
1295 << 8) | (blue);
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001296 break;
1297 }
1298 return 0;
1299}
1300
Aaro Koskinenc4fa7df2011-04-18 22:14:05 +03001301/* ----------- FBDev related routines for all series ---------- */
1302
1303static int XGIfb_get_fix(struct fb_fix_screeninfo *fix, int con,
1304 struct fb_info *info)
1305{
Aaro Koskinenfd26d422011-10-11 21:47:19 +03001306 struct xgifb_video_info *xgifb_info = info->par;
1307
Aaro Koskinenc4fa7df2011-04-18 22:14:05 +03001308 memset(fix, 0, sizeof(struct fb_fix_screeninfo));
1309
Peter Huewe176f7842012-06-14 00:21:39 +02001310 strncpy(fix->id, "XGI", sizeof(fix->id) - 1);
1311
Peter Huewe95649c42012-06-14 00:21:40 +02001312 /* if register_framebuffer has been called, we must lock */
1313 if (atomic_read(&info->count))
1314 mutex_lock(&info->mm_lock);
Aaro Koskinenc4fa7df2011-04-18 22:14:05 +03001315
Peter Huewe95649c42012-06-14 00:21:40 +02001316 fix->smem_start = xgifb_info->video_base;
Aaro Koskinenfd26d422011-10-11 21:47:19 +03001317 fix->smem_len = xgifb_info->video_size;
Aaro Koskinenc4fa7df2011-04-18 22:14:05 +03001318
Peter Huewe95649c42012-06-14 00:21:40 +02001319 /* if register_framebuffer has been called, we can unlock */
1320 if (atomic_read(&info->count))
1321 mutex_unlock(&info->mm_lock);
1322
Aaro Koskinende351ba2011-08-19 22:40:27 +03001323 fix->type = FB_TYPE_PACKED_PIXELS;
Aaro Koskinenc4fa7df2011-04-18 22:14:05 +03001324 fix->type_aux = 0;
Aaro Koskinenfd26d422011-10-11 21:47:19 +03001325 if (xgifb_info->video_bpp == 8)
Aaro Koskinenc4fa7df2011-04-18 22:14:05 +03001326 fix->visual = FB_VISUAL_PSEUDOCOLOR;
1327 else
1328 fix->visual = FB_VISUAL_DIRECTCOLOR;
1329 fix->xpanstep = 0;
Aaro Koskinenc4fa7df2011-04-18 22:14:05 +03001330 if (XGIfb_ypan)
1331 fix->ypanstep = 1;
Aaro Koskinenc4fa7df2011-04-18 22:14:05 +03001332 fix->ywrapstep = 0;
Aaro Koskinenfd26d422011-10-11 21:47:19 +03001333 fix->line_length = xgifb_info->video_linelength;
1334 fix->mmio_start = xgifb_info->mmio_base;
1335 fix->mmio_len = xgifb_info->mmio_size;
Peter Huewefc39dcb2012-01-15 19:22:12 +01001336 fix->accel = FB_ACCEL_SIS_XABRE;
Aaro Koskinenc4fa7df2011-04-18 22:14:05 +03001337
Aaro Koskinenc4fa7df2011-04-18 22:14:05 +03001338 return 0;
1339}
1340
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001341static int XGIfb_set_par(struct fb_info *info)
1342{
1343 int err;
1344
Prashant P. Shahb654f872010-09-06 17:34:26 +05301345 /* printk("XGIfb: inside set_par\n"); */
1346 err = XGIfb_do_set_var(&info->var, 1, info);
1347 if (err)
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001348 return err;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001349 XGIfb_get_fix(&info->fix, -1, info);
Prashant P. Shahb654f872010-09-06 17:34:26 +05301350 /* printk("XGIfb: end of set_par\n"); */
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001351 return 0;
1352}
1353
Prashant P. Shahb654f872010-09-06 17:34:26 +05301354static int XGIfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001355{
Aaro Koskinenfd26d422011-10-11 21:47:19 +03001356 struct xgifb_video_info *xgifb_info = info->par;
Prashant P. Shahb654f872010-09-06 17:34:26 +05301357 unsigned int htotal = var->left_margin + var->xres + var->right_margin
1358 + var->hsync_len;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001359 unsigned int vtotal = 0;
1360 unsigned int drate = 0, hrate = 0;
1361 int found_mode = 0;
1362 int refresh_rate, search_idx;
1363
Prashant P. Shahb654f872010-09-06 17:34:26 +05301364 if ((var->vmode & FB_VMODE_MASK) == FB_VMODE_NONINTERLACED) {
1365 vtotal = var->upper_margin + var->yres + var->lower_margin
1366 + var->vsync_len;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001367 vtotal <<= 1;
Prashant P. Shahb654f872010-09-06 17:34:26 +05301368 } else if ((var->vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE) {
1369 vtotal = var->upper_margin + var->yres + var->lower_margin
1370 + var->vsync_len;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001371 vtotal <<= 2;
Prashant P. Shahb654f872010-09-06 17:34:26 +05301372 } else if ((var->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) {
1373 vtotal = var->upper_margin + (var->yres / 2)
1374 + var->lower_margin + var->vsync_len;
1375 } else
1376 vtotal = var->upper_margin + var->yres + var->lower_margin
1377 + var->vsync_len;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001378
Prashant P. Shahb654f872010-09-06 17:34:26 +05301379 if (!(htotal) || !(vtotal))
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001380 XGIFAIL("XGIfb: no valid timing data");
Prashant P. Shahb654f872010-09-06 17:34:26 +05301381
1382 if (var->pixclock && htotal && vtotal) {
1383 drate = 1000000000 / var->pixclock;
1384 hrate = (drate * 1000) / htotal;
Aaro Koskinenfd26d422011-10-11 21:47:19 +03001385 xgifb_info->refresh_rate =
Kenji Toyamaa12c27c2011-04-26 12:13:43 +08001386 (unsigned int) (hrate * 2 / vtotal);
Sam Hansen4a6b1512012-01-22 16:48:53 -08001387 pr_debug(
Prashant P. Shahb654f872010-09-06 17:34:26 +05301388 "%s: pixclock = %d ,htotal=%d, vtotal=%d\n"
1389 "%s: drate=%d, hrate=%d, refresh_rate=%d\n",
1390 __func__, var->pixclock, htotal, vtotal,
Aaro Koskinenfd26d422011-10-11 21:47:19 +03001391 __func__, drate, hrate, xgifb_info->refresh_rate);
Prashant P. Shahb654f872010-09-06 17:34:26 +05301392 } else {
Aaro Koskinenfd26d422011-10-11 21:47:19 +03001393 xgifb_info->refresh_rate = 60;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001394 }
1395
Prashant P. Shahb654f872010-09-06 17:34:26 +05301396 /*
1397 if ((var->pixclock) && (htotal)) {
1398 drate = 1E12 / var->pixclock;
1399 hrate = drate / htotal;
1400 refresh_rate = (unsigned int) (hrate / vtotal * 2 + 0.5);
1401 } else {
1402 refresh_rate = 60;
1403 }
1404 */
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001405 /* TW: Calculation wrong for 1024x600 - force it to 60Hz */
Prashant P. Shahb654f872010-09-06 17:34:26 +05301406 if ((var->xres == 1024) && (var->yres == 600))
1407 refresh_rate = 60;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001408
1409 search_idx = 0;
Prashant P. Shahb654f872010-09-06 17:34:26 +05301410 while ((XGIbios_mode[search_idx].mode_no != 0) &&
1411 (XGIbios_mode[search_idx].xres <= var->xres)) {
1412 if ((XGIbios_mode[search_idx].xres == var->xres) &&
1413 (XGIbios_mode[search_idx].yres == var->yres) &&
1414 (XGIbios_mode[search_idx].bpp == var->bits_per_pixel)) {
Aaro Koskinenfd26d422011-10-11 21:47:19 +03001415 if (XGIfb_validate_mode(xgifb_info, search_idx) > 0) {
Prashant P. Shahb654f872010-09-06 17:34:26 +05301416 found_mode = 1;
1417 break;
1418 }
1419 }
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001420 search_idx++;
1421 }
1422
Prashant P. Shahb654f872010-09-06 17:34:26 +05301423 if (!found_mode) {
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001424
Sam Hansen4a6b1512012-01-22 16:48:53 -08001425 pr_err("%dx%dx%d is no valid mode\n",
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001426 var->xres, var->yres, var->bits_per_pixel);
Prashant P. Shahb654f872010-09-06 17:34:26 +05301427 search_idx = 0;
1428 while (XGIbios_mode[search_idx].mode_no != 0) {
Prashant P. Shahb654f872010-09-06 17:34:26 +05301429 if ((var->xres <= XGIbios_mode[search_idx].xres) &&
Kenji Toyamaa12c27c2011-04-26 12:13:43 +08001430 (var->yres <= XGIbios_mode[search_idx].yres) &&
1431 (var->bits_per_pixel ==
1432 XGIbios_mode[search_idx].bpp)) {
Aaro Koskinenfd26d422011-10-11 21:47:19 +03001433 if (XGIfb_validate_mode(xgifb_info,
1434 search_idx) > 0) {
Prashant P. Shahb654f872010-09-06 17:34:26 +05301435 found_mode = 1;
1436 break;
1437 }
1438 }
1439 search_idx++;
1440 }
1441 if (found_mode) {
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001442 var->xres = XGIbios_mode[search_idx].xres;
Prashant P. Shahb654f872010-09-06 17:34:26 +05301443 var->yres = XGIbios_mode[search_idx].yres;
Sam Hansen4a6b1512012-01-22 16:48:53 -08001444 pr_debug("Adapted to mode %dx%dx%d\n",
Prashant P. Shahb654f872010-09-06 17:34:26 +05301445 var->xres, var->yres, var->bits_per_pixel);
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001446
1447 } else {
Sam Hansen4a6b1512012-01-22 16:48:53 -08001448 pr_err("Failed to find similar mode to %dx%dx%d\n",
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001449 var->xres, var->yres, var->bits_per_pixel);
Prashant P. Shahb654f872010-09-06 17:34:26 +05301450 return -EINVAL;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001451 }
1452 }
1453
1454 /* TW: TODO: Check the refresh rate */
1455
1456 /* Adapt RGB settings */
Aaro Koskinenfd26d422011-10-11 21:47:19 +03001457 XGIfb_bpp_to_var(xgifb_info, var);
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001458
1459 /* Sanity check for offsets */
1460 if (var->xoffset < 0)
1461 var->xoffset = 0;
1462 if (var->yoffset < 0)
1463 var->yoffset = 0;
1464
Prashant P. Shahb654f872010-09-06 17:34:26 +05301465 if (!XGIfb_ypan) {
1466 if (var->xres != var->xres_virtual)
1467 var->xres_virtual = var->xres;
1468 if (var->yres != var->yres_virtual)
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001469 var->yres_virtual = var->yres;
Prashant P. Shahb654f872010-09-06 17:34:26 +05301470 } /* else { */
1471 /* TW: Now patch yres_virtual if we use panning */
1472 /* May I do this? */
Aaro Koskinenfd26d422011-10-11 21:47:19 +03001473 /* var->yres_virtual = xgifb_info->heapstart /
Kenji Toyamaa12c27c2011-04-26 12:13:43 +08001474 (var->xres * (var->bits_per_pixel >> 3)); */
Prashant P. Shahb654f872010-09-06 17:34:26 +05301475 /* if (var->yres_virtual <= var->yres) { */
1476 /* TW: Paranoia check */
1477 /* var->yres_virtual = var->yres; */
1478 /* } */
1479 /* } */
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001480
1481 /* Truncate offsets to maximum if too high */
1482 if (var->xoffset > var->xres_virtual - var->xres)
1483 var->xoffset = var->xres_virtual - var->xres - 1;
1484
1485 if (var->yoffset > var->yres_virtual - var->yres)
1486 var->yoffset = var->yres_virtual - var->yres - 1;
1487
1488 /* Set everything else to 0 */
1489 var->red.msb_right =
Prashant P. Shahb654f872010-09-06 17:34:26 +05301490 var->green.msb_right =
1491 var->blue.msb_right =
1492 var->transp.offset = var->transp.length = var->transp.msb_right = 0;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001493
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001494 return 0;
1495}
1496
Prashant P. Shahb654f872010-09-06 17:34:26 +05301497static int XGIfb_pan_display(struct fb_var_screeninfo *var,
1498 struct fb_info *info)
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001499{
1500 int err;
1501
Prashant P. Shahb654f872010-09-06 17:34:26 +05301502 /* printk("\nInside pan_display:\n"); */
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001503
Laurent Pinchart0d5c6ca2011-05-25 11:34:52 +02001504 if (var->xoffset > (info->var.xres_virtual - info->var.xres))
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001505 return -EINVAL;
Laurent Pinchart0d5c6ca2011-05-25 11:34:52 +02001506 if (var->yoffset > (info->var.yres_virtual - info->var.yres))
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001507 return -EINVAL;
1508
1509 if (var->vmode & FB_VMODE_YWRAP) {
Prashant P. Shahb654f872010-09-06 17:34:26 +05301510 if (var->yoffset < 0 || var->yoffset >= info->var.yres_virtual
1511 || var->xoffset)
1512 return -EINVAL;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001513 } else {
Prashant P. Shahb654f872010-09-06 17:34:26 +05301514 if (var->xoffset + info->var.xres > info->var.xres_virtual
1515 || var->yoffset + info->var.yres
1516 > info->var.yres_virtual)
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001517 return -EINVAL;
1518 }
Laurent Pinchart0d5c6ca2011-05-25 11:34:52 +02001519 err = XGIfb_pan_var(var, info);
Prashant P. Shahb654f872010-09-06 17:34:26 +05301520 if (err < 0)
1521 return err;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001522
1523 info->var.xoffset = var->xoffset;
1524 info->var.yoffset = var->yoffset;
1525 if (var->vmode & FB_VMODE_YWRAP)
1526 info->var.vmode |= FB_VMODE_YWRAP;
1527 else
1528 info->var.vmode &= ~FB_VMODE_YWRAP;
1529
Prashant P. Shahb654f872010-09-06 17:34:26 +05301530 /* printk("End of pan_display\n"); */
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001531 return 0;
1532}
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001533
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001534static int XGIfb_blank(int blank, struct fb_info *info)
1535{
Aaro Koskinenf2df8c02011-10-11 21:47:30 +03001536 struct xgifb_video_info *xgifb_info = info->par;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001537 u8 reg;
1538
Aaro Koskinen7e119b72011-04-18 22:13:58 +03001539 reg = xgifb_reg_get(XGICR, 0x17);
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001540
Prashant P. Shahb654f872010-09-06 17:34:26 +05301541 if (blank > 0)
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001542 reg &= 0x7f;
1543 else
1544 reg |= 0x80;
1545
Aaro Koskinenb6e2dc32011-04-18 22:13:59 +03001546 xgifb_reg_set(XGICR, 0x17, reg);
1547 xgifb_reg_set(XGISR, 0x00, 0x01); /* Synchronous Reset */
1548 xgifb_reg_set(XGISR, 0x00, 0x03); /* End Reset */
Prashant P. Shahb654f872010-09-06 17:34:26 +05301549 return 0;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001550}
1551
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001552static struct fb_ops XGIfb_ops = {
Prashant P. Shahb654f872010-09-06 17:34:26 +05301553 .owner = THIS_MODULE,
1554 .fb_open = XGIfb_open,
1555 .fb_release = XGIfb_release,
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001556 .fb_check_var = XGIfb_check_var,
Prashant P. Shahb654f872010-09-06 17:34:26 +05301557 .fb_set_par = XGIfb_set_par,
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001558 .fb_setcolreg = XGIfb_setcolreg,
Prashant P. Shahb654f872010-09-06 17:34:26 +05301559 .fb_pan_display = XGIfb_pan_display,
Prashant P. Shahb654f872010-09-06 17:34:26 +05301560 .fb_blank = XGIfb_blank,
Aaro Koskinen1b402962011-02-28 20:59:22 +02001561 .fb_fillrect = cfb_fillrect,
Aaro Koskinen85c3c562011-02-28 20:59:21 +02001562 .fb_copyarea = cfb_copyarea,
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001563 .fb_imageblit = cfb_imageblit,
Prashant P. Shahb654f872010-09-06 17:34:26 +05301564 /* .fb_mmap = XGIfb_mmap, */
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001565};
1566
1567/* ---------------- Chip generation dependent routines ---------------- */
1568
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001569/* for XGI 315/550/650/740/330 */
1570
Aaro Koskinenfd26d422011-10-11 21:47:19 +03001571static int XGIfb_get_dram_size(struct xgifb_video_info *xgifb_info)
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001572{
1573
Prashant P. Shahb654f872010-09-06 17:34:26 +05301574 u8 ChannelNum, tmp;
1575 u8 reg = 0;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001576
1577 /* xorg driver sets 32MB * 1 channel */
Aaro Koskinenfd26d422011-10-11 21:47:19 +03001578 if (xgifb_info->chip == XG27)
Peter Huewefc39dcb2012-01-15 19:22:12 +01001579 xgifb_reg_set(XGISR, IND_SIS_DRAM_SIZE, 0x51);
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001580
Peter Huewefc39dcb2012-01-15 19:22:12 +01001581 reg = xgifb_reg_get(XGISR, IND_SIS_DRAM_SIZE);
Prashant P. Shahb654f872010-09-06 17:34:26 +05301582 switch ((reg & XGI_DRAM_SIZE_MASK) >> 4) {
1583 case XGI_DRAM_SIZE_1MB:
Aaro Koskinenfd26d422011-10-11 21:47:19 +03001584 xgifb_info->video_size = 0x100000;
Prashant P. Shahb654f872010-09-06 17:34:26 +05301585 break;
1586 case XGI_DRAM_SIZE_2MB:
Aaro Koskinenfd26d422011-10-11 21:47:19 +03001587 xgifb_info->video_size = 0x200000;
Prashant P. Shahb654f872010-09-06 17:34:26 +05301588 break;
1589 case XGI_DRAM_SIZE_4MB:
Aaro Koskinenfd26d422011-10-11 21:47:19 +03001590 xgifb_info->video_size = 0x400000;
Prashant P. Shahb654f872010-09-06 17:34:26 +05301591 break;
1592 case XGI_DRAM_SIZE_8MB:
Aaro Koskinenfd26d422011-10-11 21:47:19 +03001593 xgifb_info->video_size = 0x800000;
Prashant P. Shahb654f872010-09-06 17:34:26 +05301594 break;
1595 case XGI_DRAM_SIZE_16MB:
Aaro Koskinenfd26d422011-10-11 21:47:19 +03001596 xgifb_info->video_size = 0x1000000;
Prashant P. Shahb654f872010-09-06 17:34:26 +05301597 break;
1598 case XGI_DRAM_SIZE_32MB:
Aaro Koskinenfd26d422011-10-11 21:47:19 +03001599 xgifb_info->video_size = 0x2000000;
Prashant P. Shahb654f872010-09-06 17:34:26 +05301600 break;
1601 case XGI_DRAM_SIZE_64MB:
Aaro Koskinenfd26d422011-10-11 21:47:19 +03001602 xgifb_info->video_size = 0x4000000;
Prashant P. Shahb654f872010-09-06 17:34:26 +05301603 break;
1604 case XGI_DRAM_SIZE_128MB:
Aaro Koskinenfd26d422011-10-11 21:47:19 +03001605 xgifb_info->video_size = 0x8000000;
Prashant P. Shahb654f872010-09-06 17:34:26 +05301606 break;
1607 case XGI_DRAM_SIZE_256MB:
Aaro Koskinenfd26d422011-10-11 21:47:19 +03001608 xgifb_info->video_size = 0x10000000;
Prashant P. Shahb654f872010-09-06 17:34:26 +05301609 break;
1610 default:
1611 return -1;
1612 }
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001613
Prashant P. Shahb654f872010-09-06 17:34:26 +05301614 tmp = (reg & 0x0c) >> 2;
Aaro Koskinenfd26d422011-10-11 21:47:19 +03001615 switch (xgifb_info->chip) {
Prashant P. Shahb654f872010-09-06 17:34:26 +05301616 case XG20:
1617 case XG21:
1618 case XG27:
1619 ChannelNum = 1;
1620 break;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001621
Prashant P. Shahb654f872010-09-06 17:34:26 +05301622 case XG42:
1623 if (reg & 0x04)
1624 ChannelNum = 2;
1625 else
1626 ChannelNum = 1;
1627 break;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001628
Prashant P. Shahb654f872010-09-06 17:34:26 +05301629 case XG40:
1630 default:
1631 if (tmp == 2)
1632 ChannelNum = 2;
1633 else if (tmp == 3)
1634 ChannelNum = 3;
1635 else
1636 ChannelNum = 1;
1637 break;
1638 }
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001639
Aaro Koskinenfd26d422011-10-11 21:47:19 +03001640 xgifb_info->video_size = xgifb_info->video_size * ChannelNum;
Prashant P. Shahb654f872010-09-06 17:34:26 +05301641 /* PLiad fixed for benchmarking and fb set */
Aaro Koskinenfd26d422011-10-11 21:47:19 +03001642 /* xgifb_info->video_size = 0x200000; */ /* 1024x768x16 */
1643 /* xgifb_info->video_size = 0x1000000; */ /* benchmark */
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001644
Sam Hansen4a6b1512012-01-22 16:48:53 -08001645 pr_info("SR14=%x DramSzie %x ChannelNum %x\n",
Kenji Toyamaa12c27c2011-04-26 12:13:43 +08001646 reg,
Aaro Koskinenfd26d422011-10-11 21:47:19 +03001647 xgifb_info->video_size, ChannelNum);
Prashant P. Shahb654f872010-09-06 17:34:26 +05301648 return 0;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001649
1650}
1651
Aaro Koskinenfd26d422011-10-11 21:47:19 +03001652static void XGIfb_detect_VB(struct xgifb_video_info *xgifb_info)
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001653{
Prashant P. Shahb654f872010-09-06 17:34:26 +05301654 u8 cr32, temp = 0;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001655
Aaro Koskinenfd26d422011-10-11 21:47:19 +03001656 xgifb_info->TV_plug = xgifb_info->TV_type = 0;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001657
Aaro Koskinenfd26d422011-10-11 21:47:19 +03001658 switch (xgifb_info->hasVB) {
Prashant P. Shahb654f872010-09-06 17:34:26 +05301659 case HASVB_LVDS_CHRONTEL:
1660 case HASVB_CHRONTEL:
1661 break;
1662 case HASVB_301:
1663 case HASVB_302:
1664 /* XGI_Sense30x(); */ /* Yi-Lin TV Sense? */
1665 break;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001666 }
1667
Aaro Koskinen7e119b72011-04-18 22:13:58 +03001668 cr32 = xgifb_reg_get(XGICR, IND_XGI_SCRATCH_REG_CR32);
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001669
Peter Huewefc39dcb2012-01-15 19:22:12 +01001670 if ((cr32 & SIS_CRT1) && !XGIfb_crt1off)
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001671 XGIfb_crt1off = 0;
1672 else {
1673 if (cr32 & 0x5F)
1674 XGIfb_crt1off = 1;
1675 else
1676 XGIfb_crt1off = 0;
1677 }
1678
Aaro Koskinen25aa75f2011-12-06 00:10:48 +02001679 if (!xgifb_info->display2_force) {
Peter Huewefc39dcb2012-01-15 19:22:12 +01001680 if (cr32 & SIS_VB_TV)
Aaro Koskinen25aa75f2011-12-06 00:10:48 +02001681 xgifb_info->display2 = XGIFB_DISP_TV;
Peter Huewefc39dcb2012-01-15 19:22:12 +01001682 else if (cr32 & SIS_VB_LCD)
Aaro Koskinen25aa75f2011-12-06 00:10:48 +02001683 xgifb_info->display2 = XGIFB_DISP_LCD;
Peter Huewefc39dcb2012-01-15 19:22:12 +01001684 else if (cr32 & SIS_VB_CRT2)
Aaro Koskinen25aa75f2011-12-06 00:10:48 +02001685 xgifb_info->display2 = XGIFB_DISP_CRT;
1686 else
1687 xgifb_info->display2 = XGIFB_DISP_NONE;
1688 }
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001689
Prashant P. Shahb654f872010-09-06 17:34:26 +05301690 if (XGIfb_tvplug != -1)
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001691 /* PR/TW: Override with option */
Aaro Koskinenfd26d422011-10-11 21:47:19 +03001692 xgifb_info->TV_plug = XGIfb_tvplug;
Peter Huewefc39dcb2012-01-15 19:22:12 +01001693 else if (cr32 & SIS_VB_HIVISION) {
Aaro Koskinenfd26d422011-10-11 21:47:19 +03001694 xgifb_info->TV_type = TVMODE_HIVISION;
1695 xgifb_info->TV_plug = TVPLUG_SVIDEO;
Peter Huewefc39dcb2012-01-15 19:22:12 +01001696 } else if (cr32 & SIS_VB_SVIDEO)
Aaro Koskinenfd26d422011-10-11 21:47:19 +03001697 xgifb_info->TV_plug = TVPLUG_SVIDEO;
Peter Huewefc39dcb2012-01-15 19:22:12 +01001698 else if (cr32 & SIS_VB_COMPOSITE)
Aaro Koskinenfd26d422011-10-11 21:47:19 +03001699 xgifb_info->TV_plug = TVPLUG_COMPOSITE;
Peter Huewefc39dcb2012-01-15 19:22:12 +01001700 else if (cr32 & SIS_VB_SCART)
Aaro Koskinenfd26d422011-10-11 21:47:19 +03001701 xgifb_info->TV_plug = TVPLUG_SCART;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001702
Aaro Koskinenfd26d422011-10-11 21:47:19 +03001703 if (xgifb_info->TV_type == 0) {
Aaro Koskinen7e119b72011-04-18 22:13:58 +03001704 temp = xgifb_reg_get(XGICR, 0x38);
Aaro Koskinenebe78462011-03-13 12:26:08 +02001705 if (temp & 0x10)
Aaro Koskinenfd26d422011-10-11 21:47:19 +03001706 xgifb_info->TV_type = TVMODE_PAL;
Aaro Koskinenebe78462011-03-13 12:26:08 +02001707 else
Aaro Koskinenfd26d422011-10-11 21:47:19 +03001708 xgifb_info->TV_type = TVMODE_NTSC;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001709 }
1710
1711 /* TW: Copy forceCRT1 option to CRT1off if option is given */
Prashant P. Shahb654f872010-09-06 17:34:26 +05301712 if (XGIfb_forcecrt1 != -1) {
1713 if (XGIfb_forcecrt1)
1714 XGIfb_crt1off = 0;
1715 else
1716 XGIfb_crt1off = 1;
1717 }
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001718}
1719
Aaro Koskinenfd26d422011-10-11 21:47:19 +03001720static int XGIfb_has_VB(struct xgifb_video_info *xgifb_info)
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001721{
1722 u8 vb_chipid;
1723
Aaro Koskinen7e119b72011-04-18 22:13:58 +03001724 vb_chipid = xgifb_reg_get(XGIPART4, 0x00);
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001725 switch (vb_chipid) {
Prashant P. Shahb654f872010-09-06 17:34:26 +05301726 case 0x01:
Aaro Koskinenfd26d422011-10-11 21:47:19 +03001727 xgifb_info->hasVB = HASVB_301;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001728 break;
Prashant P. Shahb654f872010-09-06 17:34:26 +05301729 case 0x02:
Aaro Koskinenfd26d422011-10-11 21:47:19 +03001730 xgifb_info->hasVB = HASVB_302;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001731 break;
Prashant P. Shahb654f872010-09-06 17:34:26 +05301732 default:
Aaro Koskinenfd26d422011-10-11 21:47:19 +03001733 xgifb_info->hasVB = HASVB_NONE;
Bill Pembertondda08c52010-06-17 13:10:42 -04001734 return 0;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001735 }
Bill Pembertondda08c52010-06-17 13:10:42 -04001736 return 1;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001737}
1738
Aaro Koskinenfd26d422011-10-11 21:47:19 +03001739static void XGIfb_get_VB_type(struct xgifb_video_info *xgifb_info)
Aaro Koskinenc4fa7df2011-04-18 22:14:05 +03001740{
1741 u8 reg;
1742
Aaro Koskinenfd26d422011-10-11 21:47:19 +03001743 if (!XGIfb_has_VB(xgifb_info)) {
Aaro Koskinenc4fa7df2011-04-18 22:14:05 +03001744 reg = xgifb_reg_get(XGICR, IND_XGI_SCRATCH_REG_CR37);
Peter Huewefc39dcb2012-01-15 19:22:12 +01001745 switch ((reg & SIS_EXTERNAL_CHIP_MASK) >> 1) {
1746 case SIS_EXTERNAL_CHIP_LVDS:
Aaro Koskinenfd26d422011-10-11 21:47:19 +03001747 xgifb_info->hasVB = HASVB_LVDS;
Aaro Koskinenc4fa7df2011-04-18 22:14:05 +03001748 break;
Peter Huewefc39dcb2012-01-15 19:22:12 +01001749 case SIS_EXTERNAL_CHIP_LVDS_CHRONTEL:
Aaro Koskinenfd26d422011-10-11 21:47:19 +03001750 xgifb_info->hasVB = HASVB_LVDS_CHRONTEL;
Aaro Koskinenc4fa7df2011-04-18 22:14:05 +03001751 break;
1752 default:
1753 break;
1754 }
1755 }
1756}
1757
Aaro Koskinend27c6bc2011-08-29 23:14:23 +03001758static int __init xgifb_optval(char *fullopt, int validx)
1759{
1760 unsigned long lres;
1761
1762 if (kstrtoul(fullopt + validx, 0, &lres) < 0 || lres > INT_MAX) {
1763 pr_err("xgifb: invalid value for option: %s\n", fullopt);
1764 return 0;
1765 }
1766 return lres;
1767}
1768
Ruslan Pisarev032abf72011-07-21 11:59:11 +03001769static int __init XGIfb_setup(char *options)
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001770{
1771 char *this_opt;
1772
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001773 if (!options || !*options)
1774 return 0;
1775
Aaro Koskinen79bea042011-08-29 23:14:21 +03001776 pr_info("xgifb: options: %s\n", options);
1777
Prashant P. Shahb654f872010-09-06 17:34:26 +05301778 while ((this_opt = strsep(&options, ",")) != NULL) {
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001779
Prashant P. Shahb654f872010-09-06 17:34:26 +05301780 if (!*this_opt)
1781 continue;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001782
1783 if (!strncmp(this_opt, "mode:", 5)) {
Aaro Koskinendfbdf802011-08-29 23:14:25 +03001784 mode = this_opt + 5;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001785 } else if (!strncmp(this_opt, "vesa:", 5)) {
Aaro Koskinendfbdf802011-08-29 23:14:25 +03001786 vesa = xgifb_optval(this_opt, 5);
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001787 } else if (!strncmp(this_opt, "vrate:", 6)) {
Aaro Koskinen7548a832011-10-11 21:47:17 +03001788 refresh_rate = xgifb_optval(this_opt, 6);
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001789 } else if (!strncmp(this_opt, "rate:", 5)) {
Aaro Koskinen7548a832011-10-11 21:47:17 +03001790 refresh_rate = xgifb_optval(this_opt, 5);
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001791 } else if (!strncmp(this_opt, "crt1off", 7)) {
1792 XGIfb_crt1off = 1;
1793 } else if (!strncmp(this_opt, "filter:", 7)) {
Aaro Koskinend27c6bc2011-08-29 23:14:23 +03001794 filter = xgifb_optval(this_opt, 7);
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001795 } else if (!strncmp(this_opt, "forcecrt2type:", 14)) {
1796 XGIfb_search_crt2type(this_opt + 14);
1797 } else if (!strncmp(this_opt, "forcecrt1:", 10)) {
Aaro Koskinend27c6bc2011-08-29 23:14:23 +03001798 XGIfb_forcecrt1 = xgifb_optval(this_opt, 10);
Prashant P. Shahb654f872010-09-06 17:34:26 +05301799 } else if (!strncmp(this_opt, "tvmode:", 7)) {
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001800 XGIfb_search_tvstd(this_opt + 7);
Prashant P. Shahb654f872010-09-06 17:34:26 +05301801 } else if (!strncmp(this_opt, "tvstandard:", 11)) {
1802 XGIfb_search_tvstd(this_opt + 7);
Prashant P. Shahb654f872010-09-06 17:34:26 +05301803 } else if (!strncmp(this_opt, "dstn", 4)) {
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001804 enable_dstn = 1;
1805 /* TW: DSTN overrules forcecrt2type */
Aaro Koskinen289ea522011-10-11 21:47:37 +03001806 XGIfb_crt2type = XGIFB_DISP_LCD;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001807 } else if (!strncmp(this_opt, "noypan", 6)) {
Prashant P. Shahb654f872010-09-06 17:34:26 +05301808 XGIfb_ypan = 0;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001809 } else {
Aaro Koskinendfbdf802011-08-29 23:14:25 +03001810 mode = this_opt;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001811 }
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001812 }
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001813 return 0;
1814}
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001815
Randy Dunlap89229672010-08-10 08:46:44 -07001816static int __devinit xgifb_probe(struct pci_dev *pdev,
Prashant P. Shahb654f872010-09-06 17:34:26 +05301817 const struct pci_device_id *ent)
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001818{
Prashant P. Shahb654f872010-09-06 17:34:26 +05301819 u8 reg, reg1;
1820 u8 CR48, CR38;
Aaro Koskinenbb292232011-02-17 23:29:11 +02001821 int ret;
Aaro Koskinen19c1e882011-10-11 21:47:14 +03001822 struct fb_info *fb_info;
Aaro Koskinenfcbdda92011-10-11 21:47:20 +03001823 struct xgifb_video_info *xgifb_info;
1824 struct xgi_hw_device_info *hw_info;
Aaro Koskinenbb292232011-02-17 23:29:11 +02001825
Aaro Koskinenfcbdda92011-10-11 21:47:20 +03001826 fb_info = framebuffer_alloc(sizeof(*xgifb_info), &pdev->dev);
Prashant P. Shahb654f872010-09-06 17:34:26 +05301827 if (!fb_info)
1828 return -ENOMEM;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001829
Aaro Koskinenfcbdda92011-10-11 21:47:20 +03001830 xgifb_info = fb_info->par;
1831 hw_info = &xgifb_info->hw_info;
Aaro Koskinenfd26d422011-10-11 21:47:19 +03001832 xgifb_info->fb_info = fb_info;
1833 xgifb_info->chip_id = pdev->device;
Kenji Toyamaa12c27c2011-04-26 12:13:43 +08001834 pci_read_config_byte(pdev,
1835 PCI_REVISION_ID,
Aaro Koskinenfd26d422011-10-11 21:47:19 +03001836 &xgifb_info->revision_id);
1837 hw_info->jChipRevision = xgifb_info->revision_id;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001838
Aaro Koskinenfd26d422011-10-11 21:47:19 +03001839 xgifb_info->pcibus = pdev->bus->number;
1840 xgifb_info->pcislot = PCI_SLOT(pdev->devfn);
1841 xgifb_info->pcifunc = PCI_FUNC(pdev->devfn);
1842 xgifb_info->subsysvendor = pdev->subsystem_vendor;
1843 xgifb_info->subsysdevice = pdev->subsystem_device;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001844
Aaro Koskinenfd26d422011-10-11 21:47:19 +03001845 xgifb_info->video_base = pci_resource_start(pdev, 0);
1846 xgifb_info->mmio_base = pci_resource_start(pdev, 1);
1847 xgifb_info->mmio_size = pci_resource_len(pdev, 1);
1848 xgifb_info->vga_base = pci_resource_start(pdev, 2) + 0x30;
Dmitry Eremin-Solenikovf650caa2012-03-19 21:50:14 +04001849 pr_info("Relocate IO address: %Lx [%08lx]\n",
1850 (u64) pci_resource_start(pdev, 2),
Dmitry Eremin-Solenikov30b76812012-03-19 21:50:12 +04001851 xgifb_info->vga_base);
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001852
Aaro Koskinenbb292232011-02-17 23:29:11 +02001853 if (pci_enable_device(pdev)) {
1854 ret = -EIO;
1855 goto error;
1856 }
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001857
Aaro Koskinen25aa75f2011-12-06 00:10:48 +02001858 if (XGIfb_crt2type != -1) {
1859 xgifb_info->display2 = XGIfb_crt2type;
1860 xgifb_info->display2_force = true;
1861 }
1862
Dmitry Eremin-Solenikov9a801f22012-03-19 21:50:13 +04001863 XGIRegInit(&xgifb_info->dev_info, xgifb_info->vga_base);
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001864
Peter Huewefc39dcb2012-01-15 19:22:12 +01001865 xgifb_reg_set(XGISR, IND_SIS_PASSWORD, SIS_PASSWORD);
1866 reg1 = xgifb_reg_get(XGISR, IND_SIS_PASSWORD);
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001867
Prashant P. Shahb654f872010-09-06 17:34:26 +05301868 if (reg1 != 0xa1) { /*I/O error */
Sam Hansen4a6b1512012-01-22 16:48:53 -08001869 pr_err("I/O error!!!");
Aaro Koskinenbb292232011-02-17 23:29:11 +02001870 ret = -EIO;
Miguel Gómez05e06032012-06-06 16:22:06 +02001871 goto error_disable;
Prashant P. Shahb654f872010-09-06 17:34:26 +05301872 }
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001873
Aaro Koskinenfd26d422011-10-11 21:47:19 +03001874 switch (xgifb_info->chip_id) {
Peter Huewefc39dcb2012-01-15 19:22:12 +01001875 case PCI_DEVICE_ID_XGI_20:
Aaro Koskinene67f4d42011-04-18 22:14:00 +03001876 xgifb_reg_or(XGICR, Index_CR_GPIO_Reg3, GPIOG_EN);
Aaro Koskinen7e119b72011-04-18 22:13:58 +03001877 CR48 = xgifb_reg_get(XGICR, Index_CR_GPIO_Reg1);
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001878 if (CR48&GPIOG_READ)
Aaro Koskinenfd26d422011-10-11 21:47:19 +03001879 xgifb_info->chip = XG21;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001880 else
Aaro Koskinenfd26d422011-10-11 21:47:19 +03001881 xgifb_info->chip = XG20;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001882 break;
Peter Huewefc39dcb2012-01-15 19:22:12 +01001883 case PCI_DEVICE_ID_XGI_40:
Aaro Koskinenfd26d422011-10-11 21:47:19 +03001884 xgifb_info->chip = XG40;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001885 break;
Peter Huewefc39dcb2012-01-15 19:22:12 +01001886 case PCI_DEVICE_ID_XGI_42:
Aaro Koskinenfd26d422011-10-11 21:47:19 +03001887 xgifb_info->chip = XG42;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001888 break;
Peter Huewefc39dcb2012-01-15 19:22:12 +01001889 case PCI_DEVICE_ID_XGI_27:
Aaro Koskinenfd26d422011-10-11 21:47:19 +03001890 xgifb_info->chip = XG27;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001891 break;
Prashant P. Shahb654f872010-09-06 17:34:26 +05301892 default:
Aaro Koskinenbb292232011-02-17 23:29:11 +02001893 ret = -ENODEV;
Miguel Gómez05e06032012-06-06 16:22:06 +02001894 goto error_disable;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001895 }
1896
Sam Hansen4a6b1512012-01-22 16:48:53 -08001897 pr_info("chipid = %x\n", xgifb_info->chip);
Aaro Koskinenfd26d422011-10-11 21:47:19 +03001898 hw_info->jChipType = xgifb_info->chip;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001899
Aaro Koskinenfd26d422011-10-11 21:47:19 +03001900 if (XGIfb_get_dram_size(xgifb_info)) {
Sam Hansen4a6b1512012-01-22 16:48:53 -08001901 pr_err("Fatal error: Unable to determine RAM size.\n");
Aaro Koskinenbb292232011-02-17 23:29:11 +02001902 ret = -ENODEV;
Miguel Gómez05e06032012-06-06 16:22:06 +02001903 goto error_disable;
Prashant P. Shahb654f872010-09-06 17:34:26 +05301904 }
1905
Aaro Koskinene1521a12011-08-19 22:40:26 +03001906 /* Enable PCI_LINEAR_ADDRESSING and MMIO_ENABLE */
1907 xgifb_reg_or(XGISR,
Peter Huewefc39dcb2012-01-15 19:22:12 +01001908 IND_SIS_PCI_ADDRESS_SET,
1909 (SIS_PCI_ADDR_ENABLE | SIS_MEM_MAP_IO_ENABLE));
Aaro Koskinene1521a12011-08-19 22:40:26 +03001910 /* Enable 2D accelerator engine */
Peter Huewefc39dcb2012-01-15 19:22:12 +01001911 xgifb_reg_or(XGISR, IND_SIS_MODULE_ENABLE, SIS_ENABLE_2D);
Prashant P. Shahb654f872010-09-06 17:34:26 +05301912
Aaro Koskinenfd26d422011-10-11 21:47:19 +03001913 hw_info->ulVideoMemorySize = xgifb_info->video_size;
Prashant P. Shahb654f872010-09-06 17:34:26 +05301914
Aaro Koskinenfd26d422011-10-11 21:47:19 +03001915 if (!request_mem_region(xgifb_info->video_base,
1916 xgifb_info->video_size,
Kenji Toyamaa12c27c2011-04-26 12:13:43 +08001917 "XGIfb FB")) {
Sam Hansen4a6b1512012-01-22 16:48:53 -08001918 pr_err("unable request memory size %x\n",
Aaro Koskinenfd26d422011-10-11 21:47:19 +03001919 xgifb_info->video_size);
Sam Hansen4a6b1512012-01-22 16:48:53 -08001920 pr_err("Fatal error: Unable to reserve frame buffer memory\n");
1921 pr_err("Is there another framebuffer driver active?\n");
Aaro Koskinenbb292232011-02-17 23:29:11 +02001922 ret = -ENODEV;
Miguel Gómez05e06032012-06-06 16:22:06 +02001923 goto error_disable;
Prashant P. Shahb654f872010-09-06 17:34:26 +05301924 }
1925
Aaro Koskinenfd26d422011-10-11 21:47:19 +03001926 if (!request_mem_region(xgifb_info->mmio_base,
1927 xgifb_info->mmio_size,
Aaro Koskinen1b3909e2011-02-17 23:29:17 +02001928 "XGIfb MMIO")) {
Sam Hansen4a6b1512012-01-22 16:48:53 -08001929 pr_err("Fatal error: Unable to reserve MMIO region\n");
Aaro Koskinenbb292232011-02-17 23:29:11 +02001930 ret = -ENODEV;
Aaro Koskinen5c0ef2a2011-02-17 23:29:15 +02001931 goto error_0;
Prashant P. Shahb654f872010-09-06 17:34:26 +05301932 }
1933
Aaro Koskinenfd26d422011-10-11 21:47:19 +03001934 xgifb_info->video_vbase = hw_info->pjVideoMemoryAddress =
1935 ioremap(xgifb_info->video_base, xgifb_info->video_size);
1936 xgifb_info->mmio_vbase = ioremap(xgifb_info->mmio_base,
1937 xgifb_info->mmio_size);
Prashant P. Shahb654f872010-09-06 17:34:26 +05301938
Dmitry Eremin-Solenikovf650caa2012-03-19 21:50:14 +04001939 pr_info("Framebuffer at 0x%Lx, mapped to 0x%p, size %dk\n",
1940 (u64) xgifb_info->video_base,
Aaro Koskinenfd26d422011-10-11 21:47:19 +03001941 xgifb_info->video_vbase,
1942 xgifb_info->video_size / 1024);
Prashant P. Shahb654f872010-09-06 17:34:26 +05301943
Dmitry Eremin-Solenikovf650caa2012-03-19 21:50:14 +04001944 pr_info("MMIO at 0x%Lx, mapped to 0x%p, size %ldk\n",
1945 (u64) xgifb_info->mmio_base, xgifb_info->mmio_vbase,
Aaro Koskinenfd26d422011-10-11 21:47:19 +03001946 xgifb_info->mmio_size / 1024);
Sam Hansen4a6b1512012-01-22 16:48:53 -08001947
Aaro Koskinenfcbdda92011-10-11 21:47:20 +03001948 pci_set_drvdata(pdev, xgifb_info);
Sam Hansen4a6b1512012-01-22 16:48:53 -08001949 if (!XGIInitNew(pdev))
1950 pr_err("XGIInitNew() failed!\n");
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001951
Aaro Koskinenfd26d422011-10-11 21:47:19 +03001952 xgifb_info->mtrr = (unsigned int) 0;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001953
Aaro Koskinenfd26d422011-10-11 21:47:19 +03001954 xgifb_info->hasVB = HASVB_NONE;
1955 if ((xgifb_info->chip == XG20) ||
1956 (xgifb_info->chip == XG27)) {
1957 xgifb_info->hasVB = HASVB_NONE;
1958 } else if (xgifb_info->chip == XG21) {
Aaro Koskinene1521a12011-08-19 22:40:26 +03001959 CR38 = xgifb_reg_get(XGICR, 0x38);
Sam Hansencae9a7b2012-01-22 16:48:51 -08001960 if ((CR38&0xE0) == 0xC0)
Aaro Koskinen289ea522011-10-11 21:47:37 +03001961 xgifb_info->display2 = XGIFB_DISP_LCD;
Sam Hansencae9a7b2012-01-22 16:48:51 -08001962 else if ((CR38&0xE0) == 0x60)
Aaro Koskinenfd26d422011-10-11 21:47:19 +03001963 xgifb_info->hasVB = HASVB_CHRONTEL;
Sam Hansencae9a7b2012-01-22 16:48:51 -08001964 else
Aaro Koskinenfd26d422011-10-11 21:47:19 +03001965 xgifb_info->hasVB = HASVB_NONE;
Aaro Koskinene1521a12011-08-19 22:40:26 +03001966 } else {
Aaro Koskinenfd26d422011-10-11 21:47:19 +03001967 XGIfb_get_VB_type(xgifb_info);
Aaro Koskinene1521a12011-08-19 22:40:26 +03001968 }
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001969
Aaro Koskinenc62f2e42011-10-11 21:47:15 +03001970 hw_info->ujVBChipID = VB_CHIP_UNKNOWN;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001971
Aaro Koskinenc62f2e42011-10-11 21:47:15 +03001972 hw_info->ulExternalChip = 0;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001973
Aaro Koskinenfd26d422011-10-11 21:47:19 +03001974 switch (xgifb_info->hasVB) {
Aaro Koskinene1521a12011-08-19 22:40:26 +03001975 case HASVB_301:
1976 reg = xgifb_reg_get(XGIPART4, 0x01);
1977 if (reg >= 0xE0) {
Aaro Koskinenc62f2e42011-10-11 21:47:15 +03001978 hw_info->ujVBChipID = VB_CHIP_302LV;
Sam Hansen4a6b1512012-01-22 16:48:53 -08001979 pr_info("XGI302LV bridge detected (revision 0x%02x)\n", reg);
Aaro Koskinene1521a12011-08-19 22:40:26 +03001980 } else if (reg >= 0xD0) {
Aaro Koskinenc62f2e42011-10-11 21:47:15 +03001981 hw_info->ujVBChipID = VB_CHIP_301LV;
Sam Hansen4a6b1512012-01-22 16:48:53 -08001982 pr_info("XGI301LV bridge detected (revision 0x%02x)\n", reg);
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02001983 }
Aaro Koskinene1521a12011-08-19 22:40:26 +03001984 /* else if (reg >= 0xB0) {
Aaro Koskinenc62f2e42011-10-11 21:47:15 +03001985 hw_info->ujVBChipID = VB_CHIP_301B;
Aaro Koskinene1521a12011-08-19 22:40:26 +03001986 reg1 = xgifb_reg_get(XGIPART4, 0x23);
1987 printk("XGIfb: XGI301B bridge detected\n");
1988 } */
1989 else {
Aaro Koskinenc62f2e42011-10-11 21:47:15 +03001990 hw_info->ujVBChipID = VB_CHIP_301;
Sam Hansen4a6b1512012-01-22 16:48:53 -08001991 pr_info("XGI301 bridge detected\n");
Aaro Koskinene1521a12011-08-19 22:40:26 +03001992 }
1993 break;
1994 case HASVB_302:
1995 reg = xgifb_reg_get(XGIPART4, 0x01);
1996 if (reg >= 0xE0) {
Aaro Koskinenc62f2e42011-10-11 21:47:15 +03001997 hw_info->ujVBChipID = VB_CHIP_302LV;
Sam Hansen4a6b1512012-01-22 16:48:53 -08001998 pr_info("XGI302LV bridge detected (revision 0x%02x)\n", reg);
Aaro Koskinene1521a12011-08-19 22:40:26 +03001999 } else if (reg >= 0xD0) {
Aaro Koskinenc62f2e42011-10-11 21:47:15 +03002000 hw_info->ujVBChipID = VB_CHIP_301LV;
Sam Hansen4a6b1512012-01-22 16:48:53 -08002001 pr_info("XGI302LV bridge detected (revision 0x%02x)\n", reg);
Aaro Koskinene1521a12011-08-19 22:40:26 +03002002 } else if (reg >= 0xB0) {
2003 reg1 = xgifb_reg_get(XGIPART4, 0x23);
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02002004
Aaro Koskinenc62f2e42011-10-11 21:47:15 +03002005 hw_info->ujVBChipID = VB_CHIP_302B;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02002006
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02002007 } else {
Aaro Koskinenc62f2e42011-10-11 21:47:15 +03002008 hw_info->ujVBChipID = VB_CHIP_302;
Sam Hansen4a6b1512012-01-22 16:48:53 -08002009 pr_info("XGI302 bridge detected\n");
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02002010 }
Aaro Koskinene1521a12011-08-19 22:40:26 +03002011 break;
2012 case HASVB_LVDS:
Aaro Koskinenc62f2e42011-10-11 21:47:15 +03002013 hw_info->ulExternalChip = 0x1;
Sam Hansen4a6b1512012-01-22 16:48:53 -08002014 pr_info("LVDS transmitter detected\n");
Aaro Koskinene1521a12011-08-19 22:40:26 +03002015 break;
2016 case HASVB_TRUMPION:
Aaro Koskinenc62f2e42011-10-11 21:47:15 +03002017 hw_info->ulExternalChip = 0x2;
Sam Hansen4a6b1512012-01-22 16:48:53 -08002018 pr_info("Trumpion Zurac LVDS scaler detected\n");
Aaro Koskinene1521a12011-08-19 22:40:26 +03002019 break;
2020 case HASVB_CHRONTEL:
Aaro Koskinenc62f2e42011-10-11 21:47:15 +03002021 hw_info->ulExternalChip = 0x4;
Sam Hansen4a6b1512012-01-22 16:48:53 -08002022 pr_info("Chrontel TV encoder detected\n");
Aaro Koskinene1521a12011-08-19 22:40:26 +03002023 break;
2024 case HASVB_LVDS_CHRONTEL:
Aaro Koskinenc62f2e42011-10-11 21:47:15 +03002025 hw_info->ulExternalChip = 0x5;
Sam Hansen4a6b1512012-01-22 16:48:53 -08002026 pr_info("LVDS transmitter and Chrontel TV encoder detected\n");
Aaro Koskinene1521a12011-08-19 22:40:26 +03002027 break;
2028 default:
Sam Hansen4a6b1512012-01-22 16:48:53 -08002029 pr_info("No or unknown bridge type detected\n");
Aaro Koskinene1521a12011-08-19 22:40:26 +03002030 break;
2031 }
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02002032
Aaro Koskinenfd26d422011-10-11 21:47:19 +03002033 if (xgifb_info->hasVB != HASVB_NONE)
2034 XGIfb_detect_VB(xgifb_info);
Aaro Koskinen25aa75f2011-12-06 00:10:48 +02002035 else if (xgifb_info->chip != XG21)
2036 xgifb_info->display2 = XGIFB_DISP_NONE;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02002037
Aaro Koskinen289ea522011-10-11 21:47:37 +03002038 if (xgifb_info->display2 == XGIFB_DISP_LCD) {
Aaro Koskinene1521a12011-08-19 22:40:26 +03002039 if (!enable_dstn) {
2040 reg = xgifb_reg_get(XGICR, IND_XGI_LCD_PANEL);
2041 reg &= 0x0f;
Aaro Koskinenc62f2e42011-10-11 21:47:15 +03002042 hw_info->ulCRT2LCDType = XGI310paneltype[reg];
Aaro Koskinene1521a12011-08-19 22:40:26 +03002043 }
2044 }
2045
Aaro Koskinenc62f2e42011-10-11 21:47:15 +03002046 if ((hw_info->ujVBChipID == VB_CHIP_302B) ||
2047 (hw_info->ujVBChipID == VB_CHIP_301LV) ||
2048 (hw_info->ujVBChipID == VB_CHIP_302LV)) {
Aaro Koskinene1521a12011-08-19 22:40:26 +03002049 int tmp;
2050 tmp = xgifb_reg_get(XGICR, 0x34);
2051 if (tmp <= 0x13) {
2052 /* Currently on LCDA?
2053 *(Some BIOSes leave CR38) */
2054 tmp = xgifb_reg_get(XGICR, 0x38);
2055 if ((tmp & 0x03) == 0x03) {
2056 /* XGI_Pr.XGI_UseLCDA = 1; */
Prashant P. Shahb654f872010-09-06 17:34:26 +05302057 } else {
Kenji Toyamaa12c27c2011-04-26 12:13:43 +08002058 /* Currently on LCDA?
Aaro Koskinene1521a12011-08-19 22:40:26 +03002059 *(Some newer BIOSes set D0 in CR35) */
2060 tmp = xgifb_reg_get(XGICR, 0x35);
2061 if (tmp & 0x01) {
Prashant P. Shahb654f872010-09-06 17:34:26 +05302062 /* XGI_Pr.XGI_UseLCDA = 1; */
2063 } else {
Aaro Koskinene1521a12011-08-19 22:40:26 +03002064 tmp = xgifb_reg_get(XGICR,
2065 0x30);
2066 if (tmp & 0x20) {
2067 tmp = xgifb_reg_get(
2068 XGIPART1, 0x13);
Prashant P. Shahb654f872010-09-06 17:34:26 +05302069 }
2070 }
2071 }
Prashant P. Shahb654f872010-09-06 17:34:26 +05302072 }
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02002073
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02002074 }
2075
Aaro Koskinenccf265a2011-10-11 21:47:22 +03002076 xgifb_info->mode_idx = -1;
2077
Aaro Koskinendfbdf802011-08-29 23:14:25 +03002078 if (mode)
Aaro Koskinenccf265a2011-10-11 21:47:22 +03002079 XGIfb_search_mode(xgifb_info, mode);
Aaro Koskinendfbdf802011-08-29 23:14:25 +03002080 else if (vesa != -1)
Aaro Koskinenccf265a2011-10-11 21:47:22 +03002081 XGIfb_search_vesamode(xgifb_info, vesa);
Aaro Koskinendfbdf802011-08-29 23:14:25 +03002082
Aaro Koskinenccf265a2011-10-11 21:47:22 +03002083 if (xgifb_info->mode_idx >= 0)
2084 xgifb_info->mode_idx =
2085 XGIfb_validate_mode(xgifb_info, xgifb_info->mode_idx);
Aaro Koskinene1521a12011-08-19 22:40:26 +03002086
Aaro Koskinenccf265a2011-10-11 21:47:22 +03002087 if (xgifb_info->mode_idx < 0) {
Aaro Koskinen289ea522011-10-11 21:47:37 +03002088 if (xgifb_info->display2 == XGIFB_DISP_LCD &&
Aaro Koskinenfd26d422011-10-11 21:47:19 +03002089 xgifb_info->chip == XG21)
Aaro Koskinenccf265a2011-10-11 21:47:22 +03002090 xgifb_info->mode_idx =
Aaro Koskinenfab04b92011-12-06 00:10:45 +02002091 XGIfb_GetXG21DefaultLVDSModeIdx(xgifb_info);
Aaro Koskinenc8bec1f2011-08-29 23:14:30 +03002092 else
Aaro Koskinenccf265a2011-10-11 21:47:22 +03002093 xgifb_info->mode_idx = DEFAULT_MODE;
Aaro Koskinene1521a12011-08-19 22:40:26 +03002094 }
2095
Aaro Koskinenccf265a2011-10-11 21:47:22 +03002096 if (xgifb_info->mode_idx < 0) {
Aaro Koskinende736db2011-08-29 23:14:29 +03002097 dev_err(&pdev->dev, "no supported video mode found\n");
2098 goto error_1;
2099 }
2100
Aaro Koskinene1521a12011-08-19 22:40:26 +03002101 /* yilin set default refresh rate */
Aaro Koskinenfd26d422011-10-11 21:47:19 +03002102 xgifb_info->refresh_rate = refresh_rate;
2103 if (xgifb_info->refresh_rate == 0)
2104 xgifb_info->refresh_rate = 60;
2105 if (XGIfb_search_refresh_rate(xgifb_info,
2106 xgifb_info->refresh_rate) == 0) {
Aaro Koskinenf47f12d2012-04-07 01:13:54 +03002107 xgifb_info->rate_idx = 1;
Aaro Koskinenfd26d422011-10-11 21:47:19 +03002108 xgifb_info->refresh_rate = 60;
Aaro Koskinene1521a12011-08-19 22:40:26 +03002109 }
2110
Aaro Koskinenccf265a2011-10-11 21:47:22 +03002111 xgifb_info->video_bpp = XGIbios_mode[xgifb_info->mode_idx].bpp;
Aaro Koskinenfd26d422011-10-11 21:47:19 +03002112 xgifb_info->video_vwidth =
2113 xgifb_info->video_width =
Aaro Koskinenccf265a2011-10-11 21:47:22 +03002114 XGIbios_mode[xgifb_info->mode_idx].xres;
Aaro Koskinenfd26d422011-10-11 21:47:19 +03002115 xgifb_info->video_vheight =
2116 xgifb_info->video_height =
Aaro Koskinenccf265a2011-10-11 21:47:22 +03002117 XGIbios_mode[xgifb_info->mode_idx].yres;
Aaro Koskinenfd26d422011-10-11 21:47:19 +03002118 xgifb_info->org_x = xgifb_info->org_y = 0;
2119 xgifb_info->video_linelength =
2120 xgifb_info->video_width *
2121 (xgifb_info->video_bpp >> 3);
2122 switch (xgifb_info->video_bpp) {
Aaro Koskinene1521a12011-08-19 22:40:26 +03002123 case 8:
Aaro Koskinenfd26d422011-10-11 21:47:19 +03002124 xgifb_info->DstColor = 0x0000;
2125 xgifb_info->XGI310_AccelDepth = 0x00000000;
2126 xgifb_info->video_cmap_len = 256;
Aaro Koskinene1521a12011-08-19 22:40:26 +03002127 break;
2128 case 16:
Aaro Koskinenfd26d422011-10-11 21:47:19 +03002129 xgifb_info->DstColor = 0x8000;
2130 xgifb_info->XGI310_AccelDepth = 0x00010000;
2131 xgifb_info->video_cmap_len = 16;
Aaro Koskinene1521a12011-08-19 22:40:26 +03002132 break;
2133 case 32:
Aaro Koskinenfd26d422011-10-11 21:47:19 +03002134 xgifb_info->DstColor = 0xC000;
2135 xgifb_info->XGI310_AccelDepth = 0x00020000;
2136 xgifb_info->video_cmap_len = 16;
Aaro Koskinene1521a12011-08-19 22:40:26 +03002137 break;
2138 default:
Aaro Koskinenfd26d422011-10-11 21:47:19 +03002139 xgifb_info->video_cmap_len = 16;
Sam Hansen4a6b1512012-01-22 16:48:53 -08002140 pr_info("Unsupported depth %d\n",
Aaro Koskinenfd26d422011-10-11 21:47:19 +03002141 xgifb_info->video_bpp);
Aaro Koskinene1521a12011-08-19 22:40:26 +03002142 break;
2143 }
2144
Sam Hansen4a6b1512012-01-22 16:48:53 -08002145 pr_info("Default mode is %dx%dx%d (%dHz)\n",
Aaro Koskinenfd26d422011-10-11 21:47:19 +03002146 xgifb_info->video_width,
2147 xgifb_info->video_height,
2148 xgifb_info->video_bpp,
2149 xgifb_info->refresh_rate);
Aaro Koskinene1521a12011-08-19 22:40:26 +03002150
Aaro Koskinene9865d42011-10-11 21:47:26 +03002151 fb_info->var.red.length = 8;
2152 fb_info->var.green.length = 8;
2153 fb_info->var.blue.length = 8;
2154 fb_info->var.activate = FB_ACTIVATE_NOW;
2155 fb_info->var.height = -1;
2156 fb_info->var.width = -1;
2157 fb_info->var.vmode = FB_VMODE_NONINTERLACED;
2158 fb_info->var.xres = xgifb_info->video_width;
2159 fb_info->var.xres_virtual = xgifb_info->video_width;
2160 fb_info->var.yres = xgifb_info->video_height;
2161 fb_info->var.yres_virtual = xgifb_info->video_height;
2162 fb_info->var.bits_per_pixel = xgifb_info->video_bpp;
Aaro Koskinene1521a12011-08-19 22:40:26 +03002163
Aaro Koskinene9865d42011-10-11 21:47:26 +03002164 XGIfb_bpp_to_var(xgifb_info, &fb_info->var);
Aaro Koskinene1521a12011-08-19 22:40:26 +03002165
Aaro Koskinene9865d42011-10-11 21:47:26 +03002166 fb_info->var.pixclock = (u32) (1000000000 /
Aaro Koskinenf2df8c02011-10-11 21:47:30 +03002167 XGIfb_mode_rate_to_dclock(&xgifb_info->dev_info,
2168 hw_info,
Aaro Koskinenccf265a2011-10-11 21:47:22 +03002169 XGIbios_mode[xgifb_info->mode_idx].mode_no,
Aaro Koskinen5aa55d92011-10-11 21:47:23 +03002170 xgifb_info->rate_idx));
Aaro Koskinene1521a12011-08-19 22:40:26 +03002171
Aaro Koskinenf2df8c02011-10-11 21:47:30 +03002172 if (XGIfb_mode_rate_to_ddata(&xgifb_info->dev_info, hw_info,
Aaro Koskinen5aa55d92011-10-11 21:47:23 +03002173 XGIbios_mode[xgifb_info->mode_idx].mode_no,
2174 xgifb_info->rate_idx,
Aaro Koskinene9865d42011-10-11 21:47:26 +03002175 &fb_info->var.left_margin,
2176 &fb_info->var.right_margin,
2177 &fb_info->var.upper_margin,
2178 &fb_info->var.lower_margin,
2179 &fb_info->var.hsync_len,
2180 &fb_info->var.vsync_len,
2181 &fb_info->var.sync,
2182 &fb_info->var.vmode)) {
Aaro Koskinene1521a12011-08-19 22:40:26 +03002183
Aaro Koskinene9865d42011-10-11 21:47:26 +03002184 if ((fb_info->var.vmode & FB_VMODE_MASK) ==
Aaro Koskinene1521a12011-08-19 22:40:26 +03002185 FB_VMODE_INTERLACED) {
Aaro Koskinene9865d42011-10-11 21:47:26 +03002186 fb_info->var.yres <<= 1;
2187 fb_info->var.yres_virtual <<= 1;
2188 } else if ((fb_info->var.vmode & FB_VMODE_MASK) ==
Aaro Koskinene1521a12011-08-19 22:40:26 +03002189 FB_VMODE_DOUBLE) {
Aaro Koskinene9865d42011-10-11 21:47:26 +03002190 fb_info->var.pixclock >>= 1;
2191 fb_info->var.yres >>= 1;
2192 fb_info->var.yres_virtual >>= 1;
Aaro Koskinene1521a12011-08-19 22:40:26 +03002193 }
2194
2195 }
2196
2197 fb_info->flags = FBINFO_FLAG_DEFAULT;
Aaro Koskinenfd26d422011-10-11 21:47:19 +03002198 fb_info->screen_base = xgifb_info->video_vbase;
Aaro Koskinene1521a12011-08-19 22:40:26 +03002199 fb_info->fbops = &XGIfb_ops;
2200 XGIfb_get_fix(&fb_info->fix, -1, fb_info);
Aaro Koskinen76cabaa2011-10-11 21:47:24 +03002201 fb_info->pseudo_palette = xgifb_info->pseudo_palette;
Aaro Koskinene1521a12011-08-19 22:40:26 +03002202
2203 fb_alloc_cmap(&fb_info->cmap, 256 , 0);
2204
2205#ifdef CONFIG_MTRR
Aaro Koskinenfd26d422011-10-11 21:47:19 +03002206 xgifb_info->mtrr = mtrr_add(xgifb_info->video_base,
2207 xgifb_info->video_size, MTRR_TYPE_WRCOMB, 1);
2208 if (xgifb_info->mtrr >= 0)
Aaro Koskinen15ebe6c2011-09-11 00:29:54 +03002209 dev_info(&pdev->dev, "added MTRR\n");
Aaro Koskinene1521a12011-08-19 22:40:26 +03002210#endif
2211
2212 if (register_framebuffer(fb_info) < 0) {
2213 ret = -EINVAL;
Aaro Koskinen30284742011-09-11 00:29:53 +03002214 goto error_mtrr;
Aaro Koskinene1521a12011-08-19 22:40:26 +03002215 }
2216
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02002217 dumpVGAReg();
2218
2219 return 0;
Aaro Koskinenbb292232011-02-17 23:29:11 +02002220
Aaro Koskinen30284742011-09-11 00:29:53 +03002221error_mtrr:
2222#ifdef CONFIG_MTRR
Aaro Koskinenfd26d422011-10-11 21:47:19 +03002223 if (xgifb_info->mtrr >= 0)
2224 mtrr_del(xgifb_info->mtrr, xgifb_info->video_base,
2225 xgifb_info->video_size);
Aaro Koskinen30284742011-09-11 00:29:53 +03002226#endif /* CONFIG_MTRR */
Aaro Koskinen5c0ef2a2011-02-17 23:29:15 +02002227error_1:
Aaro Koskinenfd26d422011-10-11 21:47:19 +03002228 iounmap(xgifb_info->mmio_vbase);
2229 iounmap(xgifb_info->video_vbase);
2230 release_mem_region(xgifb_info->mmio_base, xgifb_info->mmio_size);
Aaro Koskinen5c0ef2a2011-02-17 23:29:15 +02002231error_0:
Aaro Koskinenfd26d422011-10-11 21:47:19 +03002232 release_mem_region(xgifb_info->video_base, xgifb_info->video_size);
Miguel Gómez05e06032012-06-06 16:22:06 +02002233error_disable:
2234 pci_disable_device(pdev);
Aaro Koskinenbb292232011-02-17 23:29:11 +02002235error:
2236 framebuffer_release(fb_info);
2237 return ret;
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02002238}
2239
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02002240/*****************************************************/
2241/* PCI DEVICE HANDLING */
2242/*****************************************************/
2243
2244static void __devexit xgifb_remove(struct pci_dev *pdev)
2245{
Aaro Koskinenab886ff2011-10-11 21:47:18 +03002246 struct xgifb_video_info *xgifb_info = pci_get_drvdata(pdev);
Aaro Koskinen19c1e882011-10-11 21:47:14 +03002247 struct fb_info *fb_info = xgifb_info->fb_info;
Aaro Koskinen54301b52011-10-11 21:47:13 +03002248
Prashant P. Shahb654f872010-09-06 17:34:26 +05302249 unregister_framebuffer(fb_info);
Aaro Koskinen30284742011-09-11 00:29:53 +03002250#ifdef CONFIG_MTRR
Aaro Koskinen54301b52011-10-11 21:47:13 +03002251 if (xgifb_info->mtrr >= 0)
2252 mtrr_del(xgifb_info->mtrr, xgifb_info->video_base,
2253 xgifb_info->video_size);
Aaro Koskinen30284742011-09-11 00:29:53 +03002254#endif /* CONFIG_MTRR */
Aaro Koskinen54301b52011-10-11 21:47:13 +03002255 iounmap(xgifb_info->mmio_vbase);
2256 iounmap(xgifb_info->video_vbase);
2257 release_mem_region(xgifb_info->mmio_base, xgifb_info->mmio_size);
2258 release_mem_region(xgifb_info->video_base, xgifb_info->video_size);
Miguel Gómezbf55b482012-06-06 16:22:07 +02002259 pci_disable_device(pdev);
Prashant P. Shahb654f872010-09-06 17:34:26 +05302260 framebuffer_release(fb_info);
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02002261 pci_set_drvdata(pdev, NULL);
Aaro Koskinen45dcfaf2011-02-17 23:29:16 +02002262}
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02002263
2264static struct pci_driver xgifb_driver = {
Prashant P. Shahb654f872010-09-06 17:34:26 +05302265 .name = "xgifb",
2266 .id_table = xgifb_pci_table,
2267 .probe = xgifb_probe,
2268 .remove = __devexit_p(xgifb_remove)
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02002269};
2270
Miguel Gómezd0490532012-06-06 16:22:05 +02002271
2272
2273/*****************************************************/
2274/* MODULE */
2275/*****************************************************/
2276
2277module_param(mode, charp, 0);
2278MODULE_PARM_DESC(mode,
Miguel Gómez560e8782012-06-18 13:11:59 +02002279 "Selects the desired default display mode in the format XxYxDepth "
2280 "(eg. 1024x768x16).");
Miguel Gómezd0490532012-06-06 16:22:05 +02002281
2282module_param(forcecrt2type, charp, 0);
2283MODULE_PARM_DESC(forcecrt2type,
Miguel Gómez560e8782012-06-18 13:11:59 +02002284 "Force the second display output type. Possible values are NONE, "
2285 "LCD, TV, VGA, SVIDEO or COMPOSITE.");
Miguel Gómezd0490532012-06-06 16:22:05 +02002286
2287module_param(vesa, int, 0);
2288MODULE_PARM_DESC(vesa,
Miguel Gómez560e8782012-06-18 13:11:59 +02002289 "Selects the desired default display mode by VESA mode number "
2290 "(eg. 0x117).");
Miguel Gómezd0490532012-06-06 16:22:05 +02002291
2292module_param(filter, int, 0);
2293MODULE_PARM_DESC(filter,
Miguel Gómez560e8782012-06-18 13:11:59 +02002294 "Selects TV flicker filter type (only for systems with a SiS301 video bridge). "
2295 "Possible values 0-7. Default: [no filter]).");
Miguel Gómezd0490532012-06-06 16:22:05 +02002296
Ruslan Pisarev032abf72011-07-21 11:59:11 +03002297static int __init xgifb_init(void)
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02002298{
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02002299 char *option = NULL;
2300
Aaro Koskinen2d2c8802011-12-06 00:10:49 +02002301 if (forcecrt2type != NULL)
2302 XGIfb_search_crt2type(forcecrt2type);
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02002303 if (fb_get_options("xgifb", &option))
2304 return -ENODEV;
2305 XGIfb_setup(option);
Javier Martinez Canillas328f55b2010-09-08 00:07:57 -04002306
Prashant P. Shahb654f872010-09-06 17:34:26 +05302307 return pci_register_driver(&xgifb_driver);
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02002308}
2309
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02002310static void __exit xgifb_remove_module(void)
2311{
2312 pci_unregister_driver(&xgifb_driver);
Sam Hansen4a6b1512012-01-22 16:48:53 -08002313 pr_debug("Module unloaded\n");
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02002314}
2315
Miguel Gómezd0490532012-06-06 16:22:05 +02002316MODULE_DESCRIPTION("Z7 Z9 Z9S Z11 framebuffer device driver");
2317MODULE_LICENSE("GPL");
2318MODULE_AUTHOR("XGITECH , Others");
2319module_init(xgifb_init);
apatard@mandriva.comd7636e02010-05-19 10:44:14 +02002320module_exit(xgifb_remove_module);