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