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