blob: 2379f387c50ce372407f60227e67754a035e7095 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 * TTUSB DVB driver
3 *
4 * Copyright (c) 2002 Holger Waechtler <holger@convergence.de>
5 * Copyright (c) 2003 Felix Domke <tmbinc@elitedvb.net>
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License as
9 * published by the Free Software Foundation; either version 2 of
10 * the License, or (at your option) any later version.
11 */
12#include <linux/init.h>
13#include <linux/slab.h>
14#include <linux/wait.h>
Akinobu Mitaa8a89b72008-07-04 06:33:20 -030015#include <linux/fs.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070016#include <linux/module.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070017#include <linux/usb.h>
18#include <linux/delay.h>
19#include <linux/time.h>
20#include <linux/errno.h>
Marcelo Feitoza Parisi4da006c2005-09-09 13:03:15 -070021#include <linux/jiffies.h>
Ingo Molnar3593cab2006-02-07 06:49:14 -020022#include <linux/mutex.h>
David Woodhouse0a2a7362008-05-29 19:50:06 +030023#include <linux/firmware.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070024
25#include "dvb_frontend.h"
26#include "dmxdev.h"
27#include "dvb_demux.h"
28#include "dvb_net.h"
Gavin Hamill53936392005-07-07 17:58:04 -070029#include "ves1820.h"
Linus Torvalds1da177e2005-04-16 15:20:36 -070030#include "cx22700.h"
31#include "tda1004x.h"
32#include "stv0299.h"
33#include "tda8083.h"
Thomas Kaiserb8d4c232006-04-27 21:45:20 -030034#include "stv0297.h"
Andrew de Quinceyd0205422006-04-27 21:45:01 -030035#include "lnbp21.h"
Linus Torvalds1da177e2005-04-16 15:20:36 -070036
37#include <linux/dvb/frontend.h>
38#include <linux/dvb/dmx.h>
39#include <linux/pci.h>
40
Linus Torvalds1da177e2005-04-16 15:20:36 -070041/*
42 TTUSB_HWSECTIONS:
43 the DSP supports filtering in hardware, however, since the "muxstream"
44 is a bit braindead (no matching channel masks or no matching filter mask),
45 we won't support this - yet. it doesn't event support negative filters,
46 so the best way is maybe to keep TTUSB_HWSECTIONS undef'd and just
Adrian Bunk9aaeded2006-06-30 18:19:55 +020047 parse TS data. USB bandwidth will be a problem when having large
Linus Torvalds1da177e2005-04-16 15:20:36 -070048 datastreams, especially for dvb-net, but hey, that's not my problem.
49
50 TTUSB_DISEQC, TTUSB_TONE:
51 let the STC do the diseqc/tone stuff. this isn't supported at least with
52 my TTUSB, so let it undef'd unless you want to implement another
53 frontend. never tested.
54
Jarod Wilson68a49a42011-03-24 12:56:16 -030055 debug:
Linus Torvalds1da177e2005-04-16 15:20:36 -070056 define it to > 3 for really hardcore debugging. you probably don't want
57 this unless the device doesn't load at all. > 2 for bandwidth statistics.
58*/
59
60static int debug;
Linus Torvalds1da177e2005-04-16 15:20:36 -070061module_param(debug, int, 0644);
62MODULE_PARM_DESC(debug, "Turn on/off debugging (default:off).");
63
Janne Grunau78e92002008-04-09 19:13:13 -030064DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
65
Linus Torvalds1da177e2005-04-16 15:20:36 -070066#define dprintk(x...) do { if (debug) printk(KERN_DEBUG x); } while (0)
67
68#define ISO_BUF_COUNT 4
69#define FRAMES_PER_ISO_BUF 4
70#define ISO_FRAME_SIZE 912
71#define TTUSB_MAXCHANNEL 32
72#ifdef TTUSB_HWSECTIONS
73#define TTUSB_MAXFILTER 16 /* ??? */
74#endif
75
76#define TTUSB_REV_2_2 0x22
77#define TTUSB_BUDGET_NAME "ttusb_stc_fw"
78
79/**
80 * since we're casting (struct ttusb*) <-> (struct dvb_demux*) around
81 * the dvb_demux field must be the first in struct!!
82 */
83struct ttusb {
84 struct dvb_demux dvb_demux;
85 struct dmxdev dmxdev;
86 struct dvb_net dvbnet;
87
88 /* and one for USB access. */
Ingo Molnar3593cab2006-02-07 06:49:14 -020089 struct mutex semi2c;
90 struct mutex semusb;
Linus Torvalds1da177e2005-04-16 15:20:36 -070091
Johannes Stezenbachfdc53a62005-05-16 21:54:39 -070092 struct dvb_adapter adapter;
Linus Torvalds1da177e2005-04-16 15:20:36 -070093 struct usb_device *dev;
94
95 struct i2c_adapter i2c_adap;
96
97 int disconnecting;
98 int iso_streaming;
99
100 unsigned int bulk_out_pipe;
101 unsigned int bulk_in_pipe;
102 unsigned int isoc_in_pipe;
103
104 void *iso_buffer;
105 dma_addr_t iso_dma_handle;
106
107 struct urb *iso_urb[ISO_BUF_COUNT];
108
109 int running_feed_count;
110 int last_channel;
111 int last_filter;
112
113 u8 c; /* transaction counter, wraps around... */
114 fe_sec_tone_mode_t tone;
115 fe_sec_voltage_t voltage;
116
117 int mux_state; // 0..2 - MuxSyncWord, 3 - nMuxPacks, 4 - muxpack
118 u8 mux_npacks;
119 u8 muxpack[256 + 8];
120 int muxpack_ptr, muxpack_len;
121
122 int insync;
123
124 int cc; /* MuxCounter - will increment on EVERY MUX PACKET */
125 /* (including stuffing. yes. really.) */
126
127 u8 last_result[32];
128
129 int revision;
130
Linus Torvalds1da177e2005-04-16 15:20:36 -0700131 struct dvb_frontend* fe;
132};
133
Robert P. J. Day3a4fa0a2007-10-19 23:10:43 +0200134/* ugly workaround ... don't know why it's necessary to read */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700135/* all result codes. */
136
Linus Torvalds1da177e2005-04-16 15:20:36 -0700137static int ttusb_cmd(struct ttusb *ttusb,
138 const u8 * data, int len, int needresult)
139{
140 int actual_len;
141 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700142 int i;
143
Jarod Wilson68a49a42011-03-24 12:56:16 -0300144 if (debug >= 3) {
145 printk(KERN_DEBUG ">");
146 for (i = 0; i < len; ++i)
147 printk(KERN_CONT " %02x", data[i]);
148 printk(KERN_CONT "\n");
149 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700150
Ingo Molnar3593cab2006-02-07 06:49:14 -0200151 if (mutex_lock_interruptible(&ttusb->semusb) < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700152 return -EAGAIN;
153
154 err = usb_bulk_msg(ttusb->dev, ttusb->bulk_out_pipe,
155 (u8 *) data, len, &actual_len, 1000);
156 if (err != 0) {
157 dprintk("%s: usb_bulk_msg(send) failed, err == %i!\n",
Harvey Harrisonfb9393b2008-04-08 23:20:00 -0300158 __func__, err);
Ingo Molnar3593cab2006-02-07 06:49:14 -0200159 mutex_unlock(&ttusb->semusb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700160 return err;
161 }
162 if (actual_len != len) {
Harvey Harrisonfb9393b2008-04-08 23:20:00 -0300163 dprintk("%s: only wrote %d of %d bytes\n", __func__,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700164 actual_len, len);
Ingo Molnar3593cab2006-02-07 06:49:14 -0200165 mutex_unlock(&ttusb->semusb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700166 return -1;
167 }
168
169 err = usb_bulk_msg(ttusb->dev, ttusb->bulk_in_pipe,
170 ttusb->last_result, 32, &actual_len, 1000);
171
172 if (err != 0) {
Harvey Harrisonfb9393b2008-04-08 23:20:00 -0300173 printk("%s: failed, receive error %d\n", __func__,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700174 err);
Ingo Molnar3593cab2006-02-07 06:49:14 -0200175 mutex_unlock(&ttusb->semusb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700176 return err;
177 }
Jarod Wilson68a49a42011-03-24 12:56:16 -0300178
179 if (debug >= 3) {
180 actual_len = ttusb->last_result[3] + 4;
181 printk(KERN_DEBUG "<");
182 for (i = 0; i < actual_len; ++i)
183 printk(KERN_CONT " %02x", ttusb->last_result[i]);
184 printk(KERN_CONT "\n");
185 }
186
Linus Torvalds1da177e2005-04-16 15:20:36 -0700187 if (!needresult)
Ingo Molnar3593cab2006-02-07 06:49:14 -0200188 mutex_unlock(&ttusb->semusb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700189 return 0;
190}
191
192static int ttusb_result(struct ttusb *ttusb, u8 * data, int len)
193{
194 memcpy(data, ttusb->last_result, len);
Ingo Molnar3593cab2006-02-07 06:49:14 -0200195 mutex_unlock(&ttusb->semusb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700196 return 0;
197}
198
199static int ttusb_i2c_msg(struct ttusb *ttusb,
200 u8 addr, u8 * snd_buf, u8 snd_len, u8 * rcv_buf,
201 u8 rcv_len)
202{
203 u8 b[0x28];
204 u8 id = ++ttusb->c;
205 int i, err;
206
207 if (snd_len > 0x28 - 7 || rcv_len > 0x20 - 7)
208 return -EINVAL;
209
210 b[0] = 0xaa;
211 b[1] = id;
212 b[2] = 0x31;
213 b[3] = snd_len + 3;
214 b[4] = addr << 1;
215 b[5] = snd_len;
216 b[6] = rcv_len;
217
218 for (i = 0; i < snd_len; i++)
219 b[7 + i] = snd_buf[i];
220
221 err = ttusb_cmd(ttusb, b, snd_len + 7, 1);
222
223 if (err)
224 return -EREMOTEIO;
225
226 err = ttusb_result(ttusb, b, 0x20);
227
Mauro Carvalho Chehab9101e622005-12-12 00:37:24 -0800228 /* check if the i2c transaction was successful */
229 if ((snd_len != b[5]) || (rcv_len != b[6])) return -EREMOTEIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700230
231 if (rcv_len > 0) {
232
233 if (err || b[0] != 0x55 || b[1] != id) {
234 dprintk
235 ("%s: usb_bulk_msg(recv) failed, err == %i, id == %02x, b == ",
Harvey Harrisonfb9393b2008-04-08 23:20:00 -0300236 __func__, err, id);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700237 return -EREMOTEIO;
238 }
239
240 for (i = 0; i < rcv_len; i++)
241 rcv_buf[i] = b[7 + i];
242 }
243
244 return rcv_len;
245}
246
247static int master_xfer(struct i2c_adapter* adapter, struct i2c_msg *msg, int num)
248{
249 struct ttusb *ttusb = i2c_get_adapdata(adapter);
250 int i = 0;
251 int inc;
252
Ingo Molnar3593cab2006-02-07 06:49:14 -0200253 if (mutex_lock_interruptible(&ttusb->semi2c) < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700254 return -EAGAIN;
255
256 while (i < num) {
257 u8 addr, snd_len, rcv_len, *snd_buf, *rcv_buf;
258 int err;
259
260 if (num > i + 1 && (msg[i + 1].flags & I2C_M_RD)) {
261 addr = msg[i].addr;
262 snd_buf = msg[i].buf;
263 snd_len = msg[i].len;
264 rcv_buf = msg[i + 1].buf;
265 rcv_len = msg[i + 1].len;
266 inc = 2;
267 } else {
268 addr = msg[i].addr;
269 snd_buf = msg[i].buf;
270 snd_len = msg[i].len;
271 rcv_buf = NULL;
272 rcv_len = 0;
273 inc = 1;
274 }
275
276 err = ttusb_i2c_msg(ttusb, addr,
277 snd_buf, snd_len, rcv_buf, rcv_len);
278
279 if (err < rcv_len) {
Harvey Harrisonfb9393b2008-04-08 23:20:00 -0300280 dprintk("%s: i == %i\n", __func__, i);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700281 break;
282 }
283
284 i += inc;
285 }
286
Ingo Molnar3593cab2006-02-07 06:49:14 -0200287 mutex_unlock(&ttusb->semi2c);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700288 return i;
289}
290
Linus Torvalds1da177e2005-04-16 15:20:36 -0700291static int ttusb_boot_dsp(struct ttusb *ttusb)
292{
David Woodhouse0a2a7362008-05-29 19:50:06 +0300293 const struct firmware *fw;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700294 int i, err;
295 u8 b[40];
296
David Woodhouse0a2a7362008-05-29 19:50:06 +0300297 err = request_firmware(&fw, "ttusb-budget/dspbootcode.bin",
298 &ttusb->dev->dev);
299 if (err) {
300 printk(KERN_ERR "ttusb-budget: failed to request firmware\n");
301 return err;
302 }
303
Linus Torvalds1da177e2005-04-16 15:20:36 -0700304 /* BootBlock */
305 b[0] = 0xaa;
306 b[2] = 0x13;
307 b[3] = 28;
308
309 /* upload dsp code in 32 byte steps (36 didn't work for me ...) */
310 /* 32 is max packet size, no messages should be splitted. */
David Woodhouse0a2a7362008-05-29 19:50:06 +0300311 for (i = 0; i < fw->size; i += 28) {
312 memcpy(&b[4], &fw->data[i], 28);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700313
314 b[1] = ++ttusb->c;
315
316 err = ttusb_cmd(ttusb, b, 32, 0);
317 if (err)
318 goto done;
319 }
320
321 /* last block ... */
322 b[1] = ++ttusb->c;
323 b[2] = 0x13;
324 b[3] = 0;
325
326 err = ttusb_cmd(ttusb, b, 4, 0);
327 if (err)
328 goto done;
329
330 /* BootEnd */
331 b[1] = ++ttusb->c;
332 b[2] = 0x14;
333 b[3] = 0;
334
335 err = ttusb_cmd(ttusb, b, 4, 0);
336
337 done:
Jesper Juhlba0fd562011-02-06 17:49:02 -0300338 release_firmware(fw);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700339 if (err) {
340 dprintk("%s: usb_bulk_msg() failed, return value %i!\n",
Harvey Harrisonfb9393b2008-04-08 23:20:00 -0300341 __func__, err);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700342 }
343
344 return err;
345}
346
347static int ttusb_set_channel(struct ttusb *ttusb, int chan_id, int filter_type,
348 int pid)
349{
350 int err;
351 /* SetChannel */
352 u8 b[] = { 0xaa, ++ttusb->c, 0x22, 4, chan_id, filter_type,
353 (pid >> 8) & 0xff, pid & 0xff
354 };
355
356 err = ttusb_cmd(ttusb, b, sizeof(b), 0);
357 return err;
358}
359
360static int ttusb_del_channel(struct ttusb *ttusb, int channel_id)
361{
362 int err;
363 /* DelChannel */
364 u8 b[] = { 0xaa, ++ttusb->c, 0x23, 1, channel_id };
365
366 err = ttusb_cmd(ttusb, b, sizeof(b), 0);
367 return err;
368}
369
370#ifdef TTUSB_HWSECTIONS
371static int ttusb_set_filter(struct ttusb *ttusb, int filter_id,
372 int associated_chan, u8 filter[8], u8 mask[8])
373{
374 int err;
375 /* SetFilter */
376 u8 b[] = { 0xaa, 0, 0x24, 0x1a, filter_id, associated_chan,
377 filter[0], filter[1], filter[2], filter[3],
378 filter[4], filter[5], filter[6], filter[7],
379 filter[8], filter[9], filter[10], filter[11],
380 mask[0], mask[1], mask[2], mask[3],
381 mask[4], mask[5], mask[6], mask[7],
382 mask[8], mask[9], mask[10], mask[11]
383 };
384
385 err = ttusb_cmd(ttusb, b, sizeof(b), 0);
386 return err;
387}
388
389static int ttusb_del_filter(struct ttusb *ttusb, int filter_id)
390{
391 int err;
392 /* DelFilter */
393 u8 b[] = { 0xaa, ++ttusb->c, 0x25, 1, filter_id };
394
395 err = ttusb_cmd(ttusb, b, sizeof(b), 0);
396 return err;
397}
398#endif
399
400static int ttusb_init_controller(struct ttusb *ttusb)
401{
402 u8 b0[] = { 0xaa, ++ttusb->c, 0x15, 1, 0 };
403 u8 b1[] = { 0xaa, ++ttusb->c, 0x15, 1, 1 };
404 u8 b2[] = { 0xaa, ++ttusb->c, 0x32, 1, 0 };
405 /* i2c write read: 5 bytes, addr 0x10, 0x02 bytes write, 1 bytes read. */
406 u8 b3[] =
407 { 0xaa, ++ttusb->c, 0x31, 5, 0x10, 0x02, 0x01, 0x00, 0x1e };
408 u8 b4[] =
409 { 0x55, ttusb->c, 0x31, 4, 0x10, 0x02, 0x01, 0x00, 0x1e };
410
411 u8 get_version[] = { 0xaa, ++ttusb->c, 0x17, 5, 0, 0, 0, 0, 0 };
412 u8 get_dsp_version[0x20] =
413 { 0xaa, ++ttusb->c, 0x26, 28, 0, 0, 0, 0, 0 };
414 int err;
415
416 /* reset board */
417 if ((err = ttusb_cmd(ttusb, b0, sizeof(b0), 0)))
418 return err;
419
420 /* reset board (again?) */
421 if ((err = ttusb_cmd(ttusb, b1, sizeof(b1), 0)))
422 return err;
423
424 ttusb_boot_dsp(ttusb);
425
426 /* set i2c bit rate */
427 if ((err = ttusb_cmd(ttusb, b2, sizeof(b2), 0)))
428 return err;
429
430 if ((err = ttusb_cmd(ttusb, b3, sizeof(b3), 1)))
431 return err;
432
433 err = ttusb_result(ttusb, b4, sizeof(b4));
434
435 if ((err = ttusb_cmd(ttusb, get_version, sizeof(get_version), 1)))
436 return err;
437
438 if ((err = ttusb_result(ttusb, get_version, sizeof(get_version))))
439 return err;
440
Harvey Harrisonfb9393b2008-04-08 23:20:00 -0300441 dprintk("%s: stc-version: %c%c%c%c%c\n", __func__,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700442 get_version[4], get_version[5], get_version[6],
443 get_version[7], get_version[8]);
444
445 if (memcmp(get_version + 4, "V 0.0", 5) &&
446 memcmp(get_version + 4, "V 1.1", 5) &&
447 memcmp(get_version + 4, "V 2.1", 5) &&
448 memcmp(get_version + 4, "V 2.2", 5)) {
449 printk
450 ("%s: unknown STC version %c%c%c%c%c, please report!\n",
Harvey Harrisonfb9393b2008-04-08 23:20:00 -0300451 __func__, get_version[4], get_version[5],
Linus Torvalds1da177e2005-04-16 15:20:36 -0700452 get_version[6], get_version[7], get_version[8]);
453 }
454
455 ttusb->revision = ((get_version[6] - '0') << 4) |
456 (get_version[8] - '0');
457
458 err =
459 ttusb_cmd(ttusb, get_dsp_version, sizeof(get_dsp_version), 1);
460 if (err)
461 return err;
462
463 err =
464 ttusb_result(ttusb, get_dsp_version, sizeof(get_dsp_version));
465 if (err)
466 return err;
Harvey Harrisonfb9393b2008-04-08 23:20:00 -0300467 printk("%s: dsp-version: %c%c%c\n", __func__,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700468 get_dsp_version[4], get_dsp_version[5], get_dsp_version[6]);
469 return 0;
470}
471
472#ifdef TTUSB_DISEQC
473static int ttusb_send_diseqc(struct dvb_frontend* fe,
474 const struct dvb_diseqc_master_cmd *cmd)
475{
476 struct ttusb* ttusb = (struct ttusb*) fe->dvb->priv;
477 u8 b[12] = { 0xaa, ++ttusb->c, 0x18 };
478
479 int err;
480
481 b[3] = 4 + 2 + cmd->msg_len;
482 b[4] = 0xFF; /* send diseqc master, not burst */
483 b[5] = cmd->msg_len;
484
485 memcpy(b + 5, cmd->msg, cmd->msg_len);
486
487 /* Diseqc */
488 if ((err = ttusb_cmd(ttusb, b, 4 + b[3], 0))) {
489 dprintk("%s: usb_bulk_msg() failed, return value %i!\n",
Harvey Harrisonfb9393b2008-04-08 23:20:00 -0300490 __func__, err);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700491 }
492
493 return err;
494}
495#endif
496
Linus Torvalds1da177e2005-04-16 15:20:36 -0700497static int ttusb_update_lnb(struct ttusb *ttusb)
498{
499 u8 b[] = { 0xaa, ++ttusb->c, 0x16, 5, /*power: */ 1,
500 ttusb->voltage == SEC_VOLTAGE_18 ? 0 : 1,
501 ttusb->tone == SEC_TONE_ON ? 1 : 0, 1, 1
502 };
503 int err;
504
505 /* SetLNB */
506 if ((err = ttusb_cmd(ttusb, b, sizeof(b), 0))) {
507 dprintk("%s: usb_bulk_msg() failed, return value %i!\n",
Harvey Harrisonfb9393b2008-04-08 23:20:00 -0300508 __func__, err);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700509 }
510
511 return err;
512}
513
514static int ttusb_set_voltage(struct dvb_frontend* fe, fe_sec_voltage_t voltage)
515{
516 struct ttusb* ttusb = (struct ttusb*) fe->dvb->priv;
517
518 ttusb->voltage = voltage;
519 return ttusb_update_lnb(ttusb);
520}
521
522#ifdef TTUSB_TONE
523static int ttusb_set_tone(struct dvb_frontend* fe, fe_sec_tone_mode_t tone)
524{
525 struct ttusb* ttusb = (struct ttusb*) fe->dvb->priv;
526
527 ttusb->tone = tone;
528 return ttusb_update_lnb(ttusb);
529}
530#endif
531
532
533#if 0
534static void ttusb_set_led_freq(struct ttusb *ttusb, u8 freq)
535{
536 u8 b[] = { 0xaa, ++ttusb->c, 0x19, 1, freq };
537 int err, actual_len;
538
539 err = ttusb_cmd(ttusb, b, sizeof(b), 0);
540 if (err) {
541 dprintk("%s: usb_bulk_msg() failed, return value %i!\n",
Harvey Harrisonfb9393b2008-04-08 23:20:00 -0300542 __func__, err);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700543 }
544}
545#endif
546
547/*****************************************************************************/
548
549#ifdef TTUSB_HWSECTIONS
550static void ttusb_handle_ts_data(struct ttusb_channel *channel,
551 const u8 * data, int len);
552static void ttusb_handle_sec_data(struct ttusb_channel *channel,
553 const u8 * data, int len);
554#endif
555
Douglas Schilling Landgrafff699e62008-04-22 14:41:48 -0300556static int numpkt, numts, numstuff, numsec, numinvalid;
Marcelo Feitoza Parisi4da006c2005-09-09 13:03:15 -0700557static unsigned long lastj;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700558
559static void ttusb_process_muxpack(struct ttusb *ttusb, const u8 * muxpack,
560 int len)
561{
562 u16 csum = 0, cc;
563 int i;
564 for (i = 0; i < len; i += 2)
Al Virod4f979a2008-05-21 00:31:31 -0300565 csum ^= le16_to_cpup((__le16 *) (muxpack + i));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700566 if (csum) {
567 printk("%s: muxpack with incorrect checksum, ignoring\n",
Harvey Harrisonfb9393b2008-04-08 23:20:00 -0300568 __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700569 numinvalid++;
570 return;
571 }
572
573 cc = (muxpack[len - 4] << 8) | muxpack[len - 3];
574 cc &= 0x7FFF;
575 if ((cc != ttusb->cc) && (ttusb->cc != -1))
576 printk("%s: cc discontinuity (%d frames missing)\n",
Harvey Harrisonfb9393b2008-04-08 23:20:00 -0300577 __func__, (cc - ttusb->cc) & 0x7FFF);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700578 ttusb->cc = (cc + 1) & 0x7FFF;
579 if (muxpack[0] & 0x80) {
580#ifdef TTUSB_HWSECTIONS
581 /* section data */
582 int pusi = muxpack[0] & 0x40;
583 int channel = muxpack[0] & 0x1F;
584 int payload = muxpack[1];
585 const u8 *data = muxpack + 2;
586 /* check offset flag */
587 if (muxpack[0] & 0x20)
588 data++;
589
590 ttusb_handle_sec_data(ttusb->channel + channel, data,
591 payload);
592 data += payload;
593
594 if ((!!(ttusb->muxpack[0] & 0x20)) ^
595 !!(ttusb->muxpack[1] & 1))
596 data++;
597#warning TODO: pusi
598 printk("cc: %04x\n", (data[0] << 8) | data[1]);
599#endif
600 numsec++;
601 } else if (muxpack[0] == 0x47) {
602#ifdef TTUSB_HWSECTIONS
603 /* we have TS data here! */
604 int pid = ((muxpack[1] & 0x0F) << 8) | muxpack[2];
605 int channel;
606 for (channel = 0; channel < TTUSB_MAXCHANNEL; ++channel)
607 if (ttusb->channel[channel].active
608 && (pid == ttusb->channel[channel].pid))
609 ttusb_handle_ts_data(ttusb->channel +
610 channel, muxpack,
611 188);
612#endif
613 numts++;
614 dvb_dmx_swfilter_packets(&ttusb->dvb_demux, muxpack, 1);
615 } else if (muxpack[0] != 0) {
616 numinvalid++;
617 printk("illegal muxpack type %02x\n", muxpack[0]);
618 } else
619 numstuff++;
620}
621
622static void ttusb_process_frame(struct ttusb *ttusb, u8 * data, int len)
623{
624 int maxwork = 1024;
625 while (len) {
626 if (!(maxwork--)) {
Harvey Harrisonfb9393b2008-04-08 23:20:00 -0300627 printk("%s: too much work\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700628 break;
629 }
630
631 switch (ttusb->mux_state) {
632 case 0:
633 case 1:
634 case 2:
635 len--;
636 if (*data++ == 0xAA)
637 ++ttusb->mux_state;
638 else {
639 ttusb->mux_state = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700640 if (ttusb->insync) {
Jarod Wilson68a49a42011-03-24 12:56:16 -0300641 dprintk("%s: %02x\n",
642 __func__, data[-1]);
643 printk(KERN_INFO "%s: lost sync.\n",
Harvey Harrisonfb9393b2008-04-08 23:20:00 -0300644 __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700645 ttusb->insync = 0;
646 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700647 }
648 break;
649 case 3:
650 ttusb->insync = 1;
651 len--;
652 ttusb->mux_npacks = *data++;
653 ++ttusb->mux_state;
654 ttusb->muxpack_ptr = 0;
655 /* maximum bytes, until we know the length */
656 ttusb->muxpack_len = 2;
657 break;
658 case 4:
659 {
660 int avail;
661 avail = len;
662 if (avail >
663 (ttusb->muxpack_len -
664 ttusb->muxpack_ptr))
665 avail =
666 ttusb->muxpack_len -
667 ttusb->muxpack_ptr;
668 memcpy(ttusb->muxpack + ttusb->muxpack_ptr,
669 data, avail);
670 ttusb->muxpack_ptr += avail;
Eric Sesterhennae246012006-03-13 13:17:11 -0300671 BUG_ON(ttusb->muxpack_ptr > 264);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700672 data += avail;
673 len -= avail;
674 /* determine length */
675 if (ttusb->muxpack_ptr == 2) {
676 if (ttusb->muxpack[0] & 0x80) {
677 ttusb->muxpack_len =
678 ttusb->muxpack[1] + 2;
679 if (ttusb->
680 muxpack[0] & 0x20)
681 ttusb->
682 muxpack_len++;
683 if ((!!
684 (ttusb->
685 muxpack[0] & 0x20)) ^
686 !!(ttusb->
687 muxpack[1] & 1))
688 ttusb->
689 muxpack_len++;
690 ttusb->muxpack_len += 4;
691 } else if (ttusb->muxpack[0] ==
692 0x47)
693 ttusb->muxpack_len =
694 188 + 4;
695 else if (ttusb->muxpack[0] == 0x00)
696 ttusb->muxpack_len =
697 ttusb->muxpack[1] + 2 +
698 4;
699 else {
700 dprintk
701 ("%s: invalid state: first byte is %x\n",
Harvey Harrisonfb9393b2008-04-08 23:20:00 -0300702 __func__,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700703 ttusb->muxpack[0]);
704 ttusb->mux_state = 0;
705 }
706 }
707
708 /**
709 * if length is valid and we reached the end:
710 * goto next muxpack
711 */
712 if ((ttusb->muxpack_ptr >= 2) &&
713 (ttusb->muxpack_ptr ==
714 ttusb->muxpack_len)) {
715 ttusb_process_muxpack(ttusb,
716 ttusb->
717 muxpack,
718 ttusb->
719 muxpack_ptr);
720 ttusb->muxpack_ptr = 0;
721 /* maximum bytes, until we know the length */
722 ttusb->muxpack_len = 2;
723
724 /**
725 * no muxpacks left?
726 * return to search-sync state
727 */
728 if (!ttusb->mux_npacks--) {
729 ttusb->mux_state = 0;
730 break;
731 }
732 }
733 break;
734 }
735 default:
736 BUG();
737 break;
738 }
739 }
740}
741
David Howells7d12e782006-10-05 14:55:46 +0100742static void ttusb_iso_irq(struct urb *urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700743{
744 struct ttusb *ttusb = urb->context;
Jarod Wilson68a49a42011-03-24 12:56:16 -0300745 struct usb_iso_packet_descriptor *d;
746 u8 *data;
747 int len, i;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700748
749 if (!ttusb->iso_streaming)
750 return;
751
752#if 0
753 printk("%s: status %d, errcount == %d, length == %i\n",
Harvey Harrisonfb9393b2008-04-08 23:20:00 -0300754 __func__,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700755 urb->status, urb->error_count, urb->actual_length);
756#endif
757
758 if (!urb->status) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700759 for (i = 0; i < urb->number_of_packets; ++i) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700760 numpkt++;
Marcelo Feitoza Parisi4da006c2005-09-09 13:03:15 -0700761 if (time_after_eq(jiffies, lastj + HZ)) {
Jarod Wilson68a49a42011-03-24 12:56:16 -0300762 dprintk("frames/s: %lu (ts: %d, stuff %d, "
763 "sec: %d, invalid: %d, all: %d)\n",
764 numpkt * HZ / (jiffies - lastj),
765 numts, numstuff, numsec, numinvalid,
766 numts + numstuff + numsec + numinvalid);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700767 numts = numstuff = numsec = numinvalid = 0;
768 lastj = jiffies;
769 numpkt = 0;
770 }
771 d = &urb->iso_frame_desc[i];
772 data = urb->transfer_buffer + d->offset;
773 len = d->actual_length;
774 d->actual_length = 0;
775 d->status = 0;
776 ttusb_process_frame(ttusb, data, len);
777 }
778 }
779 usb_submit_urb(urb, GFP_ATOMIC);
780}
781
782static void ttusb_free_iso_urbs(struct ttusb *ttusb)
783{
784 int i;
785
786 for (i = 0; i < ISO_BUF_COUNT; i++)
787 if (ttusb->iso_urb[i])
788 usb_free_urb(ttusb->iso_urb[i]);
789
790 pci_free_consistent(NULL,
791 ISO_FRAME_SIZE * FRAMES_PER_ISO_BUF *
792 ISO_BUF_COUNT, ttusb->iso_buffer,
793 ttusb->iso_dma_handle);
794}
795
796static int ttusb_alloc_iso_urbs(struct ttusb *ttusb)
797{
798 int i;
799
800 ttusb->iso_buffer = pci_alloc_consistent(NULL,
801 ISO_FRAME_SIZE *
802 FRAMES_PER_ISO_BUF *
803 ISO_BUF_COUNT,
804 &ttusb->iso_dma_handle);
805
Douglas Schilling Landgraf11eb2602008-11-11 23:30:49 -0300806 if (!ttusb->iso_buffer) {
807 dprintk("%s: pci_alloc_consistent - not enough memory\n",
808 __func__);
809 return -ENOMEM;
810 }
811
Linus Torvalds1da177e2005-04-16 15:20:36 -0700812 memset(ttusb->iso_buffer, 0,
813 ISO_FRAME_SIZE * FRAMES_PER_ISO_BUF * ISO_BUF_COUNT);
814
815 for (i = 0; i < ISO_BUF_COUNT; i++) {
816 struct urb *urb;
817
818 if (!
819 (urb =
820 usb_alloc_urb(FRAMES_PER_ISO_BUF, GFP_ATOMIC))) {
821 ttusb_free_iso_urbs(ttusb);
822 return -ENOMEM;
823 }
824
825 ttusb->iso_urb[i] = urb;
826 }
827
828 return 0;
829}
830
831static void ttusb_stop_iso_xfer(struct ttusb *ttusb)
832{
833 int i;
834
835 for (i = 0; i < ISO_BUF_COUNT; i++)
836 usb_kill_urb(ttusb->iso_urb[i]);
837
838 ttusb->iso_streaming = 0;
839}
840
841static int ttusb_start_iso_xfer(struct ttusb *ttusb)
842{
843 int i, j, err, buffer_offset = 0;
844
845 if (ttusb->iso_streaming) {
Harvey Harrisonfb9393b2008-04-08 23:20:00 -0300846 printk("%s: iso xfer already running!\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700847 return 0;
848 }
849
850 ttusb->cc = -1;
851 ttusb->insync = 0;
852 ttusb->mux_state = 0;
853
854 for (i = 0; i < ISO_BUF_COUNT; i++) {
855 int frame_offset = 0;
856 struct urb *urb = ttusb->iso_urb[i];
857
858 urb->dev = ttusb->dev;
859 urb->context = ttusb;
860 urb->complete = ttusb_iso_irq;
861 urb->pipe = ttusb->isoc_in_pipe;
862 urb->transfer_flags = URB_ISO_ASAP;
863 urb->interval = 1;
864 urb->number_of_packets = FRAMES_PER_ISO_BUF;
865 urb->transfer_buffer_length =
866 ISO_FRAME_SIZE * FRAMES_PER_ISO_BUF;
867 urb->transfer_buffer = ttusb->iso_buffer + buffer_offset;
868 buffer_offset += ISO_FRAME_SIZE * FRAMES_PER_ISO_BUF;
869
870 for (j = 0; j < FRAMES_PER_ISO_BUF; j++) {
871 urb->iso_frame_desc[j].offset = frame_offset;
872 urb->iso_frame_desc[j].length = ISO_FRAME_SIZE;
873 frame_offset += ISO_FRAME_SIZE;
874 }
875 }
876
877 for (i = 0; i < ISO_BUF_COUNT; i++) {
878 if ((err = usb_submit_urb(ttusb->iso_urb[i], GFP_ATOMIC))) {
879 ttusb_stop_iso_xfer(ttusb);
880 printk
881 ("%s: failed urb submission (%i: err = %i)!\n",
Harvey Harrisonfb9393b2008-04-08 23:20:00 -0300882 __func__, i, err);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700883 return err;
884 }
885 }
886
887 ttusb->iso_streaming = 1;
888
889 return 0;
890}
891
892#ifdef TTUSB_HWSECTIONS
893static void ttusb_handle_ts_data(struct dvb_demux_feed *dvbdmxfeed, const u8 * data,
894 int len)
895{
896 dvbdmxfeed->cb.ts(data, len, 0, 0, &dvbdmxfeed->feed.ts, 0);
897}
898
899static void ttusb_handle_sec_data(struct dvb_demux_feed *dvbdmxfeed, const u8 * data,
900 int len)
901{
902// struct dvb_demux_feed *dvbdmxfeed = channel->dvbdmxfeed;
903#error TODO: handle ugly stuff
904// dvbdmxfeed->cb.sec(data, len, 0, 0, &dvbdmxfeed->feed.sec, 0);
905}
906#endif
907
908static int ttusb_start_feed(struct dvb_demux_feed *dvbdmxfeed)
909{
910 struct ttusb *ttusb = (struct ttusb *) dvbdmxfeed->demux;
911 int feed_type = 1;
912
913 dprintk("ttusb_start_feed\n");
914
915 switch (dvbdmxfeed->type) {
916 case DMX_TYPE_TS:
917 break;
918 case DMX_TYPE_SEC:
919 break;
920 default:
921 return -EINVAL;
922 }
923
924 if (dvbdmxfeed->type == DMX_TYPE_TS) {
925 switch (dvbdmxfeed->pes_type) {
926 case DMX_TS_PES_VIDEO:
927 case DMX_TS_PES_AUDIO:
928 case DMX_TS_PES_TELETEXT:
929 case DMX_TS_PES_PCR:
930 case DMX_TS_PES_OTHER:
931 break;
932 default:
933 return -EINVAL;
934 }
935 }
936
937#ifdef TTUSB_HWSECTIONS
938#error TODO: allocate filters
939 if (dvbdmxfeed->type == DMX_TYPE_TS) {
940 feed_type = 1;
941 } else if (dvbdmxfeed->type == DMX_TYPE_SEC) {
942 feed_type = 2;
943 }
944#endif
945
946 ttusb_set_channel(ttusb, dvbdmxfeed->index, feed_type, dvbdmxfeed->pid);
947
948 if (0 == ttusb->running_feed_count++)
949 ttusb_start_iso_xfer(ttusb);
950
951 return 0;
952}
953
954static int ttusb_stop_feed(struct dvb_demux_feed *dvbdmxfeed)
955{
956 struct ttusb *ttusb = (struct ttusb *) dvbdmxfeed->demux;
957
958 ttusb_del_channel(ttusb, dvbdmxfeed->index);
959
960 if (--ttusb->running_feed_count == 0)
961 ttusb_stop_iso_xfer(ttusb);
962
963 return 0;
964}
965
966static int ttusb_setup_interfaces(struct ttusb *ttusb)
967{
968 usb_set_interface(ttusb->dev, 1, 1);
969
970 ttusb->bulk_out_pipe = usb_sndbulkpipe(ttusb->dev, 1);
971 ttusb->bulk_in_pipe = usb_rcvbulkpipe(ttusb->dev, 1);
972 ttusb->isoc_in_pipe = usb_rcvisocpipe(ttusb->dev, 2);
973
974 return 0;
975}
976
977#if 0
978static u8 stc_firmware[8192];
979
980static int stc_open(struct inode *inode, struct file *file)
981{
982 struct ttusb *ttusb = file->private_data;
983 int addr;
984
985 for (addr = 0; addr < 8192; addr += 16) {
986 u8 snd_buf[2] = { addr >> 8, addr & 0xFF };
987 ttusb_i2c_msg(ttusb, 0x50, snd_buf, 2, stc_firmware + addr,
988 16);
989 }
990
991 return 0;
992}
993
994static ssize_t stc_read(struct file *file, char *buf, size_t count,
Akinobu Mitaa8a89b72008-07-04 06:33:20 -0300995 loff_t *offset)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700996{
Akinobu Mitaa8a89b72008-07-04 06:33:20 -0300997 return simple_read_from_buffer(buf, count, offset, stc_firmware, 8192);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700998}
999
1000static int stc_release(struct inode *inode, struct file *file)
1001{
1002 return 0;
1003}
1004
Jan Engelhardt27a643b2008-04-22 14:42:01 -03001005static const struct file_operations stc_fops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001006 .owner = THIS_MODULE,
1007 .read = stc_read,
1008 .open = stc_open,
1009 .release = stc_release,
1010};
1011#endif
1012
1013static u32 functionality(struct i2c_adapter *adapter)
1014{
1015 return I2C_FUNC_I2C;
1016}
1017
1018
1019
Andrew de Quincey651b81b2006-04-18 17:47:11 -03001020static int alps_tdmb7_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001021{
Mauro Carvalho Chehab57605c92011-12-23 07:15:40 -03001022 struct dtv_frontend_properties *p = &fe->dtv_property_cache;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001023 struct ttusb* ttusb = (struct ttusb*) fe->dvb->priv;
1024 u8 data[4];
1025 struct i2c_msg msg = {.addr=0x61, .flags=0, .buf=data, .len=sizeof(data) };
1026 u32 div;
1027
Mauro Carvalho Chehab57605c92011-12-23 07:15:40 -03001028 div = (p->frequency + 36166667) / 166667;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001029
1030 data[0] = (div >> 8) & 0x7f;
1031 data[1] = div & 0xff;
1032 data[2] = ((div >> 10) & 0x60) | 0x85;
Mauro Carvalho Chehab57605c92011-12-23 07:15:40 -03001033 data[3] = p->frequency < 592000000 ? 0x40 : 0x80;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001034
Patrick Boettcherdea74862006-05-14 05:01:31 -03001035 if (fe->ops.i2c_gate_ctrl)
1036 fe->ops.i2c_gate_ctrl(fe, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001037 if (i2c_transfer(&ttusb->i2c_adap, &msg, 1) != 1) return -EIO;
1038 return 0;
1039}
1040
Johannes Stezenbachd91b7302005-05-16 21:54:38 -07001041static struct cx22700_config alps_tdmb7_config = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001042 .demod_address = 0x43,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001043};
1044
1045
1046
1047
1048
Andrew de Quincey651b81b2006-04-18 17:47:11 -03001049static int philips_tdm1316l_tuner_init(struct dvb_frontend* fe)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001050{
1051 struct ttusb* ttusb = (struct ttusb*) fe->dvb->priv;
1052 static u8 td1316_init[] = { 0x0b, 0xf5, 0x85, 0xab };
1053 static u8 disable_mc44BC374c[] = { 0x1d, 0x74, 0xa0, 0x68 };
1054 struct i2c_msg tuner_msg = { .addr=0x60, .flags=0, .buf=td1316_init, .len=sizeof(td1316_init) };
1055
1056 // setup PLL configuration
Patrick Boettcherdea74862006-05-14 05:01:31 -03001057 if (fe->ops.i2c_gate_ctrl)
1058 fe->ops.i2c_gate_ctrl(fe, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001059 if (i2c_transfer(&ttusb->i2c_adap, &tuner_msg, 1) != 1) return -EIO;
1060 msleep(1);
1061
1062 // disable the mc44BC374c (do not check for errors)
1063 tuner_msg.addr = 0x65;
1064 tuner_msg.buf = disable_mc44BC374c;
1065 tuner_msg.len = sizeof(disable_mc44BC374c);
Patrick Boettcherdea74862006-05-14 05:01:31 -03001066 if (fe->ops.i2c_gate_ctrl)
1067 fe->ops.i2c_gate_ctrl(fe, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001068 if (i2c_transfer(&ttusb->i2c_adap, &tuner_msg, 1) != 1) {
1069 i2c_transfer(&ttusb->i2c_adap, &tuner_msg, 1);
1070 }
1071
1072 return 0;
1073}
1074
Andrew de Quincey651b81b2006-04-18 17:47:11 -03001075static int philips_tdm1316l_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001076{
Mauro Carvalho Chehab57605c92011-12-23 07:15:40 -03001077 struct dtv_frontend_properties *p = &fe->dtv_property_cache;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001078 struct ttusb* ttusb = (struct ttusb*) fe->dvb->priv;
1079 u8 tuner_buf[4];
1080 struct i2c_msg tuner_msg = {.addr=0x60, .flags=0, .buf=tuner_buf, .len=sizeof(tuner_buf) };
1081 int tuner_frequency = 0;
1082 u8 band, cp, filter;
1083
1084 // determine charge pump
Mauro Carvalho Chehab57605c92011-12-23 07:15:40 -03001085 tuner_frequency = p->frequency + 36130000;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001086 if (tuner_frequency < 87000000) return -EINVAL;
1087 else if (tuner_frequency < 130000000) cp = 3;
1088 else if (tuner_frequency < 160000000) cp = 5;
1089 else if (tuner_frequency < 200000000) cp = 6;
1090 else if (tuner_frequency < 290000000) cp = 3;
1091 else if (tuner_frequency < 420000000) cp = 5;
1092 else if (tuner_frequency < 480000000) cp = 6;
1093 else if (tuner_frequency < 620000000) cp = 3;
1094 else if (tuner_frequency < 830000000) cp = 5;
1095 else if (tuner_frequency < 895000000) cp = 7;
1096 else return -EINVAL;
1097
1098 // determine band
Mauro Carvalho Chehab57605c92011-12-23 07:15:40 -03001099 if (p->frequency < 49000000)
1100 return -EINVAL;
1101 else if (p->frequency < 159000000)
1102 band = 1;
1103 else if (p->frequency < 444000000)
1104 band = 2;
1105 else if (p->frequency < 861000000)
1106 band = 4;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001107 else return -EINVAL;
1108
1109 // setup PLL filter
Mauro Carvalho Chehab57605c92011-12-23 07:15:40 -03001110 switch (p->bandwidth_hz) {
1111 case 6000000:
Andrew de Quinceyc10d14d2006-08-08 09:10:08 -03001112 tda1004x_writereg(fe, 0x0C, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001113 filter = 0;
1114 break;
1115
Mauro Carvalho Chehab57605c92011-12-23 07:15:40 -03001116 case 7000000:
Andrew de Quinceyc10d14d2006-08-08 09:10:08 -03001117 tda1004x_writereg(fe, 0x0C, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001118 filter = 0;
1119 break;
1120
Mauro Carvalho Chehab57605c92011-12-23 07:15:40 -03001121 case 8000000:
Andrew de Quinceyc10d14d2006-08-08 09:10:08 -03001122 tda1004x_writereg(fe, 0x0C, 0xFF);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001123 filter = 1;
1124 break;
1125
1126 default:
1127 return -EINVAL;
1128 }
1129
1130 // calculate divisor
1131 // ((36130000+((1000000/6)/2)) + Finput)/(1000000/6)
Mauro Carvalho Chehab57605c92011-12-23 07:15:40 -03001132 tuner_frequency = (((p->frequency / 1000) * 6) + 217280) / 1000;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001133
1134 // setup tuner buffer
1135 tuner_buf[0] = tuner_frequency >> 8;
1136 tuner_buf[1] = tuner_frequency & 0xff;
1137 tuner_buf[2] = 0xca;
1138 tuner_buf[3] = (cp << 5) | (filter << 3) | band;
1139
Patrick Boettcherdea74862006-05-14 05:01:31 -03001140 if (fe->ops.i2c_gate_ctrl)
1141 fe->ops.i2c_gate_ctrl(fe, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001142 if (i2c_transfer(&ttusb->i2c_adap, &tuner_msg, 1) != 1)
1143 return -EIO;
1144
1145 msleep(1);
1146 return 0;
1147}
1148
1149static int philips_tdm1316l_request_firmware(struct dvb_frontend* fe, const struct firmware **fw, char* name)
1150{
1151 struct ttusb* ttusb = (struct ttusb*) fe->dvb->priv;
1152
1153 return request_firmware(fw, name, &ttusb->dev->dev);
1154}
1155
1156static struct tda1004x_config philips_tdm1316l_config = {
1157
1158 .demod_address = 0x8,
1159 .invert = 1,
1160 .invert_oclk = 0,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001161 .request_firmware = philips_tdm1316l_request_firmware,
1162};
1163
1164static u8 alps_bsbe1_inittab[] = {
Mauro Carvalho Chehab9101e622005-12-12 00:37:24 -08001165 0x01, 0x15,
1166 0x02, 0x30,
1167 0x03, 0x00,
1168 0x04, 0x7d, /* F22FR = 0x7d, F22 = f_VCO / 128 / 0x7d = 22 kHz */
1169 0x05, 0x35, /* I2CT = 0, SCLT = 1, SDAT = 1 */
1170 0x06, 0x40, /* DAC not used, set to high impendance mode */
1171 0x07, 0x00, /* DAC LSB */
1172 0x08, 0x40, /* DiSEqC off, LNB power on OP2/LOCK pin on */
1173 0x09, 0x00, /* FIFO */
1174 0x0c, 0x51, /* OP1 ctl = Normal, OP1 val = 1 (LNB Power ON) */
1175 0x0d, 0x82, /* DC offset compensation = ON, beta_agc1 = 2 */
1176 0x0e, 0x23, /* alpha_tmg = 2, beta_tmg = 3 */
1177 0x10, 0x3f, // AGC2 0x3d
1178 0x11, 0x84,
1179 0x12, 0xb9,
1180 0x15, 0xc9, // lock detector threshold
1181 0x16, 0x00,
1182 0x17, 0x00,
1183 0x18, 0x00,
1184 0x19, 0x00,
1185 0x1a, 0x00,
1186 0x1f, 0x50,
1187 0x20, 0x00,
1188 0x21, 0x00,
1189 0x22, 0x00,
1190 0x23, 0x00,
1191 0x28, 0x00, // out imp: normal out type: parallel FEC mode:0
1192 0x29, 0x1e, // 1/2 threshold
1193 0x2a, 0x14, // 2/3 threshold
1194 0x2b, 0x0f, // 3/4 threshold
1195 0x2c, 0x09, // 5/6 threshold
1196 0x2d, 0x05, // 7/8 threshold
1197 0x2e, 0x01,
1198 0x31, 0x1f, // test all FECs
1199 0x32, 0x19, // viterbi and synchro search
1200 0x33, 0xfc, // rs control
1201 0x34, 0x93, // error control
1202 0x0f, 0x92,
1203 0xff, 0xff
Linus Torvalds1da177e2005-04-16 15:20:36 -07001204};
1205
1206static u8 alps_bsru6_inittab[] = {
1207 0x01, 0x15,
1208 0x02, 0x30,
1209 0x03, 0x00,
1210 0x04, 0x7d, /* F22FR = 0x7d, F22 = f_VCO / 128 / 0x7d = 22 kHz */
1211 0x05, 0x35, /* I2CT = 0, SCLT = 1, SDAT = 1 */
1212 0x06, 0x40, /* DAC not used, set to high impendance mode */
1213 0x07, 0x00, /* DAC LSB */
1214 0x08, 0x40, /* DiSEqC off, LNB power on OP2/LOCK pin on */
1215 0x09, 0x00, /* FIFO */
1216 0x0c, 0x51, /* OP1 ctl = Normal, OP1 val = 1 (LNB Power ON) */
1217 0x0d, 0x82, /* DC offset compensation = ON, beta_agc1 = 2 */
1218 0x0e, 0x23, /* alpha_tmg = 2, beta_tmg = 3 */
1219 0x10, 0x3f, // AGC2 0x3d
1220 0x11, 0x84,
Oliver Endriss7f44dcd2005-11-08 21:35:44 -08001221 0x12, 0xb9,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001222 0x15, 0xc9, // lock detector threshold
1223 0x16, 0x00,
1224 0x17, 0x00,
1225 0x18, 0x00,
1226 0x19, 0x00,
1227 0x1a, 0x00,
1228 0x1f, 0x50,
1229 0x20, 0x00,
1230 0x21, 0x00,
1231 0x22, 0x00,
1232 0x23, 0x00,
1233 0x28, 0x00, // out imp: normal out type: parallel FEC mode:0
1234 0x29, 0x1e, // 1/2 threshold
1235 0x2a, 0x14, // 2/3 threshold
1236 0x2b, 0x0f, // 3/4 threshold
1237 0x2c, 0x09, // 5/6 threshold
1238 0x2d, 0x05, // 7/8 threshold
1239 0x2e, 0x01,
1240 0x31, 0x1f, // test all FECs
1241 0x32, 0x19, // viterbi and synchro search
1242 0x33, 0xfc, // rs control
1243 0x34, 0x93, // error control
1244 0x0f, 0x52,
1245 0xff, 0xff
1246};
1247
1248static int alps_stv0299_set_symbol_rate(struct dvb_frontend *fe, u32 srate, u32 ratio)
1249{
1250 u8 aclk = 0;
1251 u8 bclk = 0;
1252
1253 if (srate < 1500000) {
1254 aclk = 0xb7;
1255 bclk = 0x47;
1256 } else if (srate < 3000000) {
1257 aclk = 0xb7;
1258 bclk = 0x4b;
1259 } else if (srate < 7000000) {
1260 aclk = 0xb7;
1261 bclk = 0x4f;
1262 } else if (srate < 14000000) {
1263 aclk = 0xb7;
1264 bclk = 0x53;
1265 } else if (srate < 30000000) {
1266 aclk = 0xb6;
1267 bclk = 0x53;
1268 } else if (srate < 45000000) {
1269 aclk = 0xb4;
1270 bclk = 0x51;
1271 }
1272
1273 stv0299_writereg(fe, 0x13, aclk);
1274 stv0299_writereg(fe, 0x14, bclk);
1275 stv0299_writereg(fe, 0x1f, (ratio >> 16) & 0xff);
1276 stv0299_writereg(fe, 0x20, (ratio >> 8) & 0xff);
1277 stv0299_writereg(fe, 0x21, (ratio) & 0xf0);
1278
1279 return 0;
1280}
1281
Andrew de Quincey651b81b2006-04-18 17:47:11 -03001282static int philips_tsa5059_tuner_set_params(struct dvb_frontend *fe, struct dvb_frontend_parameters *params)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001283{
Mauro Carvalho Chehab57605c92011-12-23 07:15:40 -03001284 struct dtv_frontend_properties *p = &fe->dtv_property_cache;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001285 struct ttusb* ttusb = (struct ttusb*) fe->dvb->priv;
1286 u8 buf[4];
1287 u32 div;
1288 struct i2c_msg msg = {.addr = 0x61,.flags = 0,.buf = buf,.len = sizeof(buf) };
1289
Mauro Carvalho Chehab57605c92011-12-23 07:15:40 -03001290 if ((p->frequency < 950000) || (p->frequency > 2150000))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001291 return -EINVAL;
1292
Mauro Carvalho Chehab57605c92011-12-23 07:15:40 -03001293 div = (p->frequency + (125 - 1)) / 125; /* round correctly */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001294 buf[0] = (div >> 8) & 0x7f;
1295 buf[1] = div & 0xff;
1296 buf[2] = 0x80 | ((div & 0x18000) >> 10) | 4;
1297 buf[3] = 0xC4;
1298
Mauro Carvalho Chehab57605c92011-12-23 07:15:40 -03001299 if (p->frequency > 1530000)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001300 buf[3] = 0xC0;
1301
1302 /* BSBE1 wants XCE bit set */
1303 if (ttusb->revision == TTUSB_REV_2_2)
1304 buf[3] |= 0x20;
1305
Patrick Boettcherdea74862006-05-14 05:01:31 -03001306 if (fe->ops.i2c_gate_ctrl)
1307 fe->ops.i2c_gate_ctrl(fe, 1);
Andrew de Quincey651b81b2006-04-18 17:47:11 -03001308 if (i2c_transfer(&ttusb->i2c_adap, &msg, 1) != 1)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001309 return -EIO;
1310
1311 return 0;
1312}
1313
1314static struct stv0299_config alps_stv0299_config = {
1315 .demod_address = 0x68,
1316 .inittab = alps_bsru6_inittab,
1317 .mclk = 88000000UL,
1318 .invert = 1,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001319 .skip_reinit = 0,
Oliver Endrissda2c7f62008-04-20 22:13:37 -03001320 .lock_output = STV0299_LOCKOUTPUT_1,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001321 .volt13_op0_op1 = STV0299_VOLT13_OP1,
1322 .min_delay_ms = 100,
1323 .set_symbol_rate = alps_stv0299_set_symbol_rate,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001324};
1325
Andrew de Quincey651b81b2006-04-18 17:47:11 -03001326static int ttusb_novas_grundig_29504_491_tuner_set_params(struct dvb_frontend *fe, struct dvb_frontend_parameters *params)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001327{
Mauro Carvalho Chehab57605c92011-12-23 07:15:40 -03001328 struct dtv_frontend_properties *p = &fe->dtv_property_cache;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001329 struct ttusb* ttusb = (struct ttusb*) fe->dvb->priv;
1330 u8 buf[4];
1331 u32 div;
1332 struct i2c_msg msg = {.addr = 0x61,.flags = 0,.buf = buf,.len = sizeof(buf) };
1333
Mauro Carvalho Chehab57605c92011-12-23 07:15:40 -03001334 div = p->frequency / 125;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001335
1336 buf[0] = (div >> 8) & 0x7f;
1337 buf[1] = div & 0xff;
1338 buf[2] = 0x8e;
1339 buf[3] = 0x00;
1340
Patrick Boettcherdea74862006-05-14 05:01:31 -03001341 if (fe->ops.i2c_gate_ctrl)
1342 fe->ops.i2c_gate_ctrl(fe, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001343 if (i2c_transfer(&ttusb->i2c_adap, &msg, 1) != 1)
1344 return -EIO;
1345
1346 return 0;
1347}
1348
1349static struct tda8083_config ttusb_novas_grundig_29504_491_config = {
1350
1351 .demod_address = 0x68,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001352};
1353
Andrew de Quincey651b81b2006-04-18 17:47:11 -03001354static int alps_tdbe2_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
Gavin Hamill53936392005-07-07 17:58:04 -07001355{
Mauro Carvalho Chehab57605c92011-12-23 07:15:40 -03001356 struct dtv_frontend_properties *p = &fe->dtv_property_cache;
Gavin Hamill53936392005-07-07 17:58:04 -07001357 struct ttusb* ttusb = fe->dvb->priv;
1358 u32 div;
1359 u8 data[4];
1360 struct i2c_msg msg = { .addr = 0x62, .flags = 0, .buf = data, .len = sizeof(data) };
1361
Mauro Carvalho Chehab57605c92011-12-23 07:15:40 -03001362 div = (p->frequency + 35937500 + 31250) / 62500;
Gavin Hamill53936392005-07-07 17:58:04 -07001363
1364 data[0] = (div >> 8) & 0x7f;
1365 data[1] = div & 0xff;
1366 data[2] = 0x85 | ((div >> 10) & 0x60);
Mauro Carvalho Chehab57605c92011-12-23 07:15:40 -03001367 data[3] = (p->frequency < 174000000 ? 0x88 : p->frequency < 470000000 ? 0x84 : 0x81);
Gavin Hamill53936392005-07-07 17:58:04 -07001368
Patrick Boettcherdea74862006-05-14 05:01:31 -03001369 if (fe->ops.i2c_gate_ctrl)
1370 fe->ops.i2c_gate_ctrl(fe, 1);
Gavin Hamill53936392005-07-07 17:58:04 -07001371 if (i2c_transfer (&ttusb->i2c_adap, &msg, 1) != 1)
1372 return -EIO;
1373
1374 return 0;
1375}
1376
1377
1378static struct ves1820_config alps_tdbe2_config = {
1379 .demod_address = 0x09,
1380 .xin = 57840000UL,
1381 .invert = 1,
1382 .selagc = VES1820_SELAGC_SIGNAMPERR,
Gavin Hamill53936392005-07-07 17:58:04 -07001383};
1384
1385static u8 read_pwm(struct ttusb* ttusb)
1386{
1387 u8 b = 0xff;
1388 u8 pwm;
1389 struct i2c_msg msg[] = { { .addr = 0x50,.flags = 0,.buf = &b,.len = 1 },
1390 { .addr = 0x50,.flags = I2C_M_RD,.buf = &pwm,.len = 1} };
1391
1392 if ((i2c_transfer(&ttusb->i2c_adap, msg, 2) != 2) || (pwm == 0xff))
1393 pwm = 0x48;
1394
1395 return pwm;
1396}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001397
1398
Thomas Kaiserb8d4c232006-04-27 21:45:20 -03001399static int dvbc_philips_tdm1316l_tuner_set_params(struct dvb_frontend *fe, struct dvb_frontend_parameters *params)
1400{
Mauro Carvalho Chehab57605c92011-12-23 07:15:40 -03001401 struct dtv_frontend_properties *p = &fe->dtv_property_cache;
Thomas Kaiserb8d4c232006-04-27 21:45:20 -03001402 struct ttusb *ttusb = (struct ttusb *) fe->dvb->priv;
1403 u8 tuner_buf[5];
1404 struct i2c_msg tuner_msg = {.addr = 0x60,
1405 .flags = 0,
1406 .buf = tuner_buf,
1407 .len = sizeof(tuner_buf) };
1408 int tuner_frequency = 0;
1409 u8 band, cp, filter;
1410
1411 // determine charge pump
Mauro Carvalho Chehab57605c92011-12-23 07:15:40 -03001412 tuner_frequency = p->frequency;
Thomas Kaiserb8d4c232006-04-27 21:45:20 -03001413 if (tuner_frequency < 87000000) {return -EINVAL;}
1414 else if (tuner_frequency < 130000000) {cp = 3; band = 1;}
1415 else if (tuner_frequency < 160000000) {cp = 5; band = 1;}
1416 else if (tuner_frequency < 200000000) {cp = 6; band = 1;}
1417 else if (tuner_frequency < 290000000) {cp = 3; band = 2;}
1418 else if (tuner_frequency < 420000000) {cp = 5; band = 2;}
1419 else if (tuner_frequency < 480000000) {cp = 6; band = 2;}
1420 else if (tuner_frequency < 620000000) {cp = 3; band = 4;}
1421 else if (tuner_frequency < 830000000) {cp = 5; band = 4;}
1422 else if (tuner_frequency < 895000000) {cp = 7; band = 4;}
1423 else {return -EINVAL;}
1424
1425 // assume PLL filter should always be 8MHz for the moment.
1426 filter = 1;
1427
1428 // calculate divisor
1429 // (Finput + Fif)/Fref; Fif = 36125000 Hz, Fref = 62500 Hz
Mauro Carvalho Chehab57605c92011-12-23 07:15:40 -03001430 tuner_frequency = ((p->frequency + 36125000) / 62500);
Thomas Kaiserb8d4c232006-04-27 21:45:20 -03001431
1432 // setup tuner buffer
1433 tuner_buf[0] = tuner_frequency >> 8;
1434 tuner_buf[1] = tuner_frequency & 0xff;
1435 tuner_buf[2] = 0xc8;
1436 tuner_buf[3] = (cp << 5) | (filter << 3) | band;
1437 tuner_buf[4] = 0x80;
1438
Patrick Boettcherdea74862006-05-14 05:01:31 -03001439 if (fe->ops.i2c_gate_ctrl)
1440 fe->ops.i2c_gate_ctrl(fe, 1);
Thomas Kaiserb8d4c232006-04-27 21:45:20 -03001441 if (i2c_transfer(&ttusb->i2c_adap, &tuner_msg, 1) != 1) {
1442 printk("dvb-ttusb-budget: dvbc_philips_tdm1316l_pll_set Error 1\n");
1443 return -EIO;
1444 }
1445
1446 msleep(50);
1447
Patrick Boettcherdea74862006-05-14 05:01:31 -03001448 if (fe->ops.i2c_gate_ctrl)
1449 fe->ops.i2c_gate_ctrl(fe, 1);
Thomas Kaiserb8d4c232006-04-27 21:45:20 -03001450 if (i2c_transfer(&ttusb->i2c_adap, &tuner_msg, 1) != 1) {
1451 printk("dvb-ttusb-budget: dvbc_philips_tdm1316l_pll_set Error 2\n");
1452 return -EIO;
1453 }
1454
1455 msleep(1);
1456
1457 return 0;
1458}
1459
1460static u8 dvbc_philips_tdm1316l_inittab[] = {
1461 0x80, 0x21,
1462 0x80, 0x20,
1463 0x81, 0x01,
1464 0x81, 0x00,
1465 0x00, 0x09,
1466 0x01, 0x69,
1467 0x03, 0x00,
1468 0x04, 0x00,
1469 0x07, 0x00,
1470 0x08, 0x00,
1471 0x20, 0x00,
1472 0x21, 0x40,
1473 0x22, 0x00,
1474 0x23, 0x00,
1475 0x24, 0x40,
1476 0x25, 0x88,
1477 0x30, 0xff,
1478 0x31, 0x00,
1479 0x32, 0xff,
1480 0x33, 0x00,
1481 0x34, 0x50,
1482 0x35, 0x7f,
1483 0x36, 0x00,
1484 0x37, 0x20,
1485 0x38, 0x00,
1486 0x40, 0x1c,
1487 0x41, 0xff,
1488 0x42, 0x29,
1489 0x43, 0x20,
1490 0x44, 0xff,
1491 0x45, 0x00,
1492 0x46, 0x00,
1493 0x49, 0x04,
1494 0x4a, 0xff,
1495 0x4b, 0x7f,
1496 0x52, 0x30,
1497 0x55, 0xae,
1498 0x56, 0x47,
1499 0x57, 0xe1,
1500 0x58, 0x3a,
1501 0x5a, 0x1e,
1502 0x5b, 0x34,
1503 0x60, 0x00,
1504 0x63, 0x00,
1505 0x64, 0x00,
1506 0x65, 0x00,
1507 0x66, 0x00,
1508 0x67, 0x00,
1509 0x68, 0x00,
1510 0x69, 0x00,
1511 0x6a, 0x02,
1512 0x6b, 0x00,
1513 0x70, 0xff,
1514 0x71, 0x00,
1515 0x72, 0x00,
1516 0x73, 0x00,
1517 0x74, 0x0c,
1518 0x80, 0x00,
1519 0x81, 0x00,
1520 0x82, 0x00,
1521 0x83, 0x00,
1522 0x84, 0x04,
1523 0x85, 0x80,
1524 0x86, 0x24,
1525 0x87, 0x78,
1526 0x88, 0x00,
1527 0x89, 0x00,
1528 0x90, 0x01,
1529 0x91, 0x01,
1530 0xa0, 0x00,
1531 0xa1, 0x00,
1532 0xa2, 0x00,
1533 0xb0, 0x91,
1534 0xb1, 0x0b,
1535 0xc0, 0x4b,
1536 0xc1, 0x00,
1537 0xc2, 0x00,
1538 0xd0, 0x00,
1539 0xd1, 0x00,
1540 0xd2, 0x00,
1541 0xd3, 0x00,
1542 0xd4, 0x00,
1543 0xd5, 0x00,
1544 0xde, 0x00,
1545 0xdf, 0x00,
1546 0x61, 0x38,
1547 0x62, 0x0a,
1548 0x53, 0x13,
1549 0x59, 0x08,
1550 0x55, 0x00,
1551 0x56, 0x40,
1552 0x57, 0x08,
1553 0x58, 0x3d,
1554 0x88, 0x10,
1555 0xa0, 0x00,
1556 0xa0, 0x00,
1557 0xa0, 0x00,
1558 0xa0, 0x04,
1559 0xff, 0xff,
1560};
1561
1562static struct stv0297_config dvbc_philips_tdm1316l_config = {
1563 .demod_address = 0x1c,
1564 .inittab = dvbc_philips_tdm1316l_inittab,
1565 .invert = 0,
1566};
1567
Linus Torvalds1da177e2005-04-16 15:20:36 -07001568static void frontend_init(struct ttusb* ttusb)
1569{
1570 switch(le16_to_cpu(ttusb->dev->descriptor.idProduct)) {
1571 case 0x1003: // Hauppauge/TT Nova-USB-S budget (stv0299/ALPS BSRU6|BSBE1(tsa5059))
1572 // try the stv0299 based first
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03001573 ttusb->fe = dvb_attach(stv0299_attach, &alps_stv0299_config, &ttusb->i2c_adap);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001574 if (ttusb->fe != NULL) {
Patrick Boettcherdea74862006-05-14 05:01:31 -03001575 ttusb->fe->ops.tuner_ops.set_params = philips_tsa5059_tuner_set_params;
Andrew de Quincey651b81b2006-04-18 17:47:11 -03001576
Linus Torvalds1da177e2005-04-16 15:20:36 -07001577 if(ttusb->revision == TTUSB_REV_2_2) { // ALPS BSBE1
1578 alps_stv0299_config.inittab = alps_bsbe1_inittab;
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03001579 dvb_attach(lnbp21_attach, ttusb->fe, &ttusb->i2c_adap, 0, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001580 } else { // ALPS BSRU6
Patrick Boettcherdea74862006-05-14 05:01:31 -03001581 ttusb->fe->ops.set_voltage = ttusb_set_voltage;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001582 }
1583 break;
1584 }
1585
1586 // Grundig 29504-491
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03001587 ttusb->fe = dvb_attach(tda8083_attach, &ttusb_novas_grundig_29504_491_config, &ttusb->i2c_adap);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001588 if (ttusb->fe != NULL) {
Patrick Boettcherdea74862006-05-14 05:01:31 -03001589 ttusb->fe->ops.tuner_ops.set_params = ttusb_novas_grundig_29504_491_tuner_set_params;
1590 ttusb->fe->ops.set_voltage = ttusb_set_voltage;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001591 break;
1592 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001593 break;
1594
Gavin Hamill53936392005-07-07 17:58:04 -07001595 case 0x1004: // Hauppauge/TT DVB-C budget (ves1820/ALPS TDBE2(sp5659))
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03001596 ttusb->fe = dvb_attach(ves1820_attach, &alps_tdbe2_config, &ttusb->i2c_adap, read_pwm(ttusb));
Andrew de Quincey651b81b2006-04-18 17:47:11 -03001597 if (ttusb->fe != NULL) {
Patrick Boettcherdea74862006-05-14 05:01:31 -03001598 ttusb->fe->ops.tuner_ops.set_params = alps_tdbe2_tuner_set_params;
Gavin Hamill53936392005-07-07 17:58:04 -07001599 break;
Andrew de Quincey651b81b2006-04-18 17:47:11 -03001600 }
Thomas Kaiserb8d4c232006-04-27 21:45:20 -03001601
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03001602 ttusb->fe = dvb_attach(stv0297_attach, &dvbc_philips_tdm1316l_config, &ttusb->i2c_adap);
Thomas Kaiserb8d4c232006-04-27 21:45:20 -03001603 if (ttusb->fe != NULL) {
Patrick Boettcherdea74862006-05-14 05:01:31 -03001604 ttusb->fe->ops.tuner_ops.set_params = dvbc_philips_tdm1316l_tuner_set_params;
Thomas Kaiserb8d4c232006-04-27 21:45:20 -03001605 break;
1606 }
Gavin Hamill53936392005-07-07 17:58:04 -07001607 break;
1608
Linus Torvalds1da177e2005-04-16 15:20:36 -07001609 case 0x1005: // Hauppauge/TT Nova-USB-t budget (tda10046/Philips td1316(tda6651tt) OR cx22700/ALPS TDMB7(??))
1610 // try the ALPS TDMB7 first
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03001611 ttusb->fe = dvb_attach(cx22700_attach, &alps_tdmb7_config, &ttusb->i2c_adap);
Andrew de Quincey651b81b2006-04-18 17:47:11 -03001612 if (ttusb->fe != NULL) {
Patrick Boettcherdea74862006-05-14 05:01:31 -03001613 ttusb->fe->ops.tuner_ops.set_params = alps_tdmb7_tuner_set_params;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001614 break;
Andrew de Quincey651b81b2006-04-18 17:47:11 -03001615 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001616
1617 // Philips td1316
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03001618 ttusb->fe = dvb_attach(tda10046_attach, &philips_tdm1316l_config, &ttusb->i2c_adap);
Andrew de Quincey651b81b2006-04-18 17:47:11 -03001619 if (ttusb->fe != NULL) {
Patrick Boettcherdea74862006-05-14 05:01:31 -03001620 ttusb->fe->ops.tuner_ops.init = philips_tdm1316l_tuner_init;
1621 ttusb->fe->ops.tuner_ops.set_params = philips_tdm1316l_tuner_set_params;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001622 break;
Andrew de Quincey651b81b2006-04-18 17:47:11 -03001623 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001624 break;
1625 }
1626
1627 if (ttusb->fe == NULL) {
Bjorn Helgaas29e66a62008-09-04 17:24:51 -03001628 printk("dvb-ttusb-budget: A frontend driver was not found for device [%04x:%04x]\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07001629 le16_to_cpu(ttusb->dev->descriptor.idVendor),
1630 le16_to_cpu(ttusb->dev->descriptor.idProduct));
1631 } else {
Johannes Stezenbachfdc53a62005-05-16 21:54:39 -07001632 if (dvb_register_frontend(&ttusb->adapter, ttusb->fe)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001633 printk("dvb-ttusb-budget: Frontend registration failed!\n");
Andrew de Quinceyf52a8382006-08-08 09:10:09 -03001634 dvb_frontend_detach(ttusb->fe);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001635 ttusb->fe = NULL;
1636 }
1637 }
1638}
1639
1640
1641
1642static struct i2c_algorithm ttusb_dec_algo = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001643 .master_xfer = master_xfer,
1644 .functionality = functionality,
1645};
1646
1647static int ttusb_probe(struct usb_interface *intf, const struct usb_device_id *id)
1648{
1649 struct usb_device *udev;
1650 struct ttusb *ttusb;
1651 int result;
1652
Harvey Harrisonfb9393b2008-04-08 23:20:00 -03001653 dprintk("%s: TTUSB DVB connected\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001654
1655 udev = interface_to_usbdev(intf);
1656
Mauro Carvalho Chehab9101e622005-12-12 00:37:24 -08001657 if (intf->altsetting->desc.bInterfaceNumber != 1) return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001658
Panagiotis Issaris74081872006-01-11 19:40:56 -02001659 if (!(ttusb = kzalloc(sizeof(struct ttusb), GFP_KERNEL)))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001660 return -ENOMEM;
1661
Linus Torvalds1da177e2005-04-16 15:20:36 -07001662 ttusb->dev = udev;
1663 ttusb->c = 0;
1664 ttusb->mux_state = 0;
Ingo Molnar3593cab2006-02-07 06:49:14 -02001665 mutex_init(&ttusb->semi2c);
1666
1667 mutex_lock(&ttusb->semi2c);
1668
1669 mutex_init(&ttusb->semusb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001670
1671 ttusb_setup_interfaces(ttusb);
1672
Douglas Schilling Landgrafb7ed7852008-11-11 23:37:39 -03001673 result = ttusb_alloc_iso_urbs(ttusb);
1674 if (result < 0) {
1675 dprintk("%s: ttusb_alloc_iso_urbs - failed\n", __func__);
1676 mutex_unlock(&ttusb->semi2c);
1677 kfree(ttusb);
1678 return result;
1679 }
1680
Linus Torvalds1da177e2005-04-16 15:20:36 -07001681 if (ttusb_init_controller(ttusb))
1682 printk("ttusb_init_controller: error\n");
1683
Ingo Molnar3593cab2006-02-07 06:49:14 -02001684 mutex_unlock(&ttusb->semi2c);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001685
Janne Grunau78e92002008-04-09 19:13:13 -03001686 result = dvb_register_adapter(&ttusb->adapter,
1687 "Technotrend/Hauppauge Nova-USB",
1688 THIS_MODULE, &udev->dev, adapter_nr);
1689 if (result < 0) {
Andrew de Quinceya064fad2006-04-06 17:05:46 -03001690 ttusb_free_iso_urbs(ttusb);
1691 kfree(ttusb);
1692 return result;
1693 }
Johannes Stezenbachfdc53a62005-05-16 21:54:39 -07001694 ttusb->adapter.priv = ttusb;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001695
1696 /* i2c */
1697 memset(&ttusb->i2c_adap, 0, sizeof(struct i2c_adapter));
1698 strcpy(ttusb->i2c_adap.name, "TTUSB DEC");
1699
1700 i2c_set_adapdata(&ttusb->i2c_adap, ttusb);
1701
Linus Torvalds1da177e2005-04-16 15:20:36 -07001702 ttusb->i2c_adap.algo = &ttusb_dec_algo;
1703 ttusb->i2c_adap.algo_data = NULL;
Jean Delvare12a917f2007-02-13 22:09:03 +01001704 ttusb->i2c_adap.dev.parent = &udev->dev;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001705
1706 result = i2c_add_adapter(&ttusb->i2c_adap);
1707 if (result) {
Johannes Stezenbachfdc53a62005-05-16 21:54:39 -07001708 dvb_unregister_adapter (&ttusb->adapter);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001709 return result;
1710 }
1711
1712 memset(&ttusb->dvb_demux, 0, sizeof(ttusb->dvb_demux));
1713
1714 ttusb->dvb_demux.dmx.capabilities =
1715 DMX_TS_FILTERING | DMX_SECTION_FILTERING;
1716 ttusb->dvb_demux.priv = NULL;
1717#ifdef TTUSB_HWSECTIONS
1718 ttusb->dvb_demux.filternum = TTUSB_MAXFILTER;
1719#else
1720 ttusb->dvb_demux.filternum = 32;
1721#endif
1722 ttusb->dvb_demux.feednum = TTUSB_MAXCHANNEL;
1723 ttusb->dvb_demux.start_feed = ttusb_start_feed;
1724 ttusb->dvb_demux.stop_feed = ttusb_stop_feed;
1725 ttusb->dvb_demux.write_to_decoder = NULL;
1726
1727 if ((result = dvb_dmx_init(&ttusb->dvb_demux)) < 0) {
1728 printk("ttusb_dvb: dvb_dmx_init failed (errno = %d)\n", result);
1729 i2c_del_adapter(&ttusb->i2c_adap);
Johannes Stezenbachfdc53a62005-05-16 21:54:39 -07001730 dvb_unregister_adapter (&ttusb->adapter);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001731 return -ENODEV;
1732 }
1733//FIXME dmxdev (nur WAS?)
1734 ttusb->dmxdev.filternum = ttusb->dvb_demux.filternum;
1735 ttusb->dmxdev.demux = &ttusb->dvb_demux.dmx;
1736 ttusb->dmxdev.capabilities = 0;
1737
Johannes Stezenbachfdc53a62005-05-16 21:54:39 -07001738 if ((result = dvb_dmxdev_init(&ttusb->dmxdev, &ttusb->adapter)) < 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001739 printk("ttusb_dvb: dvb_dmxdev_init failed (errno = %d)\n",
1740 result);
1741 dvb_dmx_release(&ttusb->dvb_demux);
1742 i2c_del_adapter(&ttusb->i2c_adap);
Johannes Stezenbachfdc53a62005-05-16 21:54:39 -07001743 dvb_unregister_adapter (&ttusb->adapter);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001744 return -ENODEV;
1745 }
1746
Johannes Stezenbachfdc53a62005-05-16 21:54:39 -07001747 if (dvb_net_init(&ttusb->adapter, &ttusb->dvbnet, &ttusb->dvb_demux.dmx)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001748 printk("ttusb_dvb: dvb_net_init failed!\n");
1749 dvb_dmxdev_release(&ttusb->dmxdev);
1750 dvb_dmx_release(&ttusb->dvb_demux);
1751 i2c_del_adapter(&ttusb->i2c_adap);
Johannes Stezenbachfdc53a62005-05-16 21:54:39 -07001752 dvb_unregister_adapter (&ttusb->adapter);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001753 return -ENODEV;
1754 }
1755
Linus Torvalds1da177e2005-04-16 15:20:36 -07001756 usb_set_intfdata(intf, (void *) ttusb);
1757
1758 frontend_init(ttusb);
1759
1760 return 0;
1761}
1762
1763static void ttusb_disconnect(struct usb_interface *intf)
1764{
1765 struct ttusb *ttusb = usb_get_intfdata(intf);
1766
1767 usb_set_intfdata(intf, NULL);
1768
1769 ttusb->disconnecting = 1;
1770
1771 ttusb_stop_iso_xfer(ttusb);
1772
1773 ttusb->dvb_demux.dmx.close(&ttusb->dvb_demux.dmx);
1774 dvb_net_release(&ttusb->dvbnet);
1775 dvb_dmxdev_release(&ttusb->dmxdev);
1776 dvb_dmx_release(&ttusb->dvb_demux);
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03001777 if (ttusb->fe != NULL) {
1778 dvb_unregister_frontend(ttusb->fe);
Andrew de Quinceyf52a8382006-08-08 09:10:09 -03001779 dvb_frontend_detach(ttusb->fe);
Andrew de Quincey2bfe0312006-08-08 09:10:08 -03001780 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001781 i2c_del_adapter(&ttusb->i2c_adap);
Johannes Stezenbachfdc53a62005-05-16 21:54:39 -07001782 dvb_unregister_adapter(&ttusb->adapter);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001783
1784 ttusb_free_iso_urbs(ttusb);
1785
1786 kfree(ttusb);
1787
Harvey Harrisonfb9393b2008-04-08 23:20:00 -03001788 dprintk("%s: TTUSB DVB disconnected\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001789}
1790
1791static struct usb_device_id ttusb_table[] = {
1792 {USB_DEVICE(0xb48, 0x1003)},
Gavin Hamill53936392005-07-07 17:58:04 -07001793 {USB_DEVICE(0xb48, 0x1004)},
Linus Torvalds1da177e2005-04-16 15:20:36 -07001794 {USB_DEVICE(0xb48, 0x1005)},
1795 {}
1796};
1797
1798MODULE_DEVICE_TABLE(usb, ttusb_table);
1799
1800static struct usb_driver ttusb_driver = {
Julian Scheel27b05fd2005-07-12 13:58:39 -07001801 .name = "ttusb",
Linus Torvalds1da177e2005-04-16 15:20:36 -07001802 .probe = ttusb_probe,
1803 .disconnect = ttusb_disconnect,
1804 .id_table = ttusb_table,
1805};
1806
1807static int __init ttusb_init(void)
1808{
1809 int err;
1810
1811 if ((err = usb_register(&ttusb_driver)) < 0) {
1812 printk("%s: usb_register failed! Error number %d",
1813 __FILE__, err);
1814 return err;
1815 }
1816
1817 return 0;
1818}
1819
1820static void __exit ttusb_exit(void)
1821{
1822 usb_deregister(&ttusb_driver);
1823}
1824
1825module_init(ttusb_init);
1826module_exit(ttusb_exit);
1827
1828MODULE_AUTHOR("Holger Waechtler <holger@convergence.de>");
1829MODULE_DESCRIPTION("TTUSB DVB Driver");
1830MODULE_LICENSE("GPL");
David Woodhouse0a2a7362008-05-29 19:50:06 +03001831MODULE_FIRMWARE("ttusb-budget/dspbootcode.bin");