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