7a9c68291fa6c95950e0204a96771e27ce3a9c8c
[linux-2.6.git] / drivers / media / dvb / ttpci / budget-patch.c
1 /*
2  * budget-patch.c: driver for Budget Patch,
3  * hardware modification of DVB-S cards enabling full TS
4  *
5  * Written by Emard <emard@softhome.net>
6  *
7  * Original idea by Roberto Deza <rdeza@unav.es>
8  *
9  * Special thanks to Holger Waechtler, Michael Hunold, Marian Durkovic
10  * and Metzlerbros
11  *
12  * This program is free software; you can redistribute it and/or
13  * modify it under the terms of the GNU General Public License
14  * as published by the Free Software Foundation; either version 2
15  * of the License, or (at your option) any later version.
16  * 
17  *
18  * This program is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21  * GNU General Public License for more details.
22  * 
23  *
24  * You should have received a copy of the GNU General Public License
25  * along with this program; if not, write to the Free Software
26  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
27  * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
28  * 
29  *
30  * the project's page is at http://www.linuxtv.org/dvb/
31  */
32
33 #include "av7110.h"
34 #include "av7110_hw.h"
35 #include "budget.h"
36 #include "stv0299.h"
37 #include "ves1x93.h"
38 #include "tda8083.h"
39
40 #define budget_patch budget
41
42 static struct saa7146_extension budget_extension;
43
44 MAKE_BUDGET_INFO(fs_1_3,"Siemens/Technotrend/Hauppauge PCI rev1.3+Budget_Patch", BUDGET_PATCH);
45
46 static struct pci_device_id pci_tbl[] = {
47         MAKE_EXTENSION_PCI(fs_1_3,0x13c2, 0x0000),
48         {
49                 .vendor    = 0,
50         }
51 };
52
53 static int budget_wdebi(struct budget_patch *budget, u32 config, int addr, u32 val, int count)
54 {
55         struct saa7146_dev *dev=budget->dev;
56
57         dprintk(2, "budget: %p\n", budget);
58
59         if (count <= 0 || count > 4)
60                 return -1;
61
62         saa7146_write(dev, DEBI_CONFIG, config);
63
64         saa7146_write(dev, DEBI_AD, val );
65         saa7146_write(dev, DEBI_COMMAND, (count << 17) | (addr & 0xffff));
66         saa7146_write(dev, MC2, (2 << 16) | 2);
67         mdelay(5);
68
69         return 0;
70 }
71
72
73 static int budget_av7110_send_fw_cmd(struct budget_patch *budget, u16* buf, int length)
74 {
75         int i;
76
77         dprintk(2, "budget: %p\n", budget);
78
79         for (i = 2; i < length; i++)
80                 budget_wdebi(budget, DEBINOSWAP, COMMAND + 2*i, (u32) buf[i], 2);
81
82         if (length)
83                 budget_wdebi(budget, DEBINOSWAP, COMMAND + 2, (u32) buf[1], 2);
84         else
85                 budget_wdebi(budget, DEBINOSWAP, COMMAND + 2, 0, 2);
86
87         budget_wdebi(budget, DEBINOSWAP, COMMAND, (u32) buf[0], 2);
88         return 0;
89 }
90
91
92 static void av7110_set22k(struct budget_patch *budget, int state)
93 {
94         u16 buf[2] = {( COMTYPE_AUDIODAC << 8) | (state ? ON22K : OFF22K), 0};
95         
96         dprintk(2, "budget: %p\n", budget);
97         budget_av7110_send_fw_cmd(budget, buf, 2);
98 }
99
100
101 static int av7110_send_diseqc_msg(struct budget_patch *budget, int len, u8 *msg, int burst)
102 {
103         int i;
104         u16 buf[18] = { ((COMTYPE_AUDIODAC << 8) | SendDiSEqC),
105                 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
106
107         dprintk(2, "budget: %p\n", budget);
108
109         if (len>10)
110                 len=10;
111
112         buf[1] = len+2;
113         buf[2] = len;
114
115         if (burst != -1)
116                 buf[3]=burst ? 0x01 : 0x00;
117         else
118                 buf[3]=0xffff;
119                 
120         for (i=0; i<len; i++)
121                 buf[i+4]=msg[i];
122
123         budget_av7110_send_fw_cmd(budget, buf, 18);
124         return 0;
125 }
126
127 static int budget_patch_set_tone(struct dvb_frontend* fe, fe_sec_tone_mode_t tone)
128 {
129         struct budget_patch* budget = (struct budget_patch*) fe->dvb->priv;
130
131         switch (tone) {
132                 case SEC_TONE_ON:
133                         av7110_set22k (budget, 1);
134                         break;
135                 case SEC_TONE_OFF:
136                         av7110_set22k (budget, 0);
137                         break;
138                 default:
139                         return -EINVAL;
140                 }
141
142         return 0;
143 }
144
145 static int budget_patch_diseqc_send_master_cmd(struct dvb_frontend* fe, struct dvb_diseqc_master_cmd* cmd)
146         {
147         struct budget_patch* budget = (struct budget_patch*) fe->dvb->priv;
148
149                 av7110_send_diseqc_msg (budget, cmd->msg_len, cmd->msg, 0);
150
151         return 0;
152         }
153
154 static int budget_patch_diseqc_send_burst(struct dvb_frontend* fe, fe_sec_mini_cmd_t minicmd)
155 {
156         struct budget_patch* budget = (struct budget_patch*) fe->dvb->priv;
157
158         av7110_send_diseqc_msg (budget, 0, NULL, minicmd);
159
160         return 0;
161         }
162
163 static int alps_bsrv2_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
164 {
165         struct budget_patch* budget = (struct budget_patch*) fe->dvb->priv;
166         u8 pwr = 0;
167         u8 buf[4];
168         struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = buf, .len = sizeof(buf) };
169         u32 div = (params->frequency + 479500) / 125;
170
171         if (params->frequency > 2000000) pwr = 3;
172         else if (params->frequency > 1800000) pwr = 2;
173         else if (params->frequency > 1600000) pwr = 1;
174         else if (params->frequency > 1200000) pwr = 0;
175         else if (params->frequency >= 1100000) pwr = 1;
176         else pwr = 2;
177
178         buf[0] = (div >> 8) & 0x7f;
179         buf[1] = div & 0xff;
180         buf[2] = ((div & 0x18000) >> 10) | 0x95;
181         buf[3] = (pwr << 6) | 0x30;
182
183         // NOTE: since we're using a prescaler of 2, we set the
184         // divisor frequency to 62.5kHz and divide by 125 above
185
186         if (i2c_transfer (&budget->i2c_adap, &msg, 1) != 1) return -EIO;
187         return 0;
188 }
189
190 static struct ves1x93_config alps_bsrv2_config = {
191         .demod_address = 0x08,
192         .xin = 90100000UL,
193         .invert_pwm = 0,
194         .pll_set = alps_bsrv2_pll_set,
195 };
196
197 static u8 alps_bsru6_inittab[] = {
198         0x01, 0x15,
199         0x02, 0x00,
200         0x03, 0x00,
201         0x04, 0x7d,   /* F22FR = 0x7d, F22 = f_VCO / 128 / 0x7d = 22 kHz */
202         0x05, 0x35,   /* I2CT = 0, SCLT = 1, SDAT = 1 */
203         0x06, 0x40,   /* DAC not used, set to high impendance mode */
204         0x07, 0x00,   /* DAC LSB */
205         0x08, 0x40,   /* DiSEqC off, LNB power on OP2/LOCK pin on */
206         0x09, 0x00,   /* FIFO */
207         0x0c, 0x51,   /* OP1 ctl = Normal, OP1 val = 1 (LNB Power ON) */
208         0x0d, 0x82,   /* DC offset compensation = ON, beta_agc1 = 2 */
209         0x0e, 0x23,   /* alpha_tmg = 2, beta_tmg = 3 */
210         0x10, 0x3f,   // AGC2  0x3d
211         0x11, 0x84,
212         0x12, 0xb5,   // Lock detect: -64  Carrier freq detect:on
213         0x15, 0xc9,   // lock detector threshold
214         0x16, 0x00,
215         0x17, 0x00,
216         0x18, 0x00,
217         0x19, 0x00,
218         0x1a, 0x00,
219         0x1f, 0x50,
220         0x20, 0x00,
221         0x21, 0x00,
222         0x22, 0x00,
223         0x23, 0x00,
224         0x28, 0x00,  // out imp: normal  out type: parallel FEC mode:0
225         0x29, 0x1e,  // 1/2 threshold
226         0x2a, 0x14,  // 2/3 threshold
227         0x2b, 0x0f,  // 3/4 threshold
228         0x2c, 0x09,  // 5/6 threshold
229         0x2d, 0x05,  // 7/8 threshold
230         0x2e, 0x01,
231         0x31, 0x1f,  // test all FECs
232         0x32, 0x19,  // viterbi and synchro search
233         0x33, 0xfc,  // rs control
234         0x34, 0x93,  // error control
235         0x0f, 0x52,
236         0xff, 0xff
237 };
238
239 static int alps_bsru6_set_symbol_rate(struct dvb_frontend* fe, u32 srate, u32 ratio)
240 {
241         u8 aclk = 0;
242         u8 bclk = 0;
243
244         if (srate < 1500000) { aclk = 0xb7; bclk = 0x47; }
245         else if (srate < 3000000) { aclk = 0xb7; bclk = 0x4b; }
246         else if (srate < 7000000) { aclk = 0xb7; bclk = 0x4f; }
247         else if (srate < 14000000) { aclk = 0xb7; bclk = 0x53; }
248         else if (srate < 30000000) { aclk = 0xb6; bclk = 0x53; }
249         else if (srate < 45000000) { aclk = 0xb4; bclk = 0x51; }
250
251         stv0299_writereg (fe, 0x13, aclk);
252         stv0299_writereg (fe, 0x14, bclk);
253         stv0299_writereg (fe, 0x1f, (ratio >> 16) & 0xff);
254         stv0299_writereg (fe, 0x20, (ratio >>  8) & 0xff);
255         stv0299_writereg (fe, 0x21, (ratio      ) & 0xf0);
256
257         return 0;
258 }
259
260 static int alps_bsru6_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
261 {
262         struct budget_patch* budget = (struct budget_patch*) fe->dvb->priv;
263         u8 data[4];
264         u32 div;
265         struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = data, .len = sizeof(data) };
266
267         if ((params->frequency < 950000) || (params->frequency > 2150000)) return -EINVAL;
268
269         div = (params->frequency + (125 - 1)) / 125; // round correctly
270         data[0] = (div >> 8) & 0x7f;
271         data[1] = div & 0xff;
272         data[2] = 0x80 | ((div & 0x18000) >> 10) | 4;
273         data[3] = 0xC4;
274
275         if (params->frequency > 1530000) data[3] = 0xc0;
276
277         if (i2c_transfer (&budget->i2c_adap, &msg, 1) != 1) return -EIO;
278         return 0;
279 }
280
281 static struct stv0299_config alps_bsru6_config = {
282
283         .demod_address = 0x68,
284         .inittab = alps_bsru6_inittab,
285         .mclk = 88000000UL,
286         .invert = 1,
287         .enhanced_tuning = 0,
288         .skip_reinit = 0,
289         .lock_output = STV0229_LOCKOUTPUT_1,
290         .volt13_op0_op1 = STV0299_VOLT13_OP1,
291         .min_delay_ms = 100,
292         .set_symbol_rate = alps_bsru6_set_symbol_rate,
293         .pll_set = alps_bsru6_pll_set,
294 };
295
296 static int grundig_29504_451_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
297 {
298         struct budget_patch* budget = (struct budget_patch*) fe->dvb->priv;
299         u32 div;
300         u8 data[4];
301         struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = data, .len = sizeof(data) };
302
303         div = params->frequency / 125;
304         data[0] = (div >> 8) & 0x7f;
305         data[1] = div & 0xff;
306         data[2] = 0x8e;
307         data[3] = 0x00;
308
309         if (i2c_transfer (&budget->i2c_adap, &msg, 1) != 1) return -EIO;
310         return 0;
311 }
312
313 struct tda8083_config grundig_29504_451_config = {
314         .demod_address = 0x68,
315         .pll_set = grundig_29504_451_pll_set,
316 };
317
318 static void frontend_init(struct budget_patch* budget)
319 {
320         switch(budget->dev->pci->subsystem_device) {
321         case 0x0000: // Hauppauge/TT WinTV DVB-S rev1.X
322
323                 // try the ALPS BSRV2 first of all
324                 budget->dvb_frontend = ves1x93_attach(&alps_bsrv2_config, &budget->i2c_adap);
325                 if (budget->dvb_frontend) {
326                         budget->dvb_frontend->ops->diseqc_send_master_cmd = budget_patch_diseqc_send_master_cmd;
327                         budget->dvb_frontend->ops->diseqc_send_burst = budget_patch_diseqc_send_burst;
328                         budget->dvb_frontend->ops->set_tone = budget_patch_set_tone;
329                         break;
330                 }
331
332                 // try the ALPS BSRU6 now
333                 budget->dvb_frontend = stv0299_attach(&alps_bsru6_config, &budget->i2c_adap);
334                 if (budget->dvb_frontend) {
335                         budget->dvb_frontend->ops->diseqc_send_master_cmd = budget_patch_diseqc_send_master_cmd;
336                         budget->dvb_frontend->ops->diseqc_send_burst = budget_patch_diseqc_send_burst;
337                         budget->dvb_frontend->ops->set_tone = budget_patch_set_tone;
338                         break;
339                 }
340
341                 // Try the grundig 29504-451
342                 budget->dvb_frontend = tda8083_attach(&grundig_29504_451_config, &budget->i2c_adap);
343                 if (budget->dvb_frontend) {
344                         budget->dvb_frontend->ops->diseqc_send_master_cmd = budget_patch_diseqc_send_master_cmd;
345                         budget->dvb_frontend->ops->diseqc_send_burst = budget_patch_diseqc_send_burst;
346                         budget->dvb_frontend->ops->set_tone = budget_patch_set_tone;
347                         break;
348                 }
349                 break;
350         }
351
352         if (budget->dvb_frontend == NULL) {
353                 printk("dvb-ttpci: A frontend driver was not found for device %04x/%04x subsystem %04x/%04x\n",
354                        budget->dev->pci->vendor,
355                        budget->dev->pci->device,
356                        budget->dev->pci->subsystem_vendor,
357                        budget->dev->pci->subsystem_device);
358         } else {
359                 if (dvb_register_frontend(budget->dvb_adapter, budget->dvb_frontend)) {
360                         printk("budget-av: Frontend registration failed!\n");
361                         if (budget->dvb_frontend->ops->release)
362                                 budget->dvb_frontend->ops->release(budget->dvb_frontend);
363                         budget->dvb_frontend = NULL;
364                 }
365         }
366 }
367
368 static int budget_patch_attach (struct saa7146_dev* dev, struct saa7146_pci_extension_data *info)
369 {
370         struct budget_patch *budget;
371         int err;
372         int count = 0;
373
374         if (!(budget = kmalloc (sizeof(struct budget_patch), GFP_KERNEL)))
375                 return -ENOMEM;
376
377         dprintk(2, "budget: %p\n", budget);
378
379         if ((err = ttpci_budget_init (budget, dev, info, THIS_MODULE))) {
380                 kfree (budget);
381                 return err;
382         }
383
384 /*
385 **      This code will setup the SAA7146_RPS1 to generate a square 
386 **      wave on GPIO3, changing when a field (TS_HEIGHT/2 "lines" of 
387 **      TS_WIDTH packets) has been acquired on SAA7146_D1B video port; 
388 **      then, this GPIO3 output which is connected to the D1B_VSYNC 
389 **      input, will trigger the acquisition of the alternate field 
390 **      and so on.
391 **      Currently, the TT_budget / WinTV_Nova cards have two ICs 
392 **      (74HCT4040, LVC74) for the generation of this VSYNC signal, 
393 **      which seems that can be done perfectly without this :-)).
394 */                                                      
395
396         // Setup RPS1 "program" (p35)
397
398         // Wait reset Source Line Counter Threshold                     (p36)
399         WRITE_RPS1(cpu_to_le32(CMD_PAUSE | RPS_INV | EVT_HS));
400         // Wait Source Line Counter Threshold                           (p36)
401         WRITE_RPS1(cpu_to_le32(CMD_PAUSE | EVT_HS));
402         // Set GPIO3=1                                                  (p42)
403         WRITE_RPS1(cpu_to_le32(CMD_WR_REG_MASK | (GPIO_CTRL>>2)));
404         WRITE_RPS1(cpu_to_le32(GPIO3_MSK));
405         WRITE_RPS1(cpu_to_le32(SAA7146_GPIO_OUTHI<<24));
406         // Wait reset Source Line Counter Threshold                     (p36)
407         WRITE_RPS1(cpu_to_le32(CMD_PAUSE | RPS_INV | EVT_HS));
408         // Wait Source Line Counter Threshold
409         WRITE_RPS1(cpu_to_le32(CMD_PAUSE | EVT_HS));
410         // Set GPIO3=0                                                  (p42)
411         WRITE_RPS1(cpu_to_le32(CMD_WR_REG_MASK | (GPIO_CTRL>>2)));
412         WRITE_RPS1(cpu_to_le32(GPIO3_MSK));
413         WRITE_RPS1(cpu_to_le32(SAA7146_GPIO_OUTLO<<24));
414         // Jump to begin of RPS program                                 (p37)
415         WRITE_RPS1(cpu_to_le32(CMD_JUMP));
416         WRITE_RPS1(cpu_to_le32(dev->d_rps1.dma_handle));
417
418         // Fix VSYNC level
419         saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTLO);
420         // Set RPS1 Address register to point to RPS code               (r108 p42)
421         saa7146_write(dev, RPS_ADDR1, dev->d_rps1.dma_handle);
422         // Set Source Line Counter Threshold, using BRS                 (rCC p43)
423         saa7146_write(dev, RPS_THRESH1, ((TS_HEIGHT/2) | MASK_12));
424         // Enable RPS1                                                  (rFC p33)
425         saa7146_write(dev, MC1, (MASK_13 | MASK_29));
426
427         dev->ext_priv = budget;
428
429         budget->dvb_adapter->priv = budget;
430         frontend_init(budget);
431
432         return 0;
433 }
434
435
436 static int budget_patch_detach (struct saa7146_dev* dev)
437 {
438         struct budget_patch *budget = (struct budget_patch*) dev->ext_priv;
439         int err;
440
441         if (budget->dvb_frontend) dvb_unregister_frontend(budget->dvb_frontend);
442
443         err = ttpci_budget_deinit (budget);
444
445         kfree (budget);
446
447         return err;
448 }
449
450
451 static int __init budget_patch_init(void) 
452 {
453         return saa7146_register_extension(&budget_extension);
454 }
455
456 static void __exit budget_patch_exit(void)
457 {
458         saa7146_unregister_extension(&budget_extension); 
459 }
460
461
462 static struct saa7146_extension budget_extension = {
463         .name           = "budget_patch dvb\0",
464         .flags          = 0,
465         
466         .module         = THIS_MODULE,
467         .pci_tbl        = pci_tbl,
468         .attach         = budget_patch_attach,
469         .detach         = budget_patch_detach,
470
471         .irq_mask       = MASK_10,
472         .irq_func       = ttpci_budget_irq10_handler,
473 };
474
475
476 module_init(budget_patch_init);
477 module_exit(budget_patch_exit);
478
479 MODULE_LICENSE("GPL");
480 MODULE_AUTHOR("Emard, Roberto Deza, Holger Waechtler, Michael Hunold, others");
481 MODULE_DESCRIPTION("Driver for full TS modified DVB-S SAA7146+AV7110 "
482                    "based so-called Budget Patch cards");
483