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