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