xref: /openbmc/linux/drivers/media/usb/ttusb-budget/dvb-ttusb-budget.c (revision cbecf716ca618fd44feda6bd9a64a8179d031fc5)
12874c5fdSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later
2786baecfSMauro Carvalho Chehab /*
3786baecfSMauro Carvalho Chehab  * TTUSB DVB driver
4786baecfSMauro Carvalho Chehab  *
5786baecfSMauro Carvalho Chehab  * Copyright (c) 2002 Holger Waechtler <holger@convergence.de>
6786baecfSMauro Carvalho Chehab  * Copyright (c) 2003 Felix Domke <tmbinc@elitedvb.net>
7786baecfSMauro Carvalho Chehab  */
8*883c84acSMauro Carvalho Chehab 
9*883c84acSMauro Carvalho Chehab #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
10*883c84acSMauro Carvalho Chehab 
11786baecfSMauro Carvalho Chehab #include <linux/init.h>
12786baecfSMauro Carvalho Chehab #include <linux/slab.h>
13786baecfSMauro Carvalho Chehab #include <linux/wait.h>
14786baecfSMauro Carvalho Chehab #include <linux/fs.h>
15786baecfSMauro Carvalho Chehab #include <linux/module.h>
16786baecfSMauro Carvalho Chehab #include <linux/usb.h>
17786baecfSMauro Carvalho Chehab #include <linux/delay.h>
18786baecfSMauro Carvalho Chehab #include <linux/time.h>
19786baecfSMauro Carvalho Chehab #include <linux/errno.h>
20786baecfSMauro Carvalho Chehab #include <linux/jiffies.h>
21786baecfSMauro Carvalho Chehab #include <linux/mutex.h>
22786baecfSMauro Carvalho Chehab #include <linux/firmware.h>
23786baecfSMauro Carvalho Chehab 
24fada1935SMauro Carvalho Chehab #include <media/dvb_frontend.h>
25fada1935SMauro Carvalho Chehab #include <media/dmxdev.h>
26fada1935SMauro Carvalho Chehab #include <media/dvb_demux.h>
27fada1935SMauro Carvalho Chehab #include <media/dvb_net.h>
28786baecfSMauro Carvalho Chehab #include "ves1820.h"
29786baecfSMauro Carvalho Chehab #include "cx22700.h"
30786baecfSMauro Carvalho Chehab #include "tda1004x.h"
31786baecfSMauro Carvalho Chehab #include "stv0299.h"
32786baecfSMauro Carvalho Chehab #include "tda8083.h"
33786baecfSMauro Carvalho Chehab #include "stv0297.h"
34786baecfSMauro Carvalho Chehab #include "lnbp21.h"
35786baecfSMauro Carvalho Chehab 
36786baecfSMauro Carvalho Chehab #include <linux/dvb/frontend.h>
37786baecfSMauro Carvalho Chehab #include <linux/dvb/dmx.h>
38786baecfSMauro Carvalho Chehab #include <linux/pci.h>
39786baecfSMauro Carvalho Chehab 
40786baecfSMauro Carvalho Chehab /*
41786baecfSMauro Carvalho Chehab   TTUSB_HWSECTIONS:
42786baecfSMauro Carvalho Chehab     the DSP supports filtering in hardware, however, since the "muxstream"
43786baecfSMauro Carvalho Chehab     is a bit braindead (no matching channel masks or no matching filter mask),
44786baecfSMauro Carvalho Chehab     we won't support this - yet. it doesn't event support negative filters,
45786baecfSMauro Carvalho Chehab     so the best way is maybe to keep TTUSB_HWSECTIONS undef'd and just
46786baecfSMauro Carvalho Chehab     parse TS data. USB bandwidth will be a problem when having large
47786baecfSMauro Carvalho Chehab     datastreams, especially for dvb-net, but hey, that's not my problem.
48786baecfSMauro Carvalho Chehab 
49786baecfSMauro Carvalho Chehab   TTUSB_DISEQC, TTUSB_TONE:
50786baecfSMauro Carvalho Chehab     let the STC do the diseqc/tone stuff. this isn't supported at least with
51786baecfSMauro Carvalho Chehab     my TTUSB, so let it undef'd unless you want to implement another
52786baecfSMauro Carvalho Chehab     frontend. never tested.
53786baecfSMauro Carvalho Chehab 
54786baecfSMauro Carvalho Chehab   debug:
55786baecfSMauro Carvalho Chehab     define it to > 3 for really hardcore debugging. you probably don't want
56786baecfSMauro Carvalho Chehab     this unless the device doesn't load at all. > 2 for bandwidth statistics.
57786baecfSMauro Carvalho Chehab */
58786baecfSMauro Carvalho Chehab 
59786baecfSMauro Carvalho Chehab static int debug;
60786baecfSMauro Carvalho Chehab module_param(debug, int, 0644);
61786baecfSMauro Carvalho Chehab MODULE_PARM_DESC(debug, "Turn on/off debugging (default:off).");
62786baecfSMauro Carvalho Chehab 
63786baecfSMauro Carvalho Chehab DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
64786baecfSMauro Carvalho Chehab 
65*883c84acSMauro Carvalho Chehab #define dprintk(fmt, arg...) do {					\
66*883c84acSMauro Carvalho Chehab 	if (debug)							\
67*883c84acSMauro Carvalho Chehab 		printk(KERN_DEBUG pr_fmt("%s: " fmt),			\
68*883c84acSMauro Carvalho Chehab 		       __func__, ##arg);				\
69*883c84acSMauro Carvalho Chehab } while (0)
70*883c84acSMauro Carvalho Chehab 
71786baecfSMauro Carvalho Chehab 
72786baecfSMauro Carvalho Chehab #define ISO_BUF_COUNT      4
73786baecfSMauro Carvalho Chehab #define FRAMES_PER_ISO_BUF 4
74786baecfSMauro Carvalho Chehab #define ISO_FRAME_SIZE     912
75786baecfSMauro Carvalho Chehab #define TTUSB_MAXCHANNEL   32
76786baecfSMauro Carvalho Chehab #ifdef TTUSB_HWSECTIONS
77786baecfSMauro Carvalho Chehab #define TTUSB_MAXFILTER    16	/* ??? */
78786baecfSMauro Carvalho Chehab #endif
79786baecfSMauro Carvalho Chehab 
80786baecfSMauro Carvalho Chehab #define TTUSB_REV_2_2	0x22
81786baecfSMauro Carvalho Chehab #define TTUSB_BUDGET_NAME "ttusb_stc_fw"
82786baecfSMauro Carvalho Chehab 
8336e3cf0cSMauro Carvalho Chehab #define MAX_SEND	0x28
8436e3cf0cSMauro Carvalho Chehab #define MAX_RCV		0x20
8536e3cf0cSMauro Carvalho Chehab 
86cba862dcSMauro Carvalho Chehab /*
87786baecfSMauro Carvalho Chehab  *  since we're casting (struct ttusb*) <-> (struct dvb_demux*) around
88786baecfSMauro Carvalho Chehab  *  the dvb_demux field must be the first in struct!!
89786baecfSMauro Carvalho Chehab  */
90786baecfSMauro Carvalho Chehab struct ttusb {
91786baecfSMauro Carvalho Chehab 	struct dvb_demux dvb_demux;
92786baecfSMauro Carvalho Chehab 	struct dmxdev dmxdev;
93786baecfSMauro Carvalho Chehab 	struct dvb_net dvbnet;
94786baecfSMauro Carvalho Chehab 
95786baecfSMauro Carvalho Chehab 	/* and one for USB access. */
96786baecfSMauro Carvalho Chehab 	struct mutex semi2c;
97786baecfSMauro Carvalho Chehab 	struct mutex semusb;
98786baecfSMauro Carvalho Chehab 
99786baecfSMauro Carvalho Chehab 	struct dvb_adapter adapter;
100786baecfSMauro Carvalho Chehab 	struct usb_device *dev;
101786baecfSMauro Carvalho Chehab 
102786baecfSMauro Carvalho Chehab 	struct i2c_adapter i2c_adap;
103786baecfSMauro Carvalho Chehab 
104786baecfSMauro Carvalho Chehab 	int disconnecting;
105786baecfSMauro Carvalho Chehab 	int iso_streaming;
106786baecfSMauro Carvalho Chehab 
107786baecfSMauro Carvalho Chehab 	unsigned int bulk_out_pipe;
108786baecfSMauro Carvalho Chehab 	unsigned int bulk_in_pipe;
109786baecfSMauro Carvalho Chehab 	unsigned int isoc_in_pipe;
110786baecfSMauro Carvalho Chehab 
111786baecfSMauro Carvalho Chehab 	void *iso_buffer;
112786baecfSMauro Carvalho Chehab 
113786baecfSMauro Carvalho Chehab 	struct urb *iso_urb[ISO_BUF_COUNT];
114786baecfSMauro Carvalho Chehab 
115786baecfSMauro Carvalho Chehab 	int running_feed_count;
116786baecfSMauro Carvalho Chehab 	int last_channel;
117786baecfSMauro Carvalho Chehab 	int last_filter;
118786baecfSMauro Carvalho Chehab 
119786baecfSMauro Carvalho Chehab 	u8 c;			/* transaction counter, wraps around...  */
1200df289a2SMauro Carvalho Chehab 	enum fe_sec_tone_mode tone;
1210df289a2SMauro Carvalho Chehab 	enum fe_sec_voltage voltage;
122786baecfSMauro Carvalho Chehab 
123786baecfSMauro Carvalho Chehab 	int mux_state;		// 0..2 - MuxSyncWord, 3 - nMuxPacks,    4 - muxpack
124786baecfSMauro Carvalho Chehab 	u8 mux_npacks;
125786baecfSMauro Carvalho Chehab 	u8 muxpack[256 + 8];
126786baecfSMauro Carvalho Chehab 	int muxpack_ptr, muxpack_len;
127786baecfSMauro Carvalho Chehab 
128786baecfSMauro Carvalho Chehab 	int insync;
129786baecfSMauro Carvalho Chehab 
130786baecfSMauro Carvalho Chehab 	int cc;			/* MuxCounter - will increment on EVERY MUX PACKET */
131786baecfSMauro Carvalho Chehab 	/* (including stuffing. yes. really.) */
132786baecfSMauro Carvalho Chehab 
13336e3cf0cSMauro Carvalho Chehab 	u8 send_buf[MAX_SEND];
13436e3cf0cSMauro Carvalho Chehab 	u8 last_result[MAX_RCV];
135786baecfSMauro Carvalho Chehab 
136786baecfSMauro Carvalho Chehab 	int revision;
137786baecfSMauro Carvalho Chehab 
138786baecfSMauro Carvalho Chehab 	struct dvb_frontend* fe;
139786baecfSMauro Carvalho Chehab };
140786baecfSMauro Carvalho Chehab 
ttusb_cmd(struct ttusb * ttusb,u8 * data,int len,int len_result)14136e3cf0cSMauro Carvalho Chehab static int ttusb_cmd(struct ttusb *ttusb, u8 *data, int len, int len_result)
142786baecfSMauro Carvalho Chehab {
143786baecfSMauro Carvalho Chehab 	int actual_len;
144786baecfSMauro Carvalho Chehab 	int err;
145786baecfSMauro Carvalho Chehab 
146786baecfSMauro Carvalho Chehab 	if (mutex_lock_interruptible(&ttusb->semusb) < 0)
147786baecfSMauro Carvalho Chehab 		return -EAGAIN;
148786baecfSMauro Carvalho Chehab 
14936e3cf0cSMauro Carvalho Chehab 	if (debug >= 3)
150*883c84acSMauro Carvalho Chehab 		dprintk("> %*ph\n", len, data);
15136e3cf0cSMauro Carvalho Chehab 
15236e3cf0cSMauro Carvalho Chehab 	memcpy(data, ttusb->send_buf, len);
15336e3cf0cSMauro Carvalho Chehab 
154786baecfSMauro Carvalho Chehab 	err = usb_bulk_msg(ttusb->dev, ttusb->bulk_out_pipe,
15536e3cf0cSMauro Carvalho Chehab 			   ttusb->send_buf, len, &actual_len, 1000);
156786baecfSMauro Carvalho Chehab 	if (err != 0) {
157*883c84acSMauro Carvalho Chehab 		dprintk("usb_bulk_msg(send) failed, err == %i!\n", err);
15836e3cf0cSMauro Carvalho Chehab 		goto err;
159786baecfSMauro Carvalho Chehab 	}
160786baecfSMauro Carvalho Chehab 	if (actual_len != len) {
16136e3cf0cSMauro Carvalho Chehab 		err = -EIO;
162*883c84acSMauro Carvalho Chehab 		dprintk("only wrote %d of %d bytes\n",
163786baecfSMauro Carvalho Chehab 			actual_len, len);
16436e3cf0cSMauro Carvalho Chehab 		goto err;
165786baecfSMauro Carvalho Chehab 	}
166786baecfSMauro Carvalho Chehab 
167786baecfSMauro Carvalho Chehab 	err = usb_bulk_msg(ttusb->dev, ttusb->bulk_in_pipe,
16836e3cf0cSMauro Carvalho Chehab 			   ttusb->last_result, MAX_RCV, &actual_len, 1000);
169786baecfSMauro Carvalho Chehab 
170786baecfSMauro Carvalho Chehab 	if (err != 0) {
171*883c84acSMauro Carvalho Chehab 		pr_err("cmd xter failed, receive error %d\n", err);
17236e3cf0cSMauro Carvalho Chehab 		goto err;
173786baecfSMauro Carvalho Chehab 	}
174786baecfSMauro Carvalho Chehab 
175786baecfSMauro Carvalho Chehab 	if (debug >= 3) {
176786baecfSMauro Carvalho Chehab 		actual_len = ttusb->last_result[3] + 4;
177*883c84acSMauro Carvalho Chehab 		dprintk("< %*ph\n", actual_len, ttusb->last_result);
178786baecfSMauro Carvalho Chehab 	}
179786baecfSMauro Carvalho Chehab 
18036e3cf0cSMauro Carvalho Chehab 	if (len_result)
18136e3cf0cSMauro Carvalho Chehab 		memcpy(ttusb->send_buf, ttusb->last_result, len_result);
182786baecfSMauro Carvalho Chehab 
18336e3cf0cSMauro Carvalho Chehab err:
184786baecfSMauro Carvalho Chehab 	mutex_unlock(&ttusb->semusb);
18536e3cf0cSMauro Carvalho Chehab 	return err;
186786baecfSMauro Carvalho Chehab }
187786baecfSMauro Carvalho Chehab 
ttusb_i2c_msg(struct ttusb * ttusb,u8 addr,u8 * snd_buf,u8 snd_len,u8 * rcv_buf,u8 rcv_len)188786baecfSMauro Carvalho Chehab static int ttusb_i2c_msg(struct ttusb *ttusb,
189786baecfSMauro Carvalho Chehab 		  u8 addr, u8 * snd_buf, u8 snd_len, u8 * rcv_buf,
190786baecfSMauro Carvalho Chehab 		  u8 rcv_len)
191786baecfSMauro Carvalho Chehab {
19236e3cf0cSMauro Carvalho Chehab 	u8 b[MAX_SEND];
193786baecfSMauro Carvalho Chehab 	u8 id = ++ttusb->c;
194786baecfSMauro Carvalho Chehab 	int i, err;
195786baecfSMauro Carvalho Chehab 
19636e3cf0cSMauro Carvalho Chehab 	if (snd_len > MAX_SEND - 7 || rcv_len > MAX_RCV - 7)
197786baecfSMauro Carvalho Chehab 		return -EINVAL;
198786baecfSMauro Carvalho Chehab 
199786baecfSMauro Carvalho Chehab 	b[0] = 0xaa;
200786baecfSMauro Carvalho Chehab 	b[1] = id;
201786baecfSMauro Carvalho Chehab 	b[2] = 0x31;
202786baecfSMauro Carvalho Chehab 	b[3] = snd_len + 3;
203786baecfSMauro Carvalho Chehab 	b[4] = addr << 1;
204786baecfSMauro Carvalho Chehab 	b[5] = snd_len;
205786baecfSMauro Carvalho Chehab 	b[6] = rcv_len;
206786baecfSMauro Carvalho Chehab 
207786baecfSMauro Carvalho Chehab 	for (i = 0; i < snd_len; i++)
208786baecfSMauro Carvalho Chehab 		b[7 + i] = snd_buf[i];
209786baecfSMauro Carvalho Chehab 
21036e3cf0cSMauro Carvalho Chehab 	err = ttusb_cmd(ttusb, b, snd_len + 7, MAX_RCV);
211786baecfSMauro Carvalho Chehab 
212786baecfSMauro Carvalho Chehab 	if (err)
213786baecfSMauro Carvalho Chehab 		return -EREMOTEIO;
214786baecfSMauro Carvalho Chehab 
215786baecfSMauro Carvalho Chehab 	/* check if the i2c transaction was successful */
216786baecfSMauro Carvalho Chehab 	if ((snd_len != b[5]) || (rcv_len != b[6])) return -EREMOTEIO;
217786baecfSMauro Carvalho Chehab 
218786baecfSMauro Carvalho Chehab 	if (rcv_len > 0) {
219786baecfSMauro Carvalho Chehab 
220786baecfSMauro Carvalho Chehab 		if (err || b[0] != 0x55 || b[1] != id) {
221*883c84acSMauro Carvalho Chehab 			dprintk("usb_bulk_msg(recv) failed, err == %i, id == %02x, b == ",
222*883c84acSMauro Carvalho Chehab 				err, id);
223786baecfSMauro Carvalho Chehab 			return -EREMOTEIO;
224786baecfSMauro Carvalho Chehab 		}
225786baecfSMauro Carvalho Chehab 
226786baecfSMauro Carvalho Chehab 		for (i = 0; i < rcv_len; i++)
227786baecfSMauro Carvalho Chehab 			rcv_buf[i] = b[7 + i];
228786baecfSMauro Carvalho Chehab 	}
229786baecfSMauro Carvalho Chehab 
230786baecfSMauro Carvalho Chehab 	return rcv_len;
231786baecfSMauro Carvalho Chehab }
232786baecfSMauro Carvalho Chehab 
master_xfer(struct i2c_adapter * adapter,struct i2c_msg * msg,int num)233786baecfSMauro Carvalho Chehab static int master_xfer(struct i2c_adapter* adapter, struct i2c_msg *msg, int num)
234786baecfSMauro Carvalho Chehab {
235786baecfSMauro Carvalho Chehab 	struct ttusb *ttusb = i2c_get_adapdata(adapter);
236786baecfSMauro Carvalho Chehab 	int i = 0;
237786baecfSMauro Carvalho Chehab 	int inc;
238786baecfSMauro Carvalho Chehab 
239786baecfSMauro Carvalho Chehab 	if (mutex_lock_interruptible(&ttusb->semi2c) < 0)
240786baecfSMauro Carvalho Chehab 		return -EAGAIN;
241786baecfSMauro Carvalho Chehab 
242786baecfSMauro Carvalho Chehab 	while (i < num) {
243786baecfSMauro Carvalho Chehab 		u8 addr, snd_len, rcv_len, *snd_buf, *rcv_buf;
244786baecfSMauro Carvalho Chehab 		int err;
245786baecfSMauro Carvalho Chehab 
246786baecfSMauro Carvalho Chehab 		if (num > i + 1 && (msg[i + 1].flags & I2C_M_RD)) {
247786baecfSMauro Carvalho Chehab 			addr = msg[i].addr;
248786baecfSMauro Carvalho Chehab 			snd_buf = msg[i].buf;
249786baecfSMauro Carvalho Chehab 			snd_len = msg[i].len;
250786baecfSMauro Carvalho Chehab 			rcv_buf = msg[i + 1].buf;
251786baecfSMauro Carvalho Chehab 			rcv_len = msg[i + 1].len;
252786baecfSMauro Carvalho Chehab 			inc = 2;
253786baecfSMauro Carvalho Chehab 		} else {
254786baecfSMauro Carvalho Chehab 			addr = msg[i].addr;
255786baecfSMauro Carvalho Chehab 			snd_buf = msg[i].buf;
256786baecfSMauro Carvalho Chehab 			snd_len = msg[i].len;
257786baecfSMauro Carvalho Chehab 			rcv_buf = NULL;
258786baecfSMauro Carvalho Chehab 			rcv_len = 0;
259786baecfSMauro Carvalho Chehab 			inc = 1;
260786baecfSMauro Carvalho Chehab 		}
261786baecfSMauro Carvalho Chehab 
262786baecfSMauro Carvalho Chehab 		err = ttusb_i2c_msg(ttusb, addr,
263786baecfSMauro Carvalho Chehab 				    snd_buf, snd_len, rcv_buf, rcv_len);
264786baecfSMauro Carvalho Chehab 
265786baecfSMauro Carvalho Chehab 		if (err < rcv_len) {
266*883c84acSMauro Carvalho Chehab 			dprintk("i == %i\n", i);
267786baecfSMauro Carvalho Chehab 			break;
268786baecfSMauro Carvalho Chehab 		}
269786baecfSMauro Carvalho Chehab 
270786baecfSMauro Carvalho Chehab 		i += inc;
271786baecfSMauro Carvalho Chehab 	}
272786baecfSMauro Carvalho Chehab 
273786baecfSMauro Carvalho Chehab 	mutex_unlock(&ttusb->semi2c);
274786baecfSMauro Carvalho Chehab 	return i;
275786baecfSMauro Carvalho Chehab }
276786baecfSMauro Carvalho Chehab 
ttusb_boot_dsp(struct ttusb * ttusb)277786baecfSMauro Carvalho Chehab static int ttusb_boot_dsp(struct ttusb *ttusb)
278786baecfSMauro Carvalho Chehab {
279786baecfSMauro Carvalho Chehab 	const struct firmware *fw;
280786baecfSMauro Carvalho Chehab 	int i, err;
281786baecfSMauro Carvalho Chehab 	u8 b[40];
282786baecfSMauro Carvalho Chehab 
283786baecfSMauro Carvalho Chehab 	err = request_firmware(&fw, "ttusb-budget/dspbootcode.bin",
284786baecfSMauro Carvalho Chehab 			       &ttusb->dev->dev);
285786baecfSMauro Carvalho Chehab 	if (err) {
286*883c84acSMauro Carvalho Chehab 		pr_err("failed to request firmware\n");
287786baecfSMauro Carvalho Chehab 		return err;
288786baecfSMauro Carvalho Chehab 	}
289786baecfSMauro Carvalho Chehab 
290786baecfSMauro Carvalho Chehab 	/* BootBlock */
291786baecfSMauro Carvalho Chehab 	b[0] = 0xaa;
292786baecfSMauro Carvalho Chehab 	b[2] = 0x13;
293786baecfSMauro Carvalho Chehab 	b[3] = 28;
294786baecfSMauro Carvalho Chehab 
295786baecfSMauro Carvalho Chehab 	/* upload dsp code in 32 byte steps (36 didn't work for me ...) */
2963e4d8f48SMauro Carvalho Chehab 	/* 32 is max packet size, no messages should be split. */
297786baecfSMauro Carvalho Chehab 	for (i = 0; i < fw->size; i += 28) {
298786baecfSMauro Carvalho Chehab 		memcpy(&b[4], &fw->data[i], 28);
299786baecfSMauro Carvalho Chehab 
300786baecfSMauro Carvalho Chehab 		b[1] = ++ttusb->c;
301786baecfSMauro Carvalho Chehab 
302786baecfSMauro Carvalho Chehab 		err = ttusb_cmd(ttusb, b, 32, 0);
303786baecfSMauro Carvalho Chehab 		if (err)
304786baecfSMauro Carvalho Chehab 			goto done;
305786baecfSMauro Carvalho Chehab 	}
306786baecfSMauro Carvalho Chehab 
307786baecfSMauro Carvalho Chehab 	/* last block ... */
308786baecfSMauro Carvalho Chehab 	b[1] = ++ttusb->c;
309786baecfSMauro Carvalho Chehab 	b[2] = 0x13;
310786baecfSMauro Carvalho Chehab 	b[3] = 0;
311786baecfSMauro Carvalho Chehab 
312786baecfSMauro Carvalho Chehab 	err = ttusb_cmd(ttusb, b, 4, 0);
313786baecfSMauro Carvalho Chehab 	if (err)
314786baecfSMauro Carvalho Chehab 		goto done;
315786baecfSMauro Carvalho Chehab 
316786baecfSMauro Carvalho Chehab 	/* BootEnd */
317786baecfSMauro Carvalho Chehab 	b[1] = ++ttusb->c;
318786baecfSMauro Carvalho Chehab 	b[2] = 0x14;
319786baecfSMauro Carvalho Chehab 	b[3] = 0;
320786baecfSMauro Carvalho Chehab 
321786baecfSMauro Carvalho Chehab 	err = ttusb_cmd(ttusb, b, 4, 0);
322786baecfSMauro Carvalho Chehab 
323786baecfSMauro Carvalho Chehab       done:
324786baecfSMauro Carvalho Chehab 	release_firmware(fw);
325786baecfSMauro Carvalho Chehab 	if (err) {
326*883c84acSMauro Carvalho Chehab 		dprintk("usb_bulk_msg() failed, return value %i!\n", err);
327786baecfSMauro Carvalho Chehab 	}
328786baecfSMauro Carvalho Chehab 
329786baecfSMauro Carvalho Chehab 	return err;
330786baecfSMauro Carvalho Chehab }
331786baecfSMauro Carvalho Chehab 
ttusb_set_channel(struct ttusb * ttusb,int chan_id,int filter_type,int pid)332786baecfSMauro Carvalho Chehab static int ttusb_set_channel(struct ttusb *ttusb, int chan_id, int filter_type,
333786baecfSMauro Carvalho Chehab 		      int pid)
334786baecfSMauro Carvalho Chehab {
335786baecfSMauro Carvalho Chehab 	int err;
336786baecfSMauro Carvalho Chehab 	/* SetChannel */
337786baecfSMauro Carvalho Chehab 	u8 b[] = { 0xaa, ++ttusb->c, 0x22, 4, chan_id, filter_type,
338786baecfSMauro Carvalho Chehab 		(pid >> 8) & 0xff, pid & 0xff
339786baecfSMauro Carvalho Chehab 	};
340786baecfSMauro Carvalho Chehab 
341786baecfSMauro Carvalho Chehab 	err = ttusb_cmd(ttusb, b, sizeof(b), 0);
342786baecfSMauro Carvalho Chehab 	return err;
343786baecfSMauro Carvalho Chehab }
344786baecfSMauro Carvalho Chehab 
ttusb_del_channel(struct ttusb * ttusb,int channel_id)345786baecfSMauro Carvalho Chehab static int ttusb_del_channel(struct ttusb *ttusb, int channel_id)
346786baecfSMauro Carvalho Chehab {
347786baecfSMauro Carvalho Chehab 	int err;
348786baecfSMauro Carvalho Chehab 	/* DelChannel */
349786baecfSMauro Carvalho Chehab 	u8 b[] = { 0xaa, ++ttusb->c, 0x23, 1, channel_id };
350786baecfSMauro Carvalho Chehab 
351786baecfSMauro Carvalho Chehab 	err = ttusb_cmd(ttusb, b, sizeof(b), 0);
352786baecfSMauro Carvalho Chehab 	return err;
353786baecfSMauro Carvalho Chehab }
354786baecfSMauro Carvalho Chehab 
355786baecfSMauro Carvalho Chehab #ifdef TTUSB_HWSECTIONS
ttusb_set_filter(struct ttusb * ttusb,int filter_id,int associated_chan,u8 filter[8],u8 mask[8])356786baecfSMauro Carvalho Chehab static int ttusb_set_filter(struct ttusb *ttusb, int filter_id,
357786baecfSMauro Carvalho Chehab 		     int associated_chan, u8 filter[8], u8 mask[8])
358786baecfSMauro Carvalho Chehab {
359786baecfSMauro Carvalho Chehab 	int err;
360786baecfSMauro Carvalho Chehab 	/* SetFilter */
361786baecfSMauro Carvalho Chehab 	u8 b[] = { 0xaa, 0, 0x24, 0x1a, filter_id, associated_chan,
362786baecfSMauro Carvalho Chehab 		filter[0], filter[1], filter[2], filter[3],
363786baecfSMauro Carvalho Chehab 		filter[4], filter[5], filter[6], filter[7],
364786baecfSMauro Carvalho Chehab 		filter[8], filter[9], filter[10], filter[11],
365786baecfSMauro Carvalho Chehab 		mask[0], mask[1], mask[2], mask[3],
366786baecfSMauro Carvalho Chehab 		mask[4], mask[5], mask[6], mask[7],
367786baecfSMauro Carvalho Chehab 		mask[8], mask[9], mask[10], mask[11]
368786baecfSMauro Carvalho Chehab 	};
369786baecfSMauro Carvalho Chehab 
370786baecfSMauro Carvalho Chehab 	err = ttusb_cmd(ttusb, b, sizeof(b), 0);
371786baecfSMauro Carvalho Chehab 	return err;
372786baecfSMauro Carvalho Chehab }
373786baecfSMauro Carvalho Chehab 
ttusb_del_filter(struct ttusb * ttusb,int filter_id)374786baecfSMauro Carvalho Chehab static int ttusb_del_filter(struct ttusb *ttusb, int filter_id)
375786baecfSMauro Carvalho Chehab {
376786baecfSMauro Carvalho Chehab 	int err;
377786baecfSMauro Carvalho Chehab 	/* DelFilter */
378786baecfSMauro Carvalho Chehab 	u8 b[] = { 0xaa, ++ttusb->c, 0x25, 1, filter_id };
379786baecfSMauro Carvalho Chehab 
380786baecfSMauro Carvalho Chehab 	err = ttusb_cmd(ttusb, b, sizeof(b), 0);
381786baecfSMauro Carvalho Chehab 	return err;
382786baecfSMauro Carvalho Chehab }
383786baecfSMauro Carvalho Chehab #endif
384786baecfSMauro Carvalho Chehab 
ttusb_init_controller(struct ttusb * ttusb)385786baecfSMauro Carvalho Chehab static int ttusb_init_controller(struct ttusb *ttusb)
386786baecfSMauro Carvalho Chehab {
387786baecfSMauro Carvalho Chehab 	u8 b0[] = { 0xaa, ++ttusb->c, 0x15, 1, 0 };
388786baecfSMauro Carvalho Chehab 	u8 b1[] = { 0xaa, ++ttusb->c, 0x15, 1, 1 };
389786baecfSMauro Carvalho Chehab 	u8 b2[] = { 0xaa, ++ttusb->c, 0x32, 1, 0 };
390786baecfSMauro Carvalho Chehab 	/* i2c write read: 5 bytes, addr 0x10, 0x02 bytes write, 1 bytes read. */
391786baecfSMauro Carvalho Chehab 	u8 b3[] =
392786baecfSMauro Carvalho Chehab 	    { 0xaa, ++ttusb->c, 0x31, 5, 0x10, 0x02, 0x01, 0x00, 0x1e };
393786baecfSMauro Carvalho Chehab 
394786baecfSMauro Carvalho Chehab 	u8 get_version[] = { 0xaa, ++ttusb->c, 0x17, 5, 0, 0, 0, 0, 0 };
395786baecfSMauro Carvalho Chehab 	u8 get_dsp_version[0x20] =
396786baecfSMauro Carvalho Chehab 	    { 0xaa, ++ttusb->c, 0x26, 28, 0, 0, 0, 0, 0 };
397786baecfSMauro Carvalho Chehab 	int err;
398786baecfSMauro Carvalho Chehab 
399786baecfSMauro Carvalho Chehab 	/* reset board */
400786baecfSMauro Carvalho Chehab 	if ((err = ttusb_cmd(ttusb, b0, sizeof(b0), 0)))
401786baecfSMauro Carvalho Chehab 		return err;
402786baecfSMauro Carvalho Chehab 
403786baecfSMauro Carvalho Chehab 	/* reset board (again?) */
404786baecfSMauro Carvalho Chehab 	if ((err = ttusb_cmd(ttusb, b1, sizeof(b1), 0)))
405786baecfSMauro Carvalho Chehab 		return err;
406786baecfSMauro Carvalho Chehab 
407786baecfSMauro Carvalho Chehab 	ttusb_boot_dsp(ttusb);
408786baecfSMauro Carvalho Chehab 
409786baecfSMauro Carvalho Chehab 	/* set i2c bit rate */
410786baecfSMauro Carvalho Chehab 	if ((err = ttusb_cmd(ttusb, b2, sizeof(b2), 0)))
411786baecfSMauro Carvalho Chehab 		return err;
412786baecfSMauro Carvalho Chehab 
41336e3cf0cSMauro Carvalho Chehab 	if ((err = ttusb_cmd(ttusb, b3, sizeof(b3), 0)))
414786baecfSMauro Carvalho Chehab 		return err;
415786baecfSMauro Carvalho Chehab 
41636e3cf0cSMauro Carvalho Chehab 	if ((err = ttusb_cmd(ttusb, get_version,
41736e3cf0cSMauro Carvalho Chehab 			     sizeof(get_version), sizeof(get_version))))
418786baecfSMauro Carvalho Chehab 		return err;
419786baecfSMauro Carvalho Chehab 
420*883c84acSMauro Carvalho Chehab 	dprintk("stc-version: %c%c%c%c%c\n", get_version[4], get_version[5],
421*883c84acSMauro Carvalho Chehab 		get_version[6], get_version[7], get_version[8]);
422786baecfSMauro Carvalho Chehab 
423786baecfSMauro Carvalho Chehab 	if (memcmp(get_version + 4, "V 0.0", 5) &&
424786baecfSMauro Carvalho Chehab 	    memcmp(get_version + 4, "V 1.1", 5) &&
425786baecfSMauro Carvalho Chehab 	    memcmp(get_version + 4, "V 2.1", 5) &&
426786baecfSMauro Carvalho Chehab 	    memcmp(get_version + 4, "V 2.2", 5)) {
427*883c84acSMauro Carvalho Chehab 		pr_err("unknown STC version %c%c%c%c%c, please report!\n",
428*883c84acSMauro Carvalho Chehab 		       get_version[4], get_version[5],
429786baecfSMauro Carvalho Chehab 		       get_version[6], get_version[7], get_version[8]);
430786baecfSMauro Carvalho Chehab 	}
431786baecfSMauro Carvalho Chehab 
432786baecfSMauro Carvalho Chehab 	ttusb->revision = ((get_version[6] - '0') << 4) |
433786baecfSMauro Carvalho Chehab 			   (get_version[8] - '0');
434786baecfSMauro Carvalho Chehab 
435786baecfSMauro Carvalho Chehab 	err =
43636e3cf0cSMauro Carvalho Chehab 	    ttusb_cmd(ttusb, get_dsp_version,
43736e3cf0cSMauro Carvalho Chehab 		      sizeof(get_dsp_version), sizeof(get_dsp_version));
438786baecfSMauro Carvalho Chehab 	if (err)
439786baecfSMauro Carvalho Chehab 		return err;
440786baecfSMauro Carvalho Chehab 
441*883c84acSMauro Carvalho Chehab 	pr_info("dsp-version: %c%c%c\n",
442786baecfSMauro Carvalho Chehab 	       get_dsp_version[4], get_dsp_version[5], get_dsp_version[6]);
443786baecfSMauro Carvalho Chehab 	return 0;
444786baecfSMauro Carvalho Chehab }
445786baecfSMauro Carvalho Chehab 
446786baecfSMauro Carvalho Chehab #ifdef TTUSB_DISEQC
ttusb_send_diseqc(struct dvb_frontend * fe,const struct dvb_diseqc_master_cmd * cmd)447786baecfSMauro Carvalho Chehab static int ttusb_send_diseqc(struct dvb_frontend* fe,
448786baecfSMauro Carvalho Chehab 			     const struct dvb_diseqc_master_cmd *cmd)
449786baecfSMauro Carvalho Chehab {
450786baecfSMauro Carvalho Chehab 	struct ttusb* ttusb = (struct ttusb*) fe->dvb->priv;
451786baecfSMauro Carvalho Chehab 	u8 b[12] = { 0xaa, ++ttusb->c, 0x18 };
452786baecfSMauro Carvalho Chehab 
453786baecfSMauro Carvalho Chehab 	int err;
454786baecfSMauro Carvalho Chehab 
455786baecfSMauro Carvalho Chehab 	b[3] = 4 + 2 + cmd->msg_len;
456786baecfSMauro Carvalho Chehab 	b[4] = 0xFF;		/* send diseqc master, not burst */
457786baecfSMauro Carvalho Chehab 	b[5] = cmd->msg_len;
458786baecfSMauro Carvalho Chehab 
459786baecfSMauro Carvalho Chehab 	memcpy(b + 5, cmd->msg, cmd->msg_len);
460786baecfSMauro Carvalho Chehab 
461786baecfSMauro Carvalho Chehab 	/* Diseqc */
462786baecfSMauro Carvalho Chehab 	if ((err = ttusb_cmd(ttusb, b, 4 + b[3], 0))) {
463*883c84acSMauro Carvalho Chehab 		dprintk("usb_bulk_msg() failed, return value %i!\n", err);
464786baecfSMauro Carvalho Chehab 	}
465786baecfSMauro Carvalho Chehab 
466786baecfSMauro Carvalho Chehab 	return err;
467786baecfSMauro Carvalho Chehab }
468786baecfSMauro Carvalho Chehab #endif
469786baecfSMauro Carvalho Chehab 
ttusb_update_lnb(struct ttusb * ttusb)470786baecfSMauro Carvalho Chehab static int ttusb_update_lnb(struct ttusb *ttusb)
471786baecfSMauro Carvalho Chehab {
472786baecfSMauro Carvalho Chehab 	u8 b[] = { 0xaa, ++ttusb->c, 0x16, 5, /*power: */ 1,
473786baecfSMauro Carvalho Chehab 		ttusb->voltage == SEC_VOLTAGE_18 ? 0 : 1,
474786baecfSMauro Carvalho Chehab 		ttusb->tone == SEC_TONE_ON ? 1 : 0, 1, 1
475786baecfSMauro Carvalho Chehab 	};
476786baecfSMauro Carvalho Chehab 	int err;
477786baecfSMauro Carvalho Chehab 
478786baecfSMauro Carvalho Chehab 	/* SetLNB */
479786baecfSMauro Carvalho Chehab 	if ((err = ttusb_cmd(ttusb, b, sizeof(b), 0))) {
480*883c84acSMauro Carvalho Chehab 		dprintk("usb_bulk_msg() failed, return value %i!\n", err);
481786baecfSMauro Carvalho Chehab 	}
482786baecfSMauro Carvalho Chehab 
483786baecfSMauro Carvalho Chehab 	return err;
484786baecfSMauro Carvalho Chehab }
485786baecfSMauro Carvalho Chehab 
ttusb_set_voltage(struct dvb_frontend * fe,enum fe_sec_voltage voltage)4860df289a2SMauro Carvalho Chehab static int ttusb_set_voltage(struct dvb_frontend *fe,
4870df289a2SMauro Carvalho Chehab 			     enum fe_sec_voltage voltage)
488786baecfSMauro Carvalho Chehab {
489786baecfSMauro Carvalho Chehab 	struct ttusb* ttusb = (struct ttusb*) fe->dvb->priv;
490786baecfSMauro Carvalho Chehab 
491786baecfSMauro Carvalho Chehab 	ttusb->voltage = voltage;
492786baecfSMauro Carvalho Chehab 	return ttusb_update_lnb(ttusb);
493786baecfSMauro Carvalho Chehab }
494786baecfSMauro Carvalho Chehab 
495786baecfSMauro Carvalho Chehab #ifdef TTUSB_TONE
ttusb_set_tone(struct dvb_frontend * fe,enum fe_sec_tone_mode tone)4960df289a2SMauro Carvalho Chehab static int ttusb_set_tone(struct dvb_frontend *fe, enum fe_sec_tone_mode tone)
497786baecfSMauro Carvalho Chehab {
498786baecfSMauro Carvalho Chehab 	struct ttusb* ttusb = (struct ttusb*) fe->dvb->priv;
499786baecfSMauro Carvalho Chehab 
500786baecfSMauro Carvalho Chehab 	ttusb->tone = tone;
501786baecfSMauro Carvalho Chehab 	return ttusb_update_lnb(ttusb);
502786baecfSMauro Carvalho Chehab }
503786baecfSMauro Carvalho Chehab #endif
504786baecfSMauro Carvalho Chehab 
505786baecfSMauro Carvalho Chehab 
506786baecfSMauro Carvalho Chehab #if 0
507786baecfSMauro Carvalho Chehab static void ttusb_set_led_freq(struct ttusb *ttusb, u8 freq)
508786baecfSMauro Carvalho Chehab {
509786baecfSMauro Carvalho Chehab 	u8 b[] = { 0xaa, ++ttusb->c, 0x19, 1, freq };
510786baecfSMauro Carvalho Chehab 	int err, actual_len;
511786baecfSMauro Carvalho Chehab 
512786baecfSMauro Carvalho Chehab 	err = ttusb_cmd(ttusb, b, sizeof(b), 0);
513786baecfSMauro Carvalho Chehab 	if (err) {
514*883c84acSMauro Carvalho Chehab 		dprintk("usb_bulk_msg() failed, return value %i!\n", err);
515786baecfSMauro Carvalho Chehab 	}
516786baecfSMauro Carvalho Chehab }
517786baecfSMauro Carvalho Chehab #endif
518786baecfSMauro Carvalho Chehab 
519786baecfSMauro Carvalho Chehab /*****************************************************************************/
520786baecfSMauro Carvalho Chehab 
521786baecfSMauro Carvalho Chehab #ifdef TTUSB_HWSECTIONS
522786baecfSMauro Carvalho Chehab static void ttusb_handle_ts_data(struct ttusb_channel *channel,
523786baecfSMauro Carvalho Chehab 				 const u8 * data, int len);
524786baecfSMauro Carvalho Chehab static void ttusb_handle_sec_data(struct ttusb_channel *channel,
525786baecfSMauro Carvalho Chehab 				  const u8 * data, int len);
526786baecfSMauro Carvalho Chehab #endif
527786baecfSMauro Carvalho Chehab 
528786baecfSMauro Carvalho Chehab static int numpkt, numts, numstuff, numsec, numinvalid;
529786baecfSMauro Carvalho Chehab static unsigned long lastj;
530786baecfSMauro Carvalho Chehab 
ttusb_process_muxpack(struct ttusb * ttusb,const u8 * muxpack,int len)531786baecfSMauro Carvalho Chehab static void ttusb_process_muxpack(struct ttusb *ttusb, const u8 * muxpack,
532786baecfSMauro Carvalho Chehab 			   int len)
533786baecfSMauro Carvalho Chehab {
534786baecfSMauro Carvalho Chehab 	u16 csum = 0, cc;
535786baecfSMauro Carvalho Chehab 	int i;
536bf5bbed1SDan Carpenter 
537bf5bbed1SDan Carpenter 	if (len < 4 || len & 0x1) {
538*883c84acSMauro Carvalho Chehab 		pr_warn("muxpack has invalid len %d\n", len);
539bf5bbed1SDan Carpenter 		numinvalid++;
540bf5bbed1SDan Carpenter 		return;
541bf5bbed1SDan Carpenter 	}
542bf5bbed1SDan Carpenter 
543786baecfSMauro Carvalho Chehab 	for (i = 0; i < len; i += 2)
544786baecfSMauro Carvalho Chehab 		csum ^= le16_to_cpup((__le16 *) (muxpack + i));
545786baecfSMauro Carvalho Chehab 	if (csum) {
546*883c84acSMauro Carvalho Chehab 		pr_warn("muxpack with incorrect checksum, ignoring\n");
547786baecfSMauro Carvalho Chehab 		numinvalid++;
548786baecfSMauro Carvalho Chehab 		return;
549786baecfSMauro Carvalho Chehab 	}
550786baecfSMauro Carvalho Chehab 
551786baecfSMauro Carvalho Chehab 	cc = (muxpack[len - 4] << 8) | muxpack[len - 3];
552786baecfSMauro Carvalho Chehab 	cc &= 0x7FFF;
553786baecfSMauro Carvalho Chehab 	if ((cc != ttusb->cc) && (ttusb->cc != -1))
554*883c84acSMauro Carvalho Chehab 		pr_warn("cc discontinuity (%d frames missing)\n",
555*883c84acSMauro Carvalho Chehab 			(cc - ttusb->cc) & 0x7FFF);
556786baecfSMauro Carvalho Chehab 	ttusb->cc = (cc + 1) & 0x7FFF;
557786baecfSMauro Carvalho Chehab 	if (muxpack[0] & 0x80) {
558786baecfSMauro Carvalho Chehab #ifdef TTUSB_HWSECTIONS
559786baecfSMauro Carvalho Chehab 		/* section data */
560786baecfSMauro Carvalho Chehab 		int pusi = muxpack[0] & 0x40;
561786baecfSMauro Carvalho Chehab 		int channel = muxpack[0] & 0x1F;
562786baecfSMauro Carvalho Chehab 		int payload = muxpack[1];
563786baecfSMauro Carvalho Chehab 		const u8 *data = muxpack + 2;
564786baecfSMauro Carvalho Chehab 		/* check offset flag */
565786baecfSMauro Carvalho Chehab 		if (muxpack[0] & 0x20)
566786baecfSMauro Carvalho Chehab 			data++;
567786baecfSMauro Carvalho Chehab 
568786baecfSMauro Carvalho Chehab 		ttusb_handle_sec_data(ttusb->channel + channel, data,
569786baecfSMauro Carvalho Chehab 				      payload);
570786baecfSMauro Carvalho Chehab 		data += payload;
571786baecfSMauro Carvalho Chehab 
572786baecfSMauro Carvalho Chehab 		if ((!!(ttusb->muxpack[0] & 0x20)) ^
573786baecfSMauro Carvalho Chehab 		    !!(ttusb->muxpack[1] & 1))
574786baecfSMauro Carvalho Chehab 			data++;
575786baecfSMauro Carvalho Chehab #warning TODO: pusi
576*883c84acSMauro Carvalho Chehab 		dprintk("cc: %04x\n", (data[0] << 8) | data[1]);
577786baecfSMauro Carvalho Chehab #endif
578786baecfSMauro Carvalho Chehab 		numsec++;
579786baecfSMauro Carvalho Chehab 	} else if (muxpack[0] == 0x47) {
580786baecfSMauro Carvalho Chehab #ifdef TTUSB_HWSECTIONS
581786baecfSMauro Carvalho Chehab 		/* we have TS data here! */
582786baecfSMauro Carvalho Chehab 		int pid = ((muxpack[1] & 0x0F) << 8) | muxpack[2];
583786baecfSMauro Carvalho Chehab 		int channel;
584786baecfSMauro Carvalho Chehab 		for (channel = 0; channel < TTUSB_MAXCHANNEL; ++channel)
585786baecfSMauro Carvalho Chehab 			if (ttusb->channel[channel].active
586786baecfSMauro Carvalho Chehab 			    && (pid == ttusb->channel[channel].pid))
587786baecfSMauro Carvalho Chehab 				ttusb_handle_ts_data(ttusb->channel +
588786baecfSMauro Carvalho Chehab 						     channel, muxpack,
589786baecfSMauro Carvalho Chehab 						     188);
590786baecfSMauro Carvalho Chehab #endif
591786baecfSMauro Carvalho Chehab 		numts++;
592786baecfSMauro Carvalho Chehab 		dvb_dmx_swfilter_packets(&ttusb->dvb_demux, muxpack, 1);
593786baecfSMauro Carvalho Chehab 	} else if (muxpack[0] != 0) {
594786baecfSMauro Carvalho Chehab 		numinvalid++;
595*883c84acSMauro Carvalho Chehab 		pr_err("illegal muxpack type %02x\n", muxpack[0]);
596786baecfSMauro Carvalho Chehab 	} else
597786baecfSMauro Carvalho Chehab 		numstuff++;
598786baecfSMauro Carvalho Chehab }
599786baecfSMauro Carvalho Chehab 
ttusb_process_frame(struct ttusb * ttusb,u8 * data,int len)600786baecfSMauro Carvalho Chehab static void ttusb_process_frame(struct ttusb *ttusb, u8 * data, int len)
601786baecfSMauro Carvalho Chehab {
602786baecfSMauro Carvalho Chehab 	int maxwork = 1024;
603786baecfSMauro Carvalho Chehab 	while (len) {
604786baecfSMauro Carvalho Chehab 		if (!(maxwork--)) {
605*883c84acSMauro Carvalho Chehab 			pr_err("too much work\n");
606786baecfSMauro Carvalho Chehab 			break;
607786baecfSMauro Carvalho Chehab 		}
608786baecfSMauro Carvalho Chehab 
609786baecfSMauro Carvalho Chehab 		switch (ttusb->mux_state) {
610786baecfSMauro Carvalho Chehab 		case 0:
611786baecfSMauro Carvalho Chehab 		case 1:
612786baecfSMauro Carvalho Chehab 		case 2:
613786baecfSMauro Carvalho Chehab 			len--;
614786baecfSMauro Carvalho Chehab 			if (*data++ == 0xAA)
615786baecfSMauro Carvalho Chehab 				++ttusb->mux_state;
616786baecfSMauro Carvalho Chehab 			else {
617786baecfSMauro Carvalho Chehab 				ttusb->mux_state = 0;
618786baecfSMauro Carvalho Chehab 				if (ttusb->insync) {
619*883c84acSMauro Carvalho Chehab 					pr_info("lost sync.\n");
620786baecfSMauro Carvalho Chehab 					ttusb->insync = 0;
621786baecfSMauro Carvalho Chehab 				}
622786baecfSMauro Carvalho Chehab 			}
623786baecfSMauro Carvalho Chehab 			break;
624786baecfSMauro Carvalho Chehab 		case 3:
625786baecfSMauro Carvalho Chehab 			ttusb->insync = 1;
626786baecfSMauro Carvalho Chehab 			len--;
627786baecfSMauro Carvalho Chehab 			ttusb->mux_npacks = *data++;
628786baecfSMauro Carvalho Chehab 			++ttusb->mux_state;
629786baecfSMauro Carvalho Chehab 			ttusb->muxpack_ptr = 0;
630786baecfSMauro Carvalho Chehab 			/* maximum bytes, until we know the length */
631786baecfSMauro Carvalho Chehab 			ttusb->muxpack_len = 2;
632786baecfSMauro Carvalho Chehab 			break;
633786baecfSMauro Carvalho Chehab 		case 4:
634786baecfSMauro Carvalho Chehab 			{
635786baecfSMauro Carvalho Chehab 				int avail;
636786baecfSMauro Carvalho Chehab 				avail = len;
637786baecfSMauro Carvalho Chehab 				if (avail >
638786baecfSMauro Carvalho Chehab 				    (ttusb->muxpack_len -
639786baecfSMauro Carvalho Chehab 				     ttusb->muxpack_ptr))
640786baecfSMauro Carvalho Chehab 					avail =
641786baecfSMauro Carvalho Chehab 					    ttusb->muxpack_len -
642786baecfSMauro Carvalho Chehab 					    ttusb->muxpack_ptr;
643786baecfSMauro Carvalho Chehab 				memcpy(ttusb->muxpack + ttusb->muxpack_ptr,
644786baecfSMauro Carvalho Chehab 				       data, avail);
645786baecfSMauro Carvalho Chehab 				ttusb->muxpack_ptr += avail;
646786baecfSMauro Carvalho Chehab 				BUG_ON(ttusb->muxpack_ptr > 264);
647786baecfSMauro Carvalho Chehab 				data += avail;
648786baecfSMauro Carvalho Chehab 				len -= avail;
649786baecfSMauro Carvalho Chehab 				/* determine length */
650786baecfSMauro Carvalho Chehab 				if (ttusb->muxpack_ptr == 2) {
651786baecfSMauro Carvalho Chehab 					if (ttusb->muxpack[0] & 0x80) {
652786baecfSMauro Carvalho Chehab 						ttusb->muxpack_len =
653786baecfSMauro Carvalho Chehab 						    ttusb->muxpack[1] + 2;
654786baecfSMauro Carvalho Chehab 						if (ttusb->
655786baecfSMauro Carvalho Chehab 						    muxpack[0] & 0x20)
656786baecfSMauro Carvalho Chehab 							ttusb->
657786baecfSMauro Carvalho Chehab 							    muxpack_len++;
658786baecfSMauro Carvalho Chehab 						if ((!!
659786baecfSMauro Carvalho Chehab 						     (ttusb->
660786baecfSMauro Carvalho Chehab 						      muxpack[0] & 0x20)) ^
661786baecfSMauro Carvalho Chehab 						    !!(ttusb->
662786baecfSMauro Carvalho Chehab 						       muxpack[1] & 1))
663786baecfSMauro Carvalho Chehab 							ttusb->
664786baecfSMauro Carvalho Chehab 							    muxpack_len++;
665786baecfSMauro Carvalho Chehab 						ttusb->muxpack_len += 4;
666786baecfSMauro Carvalho Chehab 					} else if (ttusb->muxpack[0] ==
667786baecfSMauro Carvalho Chehab 						   0x47)
668786baecfSMauro Carvalho Chehab 						ttusb->muxpack_len =
669786baecfSMauro Carvalho Chehab 						    188 + 4;
670786baecfSMauro Carvalho Chehab 					else if (ttusb->muxpack[0] == 0x00)
671786baecfSMauro Carvalho Chehab 						ttusb->muxpack_len =
672786baecfSMauro Carvalho Chehab 						    ttusb->muxpack[1] + 2 +
673786baecfSMauro Carvalho Chehab 						    4;
674786baecfSMauro Carvalho Chehab 					else {
675*883c84acSMauro Carvalho Chehab 						dprintk("invalid state: first byte is %x\n",
676786baecfSMauro Carvalho Chehab 							ttusb->muxpack[0]);
677786baecfSMauro Carvalho Chehab 						ttusb->mux_state = 0;
678786baecfSMauro Carvalho Chehab 					}
679786baecfSMauro Carvalho Chehab 				}
680786baecfSMauro Carvalho Chehab 
681cba862dcSMauro Carvalho Chehab 			/*
682786baecfSMauro Carvalho Chehab 			 * if length is valid and we reached the end:
683786baecfSMauro Carvalho Chehab 			 * goto next muxpack
684786baecfSMauro Carvalho Chehab 			 */
685786baecfSMauro Carvalho Chehab 				if ((ttusb->muxpack_ptr >= 2) &&
686786baecfSMauro Carvalho Chehab 				    (ttusb->muxpack_ptr ==
687786baecfSMauro Carvalho Chehab 				     ttusb->muxpack_len)) {
688786baecfSMauro Carvalho Chehab 					ttusb_process_muxpack(ttusb,
689786baecfSMauro Carvalho Chehab 							      ttusb->
690786baecfSMauro Carvalho Chehab 							      muxpack,
691786baecfSMauro Carvalho Chehab 							      ttusb->
692786baecfSMauro Carvalho Chehab 							      muxpack_ptr);
693786baecfSMauro Carvalho Chehab 					ttusb->muxpack_ptr = 0;
694786baecfSMauro Carvalho Chehab 					/* maximum bytes, until we know the length */
695786baecfSMauro Carvalho Chehab 					ttusb->muxpack_len = 2;
696786baecfSMauro Carvalho Chehab 
697cba862dcSMauro Carvalho Chehab 				/*
698786baecfSMauro Carvalho Chehab 				 * no muxpacks left?
699786baecfSMauro Carvalho Chehab 				 * return to search-sync state
700786baecfSMauro Carvalho Chehab 				 */
701786baecfSMauro Carvalho Chehab 					if (!ttusb->mux_npacks--) {
702786baecfSMauro Carvalho Chehab 						ttusb->mux_state = 0;
703786baecfSMauro Carvalho Chehab 						break;
704786baecfSMauro Carvalho Chehab 					}
705786baecfSMauro Carvalho Chehab 				}
706786baecfSMauro Carvalho Chehab 				break;
707786baecfSMauro Carvalho Chehab 			}
708786baecfSMauro Carvalho Chehab 		default:
709786baecfSMauro Carvalho Chehab 			BUG();
710786baecfSMauro Carvalho Chehab 			break;
711786baecfSMauro Carvalho Chehab 		}
712786baecfSMauro Carvalho Chehab 	}
713786baecfSMauro Carvalho Chehab }
714786baecfSMauro Carvalho Chehab 
ttusb_iso_irq(struct urb * urb)715786baecfSMauro Carvalho Chehab static void ttusb_iso_irq(struct urb *urb)
716786baecfSMauro Carvalho Chehab {
717786baecfSMauro Carvalho Chehab 	struct ttusb *ttusb = urb->context;
718786baecfSMauro Carvalho Chehab 	struct usb_iso_packet_descriptor *d;
719786baecfSMauro Carvalho Chehab 	u8 *data;
720786baecfSMauro Carvalho Chehab 	int len, i;
721786baecfSMauro Carvalho Chehab 
722786baecfSMauro Carvalho Chehab 	if (!ttusb->iso_streaming)
723786baecfSMauro Carvalho Chehab 		return;
724786baecfSMauro Carvalho Chehab 
725786baecfSMauro Carvalho Chehab 	if (!urb->status) {
726786baecfSMauro Carvalho Chehab 		for (i = 0; i < urb->number_of_packets; ++i) {
727786baecfSMauro Carvalho Chehab 			numpkt++;
728786baecfSMauro Carvalho Chehab 			if (time_after_eq(jiffies, lastj + HZ)) {
72980ebec68SMauro Carvalho Chehab 				dprintk("frames/s: %lu (ts: %d, stuff %d, sec: %d, invalid: %d, all: %d)\n",
730786baecfSMauro Carvalho Chehab 					numpkt * HZ / (jiffies - lastj),
731786baecfSMauro Carvalho Chehab 					numts, numstuff, numsec, numinvalid,
732786baecfSMauro Carvalho Chehab 					numts + numstuff + numsec + numinvalid);
733786baecfSMauro Carvalho Chehab 				numts = numstuff = numsec = numinvalid = 0;
734786baecfSMauro Carvalho Chehab 				lastj = jiffies;
735786baecfSMauro Carvalho Chehab 				numpkt = 0;
736786baecfSMauro Carvalho Chehab 			}
737786baecfSMauro Carvalho Chehab 			d = &urb->iso_frame_desc[i];
738786baecfSMauro Carvalho Chehab 			data = urb->transfer_buffer + d->offset;
739786baecfSMauro Carvalho Chehab 			len = d->actual_length;
740786baecfSMauro Carvalho Chehab 			d->actual_length = 0;
741786baecfSMauro Carvalho Chehab 			d->status = 0;
742786baecfSMauro Carvalho Chehab 			ttusb_process_frame(ttusb, data, len);
743786baecfSMauro Carvalho Chehab 		}
744786baecfSMauro Carvalho Chehab 	}
745786baecfSMauro Carvalho Chehab 	usb_submit_urb(urb, GFP_ATOMIC);
746786baecfSMauro Carvalho Chehab }
747786baecfSMauro Carvalho Chehab 
ttusb_free_iso_urbs(struct ttusb * ttusb)748786baecfSMauro Carvalho Chehab static void ttusb_free_iso_urbs(struct ttusb *ttusb)
749786baecfSMauro Carvalho Chehab {
750786baecfSMauro Carvalho Chehab 	int i;
751786baecfSMauro Carvalho Chehab 
752786baecfSMauro Carvalho Chehab 	for (i = 0; i < ISO_BUF_COUNT; i++)
753786baecfSMauro Carvalho Chehab 		usb_free_urb(ttusb->iso_urb[i]);
754894f3009SChristoph Hellwig 	kfree(ttusb->iso_buffer);
755786baecfSMauro Carvalho Chehab }
756786baecfSMauro Carvalho Chehab 
ttusb_alloc_iso_urbs(struct ttusb * ttusb)757786baecfSMauro Carvalho Chehab static int ttusb_alloc_iso_urbs(struct ttusb *ttusb)
758786baecfSMauro Carvalho Chehab {
759786baecfSMauro Carvalho Chehab 	int i;
760786baecfSMauro Carvalho Chehab 
761894f3009SChristoph Hellwig 	ttusb->iso_buffer = kcalloc(FRAMES_PER_ISO_BUF * ISO_BUF_COUNT,
762894f3009SChristoph Hellwig 			ISO_FRAME_SIZE, GFP_KERNEL);
763894f3009SChristoph Hellwig 	if (!ttusb->iso_buffer)
764786baecfSMauro Carvalho Chehab 		return -ENOMEM;
765786baecfSMauro Carvalho Chehab 
766786baecfSMauro Carvalho Chehab 	for (i = 0; i < ISO_BUF_COUNT; i++) {
767786baecfSMauro Carvalho Chehab 		struct urb *urb;
768786baecfSMauro Carvalho Chehab 
769786baecfSMauro Carvalho Chehab 		if (!
770786baecfSMauro Carvalho Chehab 		    (urb =
771786baecfSMauro Carvalho Chehab 		     usb_alloc_urb(FRAMES_PER_ISO_BUF, GFP_ATOMIC))) {
772786baecfSMauro Carvalho Chehab 			ttusb_free_iso_urbs(ttusb);
773786baecfSMauro Carvalho Chehab 			return -ENOMEM;
774786baecfSMauro Carvalho Chehab 		}
775786baecfSMauro Carvalho Chehab 
776786baecfSMauro Carvalho Chehab 		ttusb->iso_urb[i] = urb;
777786baecfSMauro Carvalho Chehab 	}
778786baecfSMauro Carvalho Chehab 
779786baecfSMauro Carvalho Chehab 	return 0;
780786baecfSMauro Carvalho Chehab }
781786baecfSMauro Carvalho Chehab 
ttusb_stop_iso_xfer(struct ttusb * ttusb)782786baecfSMauro Carvalho Chehab static void ttusb_stop_iso_xfer(struct ttusb *ttusb)
783786baecfSMauro Carvalho Chehab {
784786baecfSMauro Carvalho Chehab 	int i;
785786baecfSMauro Carvalho Chehab 
786786baecfSMauro Carvalho Chehab 	for (i = 0; i < ISO_BUF_COUNT; i++)
787786baecfSMauro Carvalho Chehab 		usb_kill_urb(ttusb->iso_urb[i]);
788786baecfSMauro Carvalho Chehab 
789786baecfSMauro Carvalho Chehab 	ttusb->iso_streaming = 0;
790786baecfSMauro Carvalho Chehab }
791786baecfSMauro Carvalho Chehab 
ttusb_start_iso_xfer(struct ttusb * ttusb)792786baecfSMauro Carvalho Chehab static int ttusb_start_iso_xfer(struct ttusb *ttusb)
793786baecfSMauro Carvalho Chehab {
794786baecfSMauro Carvalho Chehab 	int i, j, err, buffer_offset = 0;
795786baecfSMauro Carvalho Chehab 
796786baecfSMauro Carvalho Chehab 	if (ttusb->iso_streaming) {
797*883c84acSMauro Carvalho Chehab 		pr_err("iso xfer already running!\n");
798786baecfSMauro Carvalho Chehab 		return 0;
799786baecfSMauro Carvalho Chehab 	}
800786baecfSMauro Carvalho Chehab 
801786baecfSMauro Carvalho Chehab 	ttusb->cc = -1;
802786baecfSMauro Carvalho Chehab 	ttusb->insync = 0;
803786baecfSMauro Carvalho Chehab 	ttusb->mux_state = 0;
804786baecfSMauro Carvalho Chehab 
805786baecfSMauro Carvalho Chehab 	for (i = 0; i < ISO_BUF_COUNT; i++) {
806786baecfSMauro Carvalho Chehab 		int frame_offset = 0;
807786baecfSMauro Carvalho Chehab 		struct urb *urb = ttusb->iso_urb[i];
808786baecfSMauro Carvalho Chehab 
809786baecfSMauro Carvalho Chehab 		urb->dev = ttusb->dev;
810786baecfSMauro Carvalho Chehab 		urb->context = ttusb;
811786baecfSMauro Carvalho Chehab 		urb->complete = ttusb_iso_irq;
812786baecfSMauro Carvalho Chehab 		urb->pipe = ttusb->isoc_in_pipe;
813786baecfSMauro Carvalho Chehab 		urb->transfer_flags = URB_ISO_ASAP;
814786baecfSMauro Carvalho Chehab 		urb->interval = 1;
815786baecfSMauro Carvalho Chehab 		urb->number_of_packets = FRAMES_PER_ISO_BUF;
816786baecfSMauro Carvalho Chehab 		urb->transfer_buffer_length =
817786baecfSMauro Carvalho Chehab 		    ISO_FRAME_SIZE * FRAMES_PER_ISO_BUF;
818786baecfSMauro Carvalho Chehab 		urb->transfer_buffer = ttusb->iso_buffer + buffer_offset;
819786baecfSMauro Carvalho Chehab 		buffer_offset += ISO_FRAME_SIZE * FRAMES_PER_ISO_BUF;
820786baecfSMauro Carvalho Chehab 
821786baecfSMauro Carvalho Chehab 		for (j = 0; j < FRAMES_PER_ISO_BUF; j++) {
822786baecfSMauro Carvalho Chehab 			urb->iso_frame_desc[j].offset = frame_offset;
823786baecfSMauro Carvalho Chehab 			urb->iso_frame_desc[j].length = ISO_FRAME_SIZE;
824786baecfSMauro Carvalho Chehab 			frame_offset += ISO_FRAME_SIZE;
825786baecfSMauro Carvalho Chehab 		}
826786baecfSMauro Carvalho Chehab 	}
827786baecfSMauro Carvalho Chehab 
828786baecfSMauro Carvalho Chehab 	for (i = 0; i < ISO_BUF_COUNT; i++) {
829786baecfSMauro Carvalho Chehab 		if ((err = usb_submit_urb(ttusb->iso_urb[i], GFP_ATOMIC))) {
830786baecfSMauro Carvalho Chehab 			ttusb_stop_iso_xfer(ttusb);
831*883c84acSMauro Carvalho Chehab 			pr_err("failed urb submission (%i: err = %i)!\n",
832*883c84acSMauro Carvalho Chehab 			       i, err);
833786baecfSMauro Carvalho Chehab 			return err;
834786baecfSMauro Carvalho Chehab 		}
835786baecfSMauro Carvalho Chehab 	}
836786baecfSMauro Carvalho Chehab 
837786baecfSMauro Carvalho Chehab 	ttusb->iso_streaming = 1;
838786baecfSMauro Carvalho Chehab 
839786baecfSMauro Carvalho Chehab 	return 0;
840786baecfSMauro Carvalho Chehab }
841786baecfSMauro Carvalho Chehab 
842786baecfSMauro Carvalho Chehab #ifdef TTUSB_HWSECTIONS
ttusb_handle_ts_data(struct dvb_demux_feed * dvbdmxfeed,const u8 * data,int len)843786baecfSMauro Carvalho Chehab static void ttusb_handle_ts_data(struct dvb_demux_feed *dvbdmxfeed, const u8 * data,
844786baecfSMauro Carvalho Chehab 			  int len)
845786baecfSMauro Carvalho Chehab {
846786baecfSMauro Carvalho Chehab 	dvbdmxfeed->cb.ts(data, len, 0, 0, &dvbdmxfeed->feed.ts, 0);
847786baecfSMauro Carvalho Chehab }
848786baecfSMauro Carvalho Chehab 
ttusb_handle_sec_data(struct dvb_demux_feed * dvbdmxfeed,const u8 * data,int len)849786baecfSMauro Carvalho Chehab static void ttusb_handle_sec_data(struct dvb_demux_feed *dvbdmxfeed, const u8 * data,
850786baecfSMauro Carvalho Chehab 			   int len)
851786baecfSMauro Carvalho Chehab {
852786baecfSMauro Carvalho Chehab //      struct dvb_demux_feed *dvbdmxfeed = channel->dvbdmxfeed;
853786baecfSMauro Carvalho Chehab #error TODO: handle ugly stuff
854786baecfSMauro Carvalho Chehab //      dvbdmxfeed->cb.sec(data, len, 0, 0, &dvbdmxfeed->feed.sec, 0);
855786baecfSMauro Carvalho Chehab }
856786baecfSMauro Carvalho Chehab #endif
857786baecfSMauro Carvalho Chehab 
ttusb_start_feed(struct dvb_demux_feed * dvbdmxfeed)858786baecfSMauro Carvalho Chehab static int ttusb_start_feed(struct dvb_demux_feed *dvbdmxfeed)
859786baecfSMauro Carvalho Chehab {
860786baecfSMauro Carvalho Chehab 	struct ttusb *ttusb = (struct ttusb *) dvbdmxfeed->demux;
861786baecfSMauro Carvalho Chehab 	int feed_type = 1;
862786baecfSMauro Carvalho Chehab 
863786baecfSMauro Carvalho Chehab 	dprintk("ttusb_start_feed\n");
864786baecfSMauro Carvalho Chehab 
865786baecfSMauro Carvalho Chehab 	switch (dvbdmxfeed->type) {
866786baecfSMauro Carvalho Chehab 	case DMX_TYPE_TS:
867786baecfSMauro Carvalho Chehab 		break;
868786baecfSMauro Carvalho Chehab 	case DMX_TYPE_SEC:
869786baecfSMauro Carvalho Chehab 		break;
870786baecfSMauro Carvalho Chehab 	default:
871786baecfSMauro Carvalho Chehab 		return -EINVAL;
872786baecfSMauro Carvalho Chehab 	}
873786baecfSMauro Carvalho Chehab 
874786baecfSMauro Carvalho Chehab 	if (dvbdmxfeed->type == DMX_TYPE_TS) {
875786baecfSMauro Carvalho Chehab 		switch (dvbdmxfeed->pes_type) {
876fde04ab9SMauro Carvalho Chehab 		case DMX_PES_VIDEO:
877fde04ab9SMauro Carvalho Chehab 		case DMX_PES_AUDIO:
878fde04ab9SMauro Carvalho Chehab 		case DMX_PES_TELETEXT:
879fde04ab9SMauro Carvalho Chehab 		case DMX_PES_PCR:
880fde04ab9SMauro Carvalho Chehab 		case DMX_PES_OTHER:
881786baecfSMauro Carvalho Chehab 			break;
882786baecfSMauro Carvalho Chehab 		default:
883786baecfSMauro Carvalho Chehab 			return -EINVAL;
884786baecfSMauro Carvalho Chehab 		}
885786baecfSMauro Carvalho Chehab 	}
886786baecfSMauro Carvalho Chehab 
887786baecfSMauro Carvalho Chehab #ifdef TTUSB_HWSECTIONS
888786baecfSMauro Carvalho Chehab #error TODO: allocate filters
889786baecfSMauro Carvalho Chehab 	if (dvbdmxfeed->type == DMX_TYPE_TS) {
890786baecfSMauro Carvalho Chehab 		feed_type = 1;
891786baecfSMauro Carvalho Chehab 	} else if (dvbdmxfeed->type == DMX_TYPE_SEC) {
892786baecfSMauro Carvalho Chehab 		feed_type = 2;
893786baecfSMauro Carvalho Chehab 	}
894786baecfSMauro Carvalho Chehab #endif
895786baecfSMauro Carvalho Chehab 
896786baecfSMauro Carvalho Chehab 	ttusb_set_channel(ttusb, dvbdmxfeed->index, feed_type, dvbdmxfeed->pid);
897786baecfSMauro Carvalho Chehab 
898786baecfSMauro Carvalho Chehab 	if (0 == ttusb->running_feed_count++)
899786baecfSMauro Carvalho Chehab 		ttusb_start_iso_xfer(ttusb);
900786baecfSMauro Carvalho Chehab 
901786baecfSMauro Carvalho Chehab 	return 0;
902786baecfSMauro Carvalho Chehab }
903786baecfSMauro Carvalho Chehab 
ttusb_stop_feed(struct dvb_demux_feed * dvbdmxfeed)904786baecfSMauro Carvalho Chehab static int ttusb_stop_feed(struct dvb_demux_feed *dvbdmxfeed)
905786baecfSMauro Carvalho Chehab {
906786baecfSMauro Carvalho Chehab 	struct ttusb *ttusb = (struct ttusb *) dvbdmxfeed->demux;
907786baecfSMauro Carvalho Chehab 
908786baecfSMauro Carvalho Chehab 	ttusb_del_channel(ttusb, dvbdmxfeed->index);
909786baecfSMauro Carvalho Chehab 
910786baecfSMauro Carvalho Chehab 	if (--ttusb->running_feed_count == 0)
911786baecfSMauro Carvalho Chehab 		ttusb_stop_iso_xfer(ttusb);
912786baecfSMauro Carvalho Chehab 
913786baecfSMauro Carvalho Chehab 	return 0;
914786baecfSMauro Carvalho Chehab }
915786baecfSMauro Carvalho Chehab 
ttusb_setup_interfaces(struct ttusb * ttusb)916786baecfSMauro Carvalho Chehab static int ttusb_setup_interfaces(struct ttusb *ttusb)
917786baecfSMauro Carvalho Chehab {
918786baecfSMauro Carvalho Chehab 	usb_set_interface(ttusb->dev, 1, 1);
919786baecfSMauro Carvalho Chehab 
920786baecfSMauro Carvalho Chehab 	ttusb->bulk_out_pipe = usb_sndbulkpipe(ttusb->dev, 1);
921786baecfSMauro Carvalho Chehab 	ttusb->bulk_in_pipe = usb_rcvbulkpipe(ttusb->dev, 1);
922786baecfSMauro Carvalho Chehab 	ttusb->isoc_in_pipe = usb_rcvisocpipe(ttusb->dev, 2);
923786baecfSMauro Carvalho Chehab 
924786baecfSMauro Carvalho Chehab 	return 0;
925786baecfSMauro Carvalho Chehab }
926786baecfSMauro Carvalho Chehab 
927786baecfSMauro Carvalho Chehab #if 0
928786baecfSMauro Carvalho Chehab static u8 stc_firmware[8192];
929786baecfSMauro Carvalho Chehab 
930786baecfSMauro Carvalho Chehab static int stc_open(struct inode *inode, struct file *file)
931786baecfSMauro Carvalho Chehab {
932786baecfSMauro Carvalho Chehab 	struct ttusb *ttusb = file->private_data;
933786baecfSMauro Carvalho Chehab 	int addr;
934786baecfSMauro Carvalho Chehab 
935786baecfSMauro Carvalho Chehab 	for (addr = 0; addr < 8192; addr += 16) {
936786baecfSMauro Carvalho Chehab 		u8 snd_buf[2] = { addr >> 8, addr & 0xFF };
937786baecfSMauro Carvalho Chehab 		ttusb_i2c_msg(ttusb, 0x50, snd_buf, 2, stc_firmware + addr,
938786baecfSMauro Carvalho Chehab 			      16);
939786baecfSMauro Carvalho Chehab 	}
940786baecfSMauro Carvalho Chehab 
941786baecfSMauro Carvalho Chehab 	return 0;
942786baecfSMauro Carvalho Chehab }
943786baecfSMauro Carvalho Chehab 
944786baecfSMauro Carvalho Chehab static ssize_t stc_read(struct file *file, char *buf, size_t count,
945786baecfSMauro Carvalho Chehab 		 loff_t *offset)
946786baecfSMauro Carvalho Chehab {
947786baecfSMauro Carvalho Chehab 	return simple_read_from_buffer(buf, count, offset, stc_firmware, 8192);
948786baecfSMauro Carvalho Chehab }
949786baecfSMauro Carvalho Chehab 
950786baecfSMauro Carvalho Chehab static int stc_release(struct inode *inode, struct file *file)
951786baecfSMauro Carvalho Chehab {
952786baecfSMauro Carvalho Chehab 	return 0;
953786baecfSMauro Carvalho Chehab }
954786baecfSMauro Carvalho Chehab 
955786baecfSMauro Carvalho Chehab static const struct file_operations stc_fops = {
956786baecfSMauro Carvalho Chehab 	.owner = THIS_MODULE,
957786baecfSMauro Carvalho Chehab 	.read = stc_read,
958786baecfSMauro Carvalho Chehab 	.open = stc_open,
959786baecfSMauro Carvalho Chehab 	.release = stc_release,
960786baecfSMauro Carvalho Chehab };
961786baecfSMauro Carvalho Chehab #endif
962786baecfSMauro Carvalho Chehab 
functionality(struct i2c_adapter * adapter)963786baecfSMauro Carvalho Chehab static u32 functionality(struct i2c_adapter *adapter)
964786baecfSMauro Carvalho Chehab {
965786baecfSMauro Carvalho Chehab 	return I2C_FUNC_I2C;
966786baecfSMauro Carvalho Chehab }
967786baecfSMauro Carvalho Chehab 
968786baecfSMauro Carvalho Chehab 
969786baecfSMauro Carvalho Chehab 
alps_tdmb7_tuner_set_params(struct dvb_frontend * fe)970786baecfSMauro Carvalho Chehab static int alps_tdmb7_tuner_set_params(struct dvb_frontend *fe)
971786baecfSMauro Carvalho Chehab {
972786baecfSMauro Carvalho Chehab 	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
973786baecfSMauro Carvalho Chehab 	struct ttusb* ttusb = (struct ttusb*) fe->dvb->priv;
974786baecfSMauro Carvalho Chehab 	u8 data[4];
975786baecfSMauro Carvalho Chehab 	struct i2c_msg msg = {.addr=0x61, .flags=0, .buf=data, .len=sizeof(data) };
976786baecfSMauro Carvalho Chehab 	u32 div;
977786baecfSMauro Carvalho Chehab 
978786baecfSMauro Carvalho Chehab 	div = (p->frequency + 36166667) / 166667;
979786baecfSMauro Carvalho Chehab 
980786baecfSMauro Carvalho Chehab 	data[0] = (div >> 8) & 0x7f;
981786baecfSMauro Carvalho Chehab 	data[1] = div & 0xff;
982786baecfSMauro Carvalho Chehab 	data[2] = ((div >> 10) & 0x60) | 0x85;
983786baecfSMauro Carvalho Chehab 	data[3] = p->frequency < 592000000 ? 0x40 : 0x80;
984786baecfSMauro Carvalho Chehab 
985786baecfSMauro Carvalho Chehab 	if (fe->ops.i2c_gate_ctrl)
986786baecfSMauro Carvalho Chehab 		fe->ops.i2c_gate_ctrl(fe, 1);
987786baecfSMauro Carvalho Chehab 	if (i2c_transfer(&ttusb->i2c_adap, &msg, 1) != 1) return -EIO;
988786baecfSMauro Carvalho Chehab 	return 0;
989786baecfSMauro Carvalho Chehab }
990786baecfSMauro Carvalho Chehab 
991786baecfSMauro Carvalho Chehab static struct cx22700_config alps_tdmb7_config = {
992786baecfSMauro Carvalho Chehab 	.demod_address = 0x43,
993786baecfSMauro Carvalho Chehab };
994786baecfSMauro Carvalho Chehab 
995786baecfSMauro Carvalho Chehab 
996786baecfSMauro Carvalho Chehab 
997786baecfSMauro Carvalho Chehab 
998786baecfSMauro Carvalho Chehab 
philips_tdm1316l_tuner_init(struct dvb_frontend * fe)999786baecfSMauro Carvalho Chehab static int philips_tdm1316l_tuner_init(struct dvb_frontend* fe)
1000786baecfSMauro Carvalho Chehab {
1001786baecfSMauro Carvalho Chehab 	struct ttusb* ttusb = (struct ttusb*) fe->dvb->priv;
1002786baecfSMauro Carvalho Chehab 	static u8 td1316_init[] = { 0x0b, 0xf5, 0x85, 0xab };
1003786baecfSMauro Carvalho Chehab 	static u8 disable_mc44BC374c[] = { 0x1d, 0x74, 0xa0, 0x68 };
1004786baecfSMauro Carvalho Chehab 	struct i2c_msg tuner_msg = { .addr=0x60, .flags=0, .buf=td1316_init, .len=sizeof(td1316_init) };
1005786baecfSMauro Carvalho Chehab 
1006786baecfSMauro Carvalho Chehab 	// setup PLL configuration
1007786baecfSMauro Carvalho Chehab 	if (fe->ops.i2c_gate_ctrl)
1008786baecfSMauro Carvalho Chehab 		fe->ops.i2c_gate_ctrl(fe, 1);
1009786baecfSMauro Carvalho Chehab 	if (i2c_transfer(&ttusb->i2c_adap, &tuner_msg, 1) != 1) return -EIO;
1010786baecfSMauro Carvalho Chehab 	msleep(1);
1011786baecfSMauro Carvalho Chehab 
1012786baecfSMauro Carvalho Chehab 	// disable the mc44BC374c (do not check for errors)
1013786baecfSMauro Carvalho Chehab 	tuner_msg.addr = 0x65;
1014786baecfSMauro Carvalho Chehab 	tuner_msg.buf = disable_mc44BC374c;
1015786baecfSMauro Carvalho Chehab 	tuner_msg.len = sizeof(disable_mc44BC374c);
1016786baecfSMauro Carvalho Chehab 	if (fe->ops.i2c_gate_ctrl)
1017786baecfSMauro Carvalho Chehab 		fe->ops.i2c_gate_ctrl(fe, 1);
1018786baecfSMauro Carvalho Chehab 	if (i2c_transfer(&ttusb->i2c_adap, &tuner_msg, 1) != 1) {
1019786baecfSMauro Carvalho Chehab 		i2c_transfer(&ttusb->i2c_adap, &tuner_msg, 1);
1020786baecfSMauro Carvalho Chehab 	}
1021786baecfSMauro Carvalho Chehab 
1022786baecfSMauro Carvalho Chehab 	return 0;
1023786baecfSMauro Carvalho Chehab }
1024786baecfSMauro Carvalho Chehab 
philips_tdm1316l_tuner_set_params(struct dvb_frontend * fe)1025786baecfSMauro Carvalho Chehab static int philips_tdm1316l_tuner_set_params(struct dvb_frontend *fe)
1026786baecfSMauro Carvalho Chehab {
1027786baecfSMauro Carvalho Chehab 	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
1028786baecfSMauro Carvalho Chehab 	struct ttusb* ttusb = (struct ttusb*) fe->dvb->priv;
1029786baecfSMauro Carvalho Chehab 	u8 tuner_buf[4];
1030786baecfSMauro Carvalho Chehab 	struct i2c_msg tuner_msg = {.addr=0x60, .flags=0, .buf=tuner_buf, .len=sizeof(tuner_buf) };
1031786baecfSMauro Carvalho Chehab 	int tuner_frequency = 0;
1032786baecfSMauro Carvalho Chehab 	u8 band, cp, filter;
1033786baecfSMauro Carvalho Chehab 
1034786baecfSMauro Carvalho Chehab 	// determine charge pump
1035786baecfSMauro Carvalho Chehab 	tuner_frequency = p->frequency + 36130000;
1036786baecfSMauro Carvalho Chehab 	if (tuner_frequency < 87000000) return -EINVAL;
1037786baecfSMauro Carvalho Chehab 	else if (tuner_frequency < 130000000) cp = 3;
1038786baecfSMauro Carvalho Chehab 	else if (tuner_frequency < 160000000) cp = 5;
1039786baecfSMauro Carvalho Chehab 	else if (tuner_frequency < 200000000) cp = 6;
1040786baecfSMauro Carvalho Chehab 	else if (tuner_frequency < 290000000) cp = 3;
1041786baecfSMauro Carvalho Chehab 	else if (tuner_frequency < 420000000) cp = 5;
1042786baecfSMauro Carvalho Chehab 	else if (tuner_frequency < 480000000) cp = 6;
1043786baecfSMauro Carvalho Chehab 	else if (tuner_frequency < 620000000) cp = 3;
1044786baecfSMauro Carvalho Chehab 	else if (tuner_frequency < 830000000) cp = 5;
1045786baecfSMauro Carvalho Chehab 	else if (tuner_frequency < 895000000) cp = 7;
1046786baecfSMauro Carvalho Chehab 	else return -EINVAL;
1047786baecfSMauro Carvalho Chehab 
1048786baecfSMauro Carvalho Chehab 	// determine band
1049786baecfSMauro Carvalho Chehab 	if (p->frequency < 49000000)
1050786baecfSMauro Carvalho Chehab 		return -EINVAL;
1051786baecfSMauro Carvalho Chehab 	else if (p->frequency < 159000000)
1052786baecfSMauro Carvalho Chehab 		band = 1;
1053786baecfSMauro Carvalho Chehab 	else if (p->frequency < 444000000)
1054786baecfSMauro Carvalho Chehab 		band = 2;
1055786baecfSMauro Carvalho Chehab 	else if (p->frequency < 861000000)
1056786baecfSMauro Carvalho Chehab 		band = 4;
1057786baecfSMauro Carvalho Chehab 	else return -EINVAL;
1058786baecfSMauro Carvalho Chehab 
1059786baecfSMauro Carvalho Chehab 	// setup PLL filter
1060786baecfSMauro Carvalho Chehab 	switch (p->bandwidth_hz) {
1061786baecfSMauro Carvalho Chehab 	case 6000000:
1062786baecfSMauro Carvalho Chehab 		tda1004x_writereg(fe, 0x0C, 0);
1063786baecfSMauro Carvalho Chehab 		filter = 0;
1064786baecfSMauro Carvalho Chehab 		break;
1065786baecfSMauro Carvalho Chehab 
1066786baecfSMauro Carvalho Chehab 	case 7000000:
1067786baecfSMauro Carvalho Chehab 		tda1004x_writereg(fe, 0x0C, 0);
1068786baecfSMauro Carvalho Chehab 		filter = 0;
1069786baecfSMauro Carvalho Chehab 		break;
1070786baecfSMauro Carvalho Chehab 
1071786baecfSMauro Carvalho Chehab 	case 8000000:
1072786baecfSMauro Carvalho Chehab 		tda1004x_writereg(fe, 0x0C, 0xFF);
1073786baecfSMauro Carvalho Chehab 		filter = 1;
1074786baecfSMauro Carvalho Chehab 		break;
1075786baecfSMauro Carvalho Chehab 
1076786baecfSMauro Carvalho Chehab 	default:
1077786baecfSMauro Carvalho Chehab 		return -EINVAL;
1078786baecfSMauro Carvalho Chehab 	}
1079786baecfSMauro Carvalho Chehab 
1080786baecfSMauro Carvalho Chehab 	// calculate divisor
1081786baecfSMauro Carvalho Chehab 	// ((36130000+((1000000/6)/2)) + Finput)/(1000000/6)
1082786baecfSMauro Carvalho Chehab 	tuner_frequency = (((p->frequency / 1000) * 6) + 217280) / 1000;
1083786baecfSMauro Carvalho Chehab 
1084786baecfSMauro Carvalho Chehab 	// setup tuner buffer
1085786baecfSMauro Carvalho Chehab 	tuner_buf[0] = tuner_frequency >> 8;
1086786baecfSMauro Carvalho Chehab 	tuner_buf[1] = tuner_frequency & 0xff;
1087786baecfSMauro Carvalho Chehab 	tuner_buf[2] = 0xca;
1088786baecfSMauro Carvalho Chehab 	tuner_buf[3] = (cp << 5) | (filter << 3) | band;
1089786baecfSMauro Carvalho Chehab 
1090786baecfSMauro Carvalho Chehab 	if (fe->ops.i2c_gate_ctrl)
1091786baecfSMauro Carvalho Chehab 		fe->ops.i2c_gate_ctrl(fe, 1);
1092786baecfSMauro Carvalho Chehab 	if (i2c_transfer(&ttusb->i2c_adap, &tuner_msg, 1) != 1)
1093786baecfSMauro Carvalho Chehab 		return -EIO;
1094786baecfSMauro Carvalho Chehab 
1095786baecfSMauro Carvalho Chehab 	msleep(1);
1096786baecfSMauro Carvalho Chehab 	return 0;
1097786baecfSMauro Carvalho Chehab }
1098786baecfSMauro Carvalho Chehab 
philips_tdm1316l_request_firmware(struct dvb_frontend * fe,const struct firmware ** fw,char * name)1099786baecfSMauro Carvalho Chehab static int philips_tdm1316l_request_firmware(struct dvb_frontend* fe, const struct firmware **fw, char* name)
1100786baecfSMauro Carvalho Chehab {
1101786baecfSMauro Carvalho Chehab 	struct ttusb* ttusb = (struct ttusb*) fe->dvb->priv;
1102786baecfSMauro Carvalho Chehab 
1103786baecfSMauro Carvalho Chehab 	return request_firmware(fw, name, &ttusb->dev->dev);
1104786baecfSMauro Carvalho Chehab }
1105786baecfSMauro Carvalho Chehab 
1106786baecfSMauro Carvalho Chehab static struct tda1004x_config philips_tdm1316l_config = {
1107786baecfSMauro Carvalho Chehab 
1108786baecfSMauro Carvalho Chehab 	.demod_address = 0x8,
1109786baecfSMauro Carvalho Chehab 	.invert = 1,
1110786baecfSMauro Carvalho Chehab 	.invert_oclk = 0,
1111786baecfSMauro Carvalho Chehab 	.request_firmware = philips_tdm1316l_request_firmware,
1112786baecfSMauro Carvalho Chehab };
1113786baecfSMauro Carvalho Chehab 
1114786baecfSMauro Carvalho Chehab static u8 alps_bsbe1_inittab[] = {
1115786baecfSMauro Carvalho Chehab 	0x01, 0x15,
1116786baecfSMauro Carvalho Chehab 	0x02, 0x30,
1117786baecfSMauro Carvalho Chehab 	0x03, 0x00,
1118786baecfSMauro Carvalho Chehab 	0x04, 0x7d,             /* F22FR = 0x7d, F22 = f_VCO / 128 / 0x7d = 22 kHz */
1119786baecfSMauro Carvalho Chehab 	0x05, 0x35,             /* I2CT = 0, SCLT = 1, SDAT = 1 */
1120786baecfSMauro Carvalho Chehab 	0x06, 0x40,             /* DAC not used, set to high impendance mode */
1121786baecfSMauro Carvalho Chehab 	0x07, 0x00,             /* DAC LSB */
1122786baecfSMauro Carvalho Chehab 	0x08, 0x40,             /* DiSEqC off, LNB power on OP2/LOCK pin on */
1123786baecfSMauro Carvalho Chehab 	0x09, 0x00,             /* FIFO */
1124786baecfSMauro Carvalho Chehab 	0x0c, 0x51,             /* OP1 ctl = Normal, OP1 val = 1 (LNB Power ON) */
1125786baecfSMauro Carvalho Chehab 	0x0d, 0x82,             /* DC offset compensation = ON, beta_agc1 = 2 */
1126786baecfSMauro Carvalho Chehab 	0x0e, 0x23,             /* alpha_tmg = 2, beta_tmg = 3 */
1127786baecfSMauro Carvalho Chehab 	0x10, 0x3f,             // AGC2  0x3d
1128786baecfSMauro Carvalho Chehab 	0x11, 0x84,
1129786baecfSMauro Carvalho Chehab 	0x12, 0xb9,
1130786baecfSMauro Carvalho Chehab 	0x15, 0xc9,             // lock detector threshold
1131786baecfSMauro Carvalho Chehab 	0x16, 0x00,
1132786baecfSMauro Carvalho Chehab 	0x17, 0x00,
1133786baecfSMauro Carvalho Chehab 	0x18, 0x00,
1134786baecfSMauro Carvalho Chehab 	0x19, 0x00,
1135786baecfSMauro Carvalho Chehab 	0x1a, 0x00,
1136786baecfSMauro Carvalho Chehab 	0x1f, 0x50,
1137786baecfSMauro Carvalho Chehab 	0x20, 0x00,
1138786baecfSMauro Carvalho Chehab 	0x21, 0x00,
1139786baecfSMauro Carvalho Chehab 	0x22, 0x00,
1140786baecfSMauro Carvalho Chehab 	0x23, 0x00,
1141786baecfSMauro Carvalho Chehab 	0x28, 0x00,             // out imp: normal  out type: parallel FEC mode:0
1142786baecfSMauro Carvalho Chehab 	0x29, 0x1e,             // 1/2 threshold
1143786baecfSMauro Carvalho Chehab 	0x2a, 0x14,             // 2/3 threshold
1144786baecfSMauro Carvalho Chehab 	0x2b, 0x0f,             // 3/4 threshold
1145786baecfSMauro Carvalho Chehab 	0x2c, 0x09,             // 5/6 threshold
1146786baecfSMauro Carvalho Chehab 	0x2d, 0x05,             // 7/8 threshold
1147786baecfSMauro Carvalho Chehab 	0x2e, 0x01,
1148786baecfSMauro Carvalho Chehab 	0x31, 0x1f,             // test all FECs
1149786baecfSMauro Carvalho Chehab 	0x32, 0x19,             // viterbi and synchro search
1150786baecfSMauro Carvalho Chehab 	0x33, 0xfc,             // rs control
1151786baecfSMauro Carvalho Chehab 	0x34, 0x93,             // error control
1152786baecfSMauro Carvalho Chehab 	0x0f, 0x92,
1153786baecfSMauro Carvalho Chehab 	0xff, 0xff
1154786baecfSMauro Carvalho Chehab };
1155786baecfSMauro Carvalho Chehab 
1156786baecfSMauro Carvalho Chehab static u8 alps_bsru6_inittab[] = {
1157786baecfSMauro Carvalho Chehab 	0x01, 0x15,
1158786baecfSMauro Carvalho Chehab 	0x02, 0x30,
1159786baecfSMauro Carvalho Chehab 	0x03, 0x00,
1160786baecfSMauro Carvalho Chehab 	0x04, 0x7d,		/* F22FR = 0x7d, F22 = f_VCO / 128 / 0x7d = 22 kHz */
1161786baecfSMauro Carvalho Chehab 	0x05, 0x35,		/* I2CT = 0, SCLT = 1, SDAT = 1 */
1162786baecfSMauro Carvalho Chehab 	0x06, 0x40,		/* DAC not used, set to high impendance mode */
1163786baecfSMauro Carvalho Chehab 	0x07, 0x00,		/* DAC LSB */
1164786baecfSMauro Carvalho Chehab 	0x08, 0x40,		/* DiSEqC off, LNB power on OP2/LOCK pin on */
1165786baecfSMauro Carvalho Chehab 	0x09, 0x00,		/* FIFO */
1166786baecfSMauro Carvalho Chehab 	0x0c, 0x51,		/* OP1 ctl = Normal, OP1 val = 1 (LNB Power ON) */
1167786baecfSMauro Carvalho Chehab 	0x0d, 0x82,		/* DC offset compensation = ON, beta_agc1 = 2 */
1168786baecfSMauro Carvalho Chehab 	0x0e, 0x23,		/* alpha_tmg = 2, beta_tmg = 3 */
1169786baecfSMauro Carvalho Chehab 	0x10, 0x3f,		// AGC2  0x3d
1170786baecfSMauro Carvalho Chehab 	0x11, 0x84,
1171786baecfSMauro Carvalho Chehab 	0x12, 0xb9,
1172786baecfSMauro Carvalho Chehab 	0x15, 0xc9,		// lock detector threshold
1173786baecfSMauro Carvalho Chehab 	0x16, 0x00,
1174786baecfSMauro Carvalho Chehab 	0x17, 0x00,
1175786baecfSMauro Carvalho Chehab 	0x18, 0x00,
1176786baecfSMauro Carvalho Chehab 	0x19, 0x00,
1177786baecfSMauro Carvalho Chehab 	0x1a, 0x00,
1178786baecfSMauro Carvalho Chehab 	0x1f, 0x50,
1179786baecfSMauro Carvalho Chehab 	0x20, 0x00,
1180786baecfSMauro Carvalho Chehab 	0x21, 0x00,
1181786baecfSMauro Carvalho Chehab 	0x22, 0x00,
1182786baecfSMauro Carvalho Chehab 	0x23, 0x00,
1183786baecfSMauro Carvalho Chehab 	0x28, 0x00,		// out imp: normal  out type: parallel FEC mode:0
1184786baecfSMauro Carvalho Chehab 	0x29, 0x1e,		// 1/2 threshold
1185786baecfSMauro Carvalho Chehab 	0x2a, 0x14,		// 2/3 threshold
1186786baecfSMauro Carvalho Chehab 	0x2b, 0x0f,		// 3/4 threshold
1187786baecfSMauro Carvalho Chehab 	0x2c, 0x09,		// 5/6 threshold
1188786baecfSMauro Carvalho Chehab 	0x2d, 0x05,		// 7/8 threshold
1189786baecfSMauro Carvalho Chehab 	0x2e, 0x01,
1190786baecfSMauro Carvalho Chehab 	0x31, 0x1f,		// test all FECs
1191786baecfSMauro Carvalho Chehab 	0x32, 0x19,		// viterbi and synchro search
1192786baecfSMauro Carvalho Chehab 	0x33, 0xfc,		// rs control
1193786baecfSMauro Carvalho Chehab 	0x34, 0x93,		// error control
1194786baecfSMauro Carvalho Chehab 	0x0f, 0x52,
1195786baecfSMauro Carvalho Chehab 	0xff, 0xff
1196786baecfSMauro Carvalho Chehab };
1197786baecfSMauro Carvalho Chehab 
alps_stv0299_set_symbol_rate(struct dvb_frontend * fe,u32 srate,u32 ratio)1198786baecfSMauro Carvalho Chehab static int alps_stv0299_set_symbol_rate(struct dvb_frontend *fe, u32 srate, u32 ratio)
1199786baecfSMauro Carvalho Chehab {
1200786baecfSMauro Carvalho Chehab 	u8 aclk = 0;
1201786baecfSMauro Carvalho Chehab 	u8 bclk = 0;
1202786baecfSMauro Carvalho Chehab 
1203786baecfSMauro Carvalho Chehab 	if (srate < 1500000) {
1204786baecfSMauro Carvalho Chehab 		aclk = 0xb7;
1205786baecfSMauro Carvalho Chehab 		bclk = 0x47;
1206786baecfSMauro Carvalho Chehab 	} else if (srate < 3000000) {
1207786baecfSMauro Carvalho Chehab 		aclk = 0xb7;
1208786baecfSMauro Carvalho Chehab 		bclk = 0x4b;
1209786baecfSMauro Carvalho Chehab 	} else if (srate < 7000000) {
1210786baecfSMauro Carvalho Chehab 		aclk = 0xb7;
1211786baecfSMauro Carvalho Chehab 		bclk = 0x4f;
1212786baecfSMauro Carvalho Chehab 	} else if (srate < 14000000) {
1213786baecfSMauro Carvalho Chehab 		aclk = 0xb7;
1214786baecfSMauro Carvalho Chehab 		bclk = 0x53;
1215786baecfSMauro Carvalho Chehab 	} else if (srate < 30000000) {
1216786baecfSMauro Carvalho Chehab 		aclk = 0xb6;
1217786baecfSMauro Carvalho Chehab 		bclk = 0x53;
1218786baecfSMauro Carvalho Chehab 	} else if (srate < 45000000) {
1219786baecfSMauro Carvalho Chehab 		aclk = 0xb4;
1220786baecfSMauro Carvalho Chehab 		bclk = 0x51;
1221786baecfSMauro Carvalho Chehab 	}
1222786baecfSMauro Carvalho Chehab 
1223786baecfSMauro Carvalho Chehab 	stv0299_writereg(fe, 0x13, aclk);
1224786baecfSMauro Carvalho Chehab 	stv0299_writereg(fe, 0x14, bclk);
1225786baecfSMauro Carvalho Chehab 	stv0299_writereg(fe, 0x1f, (ratio >> 16) & 0xff);
1226786baecfSMauro Carvalho Chehab 	stv0299_writereg(fe, 0x20, (ratio >> 8) & 0xff);
1227786baecfSMauro Carvalho Chehab 	stv0299_writereg(fe, 0x21, (ratio) & 0xf0);
1228786baecfSMauro Carvalho Chehab 
1229786baecfSMauro Carvalho Chehab 	return 0;
1230786baecfSMauro Carvalho Chehab }
1231786baecfSMauro Carvalho Chehab 
philips_tsa5059_tuner_set_params(struct dvb_frontend * fe)1232786baecfSMauro Carvalho Chehab static int philips_tsa5059_tuner_set_params(struct dvb_frontend *fe)
1233786baecfSMauro Carvalho Chehab {
1234786baecfSMauro Carvalho Chehab 	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
1235786baecfSMauro Carvalho Chehab 	struct ttusb* ttusb = (struct ttusb*) fe->dvb->priv;
1236786baecfSMauro Carvalho Chehab 	u8 buf[4];
1237786baecfSMauro Carvalho Chehab 	u32 div;
1238786baecfSMauro Carvalho Chehab 	struct i2c_msg msg = {.addr = 0x61,.flags = 0,.buf = buf,.len = sizeof(buf) };
1239786baecfSMauro Carvalho Chehab 
1240786baecfSMauro Carvalho Chehab 	if ((p->frequency < 950000) || (p->frequency > 2150000))
1241786baecfSMauro Carvalho Chehab 		return -EINVAL;
1242786baecfSMauro Carvalho Chehab 
1243786baecfSMauro Carvalho Chehab 	div = (p->frequency + (125 - 1)) / 125;	/* round correctly */
1244786baecfSMauro Carvalho Chehab 	buf[0] = (div >> 8) & 0x7f;
1245786baecfSMauro Carvalho Chehab 	buf[1] = div & 0xff;
1246786baecfSMauro Carvalho Chehab 	buf[2] = 0x80 | ((div & 0x18000) >> 10) | 4;
1247786baecfSMauro Carvalho Chehab 	buf[3] = 0xC4;
1248786baecfSMauro Carvalho Chehab 
1249786baecfSMauro Carvalho Chehab 	if (p->frequency > 1530000)
1250786baecfSMauro Carvalho Chehab 		buf[3] = 0xC0;
1251786baecfSMauro Carvalho Chehab 
1252786baecfSMauro Carvalho Chehab 	/* BSBE1 wants XCE bit set */
1253786baecfSMauro Carvalho Chehab 	if (ttusb->revision == TTUSB_REV_2_2)
1254786baecfSMauro Carvalho Chehab 		buf[3] |= 0x20;
1255786baecfSMauro Carvalho Chehab 
1256786baecfSMauro Carvalho Chehab 	if (fe->ops.i2c_gate_ctrl)
1257786baecfSMauro Carvalho Chehab 		fe->ops.i2c_gate_ctrl(fe, 1);
1258786baecfSMauro Carvalho Chehab 	if (i2c_transfer(&ttusb->i2c_adap, &msg, 1) != 1)
1259786baecfSMauro Carvalho Chehab 		return -EIO;
1260786baecfSMauro Carvalho Chehab 
1261786baecfSMauro Carvalho Chehab 	return 0;
1262786baecfSMauro Carvalho Chehab }
1263786baecfSMauro Carvalho Chehab 
1264786baecfSMauro Carvalho Chehab static struct stv0299_config alps_stv0299_config = {
1265786baecfSMauro Carvalho Chehab 	.demod_address = 0x68,
1266786baecfSMauro Carvalho Chehab 	.inittab = alps_bsru6_inittab,
1267786baecfSMauro Carvalho Chehab 	.mclk = 88000000UL,
1268786baecfSMauro Carvalho Chehab 	.invert = 1,
1269786baecfSMauro Carvalho Chehab 	.skip_reinit = 0,
1270786baecfSMauro Carvalho Chehab 	.lock_output = STV0299_LOCKOUTPUT_1,
1271786baecfSMauro Carvalho Chehab 	.volt13_op0_op1 = STV0299_VOLT13_OP1,
1272786baecfSMauro Carvalho Chehab 	.min_delay_ms = 100,
1273786baecfSMauro Carvalho Chehab 	.set_symbol_rate = alps_stv0299_set_symbol_rate,
1274786baecfSMauro Carvalho Chehab };
1275786baecfSMauro Carvalho Chehab 
ttusb_novas_grundig_29504_491_tuner_set_params(struct dvb_frontend * fe)1276786baecfSMauro Carvalho Chehab static int ttusb_novas_grundig_29504_491_tuner_set_params(struct dvb_frontend *fe)
1277786baecfSMauro Carvalho Chehab {
1278786baecfSMauro Carvalho Chehab 	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
1279786baecfSMauro Carvalho Chehab 	struct ttusb* ttusb = (struct ttusb*) fe->dvb->priv;
1280786baecfSMauro Carvalho Chehab 	u8 buf[4];
1281786baecfSMauro Carvalho Chehab 	u32 div;
1282786baecfSMauro Carvalho Chehab 	struct i2c_msg msg = {.addr = 0x61,.flags = 0,.buf = buf,.len = sizeof(buf) };
1283786baecfSMauro Carvalho Chehab 
1284786baecfSMauro Carvalho Chehab 	div = p->frequency / 125;
1285786baecfSMauro Carvalho Chehab 
1286786baecfSMauro Carvalho Chehab 	buf[0] = (div >> 8) & 0x7f;
1287786baecfSMauro Carvalho Chehab 	buf[1] = div & 0xff;
1288786baecfSMauro Carvalho Chehab 	buf[2] = 0x8e;
1289786baecfSMauro Carvalho Chehab 	buf[3] = 0x00;
1290786baecfSMauro Carvalho Chehab 
1291786baecfSMauro Carvalho Chehab 	if (fe->ops.i2c_gate_ctrl)
1292786baecfSMauro Carvalho Chehab 		fe->ops.i2c_gate_ctrl(fe, 1);
1293786baecfSMauro Carvalho Chehab 	if (i2c_transfer(&ttusb->i2c_adap, &msg, 1) != 1)
1294786baecfSMauro Carvalho Chehab 		return -EIO;
1295786baecfSMauro Carvalho Chehab 
1296786baecfSMauro Carvalho Chehab 	return 0;
1297786baecfSMauro Carvalho Chehab }
1298786baecfSMauro Carvalho Chehab 
1299786baecfSMauro Carvalho Chehab static struct tda8083_config ttusb_novas_grundig_29504_491_config = {
1300786baecfSMauro Carvalho Chehab 
1301786baecfSMauro Carvalho Chehab 	.demod_address = 0x68,
1302786baecfSMauro Carvalho Chehab };
1303786baecfSMauro Carvalho Chehab 
alps_tdbe2_tuner_set_params(struct dvb_frontend * fe)1304786baecfSMauro Carvalho Chehab static int alps_tdbe2_tuner_set_params(struct dvb_frontend *fe)
1305786baecfSMauro Carvalho Chehab {
1306786baecfSMauro Carvalho Chehab 	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
1307786baecfSMauro Carvalho Chehab 	struct ttusb* ttusb = fe->dvb->priv;
1308786baecfSMauro Carvalho Chehab 	u32 div;
1309786baecfSMauro Carvalho Chehab 	u8 data[4];
1310786baecfSMauro Carvalho Chehab 	struct i2c_msg msg = { .addr = 0x62, .flags = 0, .buf = data, .len = sizeof(data) };
1311786baecfSMauro Carvalho Chehab 
1312786baecfSMauro Carvalho Chehab 	div = (p->frequency + 35937500 + 31250) / 62500;
1313786baecfSMauro Carvalho Chehab 
1314786baecfSMauro Carvalho Chehab 	data[0] = (div >> 8) & 0x7f;
1315786baecfSMauro Carvalho Chehab 	data[1] = div & 0xff;
1316786baecfSMauro Carvalho Chehab 	data[2] = 0x85 | ((div >> 10) & 0x60);
1317786baecfSMauro Carvalho Chehab 	data[3] = (p->frequency < 174000000 ? 0x88 : p->frequency < 470000000 ? 0x84 : 0x81);
1318786baecfSMauro Carvalho Chehab 
1319786baecfSMauro Carvalho Chehab 	if (fe->ops.i2c_gate_ctrl)
1320786baecfSMauro Carvalho Chehab 		fe->ops.i2c_gate_ctrl(fe, 1);
1321786baecfSMauro Carvalho Chehab 	if (i2c_transfer (&ttusb->i2c_adap, &msg, 1) != 1)
1322786baecfSMauro Carvalho Chehab 		return -EIO;
1323786baecfSMauro Carvalho Chehab 
1324786baecfSMauro Carvalho Chehab 	return 0;
1325786baecfSMauro Carvalho Chehab }
1326786baecfSMauro Carvalho Chehab 
1327786baecfSMauro Carvalho Chehab 
1328786baecfSMauro Carvalho Chehab static struct ves1820_config alps_tdbe2_config = {
1329786baecfSMauro Carvalho Chehab 	.demod_address = 0x09,
1330786baecfSMauro Carvalho Chehab 	.xin = 57840000UL,
1331786baecfSMauro Carvalho Chehab 	.invert = 1,
1332786baecfSMauro Carvalho Chehab 	.selagc = VES1820_SELAGC_SIGNAMPERR,
1333786baecfSMauro Carvalho Chehab };
1334786baecfSMauro Carvalho Chehab 
read_pwm(struct ttusb * ttusb)1335786baecfSMauro Carvalho Chehab static u8 read_pwm(struct ttusb* ttusb)
1336786baecfSMauro Carvalho Chehab {
1337786baecfSMauro Carvalho Chehab 	u8 b = 0xff;
1338786baecfSMauro Carvalho Chehab 	u8 pwm;
1339786baecfSMauro Carvalho Chehab 	struct i2c_msg msg[] = { { .addr = 0x50,.flags = 0,.buf = &b,.len = 1 },
1340786baecfSMauro Carvalho Chehab 				{ .addr = 0x50,.flags = I2C_M_RD,.buf = &pwm,.len = 1} };
1341786baecfSMauro Carvalho Chehab 
1342786baecfSMauro Carvalho Chehab 	if ((i2c_transfer(&ttusb->i2c_adap, msg, 2) != 2) || (pwm == 0xff))
1343786baecfSMauro Carvalho Chehab 		pwm = 0x48;
1344786baecfSMauro Carvalho Chehab 
1345786baecfSMauro Carvalho Chehab 	return pwm;
1346786baecfSMauro Carvalho Chehab }
1347786baecfSMauro Carvalho Chehab 
1348786baecfSMauro Carvalho Chehab 
dvbc_philips_tdm1316l_tuner_set_params(struct dvb_frontend * fe)1349786baecfSMauro Carvalho Chehab static int dvbc_philips_tdm1316l_tuner_set_params(struct dvb_frontend *fe)
1350786baecfSMauro Carvalho Chehab {
1351786baecfSMauro Carvalho Chehab 	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
1352786baecfSMauro Carvalho Chehab 	struct ttusb *ttusb = (struct ttusb *) fe->dvb->priv;
1353786baecfSMauro Carvalho Chehab 	u8 tuner_buf[5];
1354786baecfSMauro Carvalho Chehab 	struct i2c_msg tuner_msg = {.addr = 0x60,
1355786baecfSMauro Carvalho Chehab 				    .flags = 0,
1356786baecfSMauro Carvalho Chehab 				    .buf = tuner_buf,
1357786baecfSMauro Carvalho Chehab 				    .len = sizeof(tuner_buf) };
1358786baecfSMauro Carvalho Chehab 	int tuner_frequency = 0;
1359786baecfSMauro Carvalho Chehab 	u8 band, cp, filter;
1360786baecfSMauro Carvalho Chehab 
1361786baecfSMauro Carvalho Chehab 	// determine charge pump
1362786baecfSMauro Carvalho Chehab 	tuner_frequency = p->frequency;
1363786baecfSMauro Carvalho Chehab 	if      (tuner_frequency <  87000000) {return -EINVAL;}
1364786baecfSMauro Carvalho Chehab 	else if (tuner_frequency < 130000000) {cp = 3; band = 1;}
1365786baecfSMauro Carvalho Chehab 	else if (tuner_frequency < 160000000) {cp = 5; band = 1;}
1366786baecfSMauro Carvalho Chehab 	else if (tuner_frequency < 200000000) {cp = 6; band = 1;}
1367786baecfSMauro Carvalho Chehab 	else if (tuner_frequency < 290000000) {cp = 3; band = 2;}
1368786baecfSMauro Carvalho Chehab 	else if (tuner_frequency < 420000000) {cp = 5; band = 2;}
1369786baecfSMauro Carvalho Chehab 	else if (tuner_frequency < 480000000) {cp = 6; band = 2;}
1370786baecfSMauro Carvalho Chehab 	else if (tuner_frequency < 620000000) {cp = 3; band = 4;}
1371786baecfSMauro Carvalho Chehab 	else if (tuner_frequency < 830000000) {cp = 5; band = 4;}
1372786baecfSMauro Carvalho Chehab 	else if (tuner_frequency < 895000000) {cp = 7; band = 4;}
1373786baecfSMauro Carvalho Chehab 	else {return -EINVAL;}
1374786baecfSMauro Carvalho Chehab 
1375786baecfSMauro Carvalho Chehab 	// assume PLL filter should always be 8MHz for the moment.
1376786baecfSMauro Carvalho Chehab 	filter = 1;
1377786baecfSMauro Carvalho Chehab 
1378786baecfSMauro Carvalho Chehab 	// calculate divisor
1379786baecfSMauro Carvalho Chehab 	// (Finput + Fif)/Fref; Fif = 36125000 Hz, Fref = 62500 Hz
1380786baecfSMauro Carvalho Chehab 	tuner_frequency = ((p->frequency + 36125000) / 62500);
1381786baecfSMauro Carvalho Chehab 
1382786baecfSMauro Carvalho Chehab 	// setup tuner buffer
1383786baecfSMauro Carvalho Chehab 	tuner_buf[0] = tuner_frequency >> 8;
1384786baecfSMauro Carvalho Chehab 	tuner_buf[1] = tuner_frequency & 0xff;
1385786baecfSMauro Carvalho Chehab 	tuner_buf[2] = 0xc8;
1386786baecfSMauro Carvalho Chehab 	tuner_buf[3] = (cp << 5) | (filter << 3) | band;
1387786baecfSMauro Carvalho Chehab 	tuner_buf[4] = 0x80;
1388786baecfSMauro Carvalho Chehab 
1389786baecfSMauro Carvalho Chehab 	if (fe->ops.i2c_gate_ctrl)
1390786baecfSMauro Carvalho Chehab 		fe->ops.i2c_gate_ctrl(fe, 1);
1391786baecfSMauro Carvalho Chehab 	if (i2c_transfer(&ttusb->i2c_adap, &tuner_msg, 1) != 1) {
1392*883c84acSMauro Carvalho Chehab 		pr_err("dvbc_philips_tdm1316l_pll_set Error 1\n");
1393786baecfSMauro Carvalho Chehab 		return -EIO;
1394786baecfSMauro Carvalho Chehab 	}
1395786baecfSMauro Carvalho Chehab 
1396786baecfSMauro Carvalho Chehab 	msleep(50);
1397786baecfSMauro Carvalho Chehab 
1398786baecfSMauro Carvalho Chehab 	if (fe->ops.i2c_gate_ctrl)
1399786baecfSMauro Carvalho Chehab 		fe->ops.i2c_gate_ctrl(fe, 1);
1400786baecfSMauro Carvalho Chehab 	if (i2c_transfer(&ttusb->i2c_adap, &tuner_msg, 1) != 1) {
1401*883c84acSMauro Carvalho Chehab 		pr_err("dvbc_philips_tdm1316l_pll_set Error 2\n");
1402786baecfSMauro Carvalho Chehab 		return -EIO;
1403786baecfSMauro Carvalho Chehab 	}
1404786baecfSMauro Carvalho Chehab 
1405786baecfSMauro Carvalho Chehab 	msleep(1);
1406786baecfSMauro Carvalho Chehab 
1407786baecfSMauro Carvalho Chehab 	return 0;
1408786baecfSMauro Carvalho Chehab }
1409786baecfSMauro Carvalho Chehab 
1410786baecfSMauro Carvalho Chehab static u8 dvbc_philips_tdm1316l_inittab[] = {
1411786baecfSMauro Carvalho Chehab 	0x80, 0x21,
1412786baecfSMauro Carvalho Chehab 	0x80, 0x20,
1413786baecfSMauro Carvalho Chehab 	0x81, 0x01,
1414786baecfSMauro Carvalho Chehab 	0x81, 0x00,
1415786baecfSMauro Carvalho Chehab 	0x00, 0x09,
1416786baecfSMauro Carvalho Chehab 	0x01, 0x69,
1417786baecfSMauro Carvalho Chehab 	0x03, 0x00,
1418786baecfSMauro Carvalho Chehab 	0x04, 0x00,
1419786baecfSMauro Carvalho Chehab 	0x07, 0x00,
1420786baecfSMauro Carvalho Chehab 	0x08, 0x00,
1421786baecfSMauro Carvalho Chehab 	0x20, 0x00,
1422786baecfSMauro Carvalho Chehab 	0x21, 0x40,
1423786baecfSMauro Carvalho Chehab 	0x22, 0x00,
1424786baecfSMauro Carvalho Chehab 	0x23, 0x00,
1425786baecfSMauro Carvalho Chehab 	0x24, 0x40,
1426786baecfSMauro Carvalho Chehab 	0x25, 0x88,
1427786baecfSMauro Carvalho Chehab 	0x30, 0xff,
1428786baecfSMauro Carvalho Chehab 	0x31, 0x00,
1429786baecfSMauro Carvalho Chehab 	0x32, 0xff,
1430786baecfSMauro Carvalho Chehab 	0x33, 0x00,
1431786baecfSMauro Carvalho Chehab 	0x34, 0x50,
1432786baecfSMauro Carvalho Chehab 	0x35, 0x7f,
1433786baecfSMauro Carvalho Chehab 	0x36, 0x00,
1434786baecfSMauro Carvalho Chehab 	0x37, 0x20,
1435786baecfSMauro Carvalho Chehab 	0x38, 0x00,
1436786baecfSMauro Carvalho Chehab 	0x40, 0x1c,
1437786baecfSMauro Carvalho Chehab 	0x41, 0xff,
1438786baecfSMauro Carvalho Chehab 	0x42, 0x29,
1439786baecfSMauro Carvalho Chehab 	0x43, 0x20,
1440786baecfSMauro Carvalho Chehab 	0x44, 0xff,
1441786baecfSMauro Carvalho Chehab 	0x45, 0x00,
1442786baecfSMauro Carvalho Chehab 	0x46, 0x00,
1443786baecfSMauro Carvalho Chehab 	0x49, 0x04,
1444786baecfSMauro Carvalho Chehab 	0x4a, 0xff,
1445786baecfSMauro Carvalho Chehab 	0x4b, 0x7f,
1446786baecfSMauro Carvalho Chehab 	0x52, 0x30,
1447786baecfSMauro Carvalho Chehab 	0x55, 0xae,
1448786baecfSMauro Carvalho Chehab 	0x56, 0x47,
1449786baecfSMauro Carvalho Chehab 	0x57, 0xe1,
1450786baecfSMauro Carvalho Chehab 	0x58, 0x3a,
1451786baecfSMauro Carvalho Chehab 	0x5a, 0x1e,
1452786baecfSMauro Carvalho Chehab 	0x5b, 0x34,
1453786baecfSMauro Carvalho Chehab 	0x60, 0x00,
1454786baecfSMauro Carvalho Chehab 	0x63, 0x00,
1455786baecfSMauro Carvalho Chehab 	0x64, 0x00,
1456786baecfSMauro Carvalho Chehab 	0x65, 0x00,
1457786baecfSMauro Carvalho Chehab 	0x66, 0x00,
1458786baecfSMauro Carvalho Chehab 	0x67, 0x00,
1459786baecfSMauro Carvalho Chehab 	0x68, 0x00,
1460786baecfSMauro Carvalho Chehab 	0x69, 0x00,
1461786baecfSMauro Carvalho Chehab 	0x6a, 0x02,
1462786baecfSMauro Carvalho Chehab 	0x6b, 0x00,
1463786baecfSMauro Carvalho Chehab 	0x70, 0xff,
1464786baecfSMauro Carvalho Chehab 	0x71, 0x00,
1465786baecfSMauro Carvalho Chehab 	0x72, 0x00,
1466786baecfSMauro Carvalho Chehab 	0x73, 0x00,
1467786baecfSMauro Carvalho Chehab 	0x74, 0x0c,
1468786baecfSMauro Carvalho Chehab 	0x80, 0x00,
1469786baecfSMauro Carvalho Chehab 	0x81, 0x00,
1470786baecfSMauro Carvalho Chehab 	0x82, 0x00,
1471786baecfSMauro Carvalho Chehab 	0x83, 0x00,
1472786baecfSMauro Carvalho Chehab 	0x84, 0x04,
1473786baecfSMauro Carvalho Chehab 	0x85, 0x80,
1474786baecfSMauro Carvalho Chehab 	0x86, 0x24,
1475786baecfSMauro Carvalho Chehab 	0x87, 0x78,
1476786baecfSMauro Carvalho Chehab 	0x88, 0x00,
1477786baecfSMauro Carvalho Chehab 	0x89, 0x00,
1478786baecfSMauro Carvalho Chehab 	0x90, 0x01,
1479786baecfSMauro Carvalho Chehab 	0x91, 0x01,
1480786baecfSMauro Carvalho Chehab 	0xa0, 0x00,
1481786baecfSMauro Carvalho Chehab 	0xa1, 0x00,
1482786baecfSMauro Carvalho Chehab 	0xa2, 0x00,
1483786baecfSMauro Carvalho Chehab 	0xb0, 0x91,
1484786baecfSMauro Carvalho Chehab 	0xb1, 0x0b,
1485786baecfSMauro Carvalho Chehab 	0xc0, 0x4b,
1486786baecfSMauro Carvalho Chehab 	0xc1, 0x00,
1487786baecfSMauro Carvalho Chehab 	0xc2, 0x00,
1488786baecfSMauro Carvalho Chehab 	0xd0, 0x00,
1489786baecfSMauro Carvalho Chehab 	0xd1, 0x00,
1490786baecfSMauro Carvalho Chehab 	0xd2, 0x00,
1491786baecfSMauro Carvalho Chehab 	0xd3, 0x00,
1492786baecfSMauro Carvalho Chehab 	0xd4, 0x00,
1493786baecfSMauro Carvalho Chehab 	0xd5, 0x00,
1494786baecfSMauro Carvalho Chehab 	0xde, 0x00,
1495786baecfSMauro Carvalho Chehab 	0xdf, 0x00,
1496786baecfSMauro Carvalho Chehab 	0x61, 0x38,
1497786baecfSMauro Carvalho Chehab 	0x62, 0x0a,
1498786baecfSMauro Carvalho Chehab 	0x53, 0x13,
1499786baecfSMauro Carvalho Chehab 	0x59, 0x08,
1500786baecfSMauro Carvalho Chehab 	0x55, 0x00,
1501786baecfSMauro Carvalho Chehab 	0x56, 0x40,
1502786baecfSMauro Carvalho Chehab 	0x57, 0x08,
1503786baecfSMauro Carvalho Chehab 	0x58, 0x3d,
1504786baecfSMauro Carvalho Chehab 	0x88, 0x10,
1505786baecfSMauro Carvalho Chehab 	0xa0, 0x00,
1506786baecfSMauro Carvalho Chehab 	0xa0, 0x00,
1507786baecfSMauro Carvalho Chehab 	0xa0, 0x00,
1508786baecfSMauro Carvalho Chehab 	0xa0, 0x04,
1509786baecfSMauro Carvalho Chehab 	0xff, 0xff,
1510786baecfSMauro Carvalho Chehab };
1511786baecfSMauro Carvalho Chehab 
1512786baecfSMauro Carvalho Chehab static struct stv0297_config dvbc_philips_tdm1316l_config = {
1513786baecfSMauro Carvalho Chehab 	.demod_address = 0x1c,
1514786baecfSMauro Carvalho Chehab 	.inittab = dvbc_philips_tdm1316l_inittab,
1515786baecfSMauro Carvalho Chehab 	.invert = 0,
1516786baecfSMauro Carvalho Chehab };
1517786baecfSMauro Carvalho Chehab 
frontend_init(struct ttusb * ttusb)1518786baecfSMauro Carvalho Chehab static void frontend_init(struct ttusb* ttusb)
1519786baecfSMauro Carvalho Chehab {
1520786baecfSMauro Carvalho Chehab 	switch(le16_to_cpu(ttusb->dev->descriptor.idProduct)) {
1521786baecfSMauro Carvalho Chehab 	case 0x1003: // Hauppauge/TT Nova-USB-S budget (stv0299/ALPS BSRU6|BSBE1(tsa5059))
1522786baecfSMauro Carvalho Chehab 		// try the stv0299 based first
1523786baecfSMauro Carvalho Chehab 		ttusb->fe = dvb_attach(stv0299_attach, &alps_stv0299_config, &ttusb->i2c_adap);
1524786baecfSMauro Carvalho Chehab 		if (ttusb->fe != NULL) {
1525786baecfSMauro Carvalho Chehab 			ttusb->fe->ops.tuner_ops.set_params = philips_tsa5059_tuner_set_params;
1526786baecfSMauro Carvalho Chehab 
1527786baecfSMauro Carvalho Chehab 			if(ttusb->revision == TTUSB_REV_2_2) { // ALPS BSBE1
1528786baecfSMauro Carvalho Chehab 				alps_stv0299_config.inittab = alps_bsbe1_inittab;
1529786baecfSMauro Carvalho Chehab 				dvb_attach(lnbp21_attach, ttusb->fe, &ttusb->i2c_adap, 0, 0);
1530786baecfSMauro Carvalho Chehab 			} else { // ALPS BSRU6
1531786baecfSMauro Carvalho Chehab 				ttusb->fe->ops.set_voltage = ttusb_set_voltage;
1532786baecfSMauro Carvalho Chehab 			}
1533786baecfSMauro Carvalho Chehab 			break;
1534786baecfSMauro Carvalho Chehab 		}
1535786baecfSMauro Carvalho Chehab 
1536786baecfSMauro Carvalho Chehab 		// Grundig 29504-491
1537786baecfSMauro Carvalho Chehab 		ttusb->fe = dvb_attach(tda8083_attach, &ttusb_novas_grundig_29504_491_config, &ttusb->i2c_adap);
1538786baecfSMauro Carvalho Chehab 		if (ttusb->fe != NULL) {
1539786baecfSMauro Carvalho Chehab 			ttusb->fe->ops.tuner_ops.set_params = ttusb_novas_grundig_29504_491_tuner_set_params;
1540786baecfSMauro Carvalho Chehab 			ttusb->fe->ops.set_voltage = ttusb_set_voltage;
1541786baecfSMauro Carvalho Chehab 			break;
1542786baecfSMauro Carvalho Chehab 		}
1543786baecfSMauro Carvalho Chehab 		break;
1544786baecfSMauro Carvalho Chehab 
1545786baecfSMauro Carvalho Chehab 	case 0x1004: // Hauppauge/TT DVB-C budget (ves1820/ALPS TDBE2(sp5659))
1546786baecfSMauro Carvalho Chehab 		ttusb->fe = dvb_attach(ves1820_attach, &alps_tdbe2_config, &ttusb->i2c_adap, read_pwm(ttusb));
1547786baecfSMauro Carvalho Chehab 		if (ttusb->fe != NULL) {
1548786baecfSMauro Carvalho Chehab 			ttusb->fe->ops.tuner_ops.set_params = alps_tdbe2_tuner_set_params;
1549786baecfSMauro Carvalho Chehab 			break;
1550786baecfSMauro Carvalho Chehab 		}
1551786baecfSMauro Carvalho Chehab 
1552786baecfSMauro Carvalho Chehab 		ttusb->fe = dvb_attach(stv0297_attach, &dvbc_philips_tdm1316l_config, &ttusb->i2c_adap);
1553786baecfSMauro Carvalho Chehab 		if (ttusb->fe != NULL) {
1554786baecfSMauro Carvalho Chehab 			ttusb->fe->ops.tuner_ops.set_params = dvbc_philips_tdm1316l_tuner_set_params;
1555786baecfSMauro Carvalho Chehab 			break;
1556786baecfSMauro Carvalho Chehab 		}
1557786baecfSMauro Carvalho Chehab 		break;
1558786baecfSMauro Carvalho Chehab 
1559786baecfSMauro Carvalho Chehab 	case 0x1005: // Hauppauge/TT Nova-USB-t budget (tda10046/Philips td1316(tda6651tt) OR cx22700/ALPS TDMB7(??))
1560786baecfSMauro Carvalho Chehab 		// try the ALPS TDMB7 first
1561786baecfSMauro Carvalho Chehab 		ttusb->fe = dvb_attach(cx22700_attach, &alps_tdmb7_config, &ttusb->i2c_adap);
1562786baecfSMauro Carvalho Chehab 		if (ttusb->fe != NULL) {
1563786baecfSMauro Carvalho Chehab 			ttusb->fe->ops.tuner_ops.set_params = alps_tdmb7_tuner_set_params;
1564786baecfSMauro Carvalho Chehab 			break;
1565786baecfSMauro Carvalho Chehab 		}
1566786baecfSMauro Carvalho Chehab 
1567786baecfSMauro Carvalho Chehab 		// Philips td1316
1568786baecfSMauro Carvalho Chehab 		ttusb->fe = dvb_attach(tda10046_attach, &philips_tdm1316l_config, &ttusb->i2c_adap);
1569786baecfSMauro Carvalho Chehab 		if (ttusb->fe != NULL) {
1570786baecfSMauro Carvalho Chehab 			ttusb->fe->ops.tuner_ops.init = philips_tdm1316l_tuner_init;
1571786baecfSMauro Carvalho Chehab 			ttusb->fe->ops.tuner_ops.set_params = philips_tdm1316l_tuner_set_params;
1572786baecfSMauro Carvalho Chehab 			break;
1573786baecfSMauro Carvalho Chehab 		}
1574786baecfSMauro Carvalho Chehab 		break;
1575786baecfSMauro Carvalho Chehab 	}
1576786baecfSMauro Carvalho Chehab 
1577786baecfSMauro Carvalho Chehab 	if (ttusb->fe == NULL) {
1578*883c84acSMauro Carvalho Chehab 		pr_err("no frontend driver found for device [%04x:%04x]\n",
1579786baecfSMauro Carvalho Chehab 		       le16_to_cpu(ttusb->dev->descriptor.idVendor),
1580786baecfSMauro Carvalho Chehab 		       le16_to_cpu(ttusb->dev->descriptor.idProduct));
1581786baecfSMauro Carvalho Chehab 	} else {
1582786baecfSMauro Carvalho Chehab 		if (dvb_register_frontend(&ttusb->adapter, ttusb->fe)) {
1583*883c84acSMauro Carvalho Chehab 			pr_err("Frontend registration failed!\n");
1584786baecfSMauro Carvalho Chehab 			dvb_frontend_detach(ttusb->fe);
1585786baecfSMauro Carvalho Chehab 			ttusb->fe = NULL;
1586786baecfSMauro Carvalho Chehab 		}
1587786baecfSMauro Carvalho Chehab 	}
1588786baecfSMauro Carvalho Chehab }
1589786baecfSMauro Carvalho Chehab 
1590786baecfSMauro Carvalho Chehab 
1591786baecfSMauro Carvalho Chehab 
15928d08a4c1SGustavo A. R. Silva static const struct i2c_algorithm ttusb_dec_algo = {
1593786baecfSMauro Carvalho Chehab 	.master_xfer	= master_xfer,
1594786baecfSMauro Carvalho Chehab 	.functionality	= functionality,
1595786baecfSMauro Carvalho Chehab };
1596786baecfSMauro Carvalho Chehab 
ttusb_probe(struct usb_interface * intf,const struct usb_device_id * id)1597786baecfSMauro Carvalho Chehab static int ttusb_probe(struct usb_interface *intf, const struct usb_device_id *id)
1598786baecfSMauro Carvalho Chehab {
1599786baecfSMauro Carvalho Chehab 	struct usb_device *udev;
1600786baecfSMauro Carvalho Chehab 	struct ttusb *ttusb;
1601786baecfSMauro Carvalho Chehab 	int result;
1602786baecfSMauro Carvalho Chehab 
1603*883c84acSMauro Carvalho Chehab 	dprintk("TTUSB DVB connected\n");
1604786baecfSMauro Carvalho Chehab 
1605786baecfSMauro Carvalho Chehab 	udev = interface_to_usbdev(intf);
1606786baecfSMauro Carvalho Chehab 
1607786baecfSMauro Carvalho Chehab 	if (intf->altsetting->desc.bInterfaceNumber != 1) return -ENODEV;
1608786baecfSMauro Carvalho Chehab 
1609786baecfSMauro Carvalho Chehab 	if (!(ttusb = kzalloc(sizeof(struct ttusb), GFP_KERNEL)))
1610786baecfSMauro Carvalho Chehab 		return -ENOMEM;
1611786baecfSMauro Carvalho Chehab 
1612786baecfSMauro Carvalho Chehab 	ttusb->dev = udev;
1613786baecfSMauro Carvalho Chehab 	ttusb->c = 0;
1614786baecfSMauro Carvalho Chehab 	ttusb->mux_state = 0;
1615786baecfSMauro Carvalho Chehab 	mutex_init(&ttusb->semi2c);
1616786baecfSMauro Carvalho Chehab 
1617786baecfSMauro Carvalho Chehab 	mutex_lock(&ttusb->semi2c);
1618786baecfSMauro Carvalho Chehab 
1619786baecfSMauro Carvalho Chehab 	mutex_init(&ttusb->semusb);
1620786baecfSMauro Carvalho Chehab 
1621786baecfSMauro Carvalho Chehab 	ttusb_setup_interfaces(ttusb);
1622786baecfSMauro Carvalho Chehab 
1623786baecfSMauro Carvalho Chehab 	result = ttusb_alloc_iso_urbs(ttusb);
1624786baecfSMauro Carvalho Chehab 	if (result < 0) {
1625*883c84acSMauro Carvalho Chehab 		dprintk("ttusb_alloc_iso_urbs - failed\n");
1626786baecfSMauro Carvalho Chehab 		mutex_unlock(&ttusb->semi2c);
1627786baecfSMauro Carvalho Chehab 		kfree(ttusb);
1628786baecfSMauro Carvalho Chehab 		return result;
1629786baecfSMauro Carvalho Chehab 	}
1630786baecfSMauro Carvalho Chehab 
1631786baecfSMauro Carvalho Chehab 	if (ttusb_init_controller(ttusb))
1632*883c84acSMauro Carvalho Chehab 		pr_err("ttusb_init_controller: error\n");
1633786baecfSMauro Carvalho Chehab 
1634786baecfSMauro Carvalho Chehab 	mutex_unlock(&ttusb->semi2c);
1635786baecfSMauro Carvalho Chehab 
1636786baecfSMauro Carvalho Chehab 	result = dvb_register_adapter(&ttusb->adapter,
1637786baecfSMauro Carvalho Chehab 				      "Technotrend/Hauppauge Nova-USB",
1638786baecfSMauro Carvalho Chehab 				      THIS_MODULE, &udev->dev, adapter_nr);
1639786baecfSMauro Carvalho Chehab 	if (result < 0) {
1640786baecfSMauro Carvalho Chehab 		ttusb_free_iso_urbs(ttusb);
1641786baecfSMauro Carvalho Chehab 		kfree(ttusb);
1642786baecfSMauro Carvalho Chehab 		return result;
1643786baecfSMauro Carvalho Chehab 	}
1644786baecfSMauro Carvalho Chehab 	ttusb->adapter.priv = ttusb;
1645786baecfSMauro Carvalho Chehab 
1646786baecfSMauro Carvalho Chehab 	/* i2c */
1647786baecfSMauro Carvalho Chehab 	memset(&ttusb->i2c_adap, 0, sizeof(struct i2c_adapter));
1648cc1e6315SMauro Carvalho Chehab 	strscpy(ttusb->i2c_adap.name, "TTUSB DEC", sizeof(ttusb->i2c_adap.name));
1649786baecfSMauro Carvalho Chehab 
1650786baecfSMauro Carvalho Chehab 	i2c_set_adapdata(&ttusb->i2c_adap, ttusb);
1651786baecfSMauro Carvalho Chehab 
1652786baecfSMauro Carvalho Chehab 	ttusb->i2c_adap.algo              = &ttusb_dec_algo;
1653786baecfSMauro Carvalho Chehab 	ttusb->i2c_adap.algo_data         = NULL;
1654786baecfSMauro Carvalho Chehab 	ttusb->i2c_adap.dev.parent	  = &udev->dev;
1655786baecfSMauro Carvalho Chehab 
1656786baecfSMauro Carvalho Chehab 	result = i2c_add_adapter(&ttusb->i2c_adap);
1657786baecfSMauro Carvalho Chehab 	if (result)
1658786baecfSMauro Carvalho Chehab 		goto err_unregister_adapter;
1659786baecfSMauro Carvalho Chehab 
1660786baecfSMauro Carvalho Chehab 	memset(&ttusb->dvb_demux, 0, sizeof(ttusb->dvb_demux));
1661786baecfSMauro Carvalho Chehab 
1662786baecfSMauro Carvalho Chehab 	ttusb->dvb_demux.dmx.capabilities =
1663786baecfSMauro Carvalho Chehab 	    DMX_TS_FILTERING | DMX_SECTION_FILTERING;
1664786baecfSMauro Carvalho Chehab 	ttusb->dvb_demux.priv = NULL;
1665786baecfSMauro Carvalho Chehab #ifdef TTUSB_HWSECTIONS
1666786baecfSMauro Carvalho Chehab 	ttusb->dvb_demux.filternum = TTUSB_MAXFILTER;
1667786baecfSMauro Carvalho Chehab #else
1668786baecfSMauro Carvalho Chehab 	ttusb->dvb_demux.filternum = 32;
1669786baecfSMauro Carvalho Chehab #endif
1670786baecfSMauro Carvalho Chehab 	ttusb->dvb_demux.feednum = TTUSB_MAXCHANNEL;
1671786baecfSMauro Carvalho Chehab 	ttusb->dvb_demux.start_feed = ttusb_start_feed;
1672786baecfSMauro Carvalho Chehab 	ttusb->dvb_demux.stop_feed = ttusb_stop_feed;
1673786baecfSMauro Carvalho Chehab 	ttusb->dvb_demux.write_to_decoder = NULL;
1674786baecfSMauro Carvalho Chehab 
1675786baecfSMauro Carvalho Chehab 	result = dvb_dmx_init(&ttusb->dvb_demux);
1676786baecfSMauro Carvalho Chehab 	if (result < 0) {
1677*883c84acSMauro Carvalho Chehab 		pr_err("dvb_dmx_init failed (errno = %d)\n", result);
1678786baecfSMauro Carvalho Chehab 		result = -ENODEV;
1679786baecfSMauro Carvalho Chehab 		goto err_i2c_del_adapter;
1680786baecfSMauro Carvalho Chehab 	}
1681786baecfSMauro Carvalho Chehab //FIXME dmxdev (nur WAS?)
1682786baecfSMauro Carvalho Chehab 	ttusb->dmxdev.filternum = ttusb->dvb_demux.filternum;
1683786baecfSMauro Carvalho Chehab 	ttusb->dmxdev.demux = &ttusb->dvb_demux.dmx;
1684786baecfSMauro Carvalho Chehab 	ttusb->dmxdev.capabilities = 0;
1685786baecfSMauro Carvalho Chehab 
1686786baecfSMauro Carvalho Chehab 	result = dvb_dmxdev_init(&ttusb->dmxdev, &ttusb->adapter);
1687786baecfSMauro Carvalho Chehab 	if (result < 0) {
1688*883c84acSMauro Carvalho Chehab 		pr_err("dvb_dmxdev_init failed (errno = %d)\n",
1689786baecfSMauro Carvalho Chehab 		       result);
1690786baecfSMauro Carvalho Chehab 		result = -ENODEV;
1691786baecfSMauro Carvalho Chehab 		goto err_release_dmx;
1692786baecfSMauro Carvalho Chehab 	}
1693786baecfSMauro Carvalho Chehab 
1694786baecfSMauro Carvalho Chehab 	if (dvb_net_init(&ttusb->adapter, &ttusb->dvbnet, &ttusb->dvb_demux.dmx)) {
1695*883c84acSMauro Carvalho Chehab 		pr_err("dvb_net_init failed!\n");
1696786baecfSMauro Carvalho Chehab 		result = -ENODEV;
1697786baecfSMauro Carvalho Chehab 		goto err_release_dmxdev;
1698786baecfSMauro Carvalho Chehab 	}
1699786baecfSMauro Carvalho Chehab 
1700786baecfSMauro Carvalho Chehab 	usb_set_intfdata(intf, (void *) ttusb);
1701786baecfSMauro Carvalho Chehab 
1702786baecfSMauro Carvalho Chehab 	frontend_init(ttusb);
1703786baecfSMauro Carvalho Chehab 
1704786baecfSMauro Carvalho Chehab 	return 0;
1705786baecfSMauro Carvalho Chehab 
1706786baecfSMauro Carvalho Chehab err_release_dmxdev:
1707786baecfSMauro Carvalho Chehab 	dvb_dmxdev_release(&ttusb->dmxdev);
1708786baecfSMauro Carvalho Chehab err_release_dmx:
1709786baecfSMauro Carvalho Chehab 	dvb_dmx_release(&ttusb->dvb_demux);
1710786baecfSMauro Carvalho Chehab err_i2c_del_adapter:
1711786baecfSMauro Carvalho Chehab 	i2c_del_adapter(&ttusb->i2c_adap);
1712786baecfSMauro Carvalho Chehab err_unregister_adapter:
1713786baecfSMauro Carvalho Chehab 	dvb_unregister_adapter (&ttusb->adapter);
1714b9d4b2daSAlexey Khoroshilov 	ttusb_free_iso_urbs(ttusb);
1715b9d4b2daSAlexey Khoroshilov 	kfree(ttusb);
1716786baecfSMauro Carvalho Chehab 	return result;
1717786baecfSMauro Carvalho Chehab }
1718786baecfSMauro Carvalho Chehab 
ttusb_disconnect(struct usb_interface * intf)1719786baecfSMauro Carvalho Chehab static void ttusb_disconnect(struct usb_interface *intf)
1720786baecfSMauro Carvalho Chehab {
1721786baecfSMauro Carvalho Chehab 	struct ttusb *ttusb = usb_get_intfdata(intf);
1722786baecfSMauro Carvalho Chehab 
1723786baecfSMauro Carvalho Chehab 	usb_set_intfdata(intf, NULL);
1724786baecfSMauro Carvalho Chehab 
1725786baecfSMauro Carvalho Chehab 	ttusb->disconnecting = 1;
1726786baecfSMauro Carvalho Chehab 
1727786baecfSMauro Carvalho Chehab 	ttusb_stop_iso_xfer(ttusb);
1728786baecfSMauro Carvalho Chehab 
1729786baecfSMauro Carvalho Chehab 	ttusb->dvb_demux.dmx.close(&ttusb->dvb_demux.dmx);
1730786baecfSMauro Carvalho Chehab 	dvb_net_release(&ttusb->dvbnet);
1731786baecfSMauro Carvalho Chehab 	dvb_dmxdev_release(&ttusb->dmxdev);
1732786baecfSMauro Carvalho Chehab 	dvb_dmx_release(&ttusb->dvb_demux);
1733786baecfSMauro Carvalho Chehab 	if (ttusb->fe != NULL) {
1734786baecfSMauro Carvalho Chehab 		dvb_unregister_frontend(ttusb->fe);
1735786baecfSMauro Carvalho Chehab 		dvb_frontend_detach(ttusb->fe);
1736786baecfSMauro Carvalho Chehab 	}
1737786baecfSMauro Carvalho Chehab 	i2c_del_adapter(&ttusb->i2c_adap);
1738786baecfSMauro Carvalho Chehab 	dvb_unregister_adapter(&ttusb->adapter);
1739786baecfSMauro Carvalho Chehab 
1740786baecfSMauro Carvalho Chehab 	ttusb_free_iso_urbs(ttusb);
1741786baecfSMauro Carvalho Chehab 
1742786baecfSMauro Carvalho Chehab 	kfree(ttusb);
1743786baecfSMauro Carvalho Chehab 
1744*883c84acSMauro Carvalho Chehab 	dprintk("TTUSB DVB disconnected\n");
1745786baecfSMauro Carvalho Chehab }
1746786baecfSMauro Carvalho Chehab 
17477fb2e072SArvind Yadav static const struct usb_device_id ttusb_table[] = {
1748786baecfSMauro Carvalho Chehab 	{USB_DEVICE(0xb48, 0x1003)},
1749786baecfSMauro Carvalho Chehab 	{USB_DEVICE(0xb48, 0x1004)},
1750786baecfSMauro Carvalho Chehab 	{USB_DEVICE(0xb48, 0x1005)},
1751786baecfSMauro Carvalho Chehab 	{}
1752786baecfSMauro Carvalho Chehab };
1753786baecfSMauro Carvalho Chehab 
1754786baecfSMauro Carvalho Chehab MODULE_DEVICE_TABLE(usb, ttusb_table);
1755786baecfSMauro Carvalho Chehab 
1756786baecfSMauro Carvalho Chehab static struct usb_driver ttusb_driver = {
1757786baecfSMauro Carvalho Chehab       .name		= "ttusb",
1758786baecfSMauro Carvalho Chehab       .probe		= ttusb_probe,
1759786baecfSMauro Carvalho Chehab       .disconnect	= ttusb_disconnect,
1760786baecfSMauro Carvalho Chehab       .id_table		= ttusb_table,
1761786baecfSMauro Carvalho Chehab };
1762786baecfSMauro Carvalho Chehab 
1763786baecfSMauro Carvalho Chehab module_usb_driver(ttusb_driver);
1764786baecfSMauro Carvalho Chehab 
1765786baecfSMauro Carvalho Chehab MODULE_AUTHOR("Holger Waechtler <holger@convergence.de>");
1766786baecfSMauro Carvalho Chehab MODULE_DESCRIPTION("TTUSB DVB Driver");
1767786baecfSMauro Carvalho Chehab MODULE_LICENSE("GPL");
1768786baecfSMauro Carvalho Chehab MODULE_FIRMWARE("ttusb-budget/dspbootcode.bin");
1769