1*4882a593Smuzhiyun /* SPDX-License-Identifier: GPL-2.0 */
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun *
4*4882a593Smuzhiyun * Hardware accelerated Matrox Millennium I, II, Mystique, G100, G200, G400 and G450
5*4882a593Smuzhiyun *
6*4882a593Smuzhiyun * (c) 1998-2002 Petr Vandrovec <vandrove@vc.cvut.cz>
7*4882a593Smuzhiyun *
8*4882a593Smuzhiyun */
9*4882a593Smuzhiyun #ifndef __MATROXFB_H__
10*4882a593Smuzhiyun #define __MATROXFB_H__
11*4882a593Smuzhiyun
12*4882a593Smuzhiyun /* general, but fairly heavy, debugging */
13*4882a593Smuzhiyun #undef MATROXFB_DEBUG
14*4882a593Smuzhiyun
15*4882a593Smuzhiyun /* heavy debugging: */
16*4882a593Smuzhiyun /* -- logs putc[s], so every time a char is displayed, it's logged */
17*4882a593Smuzhiyun #undef MATROXFB_DEBUG_HEAVY
18*4882a593Smuzhiyun
19*4882a593Smuzhiyun /* This one _could_ cause infinite loops */
20*4882a593Smuzhiyun /* It _does_ cause lots and lots of messages during idle loops */
21*4882a593Smuzhiyun #undef MATROXFB_DEBUG_LOOP
22*4882a593Smuzhiyun
23*4882a593Smuzhiyun /* Debug register calls, too? */
24*4882a593Smuzhiyun #undef MATROXFB_DEBUG_REG
25*4882a593Smuzhiyun
26*4882a593Smuzhiyun /* Guard accelerator accesses with spin_lock_irqsave... */
27*4882a593Smuzhiyun #undef MATROXFB_USE_SPINLOCKS
28*4882a593Smuzhiyun
29*4882a593Smuzhiyun #include <linux/module.h>
30*4882a593Smuzhiyun #include <linux/kernel.h>
31*4882a593Smuzhiyun #include <linux/errno.h>
32*4882a593Smuzhiyun #include <linux/string.h>
33*4882a593Smuzhiyun #include <linux/mm.h>
34*4882a593Smuzhiyun #include <linux/slab.h>
35*4882a593Smuzhiyun #include <linux/delay.h>
36*4882a593Smuzhiyun #include <linux/fb.h>
37*4882a593Smuzhiyun #include <linux/console.h>
38*4882a593Smuzhiyun #include <linux/selection.h>
39*4882a593Smuzhiyun #include <linux/ioport.h>
40*4882a593Smuzhiyun #include <linux/init.h>
41*4882a593Smuzhiyun #include <linux/timer.h>
42*4882a593Smuzhiyun #include <linux/pci.h>
43*4882a593Smuzhiyun #include <linux/spinlock.h>
44*4882a593Smuzhiyun #include <linux/kd.h>
45*4882a593Smuzhiyun
46*4882a593Smuzhiyun #include <asm/io.h>
47*4882a593Smuzhiyun #include <asm/unaligned.h>
48*4882a593Smuzhiyun
49*4882a593Smuzhiyun #if defined(CONFIG_PPC_PMAC)
50*4882a593Smuzhiyun #include <asm/prom.h>
51*4882a593Smuzhiyun #include "../macmodes.h"
52*4882a593Smuzhiyun #endif
53*4882a593Smuzhiyun
54*4882a593Smuzhiyun #ifdef MATROXFB_DEBUG
55*4882a593Smuzhiyun
56*4882a593Smuzhiyun #define DEBUG
57*4882a593Smuzhiyun #define DBG(x) printk(KERN_DEBUG "matroxfb: %s\n", (x));
58*4882a593Smuzhiyun
59*4882a593Smuzhiyun #ifdef MATROXFB_DEBUG_HEAVY
60*4882a593Smuzhiyun #define DBG_HEAVY(x) DBG(x)
61*4882a593Smuzhiyun #else /* MATROXFB_DEBUG_HEAVY */
62*4882a593Smuzhiyun #define DBG_HEAVY(x) /* DBG_HEAVY */
63*4882a593Smuzhiyun #endif /* MATROXFB_DEBUG_HEAVY */
64*4882a593Smuzhiyun
65*4882a593Smuzhiyun #ifdef MATROXFB_DEBUG_LOOP
66*4882a593Smuzhiyun #define DBG_LOOP(x) DBG(x)
67*4882a593Smuzhiyun #else /* MATROXFB_DEBUG_LOOP */
68*4882a593Smuzhiyun #define DBG_LOOP(x) /* DBG_LOOP */
69*4882a593Smuzhiyun #endif /* MATROXFB_DEBUG_LOOP */
70*4882a593Smuzhiyun
71*4882a593Smuzhiyun #ifdef MATROXFB_DEBUG_REG
72*4882a593Smuzhiyun #define DBG_REG(x) DBG(x)
73*4882a593Smuzhiyun #else /* MATROXFB_DEBUG_REG */
74*4882a593Smuzhiyun #define DBG_REG(x) /* DBG_REG */
75*4882a593Smuzhiyun #endif /* MATROXFB_DEBUG_REG */
76*4882a593Smuzhiyun
77*4882a593Smuzhiyun #else /* MATROXFB_DEBUG */
78*4882a593Smuzhiyun
79*4882a593Smuzhiyun #define DBG(x) /* DBG */
80*4882a593Smuzhiyun #define DBG_HEAVY(x) /* DBG_HEAVY */
81*4882a593Smuzhiyun #define DBG_REG(x) /* DBG_REG */
82*4882a593Smuzhiyun #define DBG_LOOP(x) /* DBG_LOOP */
83*4882a593Smuzhiyun
84*4882a593Smuzhiyun #endif /* MATROXFB_DEBUG */
85*4882a593Smuzhiyun
86*4882a593Smuzhiyun #ifdef DEBUG
87*4882a593Smuzhiyun #define dprintk(X...) printk(X)
88*4882a593Smuzhiyun #else
89*4882a593Smuzhiyun #define dprintk(X...) no_printk(X)
90*4882a593Smuzhiyun #endif
91*4882a593Smuzhiyun
92*4882a593Smuzhiyun #ifndef PCI_SS_VENDOR_ID_SIEMENS_NIXDORF
93*4882a593Smuzhiyun #define PCI_SS_VENDOR_ID_SIEMENS_NIXDORF 0x110A
94*4882a593Smuzhiyun #endif
95*4882a593Smuzhiyun #ifndef PCI_SS_VENDOR_ID_MATROX
96*4882a593Smuzhiyun #define PCI_SS_VENDOR_ID_MATROX PCI_VENDOR_ID_MATROX
97*4882a593Smuzhiyun #endif
98*4882a593Smuzhiyun
99*4882a593Smuzhiyun #ifndef PCI_SS_ID_MATROX_PRODUCTIVA_G100_AGP
100*4882a593Smuzhiyun #define PCI_SS_ID_MATROX_GENERIC 0xFF00
101*4882a593Smuzhiyun #define PCI_SS_ID_MATROX_PRODUCTIVA_G100_AGP 0xFF01
102*4882a593Smuzhiyun #define PCI_SS_ID_MATROX_MYSTIQUE_G200_AGP 0xFF02
103*4882a593Smuzhiyun #define PCI_SS_ID_MATROX_MILLENIUM_G200_AGP 0xFF03
104*4882a593Smuzhiyun #define PCI_SS_ID_MATROX_MARVEL_G200_AGP 0xFF04
105*4882a593Smuzhiyun #define PCI_SS_ID_MATROX_MGA_G100_PCI 0xFF05
106*4882a593Smuzhiyun #define PCI_SS_ID_MATROX_MGA_G100_AGP 0x1001
107*4882a593Smuzhiyun #define PCI_SS_ID_MATROX_MILLENNIUM_G400_MAX_AGP 0x2179
108*4882a593Smuzhiyun #define PCI_SS_ID_SIEMENS_MGA_G100_AGP 0x001E /* 30 */
109*4882a593Smuzhiyun #define PCI_SS_ID_SIEMENS_MGA_G200_AGP 0x0032 /* 50 */
110*4882a593Smuzhiyun #endif
111*4882a593Smuzhiyun
112*4882a593Smuzhiyun #define MX_VISUAL_TRUECOLOR FB_VISUAL_DIRECTCOLOR
113*4882a593Smuzhiyun #define MX_VISUAL_DIRECTCOLOR FB_VISUAL_TRUECOLOR
114*4882a593Smuzhiyun #define MX_VISUAL_PSEUDOCOLOR FB_VISUAL_PSEUDOCOLOR
115*4882a593Smuzhiyun
116*4882a593Smuzhiyun #define CNVT_TOHW(val,width) ((((val)<<(width))+0x7FFF-(val))>>16)
117*4882a593Smuzhiyun
118*4882a593Smuzhiyun /* G-series and Mystique have (almost) same DAC */
119*4882a593Smuzhiyun #undef NEED_DAC1064
120*4882a593Smuzhiyun #if defined(CONFIG_FB_MATROX_MYSTIQUE) || defined(CONFIG_FB_MATROX_G)
121*4882a593Smuzhiyun #define NEED_DAC1064 1
122*4882a593Smuzhiyun #endif
123*4882a593Smuzhiyun
124*4882a593Smuzhiyun typedef struct {
125*4882a593Smuzhiyun void __iomem* vaddr;
126*4882a593Smuzhiyun } vaddr_t;
127*4882a593Smuzhiyun
mga_readb(vaddr_t va,unsigned int offs)128*4882a593Smuzhiyun static inline unsigned int mga_readb(vaddr_t va, unsigned int offs) {
129*4882a593Smuzhiyun return readb(va.vaddr + offs);
130*4882a593Smuzhiyun }
131*4882a593Smuzhiyun
mga_writeb(vaddr_t va,unsigned int offs,u_int8_t value)132*4882a593Smuzhiyun static inline void mga_writeb(vaddr_t va, unsigned int offs, u_int8_t value) {
133*4882a593Smuzhiyun writeb(value, va.vaddr + offs);
134*4882a593Smuzhiyun }
135*4882a593Smuzhiyun
mga_writew(vaddr_t va,unsigned int offs,u_int16_t value)136*4882a593Smuzhiyun static inline void mga_writew(vaddr_t va, unsigned int offs, u_int16_t value) {
137*4882a593Smuzhiyun writew(value, va.vaddr + offs);
138*4882a593Smuzhiyun }
139*4882a593Smuzhiyun
mga_readl(vaddr_t va,unsigned int offs)140*4882a593Smuzhiyun static inline u_int32_t mga_readl(vaddr_t va, unsigned int offs) {
141*4882a593Smuzhiyun return readl(va.vaddr + offs);
142*4882a593Smuzhiyun }
143*4882a593Smuzhiyun
mga_writel(vaddr_t va,unsigned int offs,u_int32_t value)144*4882a593Smuzhiyun static inline void mga_writel(vaddr_t va, unsigned int offs, u_int32_t value) {
145*4882a593Smuzhiyun writel(value, va.vaddr + offs);
146*4882a593Smuzhiyun }
147*4882a593Smuzhiyun
mga_memcpy_toio(vaddr_t va,const void * src,int len)148*4882a593Smuzhiyun static inline void mga_memcpy_toio(vaddr_t va, const void* src, int len) {
149*4882a593Smuzhiyun #if defined(__alpha__) || defined(__i386__) || defined(__x86_64__)
150*4882a593Smuzhiyun /*
151*4882a593Smuzhiyun * iowrite32_rep works for us if:
152*4882a593Smuzhiyun * (1) Copies data as 32bit quantities, not byte after byte,
153*4882a593Smuzhiyun * (2) Performs LE ordered stores, and
154*4882a593Smuzhiyun * (3) It copes with unaligned source (destination is guaranteed to be page
155*4882a593Smuzhiyun * aligned and length is guaranteed to be multiple of 4).
156*4882a593Smuzhiyun */
157*4882a593Smuzhiyun iowrite32_rep(va.vaddr, src, len >> 2);
158*4882a593Smuzhiyun #else
159*4882a593Smuzhiyun u_int32_t __iomem* addr = va.vaddr;
160*4882a593Smuzhiyun
161*4882a593Smuzhiyun if ((unsigned long)src & 3) {
162*4882a593Smuzhiyun while (len >= 4) {
163*4882a593Smuzhiyun fb_writel(get_unaligned((u32 *)src), addr);
164*4882a593Smuzhiyun addr++;
165*4882a593Smuzhiyun len -= 4;
166*4882a593Smuzhiyun src += 4;
167*4882a593Smuzhiyun }
168*4882a593Smuzhiyun } else {
169*4882a593Smuzhiyun while (len >= 4) {
170*4882a593Smuzhiyun fb_writel(*(u32 *)src, addr);
171*4882a593Smuzhiyun addr++;
172*4882a593Smuzhiyun len -= 4;
173*4882a593Smuzhiyun src += 4;
174*4882a593Smuzhiyun }
175*4882a593Smuzhiyun }
176*4882a593Smuzhiyun #endif
177*4882a593Smuzhiyun }
178*4882a593Smuzhiyun
vaddr_add(vaddr_t * va,unsigned long offs)179*4882a593Smuzhiyun static inline void vaddr_add(vaddr_t* va, unsigned long offs) {
180*4882a593Smuzhiyun va->vaddr += offs;
181*4882a593Smuzhiyun }
182*4882a593Smuzhiyun
vaddr_va(vaddr_t va)183*4882a593Smuzhiyun static inline void __iomem* vaddr_va(vaddr_t va) {
184*4882a593Smuzhiyun return va.vaddr;
185*4882a593Smuzhiyun }
186*4882a593Smuzhiyun
187*4882a593Smuzhiyun struct my_timming {
188*4882a593Smuzhiyun unsigned int pixclock;
189*4882a593Smuzhiyun int mnp;
190*4882a593Smuzhiyun unsigned int crtc;
191*4882a593Smuzhiyun unsigned int HDisplay;
192*4882a593Smuzhiyun unsigned int HSyncStart;
193*4882a593Smuzhiyun unsigned int HSyncEnd;
194*4882a593Smuzhiyun unsigned int HTotal;
195*4882a593Smuzhiyun unsigned int VDisplay;
196*4882a593Smuzhiyun unsigned int VSyncStart;
197*4882a593Smuzhiyun unsigned int VSyncEnd;
198*4882a593Smuzhiyun unsigned int VTotal;
199*4882a593Smuzhiyun unsigned int sync;
200*4882a593Smuzhiyun int dblscan;
201*4882a593Smuzhiyun int interlaced;
202*4882a593Smuzhiyun unsigned int delay; /* CRTC delay */
203*4882a593Smuzhiyun };
204*4882a593Smuzhiyun
205*4882a593Smuzhiyun enum { M_SYSTEM_PLL, M_PIXEL_PLL_A, M_PIXEL_PLL_B, M_PIXEL_PLL_C, M_VIDEO_PLL };
206*4882a593Smuzhiyun
207*4882a593Smuzhiyun struct matrox_pll_cache {
208*4882a593Smuzhiyun unsigned int valid;
209*4882a593Smuzhiyun struct {
210*4882a593Smuzhiyun unsigned int mnp_key;
211*4882a593Smuzhiyun unsigned int mnp_value;
212*4882a593Smuzhiyun } data[4];
213*4882a593Smuzhiyun };
214*4882a593Smuzhiyun
215*4882a593Smuzhiyun struct matrox_pll_limits {
216*4882a593Smuzhiyun unsigned int vcomin;
217*4882a593Smuzhiyun unsigned int vcomax;
218*4882a593Smuzhiyun };
219*4882a593Smuzhiyun
220*4882a593Smuzhiyun struct matrox_pll_features {
221*4882a593Smuzhiyun unsigned int vco_freq_min;
222*4882a593Smuzhiyun unsigned int ref_freq;
223*4882a593Smuzhiyun unsigned int feed_div_min;
224*4882a593Smuzhiyun unsigned int feed_div_max;
225*4882a593Smuzhiyun unsigned int in_div_min;
226*4882a593Smuzhiyun unsigned int in_div_max;
227*4882a593Smuzhiyun unsigned int post_shift_max;
228*4882a593Smuzhiyun };
229*4882a593Smuzhiyun
230*4882a593Smuzhiyun struct matroxfb_par
231*4882a593Smuzhiyun {
232*4882a593Smuzhiyun unsigned int final_bppShift;
233*4882a593Smuzhiyun unsigned int cmap_len;
234*4882a593Smuzhiyun struct {
235*4882a593Smuzhiyun unsigned int bytes;
236*4882a593Smuzhiyun unsigned int pixels;
237*4882a593Smuzhiyun unsigned int chunks;
238*4882a593Smuzhiyun } ydstorg;
239*4882a593Smuzhiyun };
240*4882a593Smuzhiyun
241*4882a593Smuzhiyun struct matrox_fb_info;
242*4882a593Smuzhiyun
243*4882a593Smuzhiyun struct matrox_DAC1064_features {
244*4882a593Smuzhiyun u_int8_t xvrefctrl;
245*4882a593Smuzhiyun u_int8_t xmiscctrl;
246*4882a593Smuzhiyun };
247*4882a593Smuzhiyun
248*4882a593Smuzhiyun /* current hardware status */
249*4882a593Smuzhiyun struct mavenregs {
250*4882a593Smuzhiyun u_int8_t regs[256];
251*4882a593Smuzhiyun int mode;
252*4882a593Smuzhiyun int vlines;
253*4882a593Smuzhiyun int xtal;
254*4882a593Smuzhiyun int fv;
255*4882a593Smuzhiyun
256*4882a593Smuzhiyun u_int16_t htotal;
257*4882a593Smuzhiyun u_int16_t hcorr;
258*4882a593Smuzhiyun };
259*4882a593Smuzhiyun
260*4882a593Smuzhiyun struct matrox_crtc2 {
261*4882a593Smuzhiyun u_int32_t ctl;
262*4882a593Smuzhiyun };
263*4882a593Smuzhiyun
264*4882a593Smuzhiyun struct matrox_hw_state {
265*4882a593Smuzhiyun u_int32_t MXoptionReg;
266*4882a593Smuzhiyun unsigned char DACclk[6];
267*4882a593Smuzhiyun unsigned char DACreg[80];
268*4882a593Smuzhiyun unsigned char MiscOutReg;
269*4882a593Smuzhiyun unsigned char DACpal[768];
270*4882a593Smuzhiyun unsigned char CRTC[25];
271*4882a593Smuzhiyun unsigned char CRTCEXT[9];
272*4882a593Smuzhiyun unsigned char SEQ[5];
273*4882a593Smuzhiyun /* unused for MGA mode, but who knows... */
274*4882a593Smuzhiyun unsigned char GCTL[9];
275*4882a593Smuzhiyun /* unused for MGA mode, but who knows... */
276*4882a593Smuzhiyun unsigned char ATTR[21];
277*4882a593Smuzhiyun
278*4882a593Smuzhiyun /* TVOut only */
279*4882a593Smuzhiyun struct mavenregs maven;
280*4882a593Smuzhiyun
281*4882a593Smuzhiyun struct matrox_crtc2 crtc2;
282*4882a593Smuzhiyun };
283*4882a593Smuzhiyun
284*4882a593Smuzhiyun struct matrox_accel_data {
285*4882a593Smuzhiyun #ifdef CONFIG_FB_MATROX_MILLENIUM
286*4882a593Smuzhiyun unsigned char ramdac_rev;
287*4882a593Smuzhiyun #endif
288*4882a593Smuzhiyun u_int32_t m_dwg_rect;
289*4882a593Smuzhiyun u_int32_t m_opmode;
290*4882a593Smuzhiyun u_int32_t m_access;
291*4882a593Smuzhiyun u_int32_t m_pitch;
292*4882a593Smuzhiyun };
293*4882a593Smuzhiyun
294*4882a593Smuzhiyun struct v4l2_queryctrl;
295*4882a593Smuzhiyun struct v4l2_control;
296*4882a593Smuzhiyun
297*4882a593Smuzhiyun struct matrox_altout {
298*4882a593Smuzhiyun const char *name;
299*4882a593Smuzhiyun int (*compute)(void* altout_dev, struct my_timming* input);
300*4882a593Smuzhiyun int (*program)(void* altout_dev);
301*4882a593Smuzhiyun int (*start)(void* altout_dev);
302*4882a593Smuzhiyun int (*verifymode)(void* altout_dev, u_int32_t mode);
303*4882a593Smuzhiyun int (*getqueryctrl)(void* altout_dev,
304*4882a593Smuzhiyun struct v4l2_queryctrl* ctrl);
305*4882a593Smuzhiyun int (*getctrl)(void* altout_dev,
306*4882a593Smuzhiyun struct v4l2_control* ctrl);
307*4882a593Smuzhiyun int (*setctrl)(void* altout_dev,
308*4882a593Smuzhiyun struct v4l2_control* ctrl);
309*4882a593Smuzhiyun };
310*4882a593Smuzhiyun
311*4882a593Smuzhiyun #define MATROXFB_SRC_NONE 0
312*4882a593Smuzhiyun #define MATROXFB_SRC_CRTC1 1
313*4882a593Smuzhiyun #define MATROXFB_SRC_CRTC2 2
314*4882a593Smuzhiyun
315*4882a593Smuzhiyun enum mga_chip { MGA_2064, MGA_2164, MGA_1064, MGA_1164, MGA_G100, MGA_G200, MGA_G400, MGA_G450, MGA_G550 };
316*4882a593Smuzhiyun
317*4882a593Smuzhiyun struct matrox_bios {
318*4882a593Smuzhiyun unsigned int bios_valid : 1;
319*4882a593Smuzhiyun unsigned int pins_len;
320*4882a593Smuzhiyun unsigned char pins[128];
321*4882a593Smuzhiyun struct {
322*4882a593Smuzhiyun unsigned char vMaj, vMin, vRev;
323*4882a593Smuzhiyun } version;
324*4882a593Smuzhiyun struct {
325*4882a593Smuzhiyun unsigned char state, tvout;
326*4882a593Smuzhiyun } output;
327*4882a593Smuzhiyun };
328*4882a593Smuzhiyun
329*4882a593Smuzhiyun struct matrox_switch;
330*4882a593Smuzhiyun struct matroxfb_driver;
331*4882a593Smuzhiyun struct matroxfb_dh_fb_info;
332*4882a593Smuzhiyun
333*4882a593Smuzhiyun struct matrox_vsync {
334*4882a593Smuzhiyun wait_queue_head_t wait;
335*4882a593Smuzhiyun unsigned int cnt;
336*4882a593Smuzhiyun };
337*4882a593Smuzhiyun
338*4882a593Smuzhiyun struct matrox_fb_info {
339*4882a593Smuzhiyun struct fb_info fbcon;
340*4882a593Smuzhiyun
341*4882a593Smuzhiyun struct list_head next_fb;
342*4882a593Smuzhiyun
343*4882a593Smuzhiyun int dead;
344*4882a593Smuzhiyun int initialized;
345*4882a593Smuzhiyun unsigned int usecount;
346*4882a593Smuzhiyun
347*4882a593Smuzhiyun unsigned int userusecount;
348*4882a593Smuzhiyun unsigned long irq_flags;
349*4882a593Smuzhiyun
350*4882a593Smuzhiyun struct matroxfb_par curr;
351*4882a593Smuzhiyun struct matrox_hw_state hw;
352*4882a593Smuzhiyun
353*4882a593Smuzhiyun struct matrox_accel_data accel;
354*4882a593Smuzhiyun
355*4882a593Smuzhiyun struct pci_dev* pcidev;
356*4882a593Smuzhiyun
357*4882a593Smuzhiyun struct {
358*4882a593Smuzhiyun struct matrox_vsync vsync;
359*4882a593Smuzhiyun unsigned int pixclock;
360*4882a593Smuzhiyun int mnp;
361*4882a593Smuzhiyun int panpos;
362*4882a593Smuzhiyun } crtc1;
363*4882a593Smuzhiyun struct {
364*4882a593Smuzhiyun struct matrox_vsync vsync;
365*4882a593Smuzhiyun unsigned int pixclock;
366*4882a593Smuzhiyun int mnp;
367*4882a593Smuzhiyun struct matroxfb_dh_fb_info* info;
368*4882a593Smuzhiyun struct rw_semaphore lock;
369*4882a593Smuzhiyun } crtc2;
370*4882a593Smuzhiyun struct {
371*4882a593Smuzhiyun struct rw_semaphore lock;
372*4882a593Smuzhiyun struct {
373*4882a593Smuzhiyun int brightness, contrast, saturation, hue, gamma;
374*4882a593Smuzhiyun int testout, deflicker;
375*4882a593Smuzhiyun } tvo_params;
376*4882a593Smuzhiyun } altout;
377*4882a593Smuzhiyun #define MATROXFB_MAX_OUTPUTS 3
378*4882a593Smuzhiyun struct {
379*4882a593Smuzhiyun unsigned int src;
380*4882a593Smuzhiyun struct matrox_altout* output;
381*4882a593Smuzhiyun void* data;
382*4882a593Smuzhiyun unsigned int mode;
383*4882a593Smuzhiyun unsigned int default_src;
384*4882a593Smuzhiyun } outputs[MATROXFB_MAX_OUTPUTS];
385*4882a593Smuzhiyun
386*4882a593Smuzhiyun #define MATROXFB_MAX_FB_DRIVERS 5
387*4882a593Smuzhiyun struct matroxfb_driver* (drivers[MATROXFB_MAX_FB_DRIVERS]);
388*4882a593Smuzhiyun void* (drivers_data[MATROXFB_MAX_FB_DRIVERS]);
389*4882a593Smuzhiyun unsigned int drivers_count;
390*4882a593Smuzhiyun
391*4882a593Smuzhiyun struct {
392*4882a593Smuzhiyun unsigned long base; /* physical */
393*4882a593Smuzhiyun vaddr_t vbase; /* CPU view */
394*4882a593Smuzhiyun unsigned int len;
395*4882a593Smuzhiyun unsigned int len_usable;
396*4882a593Smuzhiyun unsigned int len_maximum;
397*4882a593Smuzhiyun } video;
398*4882a593Smuzhiyun
399*4882a593Smuzhiyun struct {
400*4882a593Smuzhiyun unsigned long base; /* physical */
401*4882a593Smuzhiyun vaddr_t vbase; /* CPU view */
402*4882a593Smuzhiyun unsigned int len;
403*4882a593Smuzhiyun } mmio;
404*4882a593Smuzhiyun
405*4882a593Smuzhiyun unsigned int max_pixel_clock;
406*4882a593Smuzhiyun unsigned int max_pixel_clock_panellink;
407*4882a593Smuzhiyun
408*4882a593Smuzhiyun struct matrox_switch* hw_switch;
409*4882a593Smuzhiyun
410*4882a593Smuzhiyun struct {
411*4882a593Smuzhiyun struct matrox_pll_features pll;
412*4882a593Smuzhiyun struct matrox_DAC1064_features DAC1064;
413*4882a593Smuzhiyun } features;
414*4882a593Smuzhiyun struct {
415*4882a593Smuzhiyun spinlock_t DAC;
416*4882a593Smuzhiyun spinlock_t accel;
417*4882a593Smuzhiyun } lock;
418*4882a593Smuzhiyun
419*4882a593Smuzhiyun enum mga_chip chip;
420*4882a593Smuzhiyun
421*4882a593Smuzhiyun int interleave;
422*4882a593Smuzhiyun int millenium;
423*4882a593Smuzhiyun int milleniumII;
424*4882a593Smuzhiyun struct {
425*4882a593Smuzhiyun int cfb4;
426*4882a593Smuzhiyun const int* vxres;
427*4882a593Smuzhiyun int cross4MB;
428*4882a593Smuzhiyun int text;
429*4882a593Smuzhiyun int plnwt;
430*4882a593Smuzhiyun int srcorg;
431*4882a593Smuzhiyun } capable;
432*4882a593Smuzhiyun int wc_cookie;
433*4882a593Smuzhiyun struct {
434*4882a593Smuzhiyun int precise_width;
435*4882a593Smuzhiyun int mga_24bpp_fix;
436*4882a593Smuzhiyun int novga;
437*4882a593Smuzhiyun int nobios;
438*4882a593Smuzhiyun int nopciretry;
439*4882a593Smuzhiyun int noinit;
440*4882a593Smuzhiyun int sgram;
441*4882a593Smuzhiyun int support32MB;
442*4882a593Smuzhiyun
443*4882a593Smuzhiyun int accelerator;
444*4882a593Smuzhiyun int text_type_aux;
445*4882a593Smuzhiyun int video64bits;
446*4882a593Smuzhiyun int crtc2;
447*4882a593Smuzhiyun int maven_capable;
448*4882a593Smuzhiyun unsigned int vgastep;
449*4882a593Smuzhiyun unsigned int textmode;
450*4882a593Smuzhiyun unsigned int textstep;
451*4882a593Smuzhiyun unsigned int textvram; /* character cells */
452*4882a593Smuzhiyun unsigned int ydstorg; /* offset in bytes from video start to usable memory */
453*4882a593Smuzhiyun /* 0 except for 6MB Millenium */
454*4882a593Smuzhiyun int memtype;
455*4882a593Smuzhiyun int g450dac;
456*4882a593Smuzhiyun int dfp_type;
457*4882a593Smuzhiyun int panellink; /* G400 DFP possible (not G450/G550) */
458*4882a593Smuzhiyun int dualhead;
459*4882a593Smuzhiyun unsigned int fbResource;
460*4882a593Smuzhiyun } devflags;
461*4882a593Smuzhiyun struct fb_ops fbops;
462*4882a593Smuzhiyun struct matrox_bios bios;
463*4882a593Smuzhiyun struct {
464*4882a593Smuzhiyun struct matrox_pll_limits pixel;
465*4882a593Smuzhiyun struct matrox_pll_limits system;
466*4882a593Smuzhiyun struct matrox_pll_limits video;
467*4882a593Smuzhiyun } limits;
468*4882a593Smuzhiyun struct {
469*4882a593Smuzhiyun struct matrox_pll_cache pixel;
470*4882a593Smuzhiyun struct matrox_pll_cache system;
471*4882a593Smuzhiyun struct matrox_pll_cache video;
472*4882a593Smuzhiyun } cache;
473*4882a593Smuzhiyun struct {
474*4882a593Smuzhiyun struct {
475*4882a593Smuzhiyun unsigned int video;
476*4882a593Smuzhiyun unsigned int system;
477*4882a593Smuzhiyun } pll;
478*4882a593Smuzhiyun struct {
479*4882a593Smuzhiyun u_int32_t opt;
480*4882a593Smuzhiyun u_int32_t opt2;
481*4882a593Smuzhiyun u_int32_t opt3;
482*4882a593Smuzhiyun u_int32_t mctlwtst;
483*4882a593Smuzhiyun u_int32_t mctlwtst_core;
484*4882a593Smuzhiyun u_int32_t memmisc;
485*4882a593Smuzhiyun u_int32_t memrdbk;
486*4882a593Smuzhiyun u_int32_t maccess;
487*4882a593Smuzhiyun } reg;
488*4882a593Smuzhiyun struct {
489*4882a593Smuzhiyun unsigned int ddr:1,
490*4882a593Smuzhiyun emrswen:1,
491*4882a593Smuzhiyun dll:1;
492*4882a593Smuzhiyun } memory;
493*4882a593Smuzhiyun } values;
494*4882a593Smuzhiyun u_int32_t cmap[16];
495*4882a593Smuzhiyun };
496*4882a593Smuzhiyun
497*4882a593Smuzhiyun #define info2minfo(info) container_of(info, struct matrox_fb_info, fbcon)
498*4882a593Smuzhiyun
499*4882a593Smuzhiyun struct matrox_switch {
500*4882a593Smuzhiyun int (*preinit)(struct matrox_fb_info *minfo);
501*4882a593Smuzhiyun void (*reset)(struct matrox_fb_info *minfo);
502*4882a593Smuzhiyun int (*init)(struct matrox_fb_info *minfo, struct my_timming*);
503*4882a593Smuzhiyun void (*restore)(struct matrox_fb_info *minfo);
504*4882a593Smuzhiyun };
505*4882a593Smuzhiyun
506*4882a593Smuzhiyun struct matroxfb_driver {
507*4882a593Smuzhiyun struct list_head node;
508*4882a593Smuzhiyun char* name;
509*4882a593Smuzhiyun void* (*probe)(struct matrox_fb_info* info);
510*4882a593Smuzhiyun void (*remove)(struct matrox_fb_info* info, void* data);
511*4882a593Smuzhiyun };
512*4882a593Smuzhiyun
513*4882a593Smuzhiyun int matroxfb_register_driver(struct matroxfb_driver* drv);
514*4882a593Smuzhiyun void matroxfb_unregister_driver(struct matroxfb_driver* drv);
515*4882a593Smuzhiyun
516*4882a593Smuzhiyun #define PCI_OPTION_REG 0x40
517*4882a593Smuzhiyun #define PCI_OPTION_ENABLE_ROM 0x40000000
518*4882a593Smuzhiyun
519*4882a593Smuzhiyun #define PCI_MGA_INDEX 0x44
520*4882a593Smuzhiyun #define PCI_MGA_DATA 0x48
521*4882a593Smuzhiyun #define PCI_OPTION2_REG 0x50
522*4882a593Smuzhiyun #define PCI_OPTION3_REG 0x54
523*4882a593Smuzhiyun #define PCI_MEMMISC_REG 0x58
524*4882a593Smuzhiyun
525*4882a593Smuzhiyun #define M_DWGCTL 0x1C00
526*4882a593Smuzhiyun #define M_MACCESS 0x1C04
527*4882a593Smuzhiyun #define M_CTLWTST 0x1C08
528*4882a593Smuzhiyun
529*4882a593Smuzhiyun #define M_PLNWT 0x1C1C
530*4882a593Smuzhiyun
531*4882a593Smuzhiyun #define M_BCOL 0x1C20
532*4882a593Smuzhiyun #define M_FCOL 0x1C24
533*4882a593Smuzhiyun
534*4882a593Smuzhiyun #define M_SGN 0x1C58
535*4882a593Smuzhiyun #define M_LEN 0x1C5C
536*4882a593Smuzhiyun #define M_AR0 0x1C60
537*4882a593Smuzhiyun #define M_AR1 0x1C64
538*4882a593Smuzhiyun #define M_AR2 0x1C68
539*4882a593Smuzhiyun #define M_AR3 0x1C6C
540*4882a593Smuzhiyun #define M_AR4 0x1C70
541*4882a593Smuzhiyun #define M_AR5 0x1C74
542*4882a593Smuzhiyun #define M_AR6 0x1C78
543*4882a593Smuzhiyun
544*4882a593Smuzhiyun #define M_CXBNDRY 0x1C80
545*4882a593Smuzhiyun #define M_FXBNDRY 0x1C84
546*4882a593Smuzhiyun #define M_YDSTLEN 0x1C88
547*4882a593Smuzhiyun #define M_PITCH 0x1C8C
548*4882a593Smuzhiyun #define M_YDST 0x1C90
549*4882a593Smuzhiyun #define M_YDSTORG 0x1C94
550*4882a593Smuzhiyun #define M_YTOP 0x1C98
551*4882a593Smuzhiyun #define M_YBOT 0x1C9C
552*4882a593Smuzhiyun
553*4882a593Smuzhiyun /* mystique only */
554*4882a593Smuzhiyun #define M_CACHEFLUSH 0x1FFF
555*4882a593Smuzhiyun
556*4882a593Smuzhiyun #define M_EXEC 0x0100
557*4882a593Smuzhiyun
558*4882a593Smuzhiyun #define M_DWG_TRAP 0x04
559*4882a593Smuzhiyun #define M_DWG_BITBLT 0x08
560*4882a593Smuzhiyun #define M_DWG_ILOAD 0x09
561*4882a593Smuzhiyun
562*4882a593Smuzhiyun #define M_DWG_LINEAR 0x0080
563*4882a593Smuzhiyun #define M_DWG_SOLID 0x0800
564*4882a593Smuzhiyun #define M_DWG_ARZERO 0x1000
565*4882a593Smuzhiyun #define M_DWG_SGNZERO 0x2000
566*4882a593Smuzhiyun #define M_DWG_SHIFTZERO 0x4000
567*4882a593Smuzhiyun
568*4882a593Smuzhiyun #define M_DWG_REPLACE 0x000C0000
569*4882a593Smuzhiyun #define M_DWG_REPLACE2 (M_DWG_REPLACE | 0x40)
570*4882a593Smuzhiyun #define M_DWG_XOR 0x00060010
571*4882a593Smuzhiyun
572*4882a593Smuzhiyun #define M_DWG_BFCOL 0x04000000
573*4882a593Smuzhiyun #define M_DWG_BMONOWF 0x08000000
574*4882a593Smuzhiyun
575*4882a593Smuzhiyun #define M_DWG_TRANSC 0x40000000
576*4882a593Smuzhiyun
577*4882a593Smuzhiyun #define M_FIFOSTATUS 0x1E10
578*4882a593Smuzhiyun #define M_STATUS 0x1E14
579*4882a593Smuzhiyun #define M_ICLEAR 0x1E18
580*4882a593Smuzhiyun #define M_IEN 0x1E1C
581*4882a593Smuzhiyun
582*4882a593Smuzhiyun #define M_VCOUNT 0x1E20
583*4882a593Smuzhiyun
584*4882a593Smuzhiyun #define M_RESET 0x1E40
585*4882a593Smuzhiyun #define M_MEMRDBK 0x1E44
586*4882a593Smuzhiyun
587*4882a593Smuzhiyun #define M_AGP2PLL 0x1E4C
588*4882a593Smuzhiyun
589*4882a593Smuzhiyun #define M_OPMODE 0x1E54
590*4882a593Smuzhiyun #define M_OPMODE_DMA_GEN_WRITE 0x00
591*4882a593Smuzhiyun #define M_OPMODE_DMA_BLIT 0x04
592*4882a593Smuzhiyun #define M_OPMODE_DMA_VECTOR_WRITE 0x08
593*4882a593Smuzhiyun #define M_OPMODE_DMA_LE 0x0000 /* little endian - no transformation */
594*4882a593Smuzhiyun #define M_OPMODE_DMA_BE_8BPP 0x0000
595*4882a593Smuzhiyun #define M_OPMODE_DMA_BE_16BPP 0x0100
596*4882a593Smuzhiyun #define M_OPMODE_DMA_BE_32BPP 0x0200
597*4882a593Smuzhiyun #define M_OPMODE_DIR_LE 0x000000 /* little endian - no transformation */
598*4882a593Smuzhiyun #define M_OPMODE_DIR_BE_8BPP 0x000000
599*4882a593Smuzhiyun #define M_OPMODE_DIR_BE_16BPP 0x010000
600*4882a593Smuzhiyun #define M_OPMODE_DIR_BE_32BPP 0x020000
601*4882a593Smuzhiyun
602*4882a593Smuzhiyun #define M_ATTR_INDEX 0x1FC0
603*4882a593Smuzhiyun #define M_ATTR_DATA 0x1FC1
604*4882a593Smuzhiyun
605*4882a593Smuzhiyun #define M_MISC_REG 0x1FC2
606*4882a593Smuzhiyun #define M_3C2_RD 0x1FC2
607*4882a593Smuzhiyun
608*4882a593Smuzhiyun #define M_SEQ_INDEX 0x1FC4
609*4882a593Smuzhiyun #define M_SEQ_DATA 0x1FC5
610*4882a593Smuzhiyun #define M_SEQ1 0x01
611*4882a593Smuzhiyun #define M_SEQ1_SCROFF 0x20
612*4882a593Smuzhiyun
613*4882a593Smuzhiyun #define M_MISC_REG_READ 0x1FCC
614*4882a593Smuzhiyun
615*4882a593Smuzhiyun #define M_GRAPHICS_INDEX 0x1FCE
616*4882a593Smuzhiyun #define M_GRAPHICS_DATA 0x1FCF
617*4882a593Smuzhiyun
618*4882a593Smuzhiyun #define M_CRTC_INDEX 0x1FD4
619*4882a593Smuzhiyun
620*4882a593Smuzhiyun #define M_ATTR_RESET 0x1FDA
621*4882a593Smuzhiyun #define M_3DA_WR 0x1FDA
622*4882a593Smuzhiyun #define M_INSTS1 0x1FDA
623*4882a593Smuzhiyun
624*4882a593Smuzhiyun #define M_EXTVGA_INDEX 0x1FDE
625*4882a593Smuzhiyun #define M_EXTVGA_DATA 0x1FDF
626*4882a593Smuzhiyun
627*4882a593Smuzhiyun /* G200 only */
628*4882a593Smuzhiyun #define M_SRCORG 0x2CB4
629*4882a593Smuzhiyun #define M_DSTORG 0x2CB8
630*4882a593Smuzhiyun
631*4882a593Smuzhiyun #define M_RAMDAC_BASE 0x3C00
632*4882a593Smuzhiyun
633*4882a593Smuzhiyun /* fortunately, same on TVP3026 and MGA1064 */
634*4882a593Smuzhiyun #define M_DAC_REG (M_RAMDAC_BASE+0)
635*4882a593Smuzhiyun #define M_DAC_VAL (M_RAMDAC_BASE+1)
636*4882a593Smuzhiyun #define M_PALETTE_MASK (M_RAMDAC_BASE+2)
637*4882a593Smuzhiyun
638*4882a593Smuzhiyun #define M_X_INDEX 0x00
639*4882a593Smuzhiyun #define M_X_DATAREG 0x0A
640*4882a593Smuzhiyun
641*4882a593Smuzhiyun #define DAC_XGENIOCTRL 0x2A
642*4882a593Smuzhiyun #define DAC_XGENIODATA 0x2B
643*4882a593Smuzhiyun
644*4882a593Smuzhiyun #define M_C2CTL 0x3C10
645*4882a593Smuzhiyun
646*4882a593Smuzhiyun #define MX_OPTION_BSWAP 0x00000000
647*4882a593Smuzhiyun
648*4882a593Smuzhiyun #ifdef __LITTLE_ENDIAN
649*4882a593Smuzhiyun #define M_OPMODE_4BPP (M_OPMODE_DMA_LE | M_OPMODE_DIR_LE | M_OPMODE_DMA_BLIT)
650*4882a593Smuzhiyun #define M_OPMODE_8BPP (M_OPMODE_DMA_LE | M_OPMODE_DIR_LE | M_OPMODE_DMA_BLIT)
651*4882a593Smuzhiyun #define M_OPMODE_16BPP (M_OPMODE_DMA_LE | M_OPMODE_DIR_LE | M_OPMODE_DMA_BLIT)
652*4882a593Smuzhiyun #define M_OPMODE_24BPP (M_OPMODE_DMA_LE | M_OPMODE_DIR_LE | M_OPMODE_DMA_BLIT)
653*4882a593Smuzhiyun #define M_OPMODE_32BPP (M_OPMODE_DMA_LE | M_OPMODE_DIR_LE | M_OPMODE_DMA_BLIT)
654*4882a593Smuzhiyun #else
655*4882a593Smuzhiyun #ifdef __BIG_ENDIAN
656*4882a593Smuzhiyun #define M_OPMODE_4BPP (M_OPMODE_DMA_LE | M_OPMODE_DIR_LE | M_OPMODE_DMA_BLIT) /* TODO */
657*4882a593Smuzhiyun #define M_OPMODE_8BPP (M_OPMODE_DMA_LE | M_OPMODE_DIR_BE_8BPP | M_OPMODE_DMA_BLIT)
658*4882a593Smuzhiyun #define M_OPMODE_16BPP (M_OPMODE_DMA_LE | M_OPMODE_DIR_BE_16BPP | M_OPMODE_DMA_BLIT)
659*4882a593Smuzhiyun #define M_OPMODE_24BPP (M_OPMODE_DMA_LE | M_OPMODE_DIR_BE_8BPP | M_OPMODE_DMA_BLIT) /* TODO, ?32 */
660*4882a593Smuzhiyun #define M_OPMODE_32BPP (M_OPMODE_DMA_LE | M_OPMODE_DIR_BE_32BPP | M_OPMODE_DMA_BLIT)
661*4882a593Smuzhiyun #else
662*4882a593Smuzhiyun #error "Byte ordering have to be defined. Cannot continue."
663*4882a593Smuzhiyun #endif
664*4882a593Smuzhiyun #endif
665*4882a593Smuzhiyun
666*4882a593Smuzhiyun #define mga_inb(addr) mga_readb(minfo->mmio.vbase, (addr))
667*4882a593Smuzhiyun #define mga_inl(addr) mga_readl(minfo->mmio.vbase, (addr))
668*4882a593Smuzhiyun #define mga_outb(addr,val) mga_writeb(minfo->mmio.vbase, (addr), (val))
669*4882a593Smuzhiyun #define mga_outw(addr,val) mga_writew(minfo->mmio.vbase, (addr), (val))
670*4882a593Smuzhiyun #define mga_outl(addr,val) mga_writel(minfo->mmio.vbase, (addr), (val))
671*4882a593Smuzhiyun #define mga_readr(port,idx) (mga_outb((port),(idx)), mga_inb((port)+1))
672*4882a593Smuzhiyun #define mga_setr(addr,port,val) mga_outw(addr, ((val)<<8) | (port))
673*4882a593Smuzhiyun
674*4882a593Smuzhiyun #define mga_fifo(n) do {} while ((mga_inl(M_FIFOSTATUS) & 0xFF) < (n))
675*4882a593Smuzhiyun
676*4882a593Smuzhiyun #define WaitTillIdle() do { mga_inl(M_STATUS); do {} while (mga_inl(M_STATUS) & 0x10000); } while (0)
677*4882a593Smuzhiyun
678*4882a593Smuzhiyun /* code speedup */
679*4882a593Smuzhiyun #ifdef CONFIG_FB_MATROX_MILLENIUM
680*4882a593Smuzhiyun #define isInterleave(x) (x->interleave)
681*4882a593Smuzhiyun #define isMillenium(x) (x->millenium)
682*4882a593Smuzhiyun #define isMilleniumII(x) (x->milleniumII)
683*4882a593Smuzhiyun #else
684*4882a593Smuzhiyun #define isInterleave(x) (0)
685*4882a593Smuzhiyun #define isMillenium(x) (0)
686*4882a593Smuzhiyun #define isMilleniumII(x) (0)
687*4882a593Smuzhiyun #endif
688*4882a593Smuzhiyun
689*4882a593Smuzhiyun #define matroxfb_DAC_lock() spin_lock(&minfo->lock.DAC)
690*4882a593Smuzhiyun #define matroxfb_DAC_unlock() spin_unlock(&minfo->lock.DAC)
691*4882a593Smuzhiyun #define matroxfb_DAC_lock_irqsave(flags) spin_lock_irqsave(&minfo->lock.DAC, flags)
692*4882a593Smuzhiyun #define matroxfb_DAC_unlock_irqrestore(flags) spin_unlock_irqrestore(&minfo->lock.DAC, flags)
693*4882a593Smuzhiyun extern void matroxfb_DAC_out(const struct matrox_fb_info *minfo, int reg,
694*4882a593Smuzhiyun int val);
695*4882a593Smuzhiyun extern int matroxfb_DAC_in(const struct matrox_fb_info *minfo, int reg);
696*4882a593Smuzhiyun extern void matroxfb_var2my(struct fb_var_screeninfo* fvsi, struct my_timming* mt);
697*4882a593Smuzhiyun extern int matroxfb_wait_for_sync(struct matrox_fb_info *minfo, u_int32_t crtc);
698*4882a593Smuzhiyun extern int matroxfb_enable_irq(struct matrox_fb_info *minfo, int reenable);
699*4882a593Smuzhiyun
700*4882a593Smuzhiyun #ifdef MATROXFB_USE_SPINLOCKS
701*4882a593Smuzhiyun #define CRITBEGIN spin_lock_irqsave(&minfo->lock.accel, critflags);
702*4882a593Smuzhiyun #define CRITEND spin_unlock_irqrestore(&minfo->lock.accel, critflags);
703*4882a593Smuzhiyun #define CRITFLAGS unsigned long critflags;
704*4882a593Smuzhiyun #else
705*4882a593Smuzhiyun #define CRITBEGIN
706*4882a593Smuzhiyun #define CRITEND
707*4882a593Smuzhiyun #define CRITFLAGS
708*4882a593Smuzhiyun #endif
709*4882a593Smuzhiyun
710*4882a593Smuzhiyun #endif /* __MATROXFB_H__ */
711