File: /usr/src/linux/drivers/video/matrox/matroxfb_g450.c

1     #include "matroxfb_g450.h"
2     #include "matroxfb_misc.h"
3     #include "matroxfb_DAC1064.h"
4     #include <linux/matroxfb.h>
5     #include <asm/uaccess.h>
6     
7     static int matroxfb_g450_get_reg(WPMINFO int reg) {
8     	int val;
9     	unsigned long flags;
10     
11     	matroxfb_DAC_lock_irqsave(flags);
12     	val = matroxfb_DAC_in(PMINFO reg);
13     	matroxfb_DAC_unlock_irqrestore(flags);
14     	return val;
15     }
16     
17     static int matroxfb_g450_set_reg(WPMINFO int reg, int val) {
18     	unsigned long flags;
19     
20     	matroxfb_DAC_lock_irqsave(flags);
21     	matroxfb_DAC_out(PMINFO reg, val);
22     	matroxfb_DAC_unlock_irqrestore(flags);
23     	return 0;
24     }
25     
26     static const struct matrox_pll_features maven_pll = {
27     	110000,
28     	27000,
29     	4, 127,
30     	2, 31,
31     	3
32     };
33     
34     static void DAC1064_calcclock(unsigned int freq, unsigned int fmax,
35     		unsigned int* in, unsigned int* feed, unsigned int* post) {
36     	unsigned int fvco;
37     	unsigned int p;
38     
39     	fvco = matroxfb_PLL_calcclock(&maven_pll, freq, fmax, in, feed, &p);
40     	/* 0 => 100 ... 275 MHz
41                1 => 243 ... 367 MHz
42                2 => 320 ... 475 MHz
43                3 => 453 ... 556 MHz
44                4 => 540 ... 594 MHz
45                5 => 588 ... 621 MHz
46                6 => 626 ... 637 MHz
47                7 => 631 ... 642 MHz
48     
49                As you can see, never choose frequency > 621 MHz, there is unavailable gap...
50                Just to be sure, currently driver uses 110 ... 500 MHz range.
51              */
52     	if (fvco <= 260000)
53     		;
54     	else if (fvco <= 350000)
55     		p |= 0x08;
56     	else if (fvco <= 460000)
57     		p |= 0x10;
58     	else if (fvco <= 550000)
59     		p |= 0x18;
60     	else if (fvco <= 590000)
61     		p |= 0x20;
62     	else
63     		p |= 0x28;
64     	*post = p;
65     	return;
66     }
67     
68     static inline int matroxfb_g450_compute_timming(struct matroxfb_g450_info* m2info,
69     		struct my_timming* mt,
70     		struct mavenregs* m) {
71     	unsigned int a, b, c;
72     
73     	DAC1064_calcclock(mt->pixclock, 500000, &a, &b, &c);
74     	m->regs[0x80] = a;
75     	m->regs[0x81] = b;
76     	m->regs[0x82] = c;
77     	printk(KERN_DEBUG "PLL: %02X %02X %02X\n", a, b, c);
78     	return 0;
79     }
80     
81     static inline int matroxfb_g450_program_timming(struct matroxfb_g450_info* m2info, const struct mavenregs* m) {
82     	MINFO_FROM(m2info->primary_dev);
83     
84     	matroxfb_g450_set_reg(PMINFO M1064_XPIXPLL2M, m->regs[0x81]);
85     	matroxfb_g450_set_reg(PMINFO M1064_XPIXPLL2N, m->regs[0x80]);
86     	matroxfb_g450_set_reg(PMINFO M1064_XPIXPLL2P, m->regs[0x82]);
87     	return 0;
88     }
89     
90     /******************************************************/
91     
92     static int matroxfb_g450_compute(void* md, struct my_timming* mt, struct matrox_hw_state* mr) {
93     	return matroxfb_g450_compute_timming(md, mt, &mr->maven);
94     }
95     
96     static int matroxfb_g450_program(void* md, const struct matrox_hw_state* mr) {
97     	return matroxfb_g450_program_timming(md, &mr->maven);
98     }
99     
100     static int matroxfb_g450_start(void* md) {
101     	return 0;
102     }
103     
104     static void matroxfb_g450_incuse(void* md) {
105     	MOD_INC_USE_COUNT;
106     }
107     
108     static void matroxfb_g450_decuse(void* md) {
109     	MOD_DEC_USE_COUNT;
110     }
111     
112     static int matroxfb_g450_set_mode(void* md, u_int32_t arg) {
113     	if (arg == MATROXFB_OUTPUT_MODE_MONITOR) {
114     		return 1;
115     	}
116     	return -EINVAL;
117     }
118     
119     static int matroxfb_g450_get_mode(void* md, u_int32_t* arg) {
120     	*arg = MATROXFB_OUTPUT_MODE_MONITOR;
121     	return 0;
122     }
123     
124     static struct matrox_altout matroxfb_g450_altout = {
125     	matroxfb_g450_compute,
126     	matroxfb_g450_program,
127     	matroxfb_g450_start,
128     	matroxfb_g450_incuse,
129     	matroxfb_g450_decuse,
130     	matroxfb_g450_set_mode,
131     	matroxfb_g450_get_mode
132     };
133     
134     static int matroxfb_g450_connect(struct matroxfb_g450_info* m2info) {
135     	MINFO_FROM(m2info->primary_dev);
136     
137     	down_write(&ACCESS_FBINFO(altout.lock));
138     	ACCESS_FBINFO(altout.device) = m2info;
139     	ACCESS_FBINFO(altout.output) = &matroxfb_g450_altout;
140     	up_write(&ACCESS_FBINFO(altout.lock));
141     	ACCESS_FBINFO(output.all) |= MATROXFB_OUTPUT_CONN_SECONDARY;
142     	return 0;
143     }
144     
145     static void matroxfb_g450_shutdown(struct matroxfb_g450_info* m2info) {
146     	MINFO_FROM(m2info->primary_dev);
147     	
148     	if (MINFO) {
149     		ACCESS_FBINFO(output.all) &= ~MATROXFB_OUTPUT_CONN_SECONDARY;
150     		ACCESS_FBINFO(output.ph) &= ~MATROXFB_OUTPUT_CONN_SECONDARY;
151     		ACCESS_FBINFO(output.sh) &= ~MATROXFB_OUTPUT_CONN_SECONDARY;
152     		down_write(&ACCESS_FBINFO(altout.lock));
153     		ACCESS_FBINFO(altout.device) = NULL;
154     		ACCESS_FBINFO(altout.output) = NULL;
155     		up_write(&ACCESS_FBINFO(altout.lock));
156     		m2info->primary_dev = NULL;
157     	}
158     }
159     
160     /* we do not have __setup() yet */
161     static void* matroxfb_g450_probe(struct matrox_fb_info* minfo) {
162     	struct matroxfb_g450_info* m2info;
163     
164     	/* hardware is not G450 incapable... */
165     	if (!ACCESS_FBINFO(devflags.g450dac))
166     		return NULL;
167     	m2info = (struct matroxfb_g450_info*)kmalloc(sizeof(*m2info), GFP_KERNEL);
168     	if (!m2info) {
169     		printk(KERN_ERR "matroxfb_g450: Not enough memory for G450 DAC control structs\n");
170     		return NULL;
171     	}
172     	memset(m2info, 0, sizeof(*m2info));
173     	m2info->primary_dev = MINFO;
174     	if (matroxfb_g450_connect(m2info)) {
175     		kfree(m2info);
176     		printk(KERN_ERR "matroxfb_g450: G450 DAC failed to initialize\n");
177     		return NULL;
178     	}
179     	return m2info;
180     }
181     
182     static void matroxfb_g450_remove(struct matrox_fb_info* minfo, void* g450) {
183     	matroxfb_g450_shutdown(g450);
184     	kfree(g450);
185     }
186     
187     static struct matroxfb_driver g450 = {
188     		name:	"Matrox G450 output #2",
189     		probe:	matroxfb_g450_probe,
190     		remove:	matroxfb_g450_remove };
191     
192     static int matroxfb_g450_init(void) {
193     	matroxfb_register_driver(&g450);
194     	return 0;
195     }
196     
197     static void matroxfb_g450_exit(void) {
198     	matroxfb_unregister_driver(&g450);
199     }
200     
201     MODULE_AUTHOR("(c) 2000 Petr Vandrovec <vandrove@vc.cvut.cz>");
202     MODULE_DESCRIPTION("Matrox G450 secondary output driver");
203     module_init(matroxfb_g450_init);
204     module_exit(matroxfb_g450_exit);
205