1786baecfSMauro Carvalho Chehab /*
2786baecfSMauro Carvalho Chehab  * TTUSB DEC Driver
3786baecfSMauro Carvalho Chehab  *
4786baecfSMauro Carvalho Chehab  * Copyright (C) 2003-2004 Alex Woods <linux-dvb@giblets.org>
5786baecfSMauro Carvalho Chehab  * IR support by Peter Beutner <p.beutner@gmx.net>
6786baecfSMauro Carvalho Chehab  *
7786baecfSMauro Carvalho Chehab  * This program is free software; you can redistribute it and/or modify
8786baecfSMauro Carvalho Chehab  * it under the terms of the GNU General Public License as published by
9786baecfSMauro Carvalho Chehab  * the Free Software Foundation; either version 2 of the License, or
10786baecfSMauro Carvalho Chehab  * (at your option) any later version.
11786baecfSMauro Carvalho Chehab  *
12786baecfSMauro Carvalho Chehab  * This program is distributed in the hope that it will be useful,
13786baecfSMauro Carvalho Chehab  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14786baecfSMauro Carvalho Chehab  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15786baecfSMauro Carvalho Chehab  * GNU General Public License for more details.
16786baecfSMauro Carvalho Chehab  *
17786baecfSMauro Carvalho Chehab  * You should have received a copy of the GNU General Public License
18786baecfSMauro Carvalho Chehab  * along with this program; if not, write to the Free Software
19786baecfSMauro Carvalho Chehab  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20786baecfSMauro Carvalho Chehab  *
21786baecfSMauro Carvalho Chehab  */
22786baecfSMauro Carvalho Chehab 
23786baecfSMauro Carvalho Chehab #include <linux/list.h>
24786baecfSMauro Carvalho Chehab #include <linux/module.h>
25786baecfSMauro Carvalho Chehab #include <linux/pci.h>
26786baecfSMauro Carvalho Chehab #include <linux/slab.h>
27786baecfSMauro Carvalho Chehab #include <linux/spinlock.h>
28786baecfSMauro Carvalho Chehab #include <linux/usb.h>
29786baecfSMauro Carvalho Chehab #include <linux/interrupt.h>
30786baecfSMauro Carvalho Chehab #include <linux/firmware.h>
31786baecfSMauro Carvalho Chehab #include <linux/crc32.h>
32786baecfSMauro Carvalho Chehab #include <linux/init.h>
33786baecfSMauro Carvalho Chehab #include <linux/input.h>
34786baecfSMauro Carvalho Chehab 
35786baecfSMauro Carvalho Chehab #include <linux/mutex.h>
36786baecfSMauro Carvalho Chehab 
37786baecfSMauro Carvalho Chehab #include "dmxdev.h"
38786baecfSMauro Carvalho Chehab #include "dvb_demux.h"
39786baecfSMauro Carvalho Chehab #include "dvb_filter.h"
40786baecfSMauro Carvalho Chehab #include "dvb_frontend.h"
41786baecfSMauro Carvalho Chehab #include "dvb_net.h"
42786baecfSMauro Carvalho Chehab #include "ttusbdecfe.h"
43786baecfSMauro Carvalho Chehab 
44786baecfSMauro Carvalho Chehab static int debug;
45786baecfSMauro Carvalho Chehab static int output_pva;
46786baecfSMauro Carvalho Chehab static int enable_rc;
47786baecfSMauro Carvalho Chehab 
48786baecfSMauro Carvalho Chehab module_param(debug, int, 0644);
49786baecfSMauro Carvalho Chehab MODULE_PARM_DESC(debug, "Turn on/off debugging (default:off).");
50786baecfSMauro Carvalho Chehab module_param(output_pva, int, 0444);
51786baecfSMauro Carvalho Chehab MODULE_PARM_DESC(output_pva, "Output PVA from dvr device (default:off)");
52786baecfSMauro Carvalho Chehab module_param(enable_rc, int, 0644);
53786baecfSMauro Carvalho Chehab MODULE_PARM_DESC(enable_rc, "Turn on/off IR remote control(default: off)");
54786baecfSMauro Carvalho Chehab 
55786baecfSMauro Carvalho Chehab DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
56786baecfSMauro Carvalho Chehab 
57786baecfSMauro Carvalho Chehab #define dprintk	if (debug) printk
58786baecfSMauro Carvalho Chehab 
59786baecfSMauro Carvalho Chehab #define DRIVER_NAME		"TechnoTrend/Hauppauge DEC USB"
60786baecfSMauro Carvalho Chehab 
61786baecfSMauro Carvalho Chehab #define COMMAND_PIPE		0x03
62786baecfSMauro Carvalho Chehab #define RESULT_PIPE		0x04
63786baecfSMauro Carvalho Chehab #define IN_PIPE			0x08
64786baecfSMauro Carvalho Chehab #define OUT_PIPE		0x07
65786baecfSMauro Carvalho Chehab #define IRQ_PIPE		0x0A
66786baecfSMauro Carvalho Chehab 
67786baecfSMauro Carvalho Chehab #define COMMAND_PACKET_SIZE	0x3c
68786baecfSMauro Carvalho Chehab #define ARM_PACKET_SIZE		0x1000
69786baecfSMauro Carvalho Chehab #define IRQ_PACKET_SIZE		0x8
70786baecfSMauro Carvalho Chehab 
71786baecfSMauro Carvalho Chehab #define ISO_BUF_COUNT		0x04
72786baecfSMauro Carvalho Chehab #define FRAMES_PER_ISO_BUF	0x04
73786baecfSMauro Carvalho Chehab #define ISO_FRAME_SIZE		0x0380
74786baecfSMauro Carvalho Chehab 
75786baecfSMauro Carvalho Chehab #define	MAX_PVA_LENGTH		6144
76786baecfSMauro Carvalho Chehab 
77786baecfSMauro Carvalho Chehab enum ttusb_dec_model {
78786baecfSMauro Carvalho Chehab 	TTUSB_DEC2000T,
79786baecfSMauro Carvalho Chehab 	TTUSB_DEC2540T,
80786baecfSMauro Carvalho Chehab 	TTUSB_DEC3000S
81786baecfSMauro Carvalho Chehab };
82786baecfSMauro Carvalho Chehab 
83786baecfSMauro Carvalho Chehab enum ttusb_dec_packet_type {
84786baecfSMauro Carvalho Chehab 	TTUSB_DEC_PACKET_PVA,
85786baecfSMauro Carvalho Chehab 	TTUSB_DEC_PACKET_SECTION,
86786baecfSMauro Carvalho Chehab 	TTUSB_DEC_PACKET_EMPTY
87786baecfSMauro Carvalho Chehab };
88786baecfSMauro Carvalho Chehab 
89786baecfSMauro Carvalho Chehab enum ttusb_dec_interface {
90786baecfSMauro Carvalho Chehab 	TTUSB_DEC_INTERFACE_INITIAL,
91786baecfSMauro Carvalho Chehab 	TTUSB_DEC_INTERFACE_IN,
92786baecfSMauro Carvalho Chehab 	TTUSB_DEC_INTERFACE_OUT
93786baecfSMauro Carvalho Chehab };
94786baecfSMauro Carvalho Chehab 
95786baecfSMauro Carvalho Chehab struct ttusb_dec {
96786baecfSMauro Carvalho Chehab 	enum ttusb_dec_model		model;
97786baecfSMauro Carvalho Chehab 	char				*model_name;
98786baecfSMauro Carvalho Chehab 	char				*firmware_name;
99786baecfSMauro Carvalho Chehab 	int				can_playback;
100786baecfSMauro Carvalho Chehab 
101786baecfSMauro Carvalho Chehab 	/* DVB bits */
102786baecfSMauro Carvalho Chehab 	struct dvb_adapter		adapter;
103786baecfSMauro Carvalho Chehab 	struct dmxdev			dmxdev;
104786baecfSMauro Carvalho Chehab 	struct dvb_demux		demux;
105786baecfSMauro Carvalho Chehab 	struct dmx_frontend		frontend;
106786baecfSMauro Carvalho Chehab 	struct dvb_net			dvb_net;
107786baecfSMauro Carvalho Chehab 	struct dvb_frontend*		fe;
108786baecfSMauro Carvalho Chehab 
109786baecfSMauro Carvalho Chehab 	u16			pid[DMX_PES_OTHER];
110786baecfSMauro Carvalho Chehab 
111786baecfSMauro Carvalho Chehab 	/* USB bits */
112786baecfSMauro Carvalho Chehab 	struct usb_device		*udev;
113786baecfSMauro Carvalho Chehab 	u8				trans_count;
114786baecfSMauro Carvalho Chehab 	unsigned int			command_pipe;
115786baecfSMauro Carvalho Chehab 	unsigned int			result_pipe;
116786baecfSMauro Carvalho Chehab 	unsigned int			in_pipe;
117786baecfSMauro Carvalho Chehab 	unsigned int			out_pipe;
118786baecfSMauro Carvalho Chehab 	unsigned int			irq_pipe;
119786baecfSMauro Carvalho Chehab 	enum ttusb_dec_interface	interface;
120786baecfSMauro Carvalho Chehab 	struct mutex			usb_mutex;
121786baecfSMauro Carvalho Chehab 
122786baecfSMauro Carvalho Chehab 	void			*irq_buffer;
123786baecfSMauro Carvalho Chehab 	struct urb		*irq_urb;
124786baecfSMauro Carvalho Chehab 	dma_addr_t		irq_dma_handle;
125786baecfSMauro Carvalho Chehab 	void			*iso_buffer;
126786baecfSMauro Carvalho Chehab 	dma_addr_t		iso_dma_handle;
127786baecfSMauro Carvalho Chehab 	struct urb		*iso_urb[ISO_BUF_COUNT];
128786baecfSMauro Carvalho Chehab 	int			iso_stream_count;
129786baecfSMauro Carvalho Chehab 	struct mutex		iso_mutex;
130786baecfSMauro Carvalho Chehab 
131786baecfSMauro Carvalho Chehab 	u8				packet[MAX_PVA_LENGTH + 4];
132786baecfSMauro Carvalho Chehab 	enum ttusb_dec_packet_type	packet_type;
133786baecfSMauro Carvalho Chehab 	int				packet_state;
134786baecfSMauro Carvalho Chehab 	int				packet_length;
135786baecfSMauro Carvalho Chehab 	int				packet_payload_length;
136786baecfSMauro Carvalho Chehab 	u16				next_packet_id;
137786baecfSMauro Carvalho Chehab 
138786baecfSMauro Carvalho Chehab 	int				pva_stream_count;
139786baecfSMauro Carvalho Chehab 	int				filter_stream_count;
140786baecfSMauro Carvalho Chehab 
141786baecfSMauro Carvalho Chehab 	struct dvb_filter_pes2ts	a_pes2ts;
142786baecfSMauro Carvalho Chehab 	struct dvb_filter_pes2ts	v_pes2ts;
143786baecfSMauro Carvalho Chehab 
144786baecfSMauro Carvalho Chehab 	u8			v_pes[16 + MAX_PVA_LENGTH];
145786baecfSMauro Carvalho Chehab 	int			v_pes_length;
146786baecfSMauro Carvalho Chehab 	int			v_pes_postbytes;
147786baecfSMauro Carvalho Chehab 
148786baecfSMauro Carvalho Chehab 	struct list_head	urb_frame_list;
149786baecfSMauro Carvalho Chehab 	struct tasklet_struct	urb_tasklet;
150786baecfSMauro Carvalho Chehab 	spinlock_t		urb_frame_list_lock;
151786baecfSMauro Carvalho Chehab 
152786baecfSMauro Carvalho Chehab 	struct dvb_demux_filter	*audio_filter;
153786baecfSMauro Carvalho Chehab 	struct dvb_demux_filter	*video_filter;
154786baecfSMauro Carvalho Chehab 	struct list_head	filter_info_list;
155786baecfSMauro Carvalho Chehab 	spinlock_t		filter_info_list_lock;
156786baecfSMauro Carvalho Chehab 
157786baecfSMauro Carvalho Chehab 	struct input_dev	*rc_input_dev;
158786baecfSMauro Carvalho Chehab 	char			rc_phys[64];
159786baecfSMauro Carvalho Chehab 
160786baecfSMauro Carvalho Chehab 	int			active; /* Loaded successfully */
161786baecfSMauro Carvalho Chehab };
162786baecfSMauro Carvalho Chehab 
163786baecfSMauro Carvalho Chehab struct urb_frame {
164786baecfSMauro Carvalho Chehab 	u8			data[ISO_FRAME_SIZE];
165786baecfSMauro Carvalho Chehab 	int			length;
166786baecfSMauro Carvalho Chehab 	struct list_head	urb_frame_list;
167786baecfSMauro Carvalho Chehab };
168786baecfSMauro Carvalho Chehab 
169786baecfSMauro Carvalho Chehab struct filter_info {
170786baecfSMauro Carvalho Chehab 	u8			stream_id;
171786baecfSMauro Carvalho Chehab 	struct dvb_demux_filter	*filter;
172786baecfSMauro Carvalho Chehab 	struct list_head	filter_info_list;
173786baecfSMauro Carvalho Chehab };
174786baecfSMauro Carvalho Chehab 
175786baecfSMauro Carvalho Chehab static u16 rc_keys[] = {
176786baecfSMauro Carvalho Chehab 	KEY_POWER,
177786baecfSMauro Carvalho Chehab 	KEY_MUTE,
178786baecfSMauro Carvalho Chehab 	KEY_1,
179786baecfSMauro Carvalho Chehab 	KEY_2,
180786baecfSMauro Carvalho Chehab 	KEY_3,
181786baecfSMauro Carvalho Chehab 	KEY_4,
182786baecfSMauro Carvalho Chehab 	KEY_5,
183786baecfSMauro Carvalho Chehab 	KEY_6,
184786baecfSMauro Carvalho Chehab 	KEY_7,
185786baecfSMauro Carvalho Chehab 	KEY_8,
186786baecfSMauro Carvalho Chehab 	KEY_9,
187786baecfSMauro Carvalho Chehab 	KEY_0,
188786baecfSMauro Carvalho Chehab 	KEY_CHANNELUP,
189786baecfSMauro Carvalho Chehab 	KEY_VOLUMEDOWN,
190786baecfSMauro Carvalho Chehab 	KEY_OK,
191786baecfSMauro Carvalho Chehab 	KEY_VOLUMEUP,
192786baecfSMauro Carvalho Chehab 	KEY_CHANNELDOWN,
193786baecfSMauro Carvalho Chehab 	KEY_PREVIOUS,
194786baecfSMauro Carvalho Chehab 	KEY_ESC,
195786baecfSMauro Carvalho Chehab 	KEY_RED,
196786baecfSMauro Carvalho Chehab 	KEY_GREEN,
197786baecfSMauro Carvalho Chehab 	KEY_YELLOW,
198786baecfSMauro Carvalho Chehab 	KEY_BLUE,
199786baecfSMauro Carvalho Chehab 	KEY_OPTION,
200786baecfSMauro Carvalho Chehab 	KEY_M,
201786baecfSMauro Carvalho Chehab 	KEY_RADIO
202786baecfSMauro Carvalho Chehab };
203786baecfSMauro Carvalho Chehab 
204786baecfSMauro Carvalho Chehab static void ttusb_dec_set_model(struct ttusb_dec *dec,
205786baecfSMauro Carvalho Chehab 				enum ttusb_dec_model model);
206786baecfSMauro Carvalho Chehab 
207786baecfSMauro Carvalho Chehab static void ttusb_dec_handle_irq( struct urb *urb)
208786baecfSMauro Carvalho Chehab {
209786baecfSMauro Carvalho Chehab 	struct ttusb_dec * dec = urb->context;
210786baecfSMauro Carvalho Chehab 	char *buffer = dec->irq_buffer;
211786baecfSMauro Carvalho Chehab 	int retval;
212786baecfSMauro Carvalho Chehab 
213786baecfSMauro Carvalho Chehab 	switch(urb->status) {
214786baecfSMauro Carvalho Chehab 		case 0: /*success*/
215786baecfSMauro Carvalho Chehab 			break;
216786baecfSMauro Carvalho Chehab 		case -ECONNRESET:
217786baecfSMauro Carvalho Chehab 		case -ENOENT:
218786baecfSMauro Carvalho Chehab 		case -ESHUTDOWN:
219786baecfSMauro Carvalho Chehab 		case -ETIME:
220786baecfSMauro Carvalho Chehab 			/* this urb is dead, cleanup */
221786baecfSMauro Carvalho Chehab 			dprintk("%s:urb shutting down with status: %d\n",
222786baecfSMauro Carvalho Chehab 					__func__, urb->status);
223786baecfSMauro Carvalho Chehab 			return;
224786baecfSMauro Carvalho Chehab 		default:
225786baecfSMauro Carvalho Chehab 			dprintk("%s:nonzero status received: %d\n",
226786baecfSMauro Carvalho Chehab 					__func__,urb->status);
227786baecfSMauro Carvalho Chehab 			goto exit;
228786baecfSMauro Carvalho Chehab 	}
229786baecfSMauro Carvalho Chehab 
230786baecfSMauro Carvalho Chehab 	if( (buffer[0] == 0x1) && (buffer[2] == 0x15) )  {
231786baecfSMauro Carvalho Chehab 		/* IR - Event */
232786baecfSMauro Carvalho Chehab 		/* this is an fact a bit too simple implementation;
233786baecfSMauro Carvalho Chehab 		 * the box also reports a keyrepeat signal
234786baecfSMauro Carvalho Chehab 		 * (with buffer[3] == 0x40) in an intervall of ~100ms.
235786baecfSMauro Carvalho Chehab 		 * But to handle this correctly we had to imlemenent some
236786baecfSMauro Carvalho Chehab 		 * kind of timer which signals a 'key up' event if no
237786baecfSMauro Carvalho Chehab 		 * keyrepeat signal is received for lets say 200ms.
238786baecfSMauro Carvalho Chehab 		 * this should/could be added later ...
239786baecfSMauro Carvalho Chehab 		 * for now lets report each signal as a key down and up*/
240786baecfSMauro Carvalho Chehab 		dprintk("%s:rc signal:%d\n", __func__, buffer[4]);
241786baecfSMauro Carvalho Chehab 		input_report_key(dec->rc_input_dev, rc_keys[buffer[4] - 1], 1);
242786baecfSMauro Carvalho Chehab 		input_sync(dec->rc_input_dev);
243786baecfSMauro Carvalho Chehab 		input_report_key(dec->rc_input_dev, rc_keys[buffer[4] - 1], 0);
244786baecfSMauro Carvalho Chehab 		input_sync(dec->rc_input_dev);
245786baecfSMauro Carvalho Chehab 	}
246786baecfSMauro Carvalho Chehab 
247786baecfSMauro Carvalho Chehab exit:	retval = usb_submit_urb(urb, GFP_ATOMIC);
248786baecfSMauro Carvalho Chehab 	if(retval)
249786baecfSMauro Carvalho Chehab 		printk("%s - usb_commit_urb failed with result: %d\n",
250786baecfSMauro Carvalho Chehab 			__func__, retval);
251786baecfSMauro Carvalho Chehab }
252786baecfSMauro Carvalho Chehab 
253786baecfSMauro Carvalho Chehab static u16 crc16(u16 crc, const u8 *buf, size_t len)
254786baecfSMauro Carvalho Chehab {
255786baecfSMauro Carvalho Chehab 	u16 tmp;
256786baecfSMauro Carvalho Chehab 
257786baecfSMauro Carvalho Chehab 	while (len--) {
258786baecfSMauro Carvalho Chehab 		crc ^= *buf++;
259786baecfSMauro Carvalho Chehab 		crc ^= (u8)crc >> 4;
260786baecfSMauro Carvalho Chehab 		tmp = (u8)crc;
261786baecfSMauro Carvalho Chehab 		crc ^= (tmp ^ (tmp << 1)) << 4;
262786baecfSMauro Carvalho Chehab 	}
263786baecfSMauro Carvalho Chehab 	return crc;
264786baecfSMauro Carvalho Chehab }
265786baecfSMauro Carvalho Chehab 
266786baecfSMauro Carvalho Chehab static int ttusb_dec_send_command(struct ttusb_dec *dec, const u8 command,
267786baecfSMauro Carvalho Chehab 				  int param_length, const u8 params[],
268786baecfSMauro Carvalho Chehab 				  int *result_length, u8 cmd_result[])
269786baecfSMauro Carvalho Chehab {
270786baecfSMauro Carvalho Chehab 	int result, actual_len, i;
271786baecfSMauro Carvalho Chehab 	u8 *b;
272786baecfSMauro Carvalho Chehab 
273786baecfSMauro Carvalho Chehab 	dprintk("%s\n", __func__);
274786baecfSMauro Carvalho Chehab 
275786baecfSMauro Carvalho Chehab 	b = kmalloc(COMMAND_PACKET_SIZE + 4, GFP_KERNEL);
276786baecfSMauro Carvalho Chehab 	if (!b)
277786baecfSMauro Carvalho Chehab 		return -ENOMEM;
278786baecfSMauro Carvalho Chehab 
279786baecfSMauro Carvalho Chehab 	if ((result = mutex_lock_interruptible(&dec->usb_mutex))) {
280786baecfSMauro Carvalho Chehab 		kfree(b);
281786baecfSMauro Carvalho Chehab 		printk("%s: Failed to lock usb mutex.\n", __func__);
282786baecfSMauro Carvalho Chehab 		return result;
283786baecfSMauro Carvalho Chehab 	}
284786baecfSMauro Carvalho Chehab 
285786baecfSMauro Carvalho Chehab 	b[0] = 0xaa;
286786baecfSMauro Carvalho Chehab 	b[1] = ++dec->trans_count;
287786baecfSMauro Carvalho Chehab 	b[2] = command;
288786baecfSMauro Carvalho Chehab 	b[3] = param_length;
289786baecfSMauro Carvalho Chehab 
290786baecfSMauro Carvalho Chehab 	if (params)
291786baecfSMauro Carvalho Chehab 		memcpy(&b[4], params, param_length);
292786baecfSMauro Carvalho Chehab 
293786baecfSMauro Carvalho Chehab 	if (debug) {
294786baecfSMauro Carvalho Chehab 		printk("%s: command: ", __func__);
295786baecfSMauro Carvalho Chehab 		for (i = 0; i < param_length + 4; i++)
296786baecfSMauro Carvalho Chehab 			printk("0x%02X ", b[i]);
297786baecfSMauro Carvalho Chehab 		printk("\n");
298786baecfSMauro Carvalho Chehab 	}
299786baecfSMauro Carvalho Chehab 
300786baecfSMauro Carvalho Chehab 	result = usb_bulk_msg(dec->udev, dec->command_pipe, b,
301786baecfSMauro Carvalho Chehab 			      COMMAND_PACKET_SIZE + 4, &actual_len, 1000);
302786baecfSMauro Carvalho Chehab 
303786baecfSMauro Carvalho Chehab 	if (result) {
304786baecfSMauro Carvalho Chehab 		printk("%s: command bulk message failed: error %d\n",
305786baecfSMauro Carvalho Chehab 		       __func__, result);
306786baecfSMauro Carvalho Chehab 		mutex_unlock(&dec->usb_mutex);
307786baecfSMauro Carvalho Chehab 		kfree(b);
308786baecfSMauro Carvalho Chehab 		return result;
309786baecfSMauro Carvalho Chehab 	}
310786baecfSMauro Carvalho Chehab 
311786baecfSMauro Carvalho Chehab 	result = usb_bulk_msg(dec->udev, dec->result_pipe, b,
312786baecfSMauro Carvalho Chehab 			      COMMAND_PACKET_SIZE + 4, &actual_len, 1000);
313786baecfSMauro Carvalho Chehab 
314786baecfSMauro Carvalho Chehab 	if (result) {
315786baecfSMauro Carvalho Chehab 		printk("%s: result bulk message failed: error %d\n",
316786baecfSMauro Carvalho Chehab 		       __func__, result);
317786baecfSMauro Carvalho Chehab 		mutex_unlock(&dec->usb_mutex);
318786baecfSMauro Carvalho Chehab 		kfree(b);
319786baecfSMauro Carvalho Chehab 		return result;
320786baecfSMauro Carvalho Chehab 	} else {
321786baecfSMauro Carvalho Chehab 		if (debug) {
322786baecfSMauro Carvalho Chehab 			printk("%s: result: ", __func__);
323786baecfSMauro Carvalho Chehab 			for (i = 0; i < actual_len; i++)
324786baecfSMauro Carvalho Chehab 				printk("0x%02X ", b[i]);
325786baecfSMauro Carvalho Chehab 			printk("\n");
326786baecfSMauro Carvalho Chehab 		}
327786baecfSMauro Carvalho Chehab 
328786baecfSMauro Carvalho Chehab 		if (result_length)
329786baecfSMauro Carvalho Chehab 			*result_length = b[3];
330786baecfSMauro Carvalho Chehab 		if (cmd_result && b[3] > 0)
331786baecfSMauro Carvalho Chehab 			memcpy(cmd_result, &b[4], b[3]);
332786baecfSMauro Carvalho Chehab 
333786baecfSMauro Carvalho Chehab 		mutex_unlock(&dec->usb_mutex);
334786baecfSMauro Carvalho Chehab 
335786baecfSMauro Carvalho Chehab 		kfree(b);
336786baecfSMauro Carvalho Chehab 		return 0;
337786baecfSMauro Carvalho Chehab 	}
338786baecfSMauro Carvalho Chehab }
339786baecfSMauro Carvalho Chehab 
340786baecfSMauro Carvalho Chehab static int ttusb_dec_get_stb_state (struct ttusb_dec *dec, unsigned int *mode,
341786baecfSMauro Carvalho Chehab 				    unsigned int *model, unsigned int *version)
342786baecfSMauro Carvalho Chehab {
343786baecfSMauro Carvalho Chehab 	u8 c[COMMAND_PACKET_SIZE];
344786baecfSMauro Carvalho Chehab 	int c_length;
345786baecfSMauro Carvalho Chehab 	int result;
346786baecfSMauro Carvalho Chehab 	__be32 tmp;
347786baecfSMauro Carvalho Chehab 
348786baecfSMauro Carvalho Chehab 	dprintk("%s\n", __func__);
349786baecfSMauro Carvalho Chehab 
350786baecfSMauro Carvalho Chehab 	result = ttusb_dec_send_command(dec, 0x08, 0, NULL, &c_length, c);
351786baecfSMauro Carvalho Chehab 	if (result)
352786baecfSMauro Carvalho Chehab 		return result;
353786baecfSMauro Carvalho Chehab 
354786baecfSMauro Carvalho Chehab 	if (c_length >= 0x0c) {
355786baecfSMauro Carvalho Chehab 		if (mode != NULL) {
356786baecfSMauro Carvalho Chehab 			memcpy(&tmp, c, 4);
357786baecfSMauro Carvalho Chehab 			*mode = ntohl(tmp);
358786baecfSMauro Carvalho Chehab 		}
359786baecfSMauro Carvalho Chehab 		if (model != NULL) {
360786baecfSMauro Carvalho Chehab 			memcpy(&tmp, &c[4], 4);
361786baecfSMauro Carvalho Chehab 			*model = ntohl(tmp);
362786baecfSMauro Carvalho Chehab 		}
363786baecfSMauro Carvalho Chehab 		if (version != NULL) {
364786baecfSMauro Carvalho Chehab 			memcpy(&tmp, &c[8], 4);
365786baecfSMauro Carvalho Chehab 			*version = ntohl(tmp);
366786baecfSMauro Carvalho Chehab 		}
367786baecfSMauro Carvalho Chehab 		return 0;
368786baecfSMauro Carvalho Chehab 	} else {
369cf732b5fSAlexey Khoroshilov 		return -ENOENT;
370786baecfSMauro Carvalho Chehab 	}
371786baecfSMauro Carvalho Chehab }
372786baecfSMauro Carvalho Chehab 
373786baecfSMauro Carvalho Chehab static int ttusb_dec_audio_pes2ts_cb(void *priv, unsigned char *data)
374786baecfSMauro Carvalho Chehab {
375786baecfSMauro Carvalho Chehab 	struct ttusb_dec *dec = priv;
376786baecfSMauro Carvalho Chehab 
377786baecfSMauro Carvalho Chehab 	dec->audio_filter->feed->cb.ts(data, 188, NULL, 0,
378786baecfSMauro Carvalho Chehab 				       &dec->audio_filter->feed->feed.ts,
379786baecfSMauro Carvalho Chehab 				       DMX_OK);
380786baecfSMauro Carvalho Chehab 
381786baecfSMauro Carvalho Chehab 	return 0;
382786baecfSMauro Carvalho Chehab }
383786baecfSMauro Carvalho Chehab 
384786baecfSMauro Carvalho Chehab static int ttusb_dec_video_pes2ts_cb(void *priv, unsigned char *data)
385786baecfSMauro Carvalho Chehab {
386786baecfSMauro Carvalho Chehab 	struct ttusb_dec *dec = priv;
387786baecfSMauro Carvalho Chehab 
388786baecfSMauro Carvalho Chehab 	dec->video_filter->feed->cb.ts(data, 188, NULL, 0,
389786baecfSMauro Carvalho Chehab 				       &dec->video_filter->feed->feed.ts,
390786baecfSMauro Carvalho Chehab 				       DMX_OK);
391786baecfSMauro Carvalho Chehab 
392786baecfSMauro Carvalho Chehab 	return 0;
393786baecfSMauro Carvalho Chehab }
394786baecfSMauro Carvalho Chehab 
395786baecfSMauro Carvalho Chehab static void ttusb_dec_set_pids(struct ttusb_dec *dec)
396786baecfSMauro Carvalho Chehab {
397786baecfSMauro Carvalho Chehab 	u8 b[] = { 0x00, 0x00, 0x00, 0x00,
398786baecfSMauro Carvalho Chehab 		   0x00, 0x00, 0xff, 0xff,
399786baecfSMauro Carvalho Chehab 		   0xff, 0xff, 0xff, 0xff };
400786baecfSMauro Carvalho Chehab 
401786baecfSMauro Carvalho Chehab 	__be16 pcr = htons(dec->pid[DMX_PES_PCR]);
402786baecfSMauro Carvalho Chehab 	__be16 audio = htons(dec->pid[DMX_PES_AUDIO]);
403786baecfSMauro Carvalho Chehab 	__be16 video = htons(dec->pid[DMX_PES_VIDEO]);
404786baecfSMauro Carvalho Chehab 
405786baecfSMauro Carvalho Chehab 	dprintk("%s\n", __func__);
406786baecfSMauro Carvalho Chehab 
407786baecfSMauro Carvalho Chehab 	memcpy(&b[0], &pcr, 2);
408786baecfSMauro Carvalho Chehab 	memcpy(&b[2], &audio, 2);
409786baecfSMauro Carvalho Chehab 	memcpy(&b[4], &video, 2);
410786baecfSMauro Carvalho Chehab 
411786baecfSMauro Carvalho Chehab 	ttusb_dec_send_command(dec, 0x50, sizeof(b), b, NULL, NULL);
412786baecfSMauro Carvalho Chehab 
413786baecfSMauro Carvalho Chehab 	dvb_filter_pes2ts_init(&dec->a_pes2ts, dec->pid[DMX_PES_AUDIO],
414786baecfSMauro Carvalho Chehab 			       ttusb_dec_audio_pes2ts_cb, dec);
415786baecfSMauro Carvalho Chehab 	dvb_filter_pes2ts_init(&dec->v_pes2ts, dec->pid[DMX_PES_VIDEO],
416786baecfSMauro Carvalho Chehab 			       ttusb_dec_video_pes2ts_cb, dec);
417786baecfSMauro Carvalho Chehab 	dec->v_pes_length = 0;
418786baecfSMauro Carvalho Chehab 	dec->v_pes_postbytes = 0;
419786baecfSMauro Carvalho Chehab }
420786baecfSMauro Carvalho Chehab 
421786baecfSMauro Carvalho Chehab static void ttusb_dec_process_pva(struct ttusb_dec *dec, u8 *pva, int length)
422786baecfSMauro Carvalho Chehab {
423786baecfSMauro Carvalho Chehab 	if (length < 8) {
424786baecfSMauro Carvalho Chehab 		printk("%s: packet too short - discarding\n", __func__);
425786baecfSMauro Carvalho Chehab 		return;
426786baecfSMauro Carvalho Chehab 	}
427786baecfSMauro Carvalho Chehab 
428786baecfSMauro Carvalho Chehab 	if (length > 8 + MAX_PVA_LENGTH) {
429786baecfSMauro Carvalho Chehab 		printk("%s: packet too long - discarding\n", __func__);
430786baecfSMauro Carvalho Chehab 		return;
431786baecfSMauro Carvalho Chehab 	}
432786baecfSMauro Carvalho Chehab 
433786baecfSMauro Carvalho Chehab 	switch (pva[2]) {
434786baecfSMauro Carvalho Chehab 
435786baecfSMauro Carvalho Chehab 	case 0x01: {		/* VideoStream */
436786baecfSMauro Carvalho Chehab 		int prebytes = pva[5] & 0x03;
437786baecfSMauro Carvalho Chehab 		int postbytes = (pva[5] & 0x0c) >> 2;
438786baecfSMauro Carvalho Chehab 		__be16 v_pes_payload_length;
439786baecfSMauro Carvalho Chehab 
440786baecfSMauro Carvalho Chehab 		if (output_pva) {
441786baecfSMauro Carvalho Chehab 			dec->video_filter->feed->cb.ts(pva, length, NULL, 0,
442786baecfSMauro Carvalho Chehab 				&dec->video_filter->feed->feed.ts, DMX_OK);
443786baecfSMauro Carvalho Chehab 			return;
444786baecfSMauro Carvalho Chehab 		}
445786baecfSMauro Carvalho Chehab 
446786baecfSMauro Carvalho Chehab 		if (dec->v_pes_postbytes > 0 &&
447786baecfSMauro Carvalho Chehab 		    dec->v_pes_postbytes == prebytes) {
448786baecfSMauro Carvalho Chehab 			memcpy(&dec->v_pes[dec->v_pes_length],
449786baecfSMauro Carvalho Chehab 			       &pva[12], prebytes);
450786baecfSMauro Carvalho Chehab 
451786baecfSMauro Carvalho Chehab 			dvb_filter_pes2ts(&dec->v_pes2ts, dec->v_pes,
452786baecfSMauro Carvalho Chehab 					  dec->v_pes_length + prebytes, 1);
453786baecfSMauro Carvalho Chehab 		}
454786baecfSMauro Carvalho Chehab 
455786baecfSMauro Carvalho Chehab 		if (pva[5] & 0x10) {
456786baecfSMauro Carvalho Chehab 			dec->v_pes[7] = 0x80;
457786baecfSMauro Carvalho Chehab 			dec->v_pes[8] = 0x05;
458786baecfSMauro Carvalho Chehab 
459786baecfSMauro Carvalho Chehab 			dec->v_pes[9] = 0x21 | ((pva[8] & 0xc0) >> 5);
460786baecfSMauro Carvalho Chehab 			dec->v_pes[10] = ((pva[8] & 0x3f) << 2) |
461786baecfSMauro Carvalho Chehab 					 ((pva[9] & 0xc0) >> 6);
462786baecfSMauro Carvalho Chehab 			dec->v_pes[11] = 0x01 |
463786baecfSMauro Carvalho Chehab 					 ((pva[9] & 0x3f) << 2) |
464786baecfSMauro Carvalho Chehab 					 ((pva[10] & 0x80) >> 6);
465786baecfSMauro Carvalho Chehab 			dec->v_pes[12] = ((pva[10] & 0x7f) << 1) |
466786baecfSMauro Carvalho Chehab 					 ((pva[11] & 0xc0) >> 7);
467786baecfSMauro Carvalho Chehab 			dec->v_pes[13] = 0x01 | ((pva[11] & 0x7f) << 1);
468786baecfSMauro Carvalho Chehab 
469786baecfSMauro Carvalho Chehab 			memcpy(&dec->v_pes[14], &pva[12 + prebytes],
470786baecfSMauro Carvalho Chehab 			       length - 12 - prebytes);
471786baecfSMauro Carvalho Chehab 			dec->v_pes_length = 14 + length - 12 - prebytes;
472786baecfSMauro Carvalho Chehab 		} else {
473786baecfSMauro Carvalho Chehab 			dec->v_pes[7] = 0x00;
474786baecfSMauro Carvalho Chehab 			dec->v_pes[8] = 0x00;
475786baecfSMauro Carvalho Chehab 
476786baecfSMauro Carvalho Chehab 			memcpy(&dec->v_pes[9], &pva[8], length - 8);
477786baecfSMauro Carvalho Chehab 			dec->v_pes_length = 9 + length - 8;
478786baecfSMauro Carvalho Chehab 		}
479786baecfSMauro Carvalho Chehab 
480786baecfSMauro Carvalho Chehab 		dec->v_pes_postbytes = postbytes;
481786baecfSMauro Carvalho Chehab 
482786baecfSMauro Carvalho Chehab 		if (dec->v_pes[9 + dec->v_pes[8]] == 0x00 &&
483786baecfSMauro Carvalho Chehab 		    dec->v_pes[10 + dec->v_pes[8]] == 0x00 &&
484786baecfSMauro Carvalho Chehab 		    dec->v_pes[11 + dec->v_pes[8]] == 0x01)
485786baecfSMauro Carvalho Chehab 			dec->v_pes[6] = 0x84;
486786baecfSMauro Carvalho Chehab 		else
487786baecfSMauro Carvalho Chehab 			dec->v_pes[6] = 0x80;
488786baecfSMauro Carvalho Chehab 
489786baecfSMauro Carvalho Chehab 		v_pes_payload_length = htons(dec->v_pes_length - 6 +
490786baecfSMauro Carvalho Chehab 					     postbytes);
491786baecfSMauro Carvalho Chehab 		memcpy(&dec->v_pes[4], &v_pes_payload_length, 2);
492786baecfSMauro Carvalho Chehab 
493786baecfSMauro Carvalho Chehab 		if (postbytes == 0)
494786baecfSMauro Carvalho Chehab 			dvb_filter_pes2ts(&dec->v_pes2ts, dec->v_pes,
495786baecfSMauro Carvalho Chehab 					  dec->v_pes_length, 1);
496786baecfSMauro Carvalho Chehab 
497786baecfSMauro Carvalho Chehab 		break;
498786baecfSMauro Carvalho Chehab 	}
499786baecfSMauro Carvalho Chehab 
500786baecfSMauro Carvalho Chehab 	case 0x02:		/* MainAudioStream */
501786baecfSMauro Carvalho Chehab 		if (output_pva) {
502786baecfSMauro Carvalho Chehab 			dec->audio_filter->feed->cb.ts(pva, length, NULL, 0,
503786baecfSMauro Carvalho Chehab 				&dec->audio_filter->feed->feed.ts, DMX_OK);
504786baecfSMauro Carvalho Chehab 			return;
505786baecfSMauro Carvalho Chehab 		}
506786baecfSMauro Carvalho Chehab 
507786baecfSMauro Carvalho Chehab 		dvb_filter_pes2ts(&dec->a_pes2ts, &pva[8], length - 8,
508786baecfSMauro Carvalho Chehab 				  pva[5] & 0x10);
509786baecfSMauro Carvalho Chehab 		break;
510786baecfSMauro Carvalho Chehab 
511786baecfSMauro Carvalho Chehab 	default:
512786baecfSMauro Carvalho Chehab 		printk("%s: unknown PVA type: %02x.\n", __func__,
513786baecfSMauro Carvalho Chehab 		       pva[2]);
514786baecfSMauro Carvalho Chehab 		break;
515786baecfSMauro Carvalho Chehab 	}
516786baecfSMauro Carvalho Chehab }
517786baecfSMauro Carvalho Chehab 
518786baecfSMauro Carvalho Chehab static void ttusb_dec_process_filter(struct ttusb_dec *dec, u8 *packet,
519786baecfSMauro Carvalho Chehab 				     int length)
520786baecfSMauro Carvalho Chehab {
521786baecfSMauro Carvalho Chehab 	struct list_head *item;
522786baecfSMauro Carvalho Chehab 	struct filter_info *finfo;
523786baecfSMauro Carvalho Chehab 	struct dvb_demux_filter *filter = NULL;
524786baecfSMauro Carvalho Chehab 	unsigned long flags;
525786baecfSMauro Carvalho Chehab 	u8 sid;
526786baecfSMauro Carvalho Chehab 
527786baecfSMauro Carvalho Chehab 	sid = packet[1];
528786baecfSMauro Carvalho Chehab 	spin_lock_irqsave(&dec->filter_info_list_lock, flags);
529786baecfSMauro Carvalho Chehab 	for (item = dec->filter_info_list.next; item != &dec->filter_info_list;
530786baecfSMauro Carvalho Chehab 	     item = item->next) {
531786baecfSMauro Carvalho Chehab 		finfo = list_entry(item, struct filter_info, filter_info_list);
532786baecfSMauro Carvalho Chehab 		if (finfo->stream_id == sid) {
533786baecfSMauro Carvalho Chehab 			filter = finfo->filter;
534786baecfSMauro Carvalho Chehab 			break;
535786baecfSMauro Carvalho Chehab 		}
536786baecfSMauro Carvalho Chehab 	}
537786baecfSMauro Carvalho Chehab 	spin_unlock_irqrestore(&dec->filter_info_list_lock, flags);
538786baecfSMauro Carvalho Chehab 
539786baecfSMauro Carvalho Chehab 	if (filter)
540786baecfSMauro Carvalho Chehab 		filter->feed->cb.sec(&packet[2], length - 2, NULL, 0,
541786baecfSMauro Carvalho Chehab 				     &filter->filter, DMX_OK);
542786baecfSMauro Carvalho Chehab }
543786baecfSMauro Carvalho Chehab 
544786baecfSMauro Carvalho Chehab static void ttusb_dec_process_packet(struct ttusb_dec *dec)
545786baecfSMauro Carvalho Chehab {
546786baecfSMauro Carvalho Chehab 	int i;
547786baecfSMauro Carvalho Chehab 	u16 csum = 0;
548786baecfSMauro Carvalho Chehab 	u16 packet_id;
549786baecfSMauro Carvalho Chehab 
550786baecfSMauro Carvalho Chehab 	if (dec->packet_length % 2) {
551786baecfSMauro Carvalho Chehab 		printk("%s: odd sized packet - discarding\n", __func__);
552786baecfSMauro Carvalho Chehab 		return;
553786baecfSMauro Carvalho Chehab 	}
554786baecfSMauro Carvalho Chehab 
555786baecfSMauro Carvalho Chehab 	for (i = 0; i < dec->packet_length; i += 2)
556786baecfSMauro Carvalho Chehab 		csum ^= ((dec->packet[i] << 8) + dec->packet[i + 1]);
557786baecfSMauro Carvalho Chehab 
558786baecfSMauro Carvalho Chehab 	if (csum) {
559786baecfSMauro Carvalho Chehab 		printk("%s: checksum failed - discarding\n", __func__);
560786baecfSMauro Carvalho Chehab 		return;
561786baecfSMauro Carvalho Chehab 	}
562786baecfSMauro Carvalho Chehab 
563786baecfSMauro Carvalho Chehab 	packet_id = dec->packet[dec->packet_length - 4] << 8;
564786baecfSMauro Carvalho Chehab 	packet_id += dec->packet[dec->packet_length - 3];
565786baecfSMauro Carvalho Chehab 
566786baecfSMauro Carvalho Chehab 	if ((packet_id != dec->next_packet_id) && dec->next_packet_id) {
567786baecfSMauro Carvalho Chehab 		printk("%s: warning: lost packets between %u and %u\n",
568786baecfSMauro Carvalho Chehab 		       __func__, dec->next_packet_id - 1, packet_id);
569786baecfSMauro Carvalho Chehab 	}
570786baecfSMauro Carvalho Chehab 
571786baecfSMauro Carvalho Chehab 	if (packet_id == 0xffff)
572786baecfSMauro Carvalho Chehab 		dec->next_packet_id = 0x8000;
573786baecfSMauro Carvalho Chehab 	else
574786baecfSMauro Carvalho Chehab 		dec->next_packet_id = packet_id + 1;
575786baecfSMauro Carvalho Chehab 
576786baecfSMauro Carvalho Chehab 	switch (dec->packet_type) {
577786baecfSMauro Carvalho Chehab 	case TTUSB_DEC_PACKET_PVA:
578786baecfSMauro Carvalho Chehab 		if (dec->pva_stream_count)
579786baecfSMauro Carvalho Chehab 			ttusb_dec_process_pva(dec, dec->packet,
580786baecfSMauro Carvalho Chehab 					      dec->packet_payload_length);
581786baecfSMauro Carvalho Chehab 		break;
582786baecfSMauro Carvalho Chehab 
583786baecfSMauro Carvalho Chehab 	case TTUSB_DEC_PACKET_SECTION:
584786baecfSMauro Carvalho Chehab 		if (dec->filter_stream_count)
585786baecfSMauro Carvalho Chehab 			ttusb_dec_process_filter(dec, dec->packet,
586786baecfSMauro Carvalho Chehab 						 dec->packet_payload_length);
587786baecfSMauro Carvalho Chehab 		break;
588786baecfSMauro Carvalho Chehab 
589786baecfSMauro Carvalho Chehab 	case TTUSB_DEC_PACKET_EMPTY:
590786baecfSMauro Carvalho Chehab 		break;
591786baecfSMauro Carvalho Chehab 	}
592786baecfSMauro Carvalho Chehab }
593786baecfSMauro Carvalho Chehab 
594786baecfSMauro Carvalho Chehab static void swap_bytes(u8 *b, int length)
595786baecfSMauro Carvalho Chehab {
596786baecfSMauro Carvalho Chehab 	u8 c;
597786baecfSMauro Carvalho Chehab 
598786baecfSMauro Carvalho Chehab 	length -= length % 2;
599786baecfSMauro Carvalho Chehab 	for (; length; b += 2, length -= 2) {
600786baecfSMauro Carvalho Chehab 		c = *b;
601786baecfSMauro Carvalho Chehab 		*b = *(b + 1);
602786baecfSMauro Carvalho Chehab 		*(b + 1) = c;
603786baecfSMauro Carvalho Chehab 	}
604786baecfSMauro Carvalho Chehab }
605786baecfSMauro Carvalho Chehab 
606786baecfSMauro Carvalho Chehab static void ttusb_dec_process_urb_frame(struct ttusb_dec *dec, u8 *b,
607786baecfSMauro Carvalho Chehab 					int length)
608786baecfSMauro Carvalho Chehab {
609786baecfSMauro Carvalho Chehab 	swap_bytes(b, length);
610786baecfSMauro Carvalho Chehab 
611786baecfSMauro Carvalho Chehab 	while (length) {
612786baecfSMauro Carvalho Chehab 		switch (dec->packet_state) {
613786baecfSMauro Carvalho Chehab 
614786baecfSMauro Carvalho Chehab 		case 0:
615786baecfSMauro Carvalho Chehab 		case 1:
616786baecfSMauro Carvalho Chehab 		case 2:
617786baecfSMauro Carvalho Chehab 			if (*b++ == 0xaa)
618786baecfSMauro Carvalho Chehab 				dec->packet_state++;
619786baecfSMauro Carvalho Chehab 			else
620786baecfSMauro Carvalho Chehab 				dec->packet_state = 0;
621786baecfSMauro Carvalho Chehab 
622786baecfSMauro Carvalho Chehab 			length--;
623786baecfSMauro Carvalho Chehab 			break;
624786baecfSMauro Carvalho Chehab 
625786baecfSMauro Carvalho Chehab 		case 3:
626786baecfSMauro Carvalho Chehab 			if (*b == 0x00) {
627786baecfSMauro Carvalho Chehab 				dec->packet_state++;
628786baecfSMauro Carvalho Chehab 				dec->packet_length = 0;
629786baecfSMauro Carvalho Chehab 			} else if (*b != 0xaa) {
630786baecfSMauro Carvalho Chehab 				dec->packet_state = 0;
631786baecfSMauro Carvalho Chehab 			}
632786baecfSMauro Carvalho Chehab 
633786baecfSMauro Carvalho Chehab 			b++;
634786baecfSMauro Carvalho Chehab 			length--;
635786baecfSMauro Carvalho Chehab 			break;
636786baecfSMauro Carvalho Chehab 
637786baecfSMauro Carvalho Chehab 		case 4:
638786baecfSMauro Carvalho Chehab 			dec->packet[dec->packet_length++] = *b++;
639786baecfSMauro Carvalho Chehab 
640786baecfSMauro Carvalho Chehab 			if (dec->packet_length == 2) {
641786baecfSMauro Carvalho Chehab 				if (dec->packet[0] == 'A' &&
642786baecfSMauro Carvalho Chehab 				    dec->packet[1] == 'V') {
643786baecfSMauro Carvalho Chehab 					dec->packet_type =
644786baecfSMauro Carvalho Chehab 						TTUSB_DEC_PACKET_PVA;
645786baecfSMauro Carvalho Chehab 					dec->packet_state++;
646786baecfSMauro Carvalho Chehab 				} else if (dec->packet[0] == 'S') {
647786baecfSMauro Carvalho Chehab 					dec->packet_type =
648786baecfSMauro Carvalho Chehab 						TTUSB_DEC_PACKET_SECTION;
649786baecfSMauro Carvalho Chehab 					dec->packet_state++;
650786baecfSMauro Carvalho Chehab 				} else if (dec->packet[0] == 0x00) {
651786baecfSMauro Carvalho Chehab 					dec->packet_type =
652786baecfSMauro Carvalho Chehab 						TTUSB_DEC_PACKET_EMPTY;
653786baecfSMauro Carvalho Chehab 					dec->packet_payload_length = 2;
654786baecfSMauro Carvalho Chehab 					dec->packet_state = 7;
655786baecfSMauro Carvalho Chehab 				} else {
656786baecfSMauro Carvalho Chehab 					printk("%s: unknown packet type: "
657786baecfSMauro Carvalho Chehab 					       "%02x%02x\n", __func__,
658786baecfSMauro Carvalho Chehab 					       dec->packet[0], dec->packet[1]);
659786baecfSMauro Carvalho Chehab 					dec->packet_state = 0;
660786baecfSMauro Carvalho Chehab 				}
661786baecfSMauro Carvalho Chehab 			}
662786baecfSMauro Carvalho Chehab 
663786baecfSMauro Carvalho Chehab 			length--;
664786baecfSMauro Carvalho Chehab 			break;
665786baecfSMauro Carvalho Chehab 
666786baecfSMauro Carvalho Chehab 		case 5:
667786baecfSMauro Carvalho Chehab 			dec->packet[dec->packet_length++] = *b++;
668786baecfSMauro Carvalho Chehab 
669786baecfSMauro Carvalho Chehab 			if (dec->packet_type == TTUSB_DEC_PACKET_PVA &&
670786baecfSMauro Carvalho Chehab 			    dec->packet_length == 8) {
671786baecfSMauro Carvalho Chehab 				dec->packet_state++;
672786baecfSMauro Carvalho Chehab 				dec->packet_payload_length = 8 +
673786baecfSMauro Carvalho Chehab 					(dec->packet[6] << 8) +
674786baecfSMauro Carvalho Chehab 					dec->packet[7];
675786baecfSMauro Carvalho Chehab 			} else if (dec->packet_type ==
676786baecfSMauro Carvalho Chehab 					TTUSB_DEC_PACKET_SECTION &&
677786baecfSMauro Carvalho Chehab 				   dec->packet_length == 5) {
678786baecfSMauro Carvalho Chehab 				dec->packet_state++;
679786baecfSMauro Carvalho Chehab 				dec->packet_payload_length = 5 +
680786baecfSMauro Carvalho Chehab 					((dec->packet[3] & 0x0f) << 8) +
681786baecfSMauro Carvalho Chehab 					dec->packet[4];
682786baecfSMauro Carvalho Chehab 			}
683786baecfSMauro Carvalho Chehab 
684786baecfSMauro Carvalho Chehab 			length--;
685786baecfSMauro Carvalho Chehab 			break;
686786baecfSMauro Carvalho Chehab 
687786baecfSMauro Carvalho Chehab 		case 6: {
688786baecfSMauro Carvalho Chehab 			int remainder = dec->packet_payload_length -
689786baecfSMauro Carvalho Chehab 					dec->packet_length;
690786baecfSMauro Carvalho Chehab 
691786baecfSMauro Carvalho Chehab 			if (length >= remainder) {
692786baecfSMauro Carvalho Chehab 				memcpy(dec->packet + dec->packet_length,
693786baecfSMauro Carvalho Chehab 				       b, remainder);
694786baecfSMauro Carvalho Chehab 				dec->packet_length += remainder;
695786baecfSMauro Carvalho Chehab 				b += remainder;
696786baecfSMauro Carvalho Chehab 				length -= remainder;
697786baecfSMauro Carvalho Chehab 				dec->packet_state++;
698786baecfSMauro Carvalho Chehab 			} else {
699786baecfSMauro Carvalho Chehab 				memcpy(&dec->packet[dec->packet_length],
700786baecfSMauro Carvalho Chehab 				       b, length);
701786baecfSMauro Carvalho Chehab 				dec->packet_length += length;
702786baecfSMauro Carvalho Chehab 				length = 0;
703786baecfSMauro Carvalho Chehab 			}
704786baecfSMauro Carvalho Chehab 
705786baecfSMauro Carvalho Chehab 			break;
706786baecfSMauro Carvalho Chehab 		}
707786baecfSMauro Carvalho Chehab 
708786baecfSMauro Carvalho Chehab 		case 7: {
709786baecfSMauro Carvalho Chehab 			int tail = 4;
710786baecfSMauro Carvalho Chehab 
711786baecfSMauro Carvalho Chehab 			dec->packet[dec->packet_length++] = *b++;
712786baecfSMauro Carvalho Chehab 
713786baecfSMauro Carvalho Chehab 			if (dec->packet_type == TTUSB_DEC_PACKET_SECTION &&
714786baecfSMauro Carvalho Chehab 			    dec->packet_payload_length % 2)
715786baecfSMauro Carvalho Chehab 				tail++;
716786baecfSMauro Carvalho Chehab 
717786baecfSMauro Carvalho Chehab 			if (dec->packet_length ==
718786baecfSMauro Carvalho Chehab 			    dec->packet_payload_length + tail) {
719786baecfSMauro Carvalho Chehab 				ttusb_dec_process_packet(dec);
720786baecfSMauro Carvalho Chehab 				dec->packet_state = 0;
721786baecfSMauro Carvalho Chehab 			}
722786baecfSMauro Carvalho Chehab 
723786baecfSMauro Carvalho Chehab 			length--;
724786baecfSMauro Carvalho Chehab 			break;
725786baecfSMauro Carvalho Chehab 		}
726786baecfSMauro Carvalho Chehab 
727786baecfSMauro Carvalho Chehab 		default:
728786baecfSMauro Carvalho Chehab 			printk("%s: illegal packet state encountered.\n",
729786baecfSMauro Carvalho Chehab 			       __func__);
730786baecfSMauro Carvalho Chehab 			dec->packet_state = 0;
731786baecfSMauro Carvalho Chehab 		}
732786baecfSMauro Carvalho Chehab 	}
733786baecfSMauro Carvalho Chehab }
734786baecfSMauro Carvalho Chehab 
735786baecfSMauro Carvalho Chehab static void ttusb_dec_process_urb_frame_list(unsigned long data)
736786baecfSMauro Carvalho Chehab {
737786baecfSMauro Carvalho Chehab 	struct ttusb_dec *dec = (struct ttusb_dec *)data;
738786baecfSMauro Carvalho Chehab 	struct list_head *item;
739786baecfSMauro Carvalho Chehab 	struct urb_frame *frame;
740786baecfSMauro Carvalho Chehab 	unsigned long flags;
741786baecfSMauro Carvalho Chehab 
742786baecfSMauro Carvalho Chehab 	while (1) {
743786baecfSMauro Carvalho Chehab 		spin_lock_irqsave(&dec->urb_frame_list_lock, flags);
744786baecfSMauro Carvalho Chehab 		if ((item = dec->urb_frame_list.next) != &dec->urb_frame_list) {
745786baecfSMauro Carvalho Chehab 			frame = list_entry(item, struct urb_frame,
746786baecfSMauro Carvalho Chehab 					   urb_frame_list);
747786baecfSMauro Carvalho Chehab 			list_del(&frame->urb_frame_list);
748786baecfSMauro Carvalho Chehab 		} else {
749786baecfSMauro Carvalho Chehab 			spin_unlock_irqrestore(&dec->urb_frame_list_lock,
750786baecfSMauro Carvalho Chehab 					       flags);
751786baecfSMauro Carvalho Chehab 			return;
752786baecfSMauro Carvalho Chehab 		}
753786baecfSMauro Carvalho Chehab 		spin_unlock_irqrestore(&dec->urb_frame_list_lock, flags);
754786baecfSMauro Carvalho Chehab 
755786baecfSMauro Carvalho Chehab 		ttusb_dec_process_urb_frame(dec, frame->data, frame->length);
756786baecfSMauro Carvalho Chehab 		kfree(frame);
757786baecfSMauro Carvalho Chehab 	}
758786baecfSMauro Carvalho Chehab }
759786baecfSMauro Carvalho Chehab 
760786baecfSMauro Carvalho Chehab static void ttusb_dec_process_urb(struct urb *urb)
761786baecfSMauro Carvalho Chehab {
762786baecfSMauro Carvalho Chehab 	struct ttusb_dec *dec = urb->context;
763786baecfSMauro Carvalho Chehab 
764786baecfSMauro Carvalho Chehab 	if (!urb->status) {
765786baecfSMauro Carvalho Chehab 		int i;
766786baecfSMauro Carvalho Chehab 
767786baecfSMauro Carvalho Chehab 		for (i = 0; i < FRAMES_PER_ISO_BUF; i++) {
768786baecfSMauro Carvalho Chehab 			struct usb_iso_packet_descriptor *d;
769786baecfSMauro Carvalho Chehab 			u8 *b;
770786baecfSMauro Carvalho Chehab 			int length;
771786baecfSMauro Carvalho Chehab 			struct urb_frame *frame;
772786baecfSMauro Carvalho Chehab 
773786baecfSMauro Carvalho Chehab 			d = &urb->iso_frame_desc[i];
774786baecfSMauro Carvalho Chehab 			b = urb->transfer_buffer + d->offset;
775786baecfSMauro Carvalho Chehab 			length = d->actual_length;
776786baecfSMauro Carvalho Chehab 
777786baecfSMauro Carvalho Chehab 			if ((frame = kmalloc(sizeof(struct urb_frame),
778786baecfSMauro Carvalho Chehab 					     GFP_ATOMIC))) {
779786baecfSMauro Carvalho Chehab 				unsigned long flags;
780786baecfSMauro Carvalho Chehab 
781786baecfSMauro Carvalho Chehab 				memcpy(frame->data, b, length);
782786baecfSMauro Carvalho Chehab 				frame->length = length;
783786baecfSMauro Carvalho Chehab 
784786baecfSMauro Carvalho Chehab 				spin_lock_irqsave(&dec->urb_frame_list_lock,
785786baecfSMauro Carvalho Chehab 						     flags);
786786baecfSMauro Carvalho Chehab 				list_add_tail(&frame->urb_frame_list,
787786baecfSMauro Carvalho Chehab 					      &dec->urb_frame_list);
788786baecfSMauro Carvalho Chehab 				spin_unlock_irqrestore(&dec->urb_frame_list_lock,
789786baecfSMauro Carvalho Chehab 						       flags);
790786baecfSMauro Carvalho Chehab 
791786baecfSMauro Carvalho Chehab 				tasklet_schedule(&dec->urb_tasklet);
792786baecfSMauro Carvalho Chehab 			}
793786baecfSMauro Carvalho Chehab 		}
794786baecfSMauro Carvalho Chehab 	} else {
795786baecfSMauro Carvalho Chehab 		 /* -ENOENT is expected when unlinking urbs */
796786baecfSMauro Carvalho Chehab 		if (urb->status != -ENOENT)
797786baecfSMauro Carvalho Chehab 			dprintk("%s: urb error: %d\n", __func__,
798786baecfSMauro Carvalho Chehab 				urb->status);
799786baecfSMauro Carvalho Chehab 	}
800786baecfSMauro Carvalho Chehab 
801786baecfSMauro Carvalho Chehab 	if (dec->iso_stream_count)
802786baecfSMauro Carvalho Chehab 		usb_submit_urb(urb, GFP_ATOMIC);
803786baecfSMauro Carvalho Chehab }
804786baecfSMauro Carvalho Chehab 
805786baecfSMauro Carvalho Chehab static void ttusb_dec_setup_urbs(struct ttusb_dec *dec)
806786baecfSMauro Carvalho Chehab {
807786baecfSMauro Carvalho Chehab 	int i, j, buffer_offset = 0;
808786baecfSMauro Carvalho Chehab 
809786baecfSMauro Carvalho Chehab 	dprintk("%s\n", __func__);
810786baecfSMauro Carvalho Chehab 
811786baecfSMauro Carvalho Chehab 	for (i = 0; i < ISO_BUF_COUNT; i++) {
812786baecfSMauro Carvalho Chehab 		int frame_offset = 0;
813786baecfSMauro Carvalho Chehab 		struct urb *urb = dec->iso_urb[i];
814786baecfSMauro Carvalho Chehab 
815786baecfSMauro Carvalho Chehab 		urb->dev = dec->udev;
816786baecfSMauro Carvalho Chehab 		urb->context = dec;
817786baecfSMauro Carvalho Chehab 		urb->complete = ttusb_dec_process_urb;
818786baecfSMauro Carvalho Chehab 		urb->pipe = dec->in_pipe;
819786baecfSMauro Carvalho Chehab 		urb->transfer_flags = URB_ISO_ASAP;
820786baecfSMauro Carvalho Chehab 		urb->interval = 1;
821786baecfSMauro Carvalho Chehab 		urb->number_of_packets = FRAMES_PER_ISO_BUF;
822786baecfSMauro Carvalho Chehab 		urb->transfer_buffer_length = ISO_FRAME_SIZE *
823786baecfSMauro Carvalho Chehab 					      FRAMES_PER_ISO_BUF;
824786baecfSMauro Carvalho Chehab 		urb->transfer_buffer = dec->iso_buffer + buffer_offset;
825786baecfSMauro Carvalho Chehab 		buffer_offset += ISO_FRAME_SIZE * FRAMES_PER_ISO_BUF;
826786baecfSMauro Carvalho Chehab 
827786baecfSMauro Carvalho Chehab 		for (j = 0; j < FRAMES_PER_ISO_BUF; j++) {
828786baecfSMauro Carvalho Chehab 			urb->iso_frame_desc[j].offset = frame_offset;
829786baecfSMauro Carvalho Chehab 			urb->iso_frame_desc[j].length = ISO_FRAME_SIZE;
830786baecfSMauro Carvalho Chehab 			frame_offset += ISO_FRAME_SIZE;
831786baecfSMauro Carvalho Chehab 		}
832786baecfSMauro Carvalho Chehab 	}
833786baecfSMauro Carvalho Chehab }
834786baecfSMauro Carvalho Chehab 
835786baecfSMauro Carvalho Chehab static void ttusb_dec_stop_iso_xfer(struct ttusb_dec *dec)
836786baecfSMauro Carvalho Chehab {
837786baecfSMauro Carvalho Chehab 	int i;
838786baecfSMauro Carvalho Chehab 
839786baecfSMauro Carvalho Chehab 	dprintk("%s\n", __func__);
840786baecfSMauro Carvalho Chehab 
841786baecfSMauro Carvalho Chehab 	if (mutex_lock_interruptible(&dec->iso_mutex))
842786baecfSMauro Carvalho Chehab 		return;
843786baecfSMauro Carvalho Chehab 
844786baecfSMauro Carvalho Chehab 	dec->iso_stream_count--;
845786baecfSMauro Carvalho Chehab 
846786baecfSMauro Carvalho Chehab 	if (!dec->iso_stream_count) {
847786baecfSMauro Carvalho Chehab 		for (i = 0; i < ISO_BUF_COUNT; i++)
848786baecfSMauro Carvalho Chehab 			usb_kill_urb(dec->iso_urb[i]);
849786baecfSMauro Carvalho Chehab 	}
850786baecfSMauro Carvalho Chehab 
851786baecfSMauro Carvalho Chehab 	mutex_unlock(&dec->iso_mutex);
852786baecfSMauro Carvalho Chehab }
853786baecfSMauro Carvalho Chehab 
854786baecfSMauro Carvalho Chehab /* Setting the interface of the DEC tends to take down the USB communications
855786baecfSMauro Carvalho Chehab  * for a short period, so it's important not to call this function just before
856786baecfSMauro Carvalho Chehab  * trying to talk to it.
857786baecfSMauro Carvalho Chehab  */
858786baecfSMauro Carvalho Chehab static int ttusb_dec_set_interface(struct ttusb_dec *dec,
859786baecfSMauro Carvalho Chehab 				   enum ttusb_dec_interface interface)
860786baecfSMauro Carvalho Chehab {
861786baecfSMauro Carvalho Chehab 	int result = 0;
862786baecfSMauro Carvalho Chehab 	u8 b[] = { 0x05 };
863786baecfSMauro Carvalho Chehab 
864786baecfSMauro Carvalho Chehab 	if (interface != dec->interface) {
865786baecfSMauro Carvalho Chehab 		switch (interface) {
866786baecfSMauro Carvalho Chehab 		case TTUSB_DEC_INTERFACE_INITIAL:
867786baecfSMauro Carvalho Chehab 			result = usb_set_interface(dec->udev, 0, 0);
868786baecfSMauro Carvalho Chehab 			break;
869786baecfSMauro Carvalho Chehab 		case TTUSB_DEC_INTERFACE_IN:
870786baecfSMauro Carvalho Chehab 			result = ttusb_dec_send_command(dec, 0x80, sizeof(b),
871786baecfSMauro Carvalho Chehab 							b, NULL, NULL);
872786baecfSMauro Carvalho Chehab 			if (result)
873786baecfSMauro Carvalho Chehab 				return result;
874786baecfSMauro Carvalho Chehab 			result = usb_set_interface(dec->udev, 0, 8);
875786baecfSMauro Carvalho Chehab 			break;
876786baecfSMauro Carvalho Chehab 		case TTUSB_DEC_INTERFACE_OUT:
877786baecfSMauro Carvalho Chehab 			result = usb_set_interface(dec->udev, 0, 1);
878786baecfSMauro Carvalho Chehab 			break;
879786baecfSMauro Carvalho Chehab 		}
880786baecfSMauro Carvalho Chehab 
881786baecfSMauro Carvalho Chehab 		if (result)
882786baecfSMauro Carvalho Chehab 			return result;
883786baecfSMauro Carvalho Chehab 
884786baecfSMauro Carvalho Chehab 		dec->interface = interface;
885786baecfSMauro Carvalho Chehab 	}
886786baecfSMauro Carvalho Chehab 
887786baecfSMauro Carvalho Chehab 	return 0;
888786baecfSMauro Carvalho Chehab }
889786baecfSMauro Carvalho Chehab 
890786baecfSMauro Carvalho Chehab static int ttusb_dec_start_iso_xfer(struct ttusb_dec *dec)
891786baecfSMauro Carvalho Chehab {
892786baecfSMauro Carvalho Chehab 	int i, result;
893786baecfSMauro Carvalho Chehab 
894786baecfSMauro Carvalho Chehab 	dprintk("%s\n", __func__);
895786baecfSMauro Carvalho Chehab 
896786baecfSMauro Carvalho Chehab 	if (mutex_lock_interruptible(&dec->iso_mutex))
897786baecfSMauro Carvalho Chehab 		return -EAGAIN;
898786baecfSMauro Carvalho Chehab 
899786baecfSMauro Carvalho Chehab 	if (!dec->iso_stream_count) {
900786baecfSMauro Carvalho Chehab 		ttusb_dec_setup_urbs(dec);
901786baecfSMauro Carvalho Chehab 
902786baecfSMauro Carvalho Chehab 		dec->packet_state = 0;
903786baecfSMauro Carvalho Chehab 		dec->v_pes_postbytes = 0;
904786baecfSMauro Carvalho Chehab 		dec->next_packet_id = 0;
905786baecfSMauro Carvalho Chehab 
906786baecfSMauro Carvalho Chehab 		for (i = 0; i < ISO_BUF_COUNT; i++) {
907786baecfSMauro Carvalho Chehab 			if ((result = usb_submit_urb(dec->iso_urb[i],
908786baecfSMauro Carvalho Chehab 						     GFP_ATOMIC))) {
909786baecfSMauro Carvalho Chehab 				printk("%s: failed urb submission %d: "
910786baecfSMauro Carvalho Chehab 				       "error %d\n", __func__, i, result);
911786baecfSMauro Carvalho Chehab 
912786baecfSMauro Carvalho Chehab 				while (i) {
913786baecfSMauro Carvalho Chehab 					usb_kill_urb(dec->iso_urb[i - 1]);
914786baecfSMauro Carvalho Chehab 					i--;
915786baecfSMauro Carvalho Chehab 				}
916786baecfSMauro Carvalho Chehab 
917786baecfSMauro Carvalho Chehab 				mutex_unlock(&dec->iso_mutex);
918786baecfSMauro Carvalho Chehab 				return result;
919786baecfSMauro Carvalho Chehab 			}
920786baecfSMauro Carvalho Chehab 		}
921786baecfSMauro Carvalho Chehab 	}
922786baecfSMauro Carvalho Chehab 
923786baecfSMauro Carvalho Chehab 	dec->iso_stream_count++;
924786baecfSMauro Carvalho Chehab 
925786baecfSMauro Carvalho Chehab 	mutex_unlock(&dec->iso_mutex);
926786baecfSMauro Carvalho Chehab 
927786baecfSMauro Carvalho Chehab 	return 0;
928786baecfSMauro Carvalho Chehab }
929786baecfSMauro Carvalho Chehab 
930786baecfSMauro Carvalho Chehab static int ttusb_dec_start_ts_feed(struct dvb_demux_feed *dvbdmxfeed)
931786baecfSMauro Carvalho Chehab {
932786baecfSMauro Carvalho Chehab 	struct dvb_demux *dvbdmx = dvbdmxfeed->demux;
933786baecfSMauro Carvalho Chehab 	struct ttusb_dec *dec = dvbdmx->priv;
934786baecfSMauro Carvalho Chehab 	u8 b0[] = { 0x05 };
935786baecfSMauro Carvalho Chehab 	int result = 0;
936786baecfSMauro Carvalho Chehab 
937786baecfSMauro Carvalho Chehab 	dprintk("%s\n", __func__);
938786baecfSMauro Carvalho Chehab 
939786baecfSMauro Carvalho Chehab 	dprintk("  ts_type:");
940786baecfSMauro Carvalho Chehab 
941786baecfSMauro Carvalho Chehab 	if (dvbdmxfeed->ts_type & TS_DECODER)
942786baecfSMauro Carvalho Chehab 		dprintk(" TS_DECODER");
943786baecfSMauro Carvalho Chehab 
944786baecfSMauro Carvalho Chehab 	if (dvbdmxfeed->ts_type & TS_PACKET)
945786baecfSMauro Carvalho Chehab 		dprintk(" TS_PACKET");
946786baecfSMauro Carvalho Chehab 
947786baecfSMauro Carvalho Chehab 	if (dvbdmxfeed->ts_type & TS_PAYLOAD_ONLY)
948786baecfSMauro Carvalho Chehab 		dprintk(" TS_PAYLOAD_ONLY");
949786baecfSMauro Carvalho Chehab 
950786baecfSMauro Carvalho Chehab 	dprintk("\n");
951786baecfSMauro Carvalho Chehab 
952786baecfSMauro Carvalho Chehab 	switch (dvbdmxfeed->pes_type) {
953786baecfSMauro Carvalho Chehab 
954fde04ab9SMauro Carvalho Chehab 	case DMX_PES_VIDEO:
955fde04ab9SMauro Carvalho Chehab 		dprintk("  pes_type: DMX_PES_VIDEO\n");
956786baecfSMauro Carvalho Chehab 		dec->pid[DMX_PES_PCR] = dvbdmxfeed->pid;
957786baecfSMauro Carvalho Chehab 		dec->pid[DMX_PES_VIDEO] = dvbdmxfeed->pid;
958786baecfSMauro Carvalho Chehab 		dec->video_filter = dvbdmxfeed->filter;
959786baecfSMauro Carvalho Chehab 		ttusb_dec_set_pids(dec);
960786baecfSMauro Carvalho Chehab 		break;
961786baecfSMauro Carvalho Chehab 
962fde04ab9SMauro Carvalho Chehab 	case DMX_PES_AUDIO:
963fde04ab9SMauro Carvalho Chehab 		dprintk("  pes_type: DMX_PES_AUDIO\n");
964786baecfSMauro Carvalho Chehab 		dec->pid[DMX_PES_AUDIO] = dvbdmxfeed->pid;
965786baecfSMauro Carvalho Chehab 		dec->audio_filter = dvbdmxfeed->filter;
966786baecfSMauro Carvalho Chehab 		ttusb_dec_set_pids(dec);
967786baecfSMauro Carvalho Chehab 		break;
968786baecfSMauro Carvalho Chehab 
969fde04ab9SMauro Carvalho Chehab 	case DMX_PES_TELETEXT:
970786baecfSMauro Carvalho Chehab 		dec->pid[DMX_PES_TELETEXT] = dvbdmxfeed->pid;
971fde04ab9SMauro Carvalho Chehab 		dprintk("  pes_type: DMX_PES_TELETEXT(not supported)\n");
972786baecfSMauro Carvalho Chehab 		return -ENOSYS;
973786baecfSMauro Carvalho Chehab 
974fde04ab9SMauro Carvalho Chehab 	case DMX_PES_PCR:
975fde04ab9SMauro Carvalho Chehab 		dprintk("  pes_type: DMX_PES_PCR\n");
976786baecfSMauro Carvalho Chehab 		dec->pid[DMX_PES_PCR] = dvbdmxfeed->pid;
977786baecfSMauro Carvalho Chehab 		ttusb_dec_set_pids(dec);
978786baecfSMauro Carvalho Chehab 		break;
979786baecfSMauro Carvalho Chehab 
980fde04ab9SMauro Carvalho Chehab 	case DMX_PES_OTHER:
981fde04ab9SMauro Carvalho Chehab 		dprintk("  pes_type: DMX_PES_OTHER(not supported)\n");
982786baecfSMauro Carvalho Chehab 		return -ENOSYS;
983786baecfSMauro Carvalho Chehab 
984786baecfSMauro Carvalho Chehab 	default:
985786baecfSMauro Carvalho Chehab 		dprintk("  pes_type: unknown (%d)\n", dvbdmxfeed->pes_type);
986786baecfSMauro Carvalho Chehab 		return -EINVAL;
987786baecfSMauro Carvalho Chehab 
988786baecfSMauro Carvalho Chehab 	}
989786baecfSMauro Carvalho Chehab 
990786baecfSMauro Carvalho Chehab 	result = ttusb_dec_send_command(dec, 0x80, sizeof(b0), b0, NULL, NULL);
991786baecfSMauro Carvalho Chehab 	if (result)
992786baecfSMauro Carvalho Chehab 		return result;
993786baecfSMauro Carvalho Chehab 
994786baecfSMauro Carvalho Chehab 	dec->pva_stream_count++;
995786baecfSMauro Carvalho Chehab 	return ttusb_dec_start_iso_xfer(dec);
996786baecfSMauro Carvalho Chehab }
997786baecfSMauro Carvalho Chehab 
998786baecfSMauro Carvalho Chehab static int ttusb_dec_start_sec_feed(struct dvb_demux_feed *dvbdmxfeed)
999786baecfSMauro Carvalho Chehab {
1000786baecfSMauro Carvalho Chehab 	struct ttusb_dec *dec = dvbdmxfeed->demux->priv;
1001786baecfSMauro Carvalho Chehab 	u8 b0[] = { 0x00, 0x00, 0x00, 0x01,
1002786baecfSMauro Carvalho Chehab 		    0x00, 0x00, 0x00, 0x00,
1003786baecfSMauro Carvalho Chehab 		    0x00, 0x00, 0x00, 0x00,
1004786baecfSMauro Carvalho Chehab 		    0x00, 0x00, 0x00, 0x00,
1005786baecfSMauro Carvalho Chehab 		    0x00, 0xff, 0x00, 0x00,
1006786baecfSMauro Carvalho Chehab 		    0x00, 0x00, 0x00, 0x00,
1007786baecfSMauro Carvalho Chehab 		    0x00, 0x00, 0x00, 0x00,
1008786baecfSMauro Carvalho Chehab 		    0x00 };
1009786baecfSMauro Carvalho Chehab 	__be16 pid;
1010786baecfSMauro Carvalho Chehab 	u8 c[COMMAND_PACKET_SIZE];
1011786baecfSMauro Carvalho Chehab 	int c_length;
1012786baecfSMauro Carvalho Chehab 	int result;
1013786baecfSMauro Carvalho Chehab 	struct filter_info *finfo;
1014786baecfSMauro Carvalho Chehab 	unsigned long flags;
1015786baecfSMauro Carvalho Chehab 	u8 x = 1;
1016786baecfSMauro Carvalho Chehab 
1017786baecfSMauro Carvalho Chehab 	dprintk("%s\n", __func__);
1018786baecfSMauro Carvalho Chehab 
1019786baecfSMauro Carvalho Chehab 	pid = htons(dvbdmxfeed->pid);
1020786baecfSMauro Carvalho Chehab 	memcpy(&b0[0], &pid, 2);
1021786baecfSMauro Carvalho Chehab 	memcpy(&b0[4], &x, 1);
1022786baecfSMauro Carvalho Chehab 	memcpy(&b0[5], &dvbdmxfeed->filter->filter.filter_value[0], 1);
1023786baecfSMauro Carvalho Chehab 
1024786baecfSMauro Carvalho Chehab 	result = ttusb_dec_send_command(dec, 0x60, sizeof(b0), b0,
1025786baecfSMauro Carvalho Chehab 					&c_length, c);
1026786baecfSMauro Carvalho Chehab 
1027786baecfSMauro Carvalho Chehab 	if (!result) {
1028786baecfSMauro Carvalho Chehab 		if (c_length == 2) {
1029786baecfSMauro Carvalho Chehab 			if (!(finfo = kmalloc(sizeof(struct filter_info),
1030786baecfSMauro Carvalho Chehab 					      GFP_ATOMIC)))
1031786baecfSMauro Carvalho Chehab 				return -ENOMEM;
1032786baecfSMauro Carvalho Chehab 
1033786baecfSMauro Carvalho Chehab 			finfo->stream_id = c[1];
1034786baecfSMauro Carvalho Chehab 			finfo->filter = dvbdmxfeed->filter;
1035786baecfSMauro Carvalho Chehab 
1036786baecfSMauro Carvalho Chehab 			spin_lock_irqsave(&dec->filter_info_list_lock, flags);
1037786baecfSMauro Carvalho Chehab 			list_add_tail(&finfo->filter_info_list,
1038786baecfSMauro Carvalho Chehab 				      &dec->filter_info_list);
1039786baecfSMauro Carvalho Chehab 			spin_unlock_irqrestore(&dec->filter_info_list_lock,
1040786baecfSMauro Carvalho Chehab 					       flags);
1041786baecfSMauro Carvalho Chehab 
1042786baecfSMauro Carvalho Chehab 			dvbdmxfeed->priv = finfo;
1043786baecfSMauro Carvalho Chehab 
1044786baecfSMauro Carvalho Chehab 			dec->filter_stream_count++;
1045786baecfSMauro Carvalho Chehab 			return ttusb_dec_start_iso_xfer(dec);
1046786baecfSMauro Carvalho Chehab 		}
1047786baecfSMauro Carvalho Chehab 
1048786baecfSMauro Carvalho Chehab 		return -EAGAIN;
1049786baecfSMauro Carvalho Chehab 	} else
1050786baecfSMauro Carvalho Chehab 		return result;
1051786baecfSMauro Carvalho Chehab }
1052786baecfSMauro Carvalho Chehab 
1053786baecfSMauro Carvalho Chehab static int ttusb_dec_start_feed(struct dvb_demux_feed *dvbdmxfeed)
1054786baecfSMauro Carvalho Chehab {
1055786baecfSMauro Carvalho Chehab 	struct dvb_demux *dvbdmx = dvbdmxfeed->demux;
1056786baecfSMauro Carvalho Chehab 
1057786baecfSMauro Carvalho Chehab 	dprintk("%s\n", __func__);
1058786baecfSMauro Carvalho Chehab 
1059786baecfSMauro Carvalho Chehab 	if (!dvbdmx->dmx.frontend)
1060786baecfSMauro Carvalho Chehab 		return -EINVAL;
1061786baecfSMauro Carvalho Chehab 
1062786baecfSMauro Carvalho Chehab 	dprintk("  pid: 0x%04X\n", dvbdmxfeed->pid);
1063786baecfSMauro Carvalho Chehab 
1064786baecfSMauro Carvalho Chehab 	switch (dvbdmxfeed->type) {
1065786baecfSMauro Carvalho Chehab 
1066786baecfSMauro Carvalho Chehab 	case DMX_TYPE_TS:
1067786baecfSMauro Carvalho Chehab 		return ttusb_dec_start_ts_feed(dvbdmxfeed);
1068786baecfSMauro Carvalho Chehab 		break;
1069786baecfSMauro Carvalho Chehab 
1070786baecfSMauro Carvalho Chehab 	case DMX_TYPE_SEC:
1071786baecfSMauro Carvalho Chehab 		return ttusb_dec_start_sec_feed(dvbdmxfeed);
1072786baecfSMauro Carvalho Chehab 		break;
1073786baecfSMauro Carvalho Chehab 
1074786baecfSMauro Carvalho Chehab 	default:
1075786baecfSMauro Carvalho Chehab 		dprintk("  type: unknown (%d)\n", dvbdmxfeed->type);
1076786baecfSMauro Carvalho Chehab 		return -EINVAL;
1077786baecfSMauro Carvalho Chehab 
1078786baecfSMauro Carvalho Chehab 	}
1079786baecfSMauro Carvalho Chehab }
1080786baecfSMauro Carvalho Chehab 
1081786baecfSMauro Carvalho Chehab static int ttusb_dec_stop_ts_feed(struct dvb_demux_feed *dvbdmxfeed)
1082786baecfSMauro Carvalho Chehab {
1083786baecfSMauro Carvalho Chehab 	struct ttusb_dec *dec = dvbdmxfeed->demux->priv;
1084786baecfSMauro Carvalho Chehab 	u8 b0[] = { 0x00 };
1085786baecfSMauro Carvalho Chehab 
1086786baecfSMauro Carvalho Chehab 	ttusb_dec_send_command(dec, 0x81, sizeof(b0), b0, NULL, NULL);
1087786baecfSMauro Carvalho Chehab 
1088786baecfSMauro Carvalho Chehab 	dec->pva_stream_count--;
1089786baecfSMauro Carvalho Chehab 
1090786baecfSMauro Carvalho Chehab 	ttusb_dec_stop_iso_xfer(dec);
1091786baecfSMauro Carvalho Chehab 
1092786baecfSMauro Carvalho Chehab 	return 0;
1093786baecfSMauro Carvalho Chehab }
1094786baecfSMauro Carvalho Chehab 
1095786baecfSMauro Carvalho Chehab static int ttusb_dec_stop_sec_feed(struct dvb_demux_feed *dvbdmxfeed)
1096786baecfSMauro Carvalho Chehab {
1097786baecfSMauro Carvalho Chehab 	struct ttusb_dec *dec = dvbdmxfeed->demux->priv;
1098786baecfSMauro Carvalho Chehab 	u8 b0[] = { 0x00, 0x00 };
1099786baecfSMauro Carvalho Chehab 	struct filter_info *finfo = (struct filter_info *)dvbdmxfeed->priv;
1100786baecfSMauro Carvalho Chehab 	unsigned long flags;
1101786baecfSMauro Carvalho Chehab 
1102786baecfSMauro Carvalho Chehab 	b0[1] = finfo->stream_id;
1103786baecfSMauro Carvalho Chehab 	spin_lock_irqsave(&dec->filter_info_list_lock, flags);
1104786baecfSMauro Carvalho Chehab 	list_del(&finfo->filter_info_list);
1105786baecfSMauro Carvalho Chehab 	spin_unlock_irqrestore(&dec->filter_info_list_lock, flags);
1106786baecfSMauro Carvalho Chehab 	kfree(finfo);
1107786baecfSMauro Carvalho Chehab 	ttusb_dec_send_command(dec, 0x62, sizeof(b0), b0, NULL, NULL);
1108786baecfSMauro Carvalho Chehab 
1109786baecfSMauro Carvalho Chehab 	dec->filter_stream_count--;
1110786baecfSMauro Carvalho Chehab 
1111786baecfSMauro Carvalho Chehab 	ttusb_dec_stop_iso_xfer(dec);
1112786baecfSMauro Carvalho Chehab 
1113786baecfSMauro Carvalho Chehab 	return 0;
1114786baecfSMauro Carvalho Chehab }
1115786baecfSMauro Carvalho Chehab 
1116786baecfSMauro Carvalho Chehab static int ttusb_dec_stop_feed(struct dvb_demux_feed *dvbdmxfeed)
1117786baecfSMauro Carvalho Chehab {
1118786baecfSMauro Carvalho Chehab 	dprintk("%s\n", __func__);
1119786baecfSMauro Carvalho Chehab 
1120786baecfSMauro Carvalho Chehab 	switch (dvbdmxfeed->type) {
1121786baecfSMauro Carvalho Chehab 	case DMX_TYPE_TS:
1122786baecfSMauro Carvalho Chehab 		return ttusb_dec_stop_ts_feed(dvbdmxfeed);
1123786baecfSMauro Carvalho Chehab 		break;
1124786baecfSMauro Carvalho Chehab 
1125786baecfSMauro Carvalho Chehab 	case DMX_TYPE_SEC:
1126786baecfSMauro Carvalho Chehab 		return ttusb_dec_stop_sec_feed(dvbdmxfeed);
1127786baecfSMauro Carvalho Chehab 		break;
1128786baecfSMauro Carvalho Chehab 	}
1129786baecfSMauro Carvalho Chehab 
1130786baecfSMauro Carvalho Chehab 	return 0;
1131786baecfSMauro Carvalho Chehab }
1132786baecfSMauro Carvalho Chehab 
1133786baecfSMauro Carvalho Chehab static void ttusb_dec_free_iso_urbs(struct ttusb_dec *dec)
1134786baecfSMauro Carvalho Chehab {
1135786baecfSMauro Carvalho Chehab 	int i;
1136786baecfSMauro Carvalho Chehab 
1137786baecfSMauro Carvalho Chehab 	dprintk("%s\n", __func__);
1138786baecfSMauro Carvalho Chehab 
1139786baecfSMauro Carvalho Chehab 	for (i = 0; i < ISO_BUF_COUNT; i++)
1140786baecfSMauro Carvalho Chehab 		usb_free_urb(dec->iso_urb[i]);
1141786baecfSMauro Carvalho Chehab 
1142786baecfSMauro Carvalho Chehab 	pci_free_consistent(NULL,
1143786baecfSMauro Carvalho Chehab 			    ISO_FRAME_SIZE * (FRAMES_PER_ISO_BUF *
1144786baecfSMauro Carvalho Chehab 					      ISO_BUF_COUNT),
1145786baecfSMauro Carvalho Chehab 			    dec->iso_buffer, dec->iso_dma_handle);
1146786baecfSMauro Carvalho Chehab }
1147786baecfSMauro Carvalho Chehab 
1148786baecfSMauro Carvalho Chehab static int ttusb_dec_alloc_iso_urbs(struct ttusb_dec *dec)
1149786baecfSMauro Carvalho Chehab {
1150786baecfSMauro Carvalho Chehab 	int i;
1151786baecfSMauro Carvalho Chehab 
1152786baecfSMauro Carvalho Chehab 	dprintk("%s\n", __func__);
1153786baecfSMauro Carvalho Chehab 
1154786baecfSMauro Carvalho Chehab 	dec->iso_buffer = pci_alloc_consistent(NULL,
1155786baecfSMauro Carvalho Chehab 					       ISO_FRAME_SIZE *
1156786baecfSMauro Carvalho Chehab 					       (FRAMES_PER_ISO_BUF *
1157786baecfSMauro Carvalho Chehab 						ISO_BUF_COUNT),
1158786baecfSMauro Carvalho Chehab 					       &dec->iso_dma_handle);
1159786baecfSMauro Carvalho Chehab 
1160786baecfSMauro Carvalho Chehab 	if (!dec->iso_buffer) {
1161786baecfSMauro Carvalho Chehab 		dprintk("%s: pci_alloc_consistent - not enough memory\n",
1162786baecfSMauro Carvalho Chehab 			__func__);
1163786baecfSMauro Carvalho Chehab 		return -ENOMEM;
1164786baecfSMauro Carvalho Chehab 	}
1165786baecfSMauro Carvalho Chehab 
1166786baecfSMauro Carvalho Chehab 	memset(dec->iso_buffer, 0,
1167786baecfSMauro Carvalho Chehab 	       ISO_FRAME_SIZE * (FRAMES_PER_ISO_BUF * ISO_BUF_COUNT));
1168786baecfSMauro Carvalho Chehab 
1169786baecfSMauro Carvalho Chehab 	for (i = 0; i < ISO_BUF_COUNT; i++) {
1170786baecfSMauro Carvalho Chehab 		struct urb *urb;
1171786baecfSMauro Carvalho Chehab 
1172786baecfSMauro Carvalho Chehab 		if (!(urb = usb_alloc_urb(FRAMES_PER_ISO_BUF, GFP_ATOMIC))) {
1173786baecfSMauro Carvalho Chehab 			ttusb_dec_free_iso_urbs(dec);
1174786baecfSMauro Carvalho Chehab 			return -ENOMEM;
1175786baecfSMauro Carvalho Chehab 		}
1176786baecfSMauro Carvalho Chehab 
1177786baecfSMauro Carvalho Chehab 		dec->iso_urb[i] = urb;
1178786baecfSMauro Carvalho Chehab 	}
1179786baecfSMauro Carvalho Chehab 
1180786baecfSMauro Carvalho Chehab 	ttusb_dec_setup_urbs(dec);
1181786baecfSMauro Carvalho Chehab 
1182786baecfSMauro Carvalho Chehab 	return 0;
1183786baecfSMauro Carvalho Chehab }
1184786baecfSMauro Carvalho Chehab 
1185786baecfSMauro Carvalho Chehab static void ttusb_dec_init_tasklet(struct ttusb_dec *dec)
1186786baecfSMauro Carvalho Chehab {
1187786baecfSMauro Carvalho Chehab 	spin_lock_init(&dec->urb_frame_list_lock);
1188786baecfSMauro Carvalho Chehab 	INIT_LIST_HEAD(&dec->urb_frame_list);
1189786baecfSMauro Carvalho Chehab 	tasklet_init(&dec->urb_tasklet, ttusb_dec_process_urb_frame_list,
1190786baecfSMauro Carvalho Chehab 		     (unsigned long)dec);
1191786baecfSMauro Carvalho Chehab }
1192786baecfSMauro Carvalho Chehab 
1193786baecfSMauro Carvalho Chehab static int ttusb_init_rc( struct ttusb_dec *dec)
1194786baecfSMauro Carvalho Chehab {
1195786baecfSMauro Carvalho Chehab 	struct input_dev *input_dev;
1196786baecfSMauro Carvalho Chehab 	u8 b[] = { 0x00, 0x01 };
1197786baecfSMauro Carvalho Chehab 	int i;
1198786baecfSMauro Carvalho Chehab 	int err;
1199786baecfSMauro Carvalho Chehab 
1200786baecfSMauro Carvalho Chehab 	usb_make_path(dec->udev, dec->rc_phys, sizeof(dec->rc_phys));
1201786baecfSMauro Carvalho Chehab 	strlcat(dec->rc_phys, "/input0", sizeof(dec->rc_phys));
1202786baecfSMauro Carvalho Chehab 
1203786baecfSMauro Carvalho Chehab 	input_dev = input_allocate_device();
1204786baecfSMauro Carvalho Chehab 	if (!input_dev)
1205786baecfSMauro Carvalho Chehab 		return -ENOMEM;
1206786baecfSMauro Carvalho Chehab 
1207786baecfSMauro Carvalho Chehab 	input_dev->name = "ttusb_dec remote control";
1208786baecfSMauro Carvalho Chehab 	input_dev->phys = dec->rc_phys;
1209786baecfSMauro Carvalho Chehab 	input_dev->evbit[0] = BIT_MASK(EV_KEY);
1210786baecfSMauro Carvalho Chehab 	input_dev->keycodesize = sizeof(u16);
1211786baecfSMauro Carvalho Chehab 	input_dev->keycodemax = 0x1a;
1212786baecfSMauro Carvalho Chehab 	input_dev->keycode = rc_keys;
1213786baecfSMauro Carvalho Chehab 
1214786baecfSMauro Carvalho Chehab 	for (i = 0; i < ARRAY_SIZE(rc_keys); i++)
1215786baecfSMauro Carvalho Chehab 		  set_bit(rc_keys[i], input_dev->keybit);
1216786baecfSMauro Carvalho Chehab 
1217786baecfSMauro Carvalho Chehab 	err = input_register_device(input_dev);
1218786baecfSMauro Carvalho Chehab 	if (err) {
1219786baecfSMauro Carvalho Chehab 		input_free_device(input_dev);
1220786baecfSMauro Carvalho Chehab 		return err;
1221786baecfSMauro Carvalho Chehab 	}
1222786baecfSMauro Carvalho Chehab 
1223786baecfSMauro Carvalho Chehab 	dec->rc_input_dev = input_dev;
1224786baecfSMauro Carvalho Chehab 	if (usb_submit_urb(dec->irq_urb, GFP_KERNEL))
1225786baecfSMauro Carvalho Chehab 		printk("%s: usb_submit_urb failed\n",__func__);
1226786baecfSMauro Carvalho Chehab 	/* enable irq pipe */
1227786baecfSMauro Carvalho Chehab 	ttusb_dec_send_command(dec,0xb0,sizeof(b),b,NULL,NULL);
1228786baecfSMauro Carvalho Chehab 
1229786baecfSMauro Carvalho Chehab 	return 0;
1230786baecfSMauro Carvalho Chehab }
1231786baecfSMauro Carvalho Chehab 
1232786baecfSMauro Carvalho Chehab static void ttusb_dec_init_v_pes(struct ttusb_dec *dec)
1233786baecfSMauro Carvalho Chehab {
1234786baecfSMauro Carvalho Chehab 	dprintk("%s\n", __func__);
1235786baecfSMauro Carvalho Chehab 
1236786baecfSMauro Carvalho Chehab 	dec->v_pes[0] = 0x00;
1237786baecfSMauro Carvalho Chehab 	dec->v_pes[1] = 0x00;
1238786baecfSMauro Carvalho Chehab 	dec->v_pes[2] = 0x01;
1239786baecfSMauro Carvalho Chehab 	dec->v_pes[3] = 0xe0;
1240786baecfSMauro Carvalho Chehab }
1241786baecfSMauro Carvalho Chehab 
1242786baecfSMauro Carvalho Chehab static int ttusb_dec_init_usb(struct ttusb_dec *dec)
1243786baecfSMauro Carvalho Chehab {
1244cf732b5fSAlexey Khoroshilov 	int result;
1245cf732b5fSAlexey Khoroshilov 
1246786baecfSMauro Carvalho Chehab 	dprintk("%s\n", __func__);
1247786baecfSMauro Carvalho Chehab 
1248786baecfSMauro Carvalho Chehab 	mutex_init(&dec->usb_mutex);
1249786baecfSMauro Carvalho Chehab 	mutex_init(&dec->iso_mutex);
1250786baecfSMauro Carvalho Chehab 
1251786baecfSMauro Carvalho Chehab 	dec->command_pipe = usb_sndbulkpipe(dec->udev, COMMAND_PIPE);
1252786baecfSMauro Carvalho Chehab 	dec->result_pipe = usb_rcvbulkpipe(dec->udev, RESULT_PIPE);
1253786baecfSMauro Carvalho Chehab 	dec->in_pipe = usb_rcvisocpipe(dec->udev, IN_PIPE);
1254786baecfSMauro Carvalho Chehab 	dec->out_pipe = usb_sndisocpipe(dec->udev, OUT_PIPE);
1255786baecfSMauro Carvalho Chehab 	dec->irq_pipe = usb_rcvintpipe(dec->udev, IRQ_PIPE);
1256786baecfSMauro Carvalho Chehab 
1257786baecfSMauro Carvalho Chehab 	if(enable_rc) {
1258786baecfSMauro Carvalho Chehab 		dec->irq_urb = usb_alloc_urb(0, GFP_KERNEL);
1259786baecfSMauro Carvalho Chehab 		if(!dec->irq_urb) {
1260786baecfSMauro Carvalho Chehab 			return -ENOMEM;
1261786baecfSMauro Carvalho Chehab 		}
1262786baecfSMauro Carvalho Chehab 		dec->irq_buffer = usb_alloc_coherent(dec->udev,IRQ_PACKET_SIZE,
1263cf732b5fSAlexey Khoroshilov 					GFP_KERNEL, &dec->irq_dma_handle);
1264786baecfSMauro Carvalho Chehab 		if(!dec->irq_buffer) {
1265786baecfSMauro Carvalho Chehab 			usb_free_urb(dec->irq_urb);
1266786baecfSMauro Carvalho Chehab 			return -ENOMEM;
1267786baecfSMauro Carvalho Chehab 		}
1268786baecfSMauro Carvalho Chehab 		usb_fill_int_urb(dec->irq_urb, dec->udev,dec->irq_pipe,
1269786baecfSMauro Carvalho Chehab 				 dec->irq_buffer, IRQ_PACKET_SIZE,
1270786baecfSMauro Carvalho Chehab 				 ttusb_dec_handle_irq, dec, 1);
1271786baecfSMauro Carvalho Chehab 		dec->irq_urb->transfer_dma = dec->irq_dma_handle;
1272786baecfSMauro Carvalho Chehab 		dec->irq_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
1273786baecfSMauro Carvalho Chehab 	}
1274786baecfSMauro Carvalho Chehab 
1275cf732b5fSAlexey Khoroshilov 	result = ttusb_dec_alloc_iso_urbs(dec);
1276cf732b5fSAlexey Khoroshilov 	if (result) {
1277cf732b5fSAlexey Khoroshilov 		usb_free_urb(dec->irq_urb);
1278cf732b5fSAlexey Khoroshilov 		usb_free_coherent(dec->udev, IRQ_PACKET_SIZE,
1279cf732b5fSAlexey Khoroshilov 				  dec->irq_buffer, dec->irq_dma_handle);
1280cf732b5fSAlexey Khoroshilov 	}
1281cf732b5fSAlexey Khoroshilov 	return result;
1282786baecfSMauro Carvalho Chehab }
1283786baecfSMauro Carvalho Chehab 
1284786baecfSMauro Carvalho Chehab static int ttusb_dec_boot_dsp(struct ttusb_dec *dec)
1285786baecfSMauro Carvalho Chehab {
1286786baecfSMauro Carvalho Chehab 	int i, j, actual_len, result, size, trans_count;
1287786baecfSMauro Carvalho Chehab 	u8 b0[] = { 0x00, 0x00, 0x00, 0x00,
1288786baecfSMauro Carvalho Chehab 		    0x00, 0x00, 0x00, 0x00,
1289786baecfSMauro Carvalho Chehab 		    0x61, 0x00 };
1290786baecfSMauro Carvalho Chehab 	u8 b1[] = { 0x61 };
1291786baecfSMauro Carvalho Chehab 	u8 *b;
1292786baecfSMauro Carvalho Chehab 	char idstring[21];
1293786baecfSMauro Carvalho Chehab 	const u8 *firmware = NULL;
1294786baecfSMauro Carvalho Chehab 	size_t firmware_size = 0;
1295786baecfSMauro Carvalho Chehab 	u16 firmware_csum = 0;
1296786baecfSMauro Carvalho Chehab 	__be16 firmware_csum_ns;
1297786baecfSMauro Carvalho Chehab 	__be32 firmware_size_nl;
1298786baecfSMauro Carvalho Chehab 	u32 crc32_csum, crc32_check;
1299786baecfSMauro Carvalho Chehab 	__be32 tmp;
1300786baecfSMauro Carvalho Chehab 	const struct firmware *fw_entry = NULL;
1301786baecfSMauro Carvalho Chehab 
1302786baecfSMauro Carvalho Chehab 	dprintk("%s\n", __func__);
1303786baecfSMauro Carvalho Chehab 
1304cf732b5fSAlexey Khoroshilov 	result = request_firmware(&fw_entry, dec->firmware_name, &dec->udev->dev);
1305cf732b5fSAlexey Khoroshilov 	if (result) {
1306786baecfSMauro Carvalho Chehab 		printk(KERN_ERR "%s: Firmware (%s) unavailable.\n",
1307786baecfSMauro Carvalho Chehab 		       __func__, dec->firmware_name);
1308cf732b5fSAlexey Khoroshilov 		return result;
1309786baecfSMauro Carvalho Chehab 	}
1310786baecfSMauro Carvalho Chehab 
1311786baecfSMauro Carvalho Chehab 	firmware = fw_entry->data;
1312786baecfSMauro Carvalho Chehab 	firmware_size = fw_entry->size;
1313786baecfSMauro Carvalho Chehab 
1314786baecfSMauro Carvalho Chehab 	if (firmware_size < 60) {
1315786baecfSMauro Carvalho Chehab 		printk("%s: firmware size too small for DSP code (%zu < 60).\n",
1316786baecfSMauro Carvalho Chehab 			__func__, firmware_size);
1317786baecfSMauro Carvalho Chehab 		release_firmware(fw_entry);
1318cf732b5fSAlexey Khoroshilov 		return -ENOENT;
1319786baecfSMauro Carvalho Chehab 	}
1320786baecfSMauro Carvalho Chehab 
1321786baecfSMauro Carvalho Chehab 	/* a 32 bit checksum over the first 56 bytes of the DSP Code is stored
1322786baecfSMauro Carvalho Chehab 	   at offset 56 of file, so use it to check if the firmware file is
1323786baecfSMauro Carvalho Chehab 	   valid. */
1324786baecfSMauro Carvalho Chehab 	crc32_csum = crc32(~0L, firmware, 56) ^ ~0L;
1325786baecfSMauro Carvalho Chehab 	memcpy(&tmp, &firmware[56], 4);
1326786baecfSMauro Carvalho Chehab 	crc32_check = ntohl(tmp);
1327786baecfSMauro Carvalho Chehab 	if (crc32_csum != crc32_check) {
1328786baecfSMauro Carvalho Chehab 		printk("%s: crc32 check of DSP code failed (calculated "
1329786baecfSMauro Carvalho Chehab 		       "0x%08x != 0x%08x in file), file invalid.\n",
1330786baecfSMauro Carvalho Chehab 			__func__, crc32_csum, crc32_check);
1331786baecfSMauro Carvalho Chehab 		release_firmware(fw_entry);
1332cf732b5fSAlexey Khoroshilov 		return -ENOENT;
1333786baecfSMauro Carvalho Chehab 	}
1334786baecfSMauro Carvalho Chehab 	memcpy(idstring, &firmware[36], 20);
1335786baecfSMauro Carvalho Chehab 	idstring[20] = '\0';
1336786baecfSMauro Carvalho Chehab 	printk(KERN_INFO "ttusb_dec: found DSP code \"%s\".\n", idstring);
1337786baecfSMauro Carvalho Chehab 
1338786baecfSMauro Carvalho Chehab 	firmware_size_nl = htonl(firmware_size);
1339786baecfSMauro Carvalho Chehab 	memcpy(b0, &firmware_size_nl, 4);
1340786baecfSMauro Carvalho Chehab 	firmware_csum = crc16(~0, firmware, firmware_size) ^ ~0;
1341786baecfSMauro Carvalho Chehab 	firmware_csum_ns = htons(firmware_csum);
1342786baecfSMauro Carvalho Chehab 	memcpy(&b0[6], &firmware_csum_ns, 2);
1343786baecfSMauro Carvalho Chehab 
1344786baecfSMauro Carvalho Chehab 	result = ttusb_dec_send_command(dec, 0x41, sizeof(b0), b0, NULL, NULL);
1345786baecfSMauro Carvalho Chehab 
1346786baecfSMauro Carvalho Chehab 	if (result) {
1347786baecfSMauro Carvalho Chehab 		release_firmware(fw_entry);
1348786baecfSMauro Carvalho Chehab 		return result;
1349786baecfSMauro Carvalho Chehab 	}
1350786baecfSMauro Carvalho Chehab 
1351786baecfSMauro Carvalho Chehab 	trans_count = 0;
1352786baecfSMauro Carvalho Chehab 	j = 0;
1353786baecfSMauro Carvalho Chehab 
1354786baecfSMauro Carvalho Chehab 	b = kmalloc(ARM_PACKET_SIZE, GFP_KERNEL);
1355786baecfSMauro Carvalho Chehab 	if (b == NULL) {
1356786baecfSMauro Carvalho Chehab 		release_firmware(fw_entry);
1357786baecfSMauro Carvalho Chehab 		return -ENOMEM;
1358786baecfSMauro Carvalho Chehab 	}
1359786baecfSMauro Carvalho Chehab 
1360786baecfSMauro Carvalho Chehab 	for (i = 0; i < firmware_size; i += COMMAND_PACKET_SIZE) {
1361786baecfSMauro Carvalho Chehab 		size = firmware_size - i;
1362786baecfSMauro Carvalho Chehab 		if (size > COMMAND_PACKET_SIZE)
1363786baecfSMauro Carvalho Chehab 			size = COMMAND_PACKET_SIZE;
1364786baecfSMauro Carvalho Chehab 
1365786baecfSMauro Carvalho Chehab 		b[j + 0] = 0xaa;
1366786baecfSMauro Carvalho Chehab 		b[j + 1] = trans_count++;
1367786baecfSMauro Carvalho Chehab 		b[j + 2] = 0xf0;
1368786baecfSMauro Carvalho Chehab 		b[j + 3] = size;
1369786baecfSMauro Carvalho Chehab 		memcpy(&b[j + 4], &firmware[i], size);
1370786baecfSMauro Carvalho Chehab 
1371786baecfSMauro Carvalho Chehab 		j += COMMAND_PACKET_SIZE + 4;
1372786baecfSMauro Carvalho Chehab 
1373786baecfSMauro Carvalho Chehab 		if (j >= ARM_PACKET_SIZE) {
1374786baecfSMauro Carvalho Chehab 			result = usb_bulk_msg(dec->udev, dec->command_pipe, b,
1375786baecfSMauro Carvalho Chehab 					      ARM_PACKET_SIZE, &actual_len,
1376786baecfSMauro Carvalho Chehab 					      100);
1377786baecfSMauro Carvalho Chehab 			j = 0;
1378786baecfSMauro Carvalho Chehab 		} else if (size < COMMAND_PACKET_SIZE) {
1379786baecfSMauro Carvalho Chehab 			result = usb_bulk_msg(dec->udev, dec->command_pipe, b,
1380786baecfSMauro Carvalho Chehab 					      j - COMMAND_PACKET_SIZE + size,
1381786baecfSMauro Carvalho Chehab 					      &actual_len, 100);
1382786baecfSMauro Carvalho Chehab 		}
1383786baecfSMauro Carvalho Chehab 	}
1384786baecfSMauro Carvalho Chehab 
1385786baecfSMauro Carvalho Chehab 	result = ttusb_dec_send_command(dec, 0x43, sizeof(b1), b1, NULL, NULL);
1386786baecfSMauro Carvalho Chehab 
1387786baecfSMauro Carvalho Chehab 	release_firmware(fw_entry);
1388786baecfSMauro Carvalho Chehab 	kfree(b);
1389786baecfSMauro Carvalho Chehab 
1390786baecfSMauro Carvalho Chehab 	return result;
1391786baecfSMauro Carvalho Chehab }
1392786baecfSMauro Carvalho Chehab 
1393786baecfSMauro Carvalho Chehab static int ttusb_dec_init_stb(struct ttusb_dec *dec)
1394786baecfSMauro Carvalho Chehab {
1395786baecfSMauro Carvalho Chehab 	int result;
1396786baecfSMauro Carvalho Chehab 	unsigned int mode = 0, model = 0, version = 0;
1397786baecfSMauro Carvalho Chehab 
1398786baecfSMauro Carvalho Chehab 	dprintk("%s\n", __func__);
1399786baecfSMauro Carvalho Chehab 
1400786baecfSMauro Carvalho Chehab 	result = ttusb_dec_get_stb_state(dec, &mode, &model, &version);
1401cf732b5fSAlexey Khoroshilov 	if (result)
1402cf732b5fSAlexey Khoroshilov 		return result;
1403786baecfSMauro Carvalho Chehab 
1404786baecfSMauro Carvalho Chehab 	if (!mode) {
1405786baecfSMauro Carvalho Chehab 		if (version == 0xABCDEFAB)
1406786baecfSMauro Carvalho Chehab 			printk(KERN_INFO "ttusb_dec: no version "
1407786baecfSMauro Carvalho Chehab 			       "info in Firmware\n");
1408786baecfSMauro Carvalho Chehab 		else
1409786baecfSMauro Carvalho Chehab 			printk(KERN_INFO "ttusb_dec: Firmware "
1410786baecfSMauro Carvalho Chehab 			       "%x.%02x%c%c\n",
1411786baecfSMauro Carvalho Chehab 			       version >> 24, (version >> 16) & 0xff,
1412786baecfSMauro Carvalho Chehab 			       (version >> 8) & 0xff, version & 0xff);
1413786baecfSMauro Carvalho Chehab 
1414786baecfSMauro Carvalho Chehab 		result = ttusb_dec_boot_dsp(dec);
1415786baecfSMauro Carvalho Chehab 		if (result)
1416786baecfSMauro Carvalho Chehab 			return result;
1417786baecfSMauro Carvalho Chehab 	} else {
1418786baecfSMauro Carvalho Chehab 		/* We can't trust the USB IDs that some firmwares
1419786baecfSMauro Carvalho Chehab 		   give the box */
1420786baecfSMauro Carvalho Chehab 		switch (model) {
1421786baecfSMauro Carvalho Chehab 		case 0x00070001:
1422786baecfSMauro Carvalho Chehab 		case 0x00070008:
1423786baecfSMauro Carvalho Chehab 		case 0x0007000c:
1424786baecfSMauro Carvalho Chehab 			ttusb_dec_set_model(dec, TTUSB_DEC3000S);
1425786baecfSMauro Carvalho Chehab 			break;
1426786baecfSMauro Carvalho Chehab 		case 0x00070009:
1427786baecfSMauro Carvalho Chehab 		case 0x00070013:
1428786baecfSMauro Carvalho Chehab 			ttusb_dec_set_model(dec, TTUSB_DEC2000T);
1429786baecfSMauro Carvalho Chehab 			break;
1430786baecfSMauro Carvalho Chehab 		case 0x00070011:
1431786baecfSMauro Carvalho Chehab 			ttusb_dec_set_model(dec, TTUSB_DEC2540T);
1432786baecfSMauro Carvalho Chehab 			break;
1433786baecfSMauro Carvalho Chehab 		default:
1434786baecfSMauro Carvalho Chehab 			printk(KERN_ERR "%s: unknown model returned "
1435786baecfSMauro Carvalho Chehab 			       "by firmware (%08x) - please report\n",
1436786baecfSMauro Carvalho Chehab 			       __func__, model);
1437cf732b5fSAlexey Khoroshilov 			return -ENOENT;
1438786baecfSMauro Carvalho Chehab 		}
1439786baecfSMauro Carvalho Chehab 			if (version >= 0x01770000)
1440786baecfSMauro Carvalho Chehab 				dec->can_playback = 1;
1441cf732b5fSAlexey Khoroshilov 	}
1442786baecfSMauro Carvalho Chehab 	return 0;
1443786baecfSMauro Carvalho Chehab }
1444786baecfSMauro Carvalho Chehab 
1445786baecfSMauro Carvalho Chehab static int ttusb_dec_init_dvb(struct ttusb_dec *dec)
1446786baecfSMauro Carvalho Chehab {
1447786baecfSMauro Carvalho Chehab 	int result;
1448786baecfSMauro Carvalho Chehab 
1449786baecfSMauro Carvalho Chehab 	dprintk("%s\n", __func__);
1450786baecfSMauro Carvalho Chehab 
1451786baecfSMauro Carvalho Chehab 	if ((result = dvb_register_adapter(&dec->adapter,
1452786baecfSMauro Carvalho Chehab 					   dec->model_name, THIS_MODULE,
1453786baecfSMauro Carvalho Chehab 					   &dec->udev->dev,
1454786baecfSMauro Carvalho Chehab 					   adapter_nr)) < 0) {
1455786baecfSMauro Carvalho Chehab 		printk("%s: dvb_register_adapter failed: error %d\n",
1456786baecfSMauro Carvalho Chehab 		       __func__, result);
1457786baecfSMauro Carvalho Chehab 
1458786baecfSMauro Carvalho Chehab 		return result;
1459786baecfSMauro Carvalho Chehab 	}
1460786baecfSMauro Carvalho Chehab 
1461786baecfSMauro Carvalho Chehab 	dec->demux.dmx.capabilities = DMX_TS_FILTERING | DMX_SECTION_FILTERING;
1462786baecfSMauro Carvalho Chehab 
1463786baecfSMauro Carvalho Chehab 	dec->demux.priv = (void *)dec;
1464786baecfSMauro Carvalho Chehab 	dec->demux.filternum = 31;
1465786baecfSMauro Carvalho Chehab 	dec->demux.feednum = 31;
1466786baecfSMauro Carvalho Chehab 	dec->demux.start_feed = ttusb_dec_start_feed;
1467786baecfSMauro Carvalho Chehab 	dec->demux.stop_feed = ttusb_dec_stop_feed;
1468786baecfSMauro Carvalho Chehab 	dec->demux.write_to_decoder = NULL;
1469786baecfSMauro Carvalho Chehab 
1470786baecfSMauro Carvalho Chehab 	if ((result = dvb_dmx_init(&dec->demux)) < 0) {
1471786baecfSMauro Carvalho Chehab 		printk("%s: dvb_dmx_init failed: error %d\n", __func__,
1472786baecfSMauro Carvalho Chehab 		       result);
1473786baecfSMauro Carvalho Chehab 
1474786baecfSMauro Carvalho Chehab 		dvb_unregister_adapter(&dec->adapter);
1475786baecfSMauro Carvalho Chehab 
1476786baecfSMauro Carvalho Chehab 		return result;
1477786baecfSMauro Carvalho Chehab 	}
1478786baecfSMauro Carvalho Chehab 
1479786baecfSMauro Carvalho Chehab 	dec->dmxdev.filternum = 32;
1480786baecfSMauro Carvalho Chehab 	dec->dmxdev.demux = &dec->demux.dmx;
1481786baecfSMauro Carvalho Chehab 	dec->dmxdev.capabilities = 0;
1482786baecfSMauro Carvalho Chehab 
1483786baecfSMauro Carvalho Chehab 	if ((result = dvb_dmxdev_init(&dec->dmxdev, &dec->adapter)) < 0) {
1484786baecfSMauro Carvalho Chehab 		printk("%s: dvb_dmxdev_init failed: error %d\n",
1485786baecfSMauro Carvalho Chehab 		       __func__, result);
1486786baecfSMauro Carvalho Chehab 
1487786baecfSMauro Carvalho Chehab 		dvb_dmx_release(&dec->demux);
1488786baecfSMauro Carvalho Chehab 		dvb_unregister_adapter(&dec->adapter);
1489786baecfSMauro Carvalho Chehab 
1490786baecfSMauro Carvalho Chehab 		return result;
1491786baecfSMauro Carvalho Chehab 	}
1492786baecfSMauro Carvalho Chehab 
1493786baecfSMauro Carvalho Chehab 	dec->frontend.source = DMX_FRONTEND_0;
1494786baecfSMauro Carvalho Chehab 
1495786baecfSMauro Carvalho Chehab 	if ((result = dec->demux.dmx.add_frontend(&dec->demux.dmx,
1496786baecfSMauro Carvalho Chehab 						  &dec->frontend)) < 0) {
1497786baecfSMauro Carvalho Chehab 		printk("%s: dvb_dmx_init failed: error %d\n", __func__,
1498786baecfSMauro Carvalho Chehab 		       result);
1499786baecfSMauro Carvalho Chehab 
1500786baecfSMauro Carvalho Chehab 		dvb_dmxdev_release(&dec->dmxdev);
1501786baecfSMauro Carvalho Chehab 		dvb_dmx_release(&dec->demux);
1502786baecfSMauro Carvalho Chehab 		dvb_unregister_adapter(&dec->adapter);
1503786baecfSMauro Carvalho Chehab 
1504786baecfSMauro Carvalho Chehab 		return result;
1505786baecfSMauro Carvalho Chehab 	}
1506786baecfSMauro Carvalho Chehab 
1507786baecfSMauro Carvalho Chehab 	if ((result = dec->demux.dmx.connect_frontend(&dec->demux.dmx,
1508786baecfSMauro Carvalho Chehab 						      &dec->frontend)) < 0) {
1509786baecfSMauro Carvalho Chehab 		printk("%s: dvb_dmx_init failed: error %d\n", __func__,
1510786baecfSMauro Carvalho Chehab 		       result);
1511786baecfSMauro Carvalho Chehab 
1512786baecfSMauro Carvalho Chehab 		dec->demux.dmx.remove_frontend(&dec->demux.dmx, &dec->frontend);
1513786baecfSMauro Carvalho Chehab 		dvb_dmxdev_release(&dec->dmxdev);
1514786baecfSMauro Carvalho Chehab 		dvb_dmx_release(&dec->demux);
1515786baecfSMauro Carvalho Chehab 		dvb_unregister_adapter(&dec->adapter);
1516786baecfSMauro Carvalho Chehab 
1517786baecfSMauro Carvalho Chehab 		return result;
1518786baecfSMauro Carvalho Chehab 	}
1519786baecfSMauro Carvalho Chehab 
1520786baecfSMauro Carvalho Chehab 	dvb_net_init(&dec->adapter, &dec->dvb_net, &dec->demux.dmx);
1521786baecfSMauro Carvalho Chehab 
1522786baecfSMauro Carvalho Chehab 	return 0;
1523786baecfSMauro Carvalho Chehab }
1524786baecfSMauro Carvalho Chehab 
1525786baecfSMauro Carvalho Chehab static void ttusb_dec_exit_dvb(struct ttusb_dec *dec)
1526786baecfSMauro Carvalho Chehab {
1527786baecfSMauro Carvalho Chehab 	dprintk("%s\n", __func__);
1528786baecfSMauro Carvalho Chehab 
1529786baecfSMauro Carvalho Chehab 	dvb_net_release(&dec->dvb_net);
1530786baecfSMauro Carvalho Chehab 	dec->demux.dmx.close(&dec->demux.dmx);
1531786baecfSMauro Carvalho Chehab 	dec->demux.dmx.remove_frontend(&dec->demux.dmx, &dec->frontend);
1532786baecfSMauro Carvalho Chehab 	dvb_dmxdev_release(&dec->dmxdev);
1533786baecfSMauro Carvalho Chehab 	dvb_dmx_release(&dec->demux);
1534786baecfSMauro Carvalho Chehab 	if (dec->fe) {
1535786baecfSMauro Carvalho Chehab 		dvb_unregister_frontend(dec->fe);
1536786baecfSMauro Carvalho Chehab 		if (dec->fe->ops.release)
1537786baecfSMauro Carvalho Chehab 			dec->fe->ops.release(dec->fe);
1538786baecfSMauro Carvalho Chehab 	}
1539786baecfSMauro Carvalho Chehab 	dvb_unregister_adapter(&dec->adapter);
1540786baecfSMauro Carvalho Chehab }
1541786baecfSMauro Carvalho Chehab 
1542786baecfSMauro Carvalho Chehab static void ttusb_dec_exit_rc(struct ttusb_dec *dec)
1543786baecfSMauro Carvalho Chehab {
1544786baecfSMauro Carvalho Chehab 	dprintk("%s\n", __func__);
1545786baecfSMauro Carvalho Chehab 
1546786baecfSMauro Carvalho Chehab 	if (dec->rc_input_dev) {
1547786baecfSMauro Carvalho Chehab 		input_unregister_device(dec->rc_input_dev);
1548786baecfSMauro Carvalho Chehab 		dec->rc_input_dev = NULL;
1549786baecfSMauro Carvalho Chehab 	}
1550786baecfSMauro Carvalho Chehab }
1551786baecfSMauro Carvalho Chehab 
1552786baecfSMauro Carvalho Chehab 
1553786baecfSMauro Carvalho Chehab static void ttusb_dec_exit_usb(struct ttusb_dec *dec)
1554786baecfSMauro Carvalho Chehab {
1555786baecfSMauro Carvalho Chehab 	int i;
1556786baecfSMauro Carvalho Chehab 
1557786baecfSMauro Carvalho Chehab 	dprintk("%s\n", __func__);
1558786baecfSMauro Carvalho Chehab 
1559cf732b5fSAlexey Khoroshilov 	if (enable_rc) {
1560cf732b5fSAlexey Khoroshilov 		/* we have to check whether the irq URB is already submitted.
1561cf732b5fSAlexey Khoroshilov 		 * As the irq is submitted after the interface is changed,
1562cf732b5fSAlexey Khoroshilov 		 * this is the best method i figured out.
1563cf732b5fSAlexey Khoroshilov 		 * Any others?*/
1564cf732b5fSAlexey Khoroshilov 		if (dec->interface == TTUSB_DEC_INTERFACE_IN)
1565cf732b5fSAlexey Khoroshilov 			usb_kill_urb(dec->irq_urb);
1566cf732b5fSAlexey Khoroshilov 
1567cf732b5fSAlexey Khoroshilov 		usb_free_urb(dec->irq_urb);
1568cf732b5fSAlexey Khoroshilov 
1569cf732b5fSAlexey Khoroshilov 		usb_free_coherent(dec->udev, IRQ_PACKET_SIZE,
1570cf732b5fSAlexey Khoroshilov 				  dec->irq_buffer, dec->irq_dma_handle);
1571cf732b5fSAlexey Khoroshilov 	}
1572cf732b5fSAlexey Khoroshilov 
1573786baecfSMauro Carvalho Chehab 	dec->iso_stream_count = 0;
1574786baecfSMauro Carvalho Chehab 
1575786baecfSMauro Carvalho Chehab 	for (i = 0; i < ISO_BUF_COUNT; i++)
1576786baecfSMauro Carvalho Chehab 		usb_kill_urb(dec->iso_urb[i]);
1577786baecfSMauro Carvalho Chehab 
1578786baecfSMauro Carvalho Chehab 	ttusb_dec_free_iso_urbs(dec);
1579786baecfSMauro Carvalho Chehab }
1580786baecfSMauro Carvalho Chehab 
1581786baecfSMauro Carvalho Chehab static void ttusb_dec_exit_tasklet(struct ttusb_dec *dec)
1582786baecfSMauro Carvalho Chehab {
1583786baecfSMauro Carvalho Chehab 	struct list_head *item;
1584786baecfSMauro Carvalho Chehab 	struct urb_frame *frame;
1585786baecfSMauro Carvalho Chehab 
1586786baecfSMauro Carvalho Chehab 	tasklet_kill(&dec->urb_tasklet);
1587786baecfSMauro Carvalho Chehab 
1588786baecfSMauro Carvalho Chehab 	while ((item = dec->urb_frame_list.next) != &dec->urb_frame_list) {
1589786baecfSMauro Carvalho Chehab 		frame = list_entry(item, struct urb_frame, urb_frame_list);
1590786baecfSMauro Carvalho Chehab 		list_del(&frame->urb_frame_list);
1591786baecfSMauro Carvalho Chehab 		kfree(frame);
1592786baecfSMauro Carvalho Chehab 	}
1593786baecfSMauro Carvalho Chehab }
1594786baecfSMauro Carvalho Chehab 
1595786baecfSMauro Carvalho Chehab static void ttusb_dec_init_filters(struct ttusb_dec *dec)
1596786baecfSMauro Carvalho Chehab {
1597786baecfSMauro Carvalho Chehab 	INIT_LIST_HEAD(&dec->filter_info_list);
1598786baecfSMauro Carvalho Chehab 	spin_lock_init(&dec->filter_info_list_lock);
1599786baecfSMauro Carvalho Chehab }
1600786baecfSMauro Carvalho Chehab 
1601786baecfSMauro Carvalho Chehab static void ttusb_dec_exit_filters(struct ttusb_dec *dec)
1602786baecfSMauro Carvalho Chehab {
1603786baecfSMauro Carvalho Chehab 	struct list_head *item;
1604786baecfSMauro Carvalho Chehab 	struct filter_info *finfo;
1605786baecfSMauro Carvalho Chehab 
1606786baecfSMauro Carvalho Chehab 	while ((item = dec->filter_info_list.next) != &dec->filter_info_list) {
1607786baecfSMauro Carvalho Chehab 		finfo = list_entry(item, struct filter_info, filter_info_list);
1608786baecfSMauro Carvalho Chehab 		list_del(&finfo->filter_info_list);
1609786baecfSMauro Carvalho Chehab 		kfree(finfo);
1610786baecfSMauro Carvalho Chehab 	}
1611786baecfSMauro Carvalho Chehab }
1612786baecfSMauro Carvalho Chehab 
1613786baecfSMauro Carvalho Chehab static int fe_send_command(struct dvb_frontend* fe, const u8 command,
1614786baecfSMauro Carvalho Chehab 			   int param_length, const u8 params[],
1615786baecfSMauro Carvalho Chehab 			   int *result_length, u8 cmd_result[])
1616786baecfSMauro Carvalho Chehab {
1617786baecfSMauro Carvalho Chehab 	struct ttusb_dec* dec = fe->dvb->priv;
1618786baecfSMauro Carvalho Chehab 	return ttusb_dec_send_command(dec, command, param_length, params, result_length, cmd_result);
1619786baecfSMauro Carvalho Chehab }
1620786baecfSMauro Carvalho Chehab 
1621786baecfSMauro Carvalho Chehab static struct ttusbdecfe_config fe_config = {
1622786baecfSMauro Carvalho Chehab 	.send_command = fe_send_command
1623786baecfSMauro Carvalho Chehab };
1624786baecfSMauro Carvalho Chehab 
1625786baecfSMauro Carvalho Chehab static int ttusb_dec_probe(struct usb_interface *intf,
1626786baecfSMauro Carvalho Chehab 			   const struct usb_device_id *id)
1627786baecfSMauro Carvalho Chehab {
1628786baecfSMauro Carvalho Chehab 	struct usb_device *udev;
1629786baecfSMauro Carvalho Chehab 	struct ttusb_dec *dec;
1630cf732b5fSAlexey Khoroshilov 	int result;
1631786baecfSMauro Carvalho Chehab 
1632786baecfSMauro Carvalho Chehab 	dprintk("%s\n", __func__);
1633786baecfSMauro Carvalho Chehab 
1634786baecfSMauro Carvalho Chehab 	udev = interface_to_usbdev(intf);
1635786baecfSMauro Carvalho Chehab 
1636786baecfSMauro Carvalho Chehab 	if (!(dec = kzalloc(sizeof(struct ttusb_dec), GFP_KERNEL))) {
1637786baecfSMauro Carvalho Chehab 		printk("%s: couldn't allocate memory.\n", __func__);
1638786baecfSMauro Carvalho Chehab 		return -ENOMEM;
1639786baecfSMauro Carvalho Chehab 	}
1640786baecfSMauro Carvalho Chehab 
1641786baecfSMauro Carvalho Chehab 	usb_set_intfdata(intf, (void *)dec);
1642786baecfSMauro Carvalho Chehab 
1643786baecfSMauro Carvalho Chehab 	switch (id->idProduct) {
1644786baecfSMauro Carvalho Chehab 	case 0x1006:
1645786baecfSMauro Carvalho Chehab 		ttusb_dec_set_model(dec, TTUSB_DEC3000S);
1646786baecfSMauro Carvalho Chehab 		break;
1647786baecfSMauro Carvalho Chehab 
1648786baecfSMauro Carvalho Chehab 	case 0x1008:
1649786baecfSMauro Carvalho Chehab 		ttusb_dec_set_model(dec, TTUSB_DEC2000T);
1650786baecfSMauro Carvalho Chehab 		break;
1651786baecfSMauro Carvalho Chehab 
1652786baecfSMauro Carvalho Chehab 	case 0x1009:
1653786baecfSMauro Carvalho Chehab 		ttusb_dec_set_model(dec, TTUSB_DEC2540T);
1654786baecfSMauro Carvalho Chehab 		break;
1655786baecfSMauro Carvalho Chehab 	}
1656786baecfSMauro Carvalho Chehab 
1657786baecfSMauro Carvalho Chehab 	dec->udev = udev;
1658786baecfSMauro Carvalho Chehab 
1659cf732b5fSAlexey Khoroshilov 	result = ttusb_dec_init_usb(dec);
1660cf732b5fSAlexey Khoroshilov 	if (result)
1661cf732b5fSAlexey Khoroshilov 		goto err_usb;
1662cf732b5fSAlexey Khoroshilov 	result = ttusb_dec_init_stb(dec);
1663cf732b5fSAlexey Khoroshilov 	if (result)
1664cf732b5fSAlexey Khoroshilov 		goto err_stb;
1665cf732b5fSAlexey Khoroshilov 	result = ttusb_dec_init_dvb(dec);
1666cf732b5fSAlexey Khoroshilov 	if (result)
1667cf732b5fSAlexey Khoroshilov 		goto err_stb;
1668786baecfSMauro Carvalho Chehab 
1669786baecfSMauro Carvalho Chehab 	dec->adapter.priv = dec;
1670786baecfSMauro Carvalho Chehab 	switch (id->idProduct) {
1671786baecfSMauro Carvalho Chehab 	case 0x1006:
1672786baecfSMauro Carvalho Chehab 		dec->fe = ttusbdecfe_dvbs_attach(&fe_config);
1673786baecfSMauro Carvalho Chehab 		break;
1674786baecfSMauro Carvalho Chehab 
1675786baecfSMauro Carvalho Chehab 	case 0x1008:
1676786baecfSMauro Carvalho Chehab 	case 0x1009:
1677786baecfSMauro Carvalho Chehab 		dec->fe = ttusbdecfe_dvbt_attach(&fe_config);
1678786baecfSMauro Carvalho Chehab 		break;
1679786baecfSMauro Carvalho Chehab 	}
1680786baecfSMauro Carvalho Chehab 
1681786baecfSMauro Carvalho Chehab 	if (dec->fe == NULL) {
1682786baecfSMauro Carvalho Chehab 		printk("dvb-ttusb-dec: A frontend driver was not found for device [%04x:%04x]\n",
1683786baecfSMauro Carvalho Chehab 		       le16_to_cpu(dec->udev->descriptor.idVendor),
1684786baecfSMauro Carvalho Chehab 		       le16_to_cpu(dec->udev->descriptor.idProduct));
1685786baecfSMauro Carvalho Chehab 	} else {
1686786baecfSMauro Carvalho Chehab 		if (dvb_register_frontend(&dec->adapter, dec->fe)) {
1687786baecfSMauro Carvalho Chehab 			printk("budget-ci: Frontend registration failed!\n");
1688786baecfSMauro Carvalho Chehab 			if (dec->fe->ops.release)
1689786baecfSMauro Carvalho Chehab 				dec->fe->ops.release(dec->fe);
1690786baecfSMauro Carvalho Chehab 			dec->fe = NULL;
1691786baecfSMauro Carvalho Chehab 		}
1692786baecfSMauro Carvalho Chehab 	}
1693786baecfSMauro Carvalho Chehab 
1694786baecfSMauro Carvalho Chehab 	ttusb_dec_init_v_pes(dec);
1695786baecfSMauro Carvalho Chehab 	ttusb_dec_init_filters(dec);
1696786baecfSMauro Carvalho Chehab 	ttusb_dec_init_tasklet(dec);
1697786baecfSMauro Carvalho Chehab 
1698786baecfSMauro Carvalho Chehab 	dec->active = 1;
1699786baecfSMauro Carvalho Chehab 
1700786baecfSMauro Carvalho Chehab 	ttusb_dec_set_interface(dec, TTUSB_DEC_INTERFACE_IN);
1701786baecfSMauro Carvalho Chehab 
1702786baecfSMauro Carvalho Chehab 	if (enable_rc)
1703786baecfSMauro Carvalho Chehab 		ttusb_init_rc(dec);
1704786baecfSMauro Carvalho Chehab 
1705786baecfSMauro Carvalho Chehab 	return 0;
1706cf732b5fSAlexey Khoroshilov err_stb:
1707cf732b5fSAlexey Khoroshilov 	ttusb_dec_exit_usb(dec);
1708cf732b5fSAlexey Khoroshilov err_usb:
1709cf732b5fSAlexey Khoroshilov 	kfree(dec);
1710cf732b5fSAlexey Khoroshilov 	return result;
1711786baecfSMauro Carvalho Chehab }
1712786baecfSMauro Carvalho Chehab 
1713786baecfSMauro Carvalho Chehab static void ttusb_dec_disconnect(struct usb_interface *intf)
1714786baecfSMauro Carvalho Chehab {
1715786baecfSMauro Carvalho Chehab 	struct ttusb_dec *dec = usb_get_intfdata(intf);
1716786baecfSMauro Carvalho Chehab 
1717786baecfSMauro Carvalho Chehab 	usb_set_intfdata(intf, NULL);
1718786baecfSMauro Carvalho Chehab 
1719786baecfSMauro Carvalho Chehab 	dprintk("%s\n", __func__);
1720786baecfSMauro Carvalho Chehab 
1721786baecfSMauro Carvalho Chehab 	if (dec->active) {
1722786baecfSMauro Carvalho Chehab 		ttusb_dec_exit_tasklet(dec);
1723786baecfSMauro Carvalho Chehab 		ttusb_dec_exit_filters(dec);
1724786baecfSMauro Carvalho Chehab 		if(enable_rc)
1725786baecfSMauro Carvalho Chehab 			ttusb_dec_exit_rc(dec);
1726786baecfSMauro Carvalho Chehab 		ttusb_dec_exit_usb(dec);
1727786baecfSMauro Carvalho Chehab 		ttusb_dec_exit_dvb(dec);
1728786baecfSMauro Carvalho Chehab 	}
1729786baecfSMauro Carvalho Chehab 
1730786baecfSMauro Carvalho Chehab 	kfree(dec);
1731786baecfSMauro Carvalho Chehab }
1732786baecfSMauro Carvalho Chehab 
1733786baecfSMauro Carvalho Chehab static void ttusb_dec_set_model(struct ttusb_dec *dec,
1734786baecfSMauro Carvalho Chehab 				enum ttusb_dec_model model)
1735786baecfSMauro Carvalho Chehab {
1736786baecfSMauro Carvalho Chehab 	dec->model = model;
1737786baecfSMauro Carvalho Chehab 
1738786baecfSMauro Carvalho Chehab 	switch (model) {
1739786baecfSMauro Carvalho Chehab 	case TTUSB_DEC2000T:
1740786baecfSMauro Carvalho Chehab 		dec->model_name = "DEC2000-t";
1741786baecfSMauro Carvalho Chehab 		dec->firmware_name = "dvb-ttusb-dec-2000t.fw";
1742786baecfSMauro Carvalho Chehab 		break;
1743786baecfSMauro Carvalho Chehab 
1744786baecfSMauro Carvalho Chehab 	case TTUSB_DEC2540T:
1745786baecfSMauro Carvalho Chehab 		dec->model_name = "DEC2540-t";
1746786baecfSMauro Carvalho Chehab 		dec->firmware_name = "dvb-ttusb-dec-2540t.fw";
1747786baecfSMauro Carvalho Chehab 		break;
1748786baecfSMauro Carvalho Chehab 
1749786baecfSMauro Carvalho Chehab 	case TTUSB_DEC3000S:
1750786baecfSMauro Carvalho Chehab 		dec->model_name = "DEC3000-s";
1751786baecfSMauro Carvalho Chehab 		dec->firmware_name = "dvb-ttusb-dec-3000s.fw";
1752786baecfSMauro Carvalho Chehab 		break;
1753786baecfSMauro Carvalho Chehab 	}
1754786baecfSMauro Carvalho Chehab }
1755786baecfSMauro Carvalho Chehab 
1756786baecfSMauro Carvalho Chehab static struct usb_device_id ttusb_dec_table[] = {
1757786baecfSMauro Carvalho Chehab 	{USB_DEVICE(0x0b48, 0x1006)},	/* DEC3000-s */
1758786baecfSMauro Carvalho Chehab 	/*{USB_DEVICE(0x0b48, 0x1007)},	   Unconfirmed */
1759786baecfSMauro Carvalho Chehab 	{USB_DEVICE(0x0b48, 0x1008)},	/* DEC2000-t */
1760786baecfSMauro Carvalho Chehab 	{USB_DEVICE(0x0b48, 0x1009)},	/* DEC2540-t */
1761786baecfSMauro Carvalho Chehab 	{}
1762786baecfSMauro Carvalho Chehab };
1763786baecfSMauro Carvalho Chehab 
1764786baecfSMauro Carvalho Chehab static struct usb_driver ttusb_dec_driver = {
1765786baecfSMauro Carvalho Chehab 	.name		= "ttusb-dec",
1766786baecfSMauro Carvalho Chehab 	.probe		= ttusb_dec_probe,
1767786baecfSMauro Carvalho Chehab 	.disconnect	= ttusb_dec_disconnect,
1768786baecfSMauro Carvalho Chehab 	.id_table	= ttusb_dec_table,
1769786baecfSMauro Carvalho Chehab };
1770786baecfSMauro Carvalho Chehab 
1771786baecfSMauro Carvalho Chehab module_usb_driver(ttusb_dec_driver);
1772786baecfSMauro Carvalho Chehab 
1773786baecfSMauro Carvalho Chehab MODULE_AUTHOR("Alex Woods <linux-dvb@giblets.org>");
1774786baecfSMauro Carvalho Chehab MODULE_DESCRIPTION(DRIVER_NAME);
1775786baecfSMauro Carvalho Chehab MODULE_LICENSE("GPL");
1776786baecfSMauro Carvalho Chehab MODULE_DEVICE_TABLE(usb, ttusb_dec_table);
1777