1265a6510629ab39f33ece43a857089dd37978184Steven Toth/*
2265a6510629ab39f33ece43a857089dd37978184Steven Toth *  Driver for the Auvitek USB bridge
3265a6510629ab39f33ece43a857089dd37978184Steven Toth *
46d8976164dd7d10d25fe940b8546265f60ad52cdSteven Toth *  Copyright (c) 2008 Steven Toth <stoth@linuxtv.org>
5265a6510629ab39f33ece43a857089dd37978184Steven Toth *
6265a6510629ab39f33ece43a857089dd37978184Steven Toth *  This program is free software; you can redistribute it and/or modify
7265a6510629ab39f33ece43a857089dd37978184Steven Toth *  it under the terms of the GNU General Public License as published by
8265a6510629ab39f33ece43a857089dd37978184Steven Toth *  the Free Software Foundation; either version 2 of the License, or
9265a6510629ab39f33ece43a857089dd37978184Steven Toth *  (at your option) any later version.
10265a6510629ab39f33ece43a857089dd37978184Steven Toth *
11265a6510629ab39f33ece43a857089dd37978184Steven Toth *  This program is distributed in the hope that it will be useful,
12265a6510629ab39f33ece43a857089dd37978184Steven Toth *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13265a6510629ab39f33ece43a857089dd37978184Steven Toth *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14265a6510629ab39f33ece43a857089dd37978184Steven Toth *
15265a6510629ab39f33ece43a857089dd37978184Steven Toth *  GNU General Public License for more details.
16265a6510629ab39f33ece43a857089dd37978184Steven Toth *
17265a6510629ab39f33ece43a857089dd37978184Steven Toth *  You should have received a copy of the GNU General Public License
18265a6510629ab39f33ece43a857089dd37978184Steven Toth *  along with this program; if not, write to the Free Software
19265a6510629ab39f33ece43a857089dd37978184Steven Toth *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20265a6510629ab39f33ece43a857089dd37978184Steven Toth */
21265a6510629ab39f33ece43a857089dd37978184Steven Toth
22265a6510629ab39f33ece43a857089dd37978184Steven Toth#include <linux/module.h>
235a0e3ad6af8660be21ca98a971cd00f331318c05Tejun Heo#include <linux/slab.h>
24265a6510629ab39f33ece43a857089dd37978184Steven Toth#include <linux/init.h>
25265a6510629ab39f33ece43a857089dd37978184Steven Toth#include <linux/device.h>
26265a6510629ab39f33ece43a857089dd37978184Steven Toth#include <linux/suspend.h>
27265a6510629ab39f33ece43a857089dd37978184Steven Toth#include <media/v4l2-common.h>
28265a6510629ab39f33ece43a857089dd37978184Steven Toth
29265a6510629ab39f33ece43a857089dd37978184Steven Toth#include "au0828.h"
30265a6510629ab39f33ece43a857089dd37978184Steven Toth#include "au8522.h"
31265a6510629ab39f33ece43a857089dd37978184Steven Toth#include "xc5000.h"
3259d27521c0f50fadf3382e2b325a7e8a04d9a770Michael Krufky#include "mxl5007t.h"
338e8bd229eef385ab420d4fa51c611d4ddc7cb0c8Michael Krufky#include "tda18271.h"
34265a6510629ab39f33ece43a857089dd37978184Steven Toth
35265a6510629ab39f33ece43a857089dd37978184Steven TothDVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
36265a6510629ab39f33ece43a857089dd37978184Steven Toth
37a9c36aad59a06df199cdbb365d0b05663f8008f1Steven Toth#define _AU0828_BULKPIPE 0x83
38a9c36aad59a06df199cdbb365d0b05663f8008f1Steven Toth#define _BULKPIPESIZE 0xe522
39a9c36aad59a06df199cdbb365d0b05663f8008f1Steven Toth
40adeeac3b7989ad9f03651e9224c9c63e221d4310Michael Krufkystatic u8 hauppauge_hvr950q_led_states[] = {
41adeeac3b7989ad9f03651e9224c9c63e221d4310Michael Krufky	0x00, /* off */
42adeeac3b7989ad9f03651e9224c9c63e221d4310Michael Krufky	0x02, /* yellow */
43adeeac3b7989ad9f03651e9224c9c63e221d4310Michael Krufky	0x04, /* green */
44adeeac3b7989ad9f03651e9224c9c63e221d4310Michael Krufky};
45adeeac3b7989ad9f03651e9224c9c63e221d4310Michael Krufky
46adeeac3b7989ad9f03651e9224c9c63e221d4310Michael Krufkystatic struct au8522_led_config hauppauge_hvr950q_led_cfg = {
47adeeac3b7989ad9f03651e9224c9c63e221d4310Michael Krufky	.gpio_output = 0x00e0,
48adeeac3b7989ad9f03651e9224c9c63e221d4310Michael Krufky	.gpio_output_enable  = 0x6006,
49adeeac3b7989ad9f03651e9224c9c63e221d4310Michael Krufky	.gpio_output_disable = 0x0660,
50adeeac3b7989ad9f03651e9224c9c63e221d4310Michael Krufky
51adeeac3b7989ad9f03651e9224c9c63e221d4310Michael Krufky	.gpio_leds = 0x00e2,
52adeeac3b7989ad9f03651e9224c9c63e221d4310Michael Krufky	.led_states  = hauppauge_hvr950q_led_states,
53adeeac3b7989ad9f03651e9224c9c63e221d4310Michael Krufky	.num_led_states = sizeof(hauppauge_hvr950q_led_states),
54adeeac3b7989ad9f03651e9224c9c63e221d4310Michael Krufky
55adeeac3b7989ad9f03651e9224c9c63e221d4310Michael Krufky	.vsb8_strong   = 20 /* dB */ * 10,
56adeeac3b7989ad9f03651e9224c9c63e221d4310Michael Krufky	.qam64_strong  = 25 /* dB */ * 10,
57adeeac3b7989ad9f03651e9224c9c63e221d4310Michael Krufky	.qam256_strong = 32 /* dB */ * 10,
58adeeac3b7989ad9f03651e9224c9c63e221d4310Michael Krufky};
59adeeac3b7989ad9f03651e9224c9c63e221d4310Michael Krufky
60265a6510629ab39f33ece43a857089dd37978184Steven Tothstatic struct au8522_config hauppauge_hvr950q_config = {
61265a6510629ab39f33ece43a857089dd37978184Steven Toth	.demod_address = 0x8e >> 1,
62265a6510629ab39f33ece43a857089dd37978184Steven Toth	.status_mode   = AU8522_DEMODLOCKING,
63e908b6e34c1b799c830cae5f8e721f80534f9748Michael Krufky	.qam_if        = AU8522_IF_6MHZ,
64e908b6e34c1b799c830cae5f8e721f80534f9748Michael Krufky	.vsb_if        = AU8522_IF_6MHZ,
65adeeac3b7989ad9f03651e9224c9c63e221d4310Michael Krufky	.led_cfg       = &hauppauge_hvr950q_led_cfg,
66adeeac3b7989ad9f03651e9224c9c63e221d4310Michael Krufky};
67adeeac3b7989ad9f03651e9224c9c63e221d4310Michael Krufky
68adeeac3b7989ad9f03651e9224c9c63e221d4310Michael Krufkystatic struct au8522_config fusionhdtv7usb_config = {
69adeeac3b7989ad9f03651e9224c9c63e221d4310Michael Krufky	.demod_address = 0x8e >> 1,
70adeeac3b7989ad9f03651e9224c9c63e221d4310Michael Krufky	.status_mode   = AU8522_DEMODLOCKING,
71adeeac3b7989ad9f03651e9224c9c63e221d4310Michael Krufky	.qam_if        = AU8522_IF_6MHZ,
72adeeac3b7989ad9f03651e9224c9c63e221d4310Michael Krufky	.vsb_if        = AU8522_IF_6MHZ,
73265a6510629ab39f33ece43a857089dd37978184Steven Toth};
74265a6510629ab39f33ece43a857089dd37978184Steven Toth
758e8bd229eef385ab420d4fa51c611d4ddc7cb0c8Michael Krufkystatic struct au8522_config hauppauge_woodbury_config = {
768e8bd229eef385ab420d4fa51c611d4ddc7cb0c8Michael Krufky	.demod_address = 0x8e >> 1,
778e8bd229eef385ab420d4fa51c611d4ddc7cb0c8Michael Krufky	.status_mode   = AU8522_DEMODLOCKING,
788e8bd229eef385ab420d4fa51c611d4ddc7cb0c8Michael Krufky	.qam_if        = AU8522_IF_4MHZ,
798e8bd229eef385ab420d4fa51c611d4ddc7cb0c8Michael Krufky	.vsb_if        = AU8522_IF_3_25MHZ,
808e8bd229eef385ab420d4fa51c611d4ddc7cb0c8Michael Krufky};
818e8bd229eef385ab420d4fa51c611d4ddc7cb0c8Michael Krufky
82265a6510629ab39f33ece43a857089dd37978184Steven Tothstatic struct xc5000_config hauppauge_hvr950q_tunerconfig = {
83265a6510629ab39f33ece43a857089dd37978184Steven Toth	.i2c_address      = 0x61,
84265a6510629ab39f33ece43a857089dd37978184Steven Toth	.if_khz           = 6000,
85265a6510629ab39f33ece43a857089dd37978184Steven Toth};
86265a6510629ab39f33ece43a857089dd37978184Steven Toth
8759d27521c0f50fadf3382e2b325a7e8a04d9a770Michael Krufkystatic struct mxl5007t_config mxl5007t_hvr950q_config = {
8859d27521c0f50fadf3382e2b325a7e8a04d9a770Michael Krufky	.xtal_freq_hz = MxL_XTAL_24_MHZ,
8959d27521c0f50fadf3382e2b325a7e8a04d9a770Michael Krufky	.if_freq_hz = MxL_IF_6_MHZ,
9059d27521c0f50fadf3382e2b325a7e8a04d9a770Michael Krufky};
9159d27521c0f50fadf3382e2b325a7e8a04d9a770Michael Krufky
928e8bd229eef385ab420d4fa51c611d4ddc7cb0c8Michael Krufkystatic struct tda18271_config hauppauge_woodbury_tunerconfig = {
938e8bd229eef385ab420d4fa51c611d4ddc7cb0c8Michael Krufky	.gate    = TDA18271_GATE_DIGITAL,
948e8bd229eef385ab420d4fa51c611d4ddc7cb0c8Michael Krufky};
958e8bd229eef385ab420d4fa51c611d4ddc7cb0c8Michael Krufky
96265a6510629ab39f33ece43a857089dd37978184Steven Toth/*-------------------------------------------------------------------*/
97265a6510629ab39f33ece43a857089dd37978184Steven Tothstatic void urb_completion(struct urb *purb)
98265a6510629ab39f33ece43a857089dd37978184Steven Toth{
99265a6510629ab39f33ece43a857089dd37978184Steven Toth	struct au0828_dev *dev = purb->context;
100265a6510629ab39f33ece43a857089dd37978184Steven Toth	int ptype = usb_pipetype(purb->pipe);
101265a6510629ab39f33ece43a857089dd37978184Steven Toth
102f07e8e4bb790f6cb462d5d5425193cad874ac0deMichael Krufky	dprintk(2, "%s()\n", __func__);
103bc3c613cef903e73e7365986a1943b0124350018Steven Toth
1049c26de555dd3c2cb9833b4d324150aa6b5547b91Steven Toth	if (!dev)
1059c26de555dd3c2cb9833b4d324150aa6b5547b91Steven Toth		return;
1069c26de555dd3c2cb9833b4d324150aa6b5547b91Steven Toth
107265a6510629ab39f33ece43a857089dd37978184Steven Toth	if (dev->urb_streaming == 0)
108265a6510629ab39f33ece43a857089dd37978184Steven Toth		return;
109265a6510629ab39f33ece43a857089dd37978184Steven Toth
110265a6510629ab39f33ece43a857089dd37978184Steven Toth	if (ptype != PIPE_BULK) {
111f07e8e4bb790f6cb462d5d5425193cad874ac0deMichael Krufky		printk(KERN_ERR "%s() Unsupported URB type %d\n",
112f07e8e4bb790f6cb462d5d5425193cad874ac0deMichael Krufky		       __func__, ptype);
113265a6510629ab39f33ece43a857089dd37978184Steven Toth		return;
114265a6510629ab39f33ece43a857089dd37978184Steven Toth	}
115265a6510629ab39f33ece43a857089dd37978184Steven Toth
116265a6510629ab39f33ece43a857089dd37978184Steven Toth	/* Feed the transport payload into the kernel demux */
117a9c36aad59a06df199cdbb365d0b05663f8008f1Steven Toth	dvb_dmx_swfilter_packets(&dev->dvb.demux,
118a9c36aad59a06df199cdbb365d0b05663f8008f1Steven Toth		purb->transfer_buffer, purb->actual_length / 188);
119265a6510629ab39f33ece43a857089dd37978184Steven Toth
120265a6510629ab39f33ece43a857089dd37978184Steven Toth	/* Clean the buffer before we requeue */
121265a6510629ab39f33ece43a857089dd37978184Steven Toth	memset(purb->transfer_buffer, 0, URB_BUFSIZE);
122265a6510629ab39f33ece43a857089dd37978184Steven Toth
123265a6510629ab39f33ece43a857089dd37978184Steven Toth	/* Requeue URB */
124265a6510629ab39f33ece43a857089dd37978184Steven Toth	usb_submit_urb(purb, GFP_ATOMIC);
125265a6510629ab39f33ece43a857089dd37978184Steven Toth}
126265a6510629ab39f33ece43a857089dd37978184Steven Toth
127265a6510629ab39f33ece43a857089dd37978184Steven Tothstatic int stop_urb_transfer(struct au0828_dev *dev)
128265a6510629ab39f33ece43a857089dd37978184Steven Toth{
129265a6510629ab39f33ece43a857089dd37978184Steven Toth	int i;
130265a6510629ab39f33ece43a857089dd37978184Steven Toth
131f07e8e4bb790f6cb462d5d5425193cad874ac0deMichael Krufky	dprintk(2, "%s()\n", __func__);
132265a6510629ab39f33ece43a857089dd37978184Steven Toth
133265a6510629ab39f33ece43a857089dd37978184Steven Toth	for (i = 0; i < URB_COUNT; i++) {
134265a6510629ab39f33ece43a857089dd37978184Steven Toth		usb_kill_urb(dev->urbs[i]);
135265a6510629ab39f33ece43a857089dd37978184Steven Toth		kfree(dev->urbs[i]->transfer_buffer);
136265a6510629ab39f33ece43a857089dd37978184Steven Toth		usb_free_urb(dev->urbs[i]);
137265a6510629ab39f33ece43a857089dd37978184Steven Toth	}
138265a6510629ab39f33ece43a857089dd37978184Steven Toth
139265a6510629ab39f33ece43a857089dd37978184Steven Toth	dev->urb_streaming = 0;
140265a6510629ab39f33ece43a857089dd37978184Steven Toth
141265a6510629ab39f33ece43a857089dd37978184Steven Toth	return 0;
142265a6510629ab39f33ece43a857089dd37978184Steven Toth}
143265a6510629ab39f33ece43a857089dd37978184Steven Toth
144265a6510629ab39f33ece43a857089dd37978184Steven Tothstatic int start_urb_transfer(struct au0828_dev *dev)
145265a6510629ab39f33ece43a857089dd37978184Steven Toth{
146265a6510629ab39f33ece43a857089dd37978184Steven Toth	struct urb *purb;
147265a6510629ab39f33ece43a857089dd37978184Steven Toth	int i, ret = -ENOMEM;
148265a6510629ab39f33ece43a857089dd37978184Steven Toth
149f07e8e4bb790f6cb462d5d5425193cad874ac0deMichael Krufky	dprintk(2, "%s()\n", __func__);
150265a6510629ab39f33ece43a857089dd37978184Steven Toth
151265a6510629ab39f33ece43a857089dd37978184Steven Toth	if (dev->urb_streaming) {
1525376176199fdd55e6310738bfacb57bf606f16bfMichael Krufky		dprintk(2, "%s: bulk xfer already running!\n", __func__);
153265a6510629ab39f33ece43a857089dd37978184Steven Toth		return 0;
154265a6510629ab39f33ece43a857089dd37978184Steven Toth	}
155265a6510629ab39f33ece43a857089dd37978184Steven Toth
156265a6510629ab39f33ece43a857089dd37978184Steven Toth	for (i = 0; i < URB_COUNT; i++) {
157265a6510629ab39f33ece43a857089dd37978184Steven Toth
158265a6510629ab39f33ece43a857089dd37978184Steven Toth		dev->urbs[i] = usb_alloc_urb(0, GFP_KERNEL);
15918d73c58b5ea7425db05b666408f6f682d837b73Mauro Carvalho Chehab		if (!dev->urbs[i])
160265a6510629ab39f33ece43a857089dd37978184Steven Toth			goto err;
161265a6510629ab39f33ece43a857089dd37978184Steven Toth
162265a6510629ab39f33ece43a857089dd37978184Steven Toth		purb = dev->urbs[i];
163265a6510629ab39f33ece43a857089dd37978184Steven Toth
164265a6510629ab39f33ece43a857089dd37978184Steven Toth		purb->transfer_buffer = kzalloc(URB_BUFSIZE, GFP_KERNEL);
165265a6510629ab39f33ece43a857089dd37978184Steven Toth		if (!purb->transfer_buffer) {
166265a6510629ab39f33ece43a857089dd37978184Steven Toth			usb_free_urb(purb);
167a6a3a17b7fdaf824e6d73e8e4a94c9d149302f74Harvey Harrison			dev->urbs[i] = NULL;
168265a6510629ab39f33ece43a857089dd37978184Steven Toth			goto err;
169265a6510629ab39f33ece43a857089dd37978184Steven Toth		}
170265a6510629ab39f33ece43a857089dd37978184Steven Toth
171265a6510629ab39f33ece43a857089dd37978184Steven Toth		purb->status = -EINPROGRESS;
172265a6510629ab39f33ece43a857089dd37978184Steven Toth		usb_fill_bulk_urb(purb,
173265a6510629ab39f33ece43a857089dd37978184Steven Toth				  dev->usbdev,
174a8eb912c6d2c68426c2c2e0aad4c2bbec2240179Steven Toth				  usb_rcvbulkpipe(dev->usbdev,
175a8eb912c6d2c68426c2c2e0aad4c2bbec2240179Steven Toth					_AU0828_BULKPIPE),
176265a6510629ab39f33ece43a857089dd37978184Steven Toth				  purb->transfer_buffer,
177265a6510629ab39f33ece43a857089dd37978184Steven Toth				  URB_BUFSIZE,
178265a6510629ab39f33ece43a857089dd37978184Steven Toth				  urb_completion,
179265a6510629ab39f33ece43a857089dd37978184Steven Toth				  dev);
180265a6510629ab39f33ece43a857089dd37978184Steven Toth
181265a6510629ab39f33ece43a857089dd37978184Steven Toth	}
182265a6510629ab39f33ece43a857089dd37978184Steven Toth
183265a6510629ab39f33ece43a857089dd37978184Steven Toth	for (i = 0; i < URB_COUNT; i++) {
184265a6510629ab39f33ece43a857089dd37978184Steven Toth		ret = usb_submit_urb(dev->urbs[i], GFP_ATOMIC);
185265a6510629ab39f33ece43a857089dd37978184Steven Toth		if (ret != 0) {
186265a6510629ab39f33ece43a857089dd37978184Steven Toth			stop_urb_transfer(dev);
187f07e8e4bb790f6cb462d5d5425193cad874ac0deMichael Krufky			printk(KERN_ERR "%s: failed urb submission, "
188f07e8e4bb790f6cb462d5d5425193cad874ac0deMichael Krufky			       "err = %d\n", __func__, ret);
189265a6510629ab39f33ece43a857089dd37978184Steven Toth			return ret;
190265a6510629ab39f33ece43a857089dd37978184Steven Toth		}
191265a6510629ab39f33ece43a857089dd37978184Steven Toth	}
192265a6510629ab39f33ece43a857089dd37978184Steven Toth
193265a6510629ab39f33ece43a857089dd37978184Steven Toth	dev->urb_streaming = 1;
194265a6510629ab39f33ece43a857089dd37978184Steven Toth	ret = 0;
195265a6510629ab39f33ece43a857089dd37978184Steven Toth
196265a6510629ab39f33ece43a857089dd37978184Steven Totherr:
197265a6510629ab39f33ece43a857089dd37978184Steven Toth	return ret;
198265a6510629ab39f33ece43a857089dd37978184Steven Toth}
199265a6510629ab39f33ece43a857089dd37978184Steven Toth
200265a6510629ab39f33ece43a857089dd37978184Steven Tothstatic int au0828_dvb_start_feed(struct dvb_demux_feed *feed)
201265a6510629ab39f33ece43a857089dd37978184Steven Toth{
202265a6510629ab39f33ece43a857089dd37978184Steven Toth	struct dvb_demux *demux = feed->demux;
203265a6510629ab39f33ece43a857089dd37978184Steven Toth	struct au0828_dev *dev = (struct au0828_dev *) demux->priv;
204265a6510629ab39f33ece43a857089dd37978184Steven Toth	struct au0828_dvb *dvb = &dev->dvb;
205265a6510629ab39f33ece43a857089dd37978184Steven Toth	int ret = 0;
206265a6510629ab39f33ece43a857089dd37978184Steven Toth
207f07e8e4bb790f6cb462d5d5425193cad874ac0deMichael Krufky	dprintk(1, "%s()\n", __func__);
208265a6510629ab39f33ece43a857089dd37978184Steven Toth
209265a6510629ab39f33ece43a857089dd37978184Steven Toth	if (!demux->dmx.frontend)
210265a6510629ab39f33ece43a857089dd37978184Steven Toth		return -EINVAL;
211265a6510629ab39f33ece43a857089dd37978184Steven Toth
212265a6510629ab39f33ece43a857089dd37978184Steven Toth	if (dvb) {
213265a6510629ab39f33ece43a857089dd37978184Steven Toth		mutex_lock(&dvb->lock);
214265a6510629ab39f33ece43a857089dd37978184Steven Toth		if (dvb->feeding++ == 0) {
215bc3c613cef903e73e7365986a1943b0124350018Steven Toth			/* Start transport */
216265a6510629ab39f33ece43a857089dd37978184Steven Toth			au0828_write(dev, 0x608, 0x90);
217265a6510629ab39f33ece43a857089dd37978184Steven Toth			au0828_write(dev, 0x609, 0x72);
218265a6510629ab39f33ece43a857089dd37978184Steven Toth			au0828_write(dev, 0x60a, 0x71);
219265a6510629ab39f33ece43a857089dd37978184Steven Toth			au0828_write(dev, 0x60b, 0x01);
220265a6510629ab39f33ece43a857089dd37978184Steven Toth			ret = start_urb_transfer(dev);
221265a6510629ab39f33ece43a857089dd37978184Steven Toth		}
222265a6510629ab39f33ece43a857089dd37978184Steven Toth		mutex_unlock(&dvb->lock);
223265a6510629ab39f33ece43a857089dd37978184Steven Toth	}
224265a6510629ab39f33ece43a857089dd37978184Steven Toth
225265a6510629ab39f33ece43a857089dd37978184Steven Toth	return ret;
226265a6510629ab39f33ece43a857089dd37978184Steven Toth}
227265a6510629ab39f33ece43a857089dd37978184Steven Toth
228265a6510629ab39f33ece43a857089dd37978184Steven Tothstatic int au0828_dvb_stop_feed(struct dvb_demux_feed *feed)
229265a6510629ab39f33ece43a857089dd37978184Steven Toth{
230265a6510629ab39f33ece43a857089dd37978184Steven Toth	struct dvb_demux *demux = feed->demux;
231265a6510629ab39f33ece43a857089dd37978184Steven Toth	struct au0828_dev *dev = (struct au0828_dev *) demux->priv;
232265a6510629ab39f33ece43a857089dd37978184Steven Toth	struct au0828_dvb *dvb = &dev->dvb;
233265a6510629ab39f33ece43a857089dd37978184Steven Toth	int ret = 0;
234265a6510629ab39f33ece43a857089dd37978184Steven Toth
235f07e8e4bb790f6cb462d5d5425193cad874ac0deMichael Krufky	dprintk(1, "%s()\n", __func__);
236265a6510629ab39f33ece43a857089dd37978184Steven Toth
237265a6510629ab39f33ece43a857089dd37978184Steven Toth	if (dvb) {
238265a6510629ab39f33ece43a857089dd37978184Steven Toth		mutex_lock(&dvb->lock);
239265a6510629ab39f33ece43a857089dd37978184Steven Toth		if (--dvb->feeding == 0) {
240bc3c613cef903e73e7365986a1943b0124350018Steven Toth			/* Stop transport */
241265a6510629ab39f33ece43a857089dd37978184Steven Toth			au0828_write(dev, 0x608, 0x00);
242265a6510629ab39f33ece43a857089dd37978184Steven Toth			au0828_write(dev, 0x609, 0x00);
243265a6510629ab39f33ece43a857089dd37978184Steven Toth			au0828_write(dev, 0x60a, 0x00);
244265a6510629ab39f33ece43a857089dd37978184Steven Toth			au0828_write(dev, 0x60b, 0x00);
245265a6510629ab39f33ece43a857089dd37978184Steven Toth			ret = stop_urb_transfer(dev);
246265a6510629ab39f33ece43a857089dd37978184Steven Toth		}
247265a6510629ab39f33ece43a857089dd37978184Steven Toth		mutex_unlock(&dvb->lock);
248265a6510629ab39f33ece43a857089dd37978184Steven Toth	}
249265a6510629ab39f33ece43a857089dd37978184Steven Toth
250265a6510629ab39f33ece43a857089dd37978184Steven Toth	return ret;
251265a6510629ab39f33ece43a857089dd37978184Steven Toth}
252265a6510629ab39f33ece43a857089dd37978184Steven Toth
253b33d24c4cc14ee40d83a7e1ea0bfb9567d6059aaAdrian Bunkstatic int dvb_register(struct au0828_dev *dev)
254265a6510629ab39f33ece43a857089dd37978184Steven Toth{
255265a6510629ab39f33ece43a857089dd37978184Steven Toth	struct au0828_dvb *dvb = &dev->dvb;
256265a6510629ab39f33ece43a857089dd37978184Steven Toth	int result;
257265a6510629ab39f33ece43a857089dd37978184Steven Toth
258f07e8e4bb790f6cb462d5d5425193cad874ac0deMichael Krufky	dprintk(1, "%s()\n", __func__);
259bc3c613cef903e73e7365986a1943b0124350018Steven Toth
260265a6510629ab39f33ece43a857089dd37978184Steven Toth	/* register adapter */
261265a6510629ab39f33ece43a857089dd37978184Steven Toth	result = dvb_register_adapter(&dvb->adapter, DRIVER_NAME, THIS_MODULE,
262265a6510629ab39f33ece43a857089dd37978184Steven Toth				      &dev->usbdev->dev, adapter_nr);
263265a6510629ab39f33ece43a857089dd37978184Steven Toth	if (result < 0) {
264f07e8e4bb790f6cb462d5d5425193cad874ac0deMichael Krufky		printk(KERN_ERR "%s: dvb_register_adapter failed "
265f07e8e4bb790f6cb462d5d5425193cad874ac0deMichael Krufky		       "(errno = %d)\n", DRIVER_NAME, result);
266265a6510629ab39f33ece43a857089dd37978184Steven Toth		goto fail_adapter;
267265a6510629ab39f33ece43a857089dd37978184Steven Toth	}
268265a6510629ab39f33ece43a857089dd37978184Steven Toth	dvb->adapter.priv = dev;
269265a6510629ab39f33ece43a857089dd37978184Steven Toth
270265a6510629ab39f33ece43a857089dd37978184Steven Toth	/* register frontend */
271265a6510629ab39f33ece43a857089dd37978184Steven Toth	result = dvb_register_frontend(&dvb->adapter, dvb->frontend);
272265a6510629ab39f33ece43a857089dd37978184Steven Toth	if (result < 0) {
273f07e8e4bb790f6cb462d5d5425193cad874ac0deMichael Krufky		printk(KERN_ERR "%s: dvb_register_frontend failed "
274f07e8e4bb790f6cb462d5d5425193cad874ac0deMichael Krufky		       "(errno = %d)\n", DRIVER_NAME, result);
275265a6510629ab39f33ece43a857089dd37978184Steven Toth		goto fail_frontend;
276265a6510629ab39f33ece43a857089dd37978184Steven Toth	}
277265a6510629ab39f33ece43a857089dd37978184Steven Toth
278265a6510629ab39f33ece43a857089dd37978184Steven Toth	/* register demux stuff */
279265a6510629ab39f33ece43a857089dd37978184Steven Toth	dvb->demux.dmx.capabilities =
280265a6510629ab39f33ece43a857089dd37978184Steven Toth		DMX_TS_FILTERING | DMX_SECTION_FILTERING |
281265a6510629ab39f33ece43a857089dd37978184Steven Toth		DMX_MEMORY_BASED_FILTERING;
282265a6510629ab39f33ece43a857089dd37978184Steven Toth	dvb->demux.priv       = dev;
283265a6510629ab39f33ece43a857089dd37978184Steven Toth	dvb->demux.filternum  = 256;
284265a6510629ab39f33ece43a857089dd37978184Steven Toth	dvb->demux.feednum    = 256;
285265a6510629ab39f33ece43a857089dd37978184Steven Toth	dvb->demux.start_feed = au0828_dvb_start_feed;
286265a6510629ab39f33ece43a857089dd37978184Steven Toth	dvb->demux.stop_feed  = au0828_dvb_stop_feed;
287265a6510629ab39f33ece43a857089dd37978184Steven Toth	result = dvb_dmx_init(&dvb->demux);
288265a6510629ab39f33ece43a857089dd37978184Steven Toth	if (result < 0) {
289bc3c613cef903e73e7365986a1943b0124350018Steven Toth		printk(KERN_ERR "%s: dvb_dmx_init failed (errno = %d)\n",
290265a6510629ab39f33ece43a857089dd37978184Steven Toth		       DRIVER_NAME, result);
291265a6510629ab39f33ece43a857089dd37978184Steven Toth		goto fail_dmx;
292265a6510629ab39f33ece43a857089dd37978184Steven Toth	}
293265a6510629ab39f33ece43a857089dd37978184Steven Toth
294265a6510629ab39f33ece43a857089dd37978184Steven Toth	dvb->dmxdev.filternum    = 256;
295265a6510629ab39f33ece43a857089dd37978184Steven Toth	dvb->dmxdev.demux        = &dvb->demux.dmx;
296265a6510629ab39f33ece43a857089dd37978184Steven Toth	dvb->dmxdev.capabilities = 0;
297265a6510629ab39f33ece43a857089dd37978184Steven Toth	result = dvb_dmxdev_init(&dvb->dmxdev, &dvb->adapter);
298265a6510629ab39f33ece43a857089dd37978184Steven Toth	if (result < 0) {
299bc3c613cef903e73e7365986a1943b0124350018Steven Toth		printk(KERN_ERR "%s: dvb_dmxdev_init failed (errno = %d)\n",
300265a6510629ab39f33ece43a857089dd37978184Steven Toth		       DRIVER_NAME, result);
301265a6510629ab39f33ece43a857089dd37978184Steven Toth		goto fail_dmxdev;
302265a6510629ab39f33ece43a857089dd37978184Steven Toth	}
303265a6510629ab39f33ece43a857089dd37978184Steven Toth
304265a6510629ab39f33ece43a857089dd37978184Steven Toth	dvb->fe_hw.source = DMX_FRONTEND_0;
305265a6510629ab39f33ece43a857089dd37978184Steven Toth	result = dvb->demux.dmx.add_frontend(&dvb->demux.dmx, &dvb->fe_hw);
306265a6510629ab39f33ece43a857089dd37978184Steven Toth	if (result < 0) {
307f07e8e4bb790f6cb462d5d5425193cad874ac0deMichael Krufky		printk(KERN_ERR "%s: add_frontend failed "
308f07e8e4bb790f6cb462d5d5425193cad874ac0deMichael Krufky		       "(DMX_FRONTEND_0, errno = %d)\n", DRIVER_NAME, result);
309265a6510629ab39f33ece43a857089dd37978184Steven Toth		goto fail_fe_hw;
310265a6510629ab39f33ece43a857089dd37978184Steven Toth	}
311265a6510629ab39f33ece43a857089dd37978184Steven Toth
312265a6510629ab39f33ece43a857089dd37978184Steven Toth	dvb->fe_mem.source = DMX_MEMORY_FE;
313265a6510629ab39f33ece43a857089dd37978184Steven Toth	result = dvb->demux.dmx.add_frontend(&dvb->demux.dmx, &dvb->fe_mem);
314265a6510629ab39f33ece43a857089dd37978184Steven Toth	if (result < 0) {
315f07e8e4bb790f6cb462d5d5425193cad874ac0deMichael Krufky		printk(KERN_ERR "%s: add_frontend failed "
316f07e8e4bb790f6cb462d5d5425193cad874ac0deMichael Krufky		       "(DMX_MEMORY_FE, errno = %d)\n", DRIVER_NAME, result);
317265a6510629ab39f33ece43a857089dd37978184Steven Toth		goto fail_fe_mem;
318265a6510629ab39f33ece43a857089dd37978184Steven Toth	}
319265a6510629ab39f33ece43a857089dd37978184Steven Toth
320265a6510629ab39f33ece43a857089dd37978184Steven Toth	result = dvb->demux.dmx.connect_frontend(&dvb->demux.dmx, &dvb->fe_hw);
321265a6510629ab39f33ece43a857089dd37978184Steven Toth	if (result < 0) {
322bc3c613cef903e73e7365986a1943b0124350018Steven Toth		printk(KERN_ERR "%s: connect_frontend failed (errno = %d)\n",
323265a6510629ab39f33ece43a857089dd37978184Steven Toth		       DRIVER_NAME, result);
324265a6510629ab39f33ece43a857089dd37978184Steven Toth		goto fail_fe_conn;
325265a6510629ab39f33ece43a857089dd37978184Steven Toth	}
326265a6510629ab39f33ece43a857089dd37978184Steven Toth
327265a6510629ab39f33ece43a857089dd37978184Steven Toth	/* register network adapter */
328265a6510629ab39f33ece43a857089dd37978184Steven Toth	dvb_net_init(&dvb->adapter, &dvb->net, &dvb->demux.dmx);
329265a6510629ab39f33ece43a857089dd37978184Steven Toth	return 0;
330265a6510629ab39f33ece43a857089dd37978184Steven Toth
331265a6510629ab39f33ece43a857089dd37978184Steven Tothfail_fe_conn:
332265a6510629ab39f33ece43a857089dd37978184Steven Toth	dvb->demux.dmx.remove_frontend(&dvb->demux.dmx, &dvb->fe_mem);
333265a6510629ab39f33ece43a857089dd37978184Steven Tothfail_fe_mem:
334265a6510629ab39f33ece43a857089dd37978184Steven Toth	dvb->demux.dmx.remove_frontend(&dvb->demux.dmx, &dvb->fe_hw);
335265a6510629ab39f33ece43a857089dd37978184Steven Tothfail_fe_hw:
336265a6510629ab39f33ece43a857089dd37978184Steven Toth	dvb_dmxdev_release(&dvb->dmxdev);
337265a6510629ab39f33ece43a857089dd37978184Steven Tothfail_dmxdev:
338265a6510629ab39f33ece43a857089dd37978184Steven Toth	dvb_dmx_release(&dvb->demux);
339265a6510629ab39f33ece43a857089dd37978184Steven Tothfail_dmx:
340265a6510629ab39f33ece43a857089dd37978184Steven Toth	dvb_unregister_frontend(dvb->frontend);
341265a6510629ab39f33ece43a857089dd37978184Steven Tothfail_frontend:
342265a6510629ab39f33ece43a857089dd37978184Steven Toth	dvb_frontend_detach(dvb->frontend);
343265a6510629ab39f33ece43a857089dd37978184Steven Toth	dvb_unregister_adapter(&dvb->adapter);
344265a6510629ab39f33ece43a857089dd37978184Steven Tothfail_adapter:
345265a6510629ab39f33ece43a857089dd37978184Steven Toth	return result;
346265a6510629ab39f33ece43a857089dd37978184Steven Toth}
347265a6510629ab39f33ece43a857089dd37978184Steven Toth
348265a6510629ab39f33ece43a857089dd37978184Steven Tothvoid au0828_dvb_unregister(struct au0828_dev *dev)
349265a6510629ab39f33ece43a857089dd37978184Steven Toth{
350265a6510629ab39f33ece43a857089dd37978184Steven Toth	struct au0828_dvb *dvb = &dev->dvb;
351265a6510629ab39f33ece43a857089dd37978184Steven Toth
352f07e8e4bb790f6cb462d5d5425193cad874ac0deMichael Krufky	dprintk(1, "%s()\n", __func__);
353bc3c613cef903e73e7365986a1943b0124350018Steven Toth
354a9c36aad59a06df199cdbb365d0b05663f8008f1Steven Toth	if (dvb->frontend == NULL)
3559c26de555dd3c2cb9833b4d324150aa6b5547b91Steven Toth		return;
3569c26de555dd3c2cb9833b4d324150aa6b5547b91Steven Toth
357265a6510629ab39f33ece43a857089dd37978184Steven Toth	dvb_net_release(&dvb->net);
358265a6510629ab39f33ece43a857089dd37978184Steven Toth	dvb->demux.dmx.remove_frontend(&dvb->demux.dmx, &dvb->fe_mem);
359265a6510629ab39f33ece43a857089dd37978184Steven Toth	dvb->demux.dmx.remove_frontend(&dvb->demux.dmx, &dvb->fe_hw);
360265a6510629ab39f33ece43a857089dd37978184Steven Toth	dvb_dmxdev_release(&dvb->dmxdev);
361265a6510629ab39f33ece43a857089dd37978184Steven Toth	dvb_dmx_release(&dvb->demux);
362265a6510629ab39f33ece43a857089dd37978184Steven Toth	dvb_unregister_frontend(dvb->frontend);
363265a6510629ab39f33ece43a857089dd37978184Steven Toth	dvb_frontend_detach(dvb->frontend);
364265a6510629ab39f33ece43a857089dd37978184Steven Toth	dvb_unregister_adapter(&dvb->adapter);
365265a6510629ab39f33ece43a857089dd37978184Steven Toth}
366265a6510629ab39f33ece43a857089dd37978184Steven Toth
367265a6510629ab39f33ece43a857089dd37978184Steven Toth/* All the DVB attach calls go here, this function get's modified
368265a6510629ab39f33ece43a857089dd37978184Steven Toth * for each new card. No other function in this file needs
369265a6510629ab39f33ece43a857089dd37978184Steven Toth * to change.
370265a6510629ab39f33ece43a857089dd37978184Steven Toth */
371265a6510629ab39f33ece43a857089dd37978184Steven Tothint au0828_dvb_register(struct au0828_dev *dev)
372265a6510629ab39f33ece43a857089dd37978184Steven Toth{
373265a6510629ab39f33ece43a857089dd37978184Steven Toth	struct au0828_dvb *dvb = &dev->dvb;
374265a6510629ab39f33ece43a857089dd37978184Steven Toth	int ret;
375265a6510629ab39f33ece43a857089dd37978184Steven Toth
376f07e8e4bb790f6cb462d5d5425193cad874ac0deMichael Krufky	dprintk(1, "%s()\n", __func__);
377bc3c613cef903e73e7365986a1943b0124350018Steven Toth
378265a6510629ab39f33ece43a857089dd37978184Steven Toth	/* init frontend */
379f1add5b5ec2a6efaa0f5648d0dc2c56d83a3ecf8Devin Heitmueller	switch (dev->boardnr) {
380265a6510629ab39f33ece43a857089dd37978184Steven Toth	case AU0828_BOARD_HAUPPAUGE_HVR850:
381265a6510629ab39f33ece43a857089dd37978184Steven Toth	case AU0828_BOARD_HAUPPAUGE_HVR950Q:
382265a6510629ab39f33ece43a857089dd37978184Steven Toth		dvb->frontend = dvb_attach(au8522_attach,
383265a6510629ab39f33ece43a857089dd37978184Steven Toth				&hauppauge_hvr950q_config,
384265a6510629ab39f33ece43a857089dd37978184Steven Toth				&dev->i2c_adap);
38548723543aff1f46091840222490ded5fe09c0e37Michael Krufky		if (dvb->frontend != NULL)
38630650961907368b1077cade35455fe931b14da6bMichael Krufky			dvb_attach(xc5000_attach, dvb->frontend, &dev->i2c_adap,
38730650961907368b1077cade35455fe931b14da6bMichael Krufky				   &hauppauge_hvr950q_tunerconfig);
388265a6510629ab39f33ece43a857089dd37978184Steven Toth		break;
38959d27521c0f50fadf3382e2b325a7e8a04d9a770Michael Krufky	case AU0828_BOARD_HAUPPAUGE_HVR950Q_MXL:
39059d27521c0f50fadf3382e2b325a7e8a04d9a770Michael Krufky		dvb->frontend = dvb_attach(au8522_attach,
39159d27521c0f50fadf3382e2b325a7e8a04d9a770Michael Krufky				&hauppauge_hvr950q_config,
39259d27521c0f50fadf3382e2b325a7e8a04d9a770Michael Krufky				&dev->i2c_adap);
39359d27521c0f50fadf3382e2b325a7e8a04d9a770Michael Krufky		if (dvb->frontend != NULL)
39459d27521c0f50fadf3382e2b325a7e8a04d9a770Michael Krufky			dvb_attach(mxl5007t_attach, dvb->frontend,
39559d27521c0f50fadf3382e2b325a7e8a04d9a770Michael Krufky				   &dev->i2c_adap, 0x60,
39659d27521c0f50fadf3382e2b325a7e8a04d9a770Michael Krufky				   &mxl5007t_hvr950q_config);
39759d27521c0f50fadf3382e2b325a7e8a04d9a770Michael Krufky		break;
3988e8bd229eef385ab420d4fa51c611d4ddc7cb0c8Michael Krufky	case AU0828_BOARD_HAUPPAUGE_WOODBURY:
3998e8bd229eef385ab420d4fa51c611d4ddc7cb0c8Michael Krufky		dvb->frontend = dvb_attach(au8522_attach,
4008e8bd229eef385ab420d4fa51c611d4ddc7cb0c8Michael Krufky				&hauppauge_woodbury_config,
4018e8bd229eef385ab420d4fa51c611d4ddc7cb0c8Michael Krufky				&dev->i2c_adap);
4028e8bd229eef385ab420d4fa51c611d4ddc7cb0c8Michael Krufky		if (dvb->frontend != NULL)
4038e8bd229eef385ab420d4fa51c611d4ddc7cb0c8Michael Krufky			dvb_attach(tda18271_attach, dvb->frontend,
4048e8bd229eef385ab420d4fa51c611d4ddc7cb0c8Michael Krufky				   0x60, &dev->i2c_adap,
4058e8bd229eef385ab420d4fa51c611d4ddc7cb0c8Michael Krufky				   &hauppauge_woodbury_tunerconfig);
4068e8bd229eef385ab420d4fa51c611d4ddc7cb0c8Michael Krufky		break;
407adeeac3b7989ad9f03651e9224c9c63e221d4310Michael Krufky	case AU0828_BOARD_DVICO_FUSIONHDTV7:
408adeeac3b7989ad9f03651e9224c9c63e221d4310Michael Krufky		dvb->frontend = dvb_attach(au8522_attach,
409adeeac3b7989ad9f03651e9224c9c63e221d4310Michael Krufky				&fusionhdtv7usb_config,
410adeeac3b7989ad9f03651e9224c9c63e221d4310Michael Krufky				&dev->i2c_adap);
411adeeac3b7989ad9f03651e9224c9c63e221d4310Michael Krufky		if (dvb->frontend != NULL) {
412adeeac3b7989ad9f03651e9224c9c63e221d4310Michael Krufky			dvb_attach(xc5000_attach, dvb->frontend,
413adeeac3b7989ad9f03651e9224c9c63e221d4310Michael Krufky				&dev->i2c_adap,
414adeeac3b7989ad9f03651e9224c9c63e221d4310Michael Krufky				&hauppauge_hvr950q_tunerconfig);
415adeeac3b7989ad9f03651e9224c9c63e221d4310Michael Krufky		}
416adeeac3b7989ad9f03651e9224c9c63e221d4310Michael Krufky		break;
417265a6510629ab39f33ece43a857089dd37978184Steven Toth	default:
418f07e8e4bb790f6cb462d5d5425193cad874ac0deMichael Krufky		printk(KERN_WARNING "The frontend of your DVB/ATSC card "
419f07e8e4bb790f6cb462d5d5425193cad874ac0deMichael Krufky		       "isn't supported yet\n");
420265a6510629ab39f33ece43a857089dd37978184Steven Toth		break;
421265a6510629ab39f33ece43a857089dd37978184Steven Toth	}
422265a6510629ab39f33ece43a857089dd37978184Steven Toth	if (NULL == dvb->frontend) {
423f07e8e4bb790f6cb462d5d5425193cad874ac0deMichael Krufky		printk(KERN_ERR "%s() Frontend initialization failed\n",
424f07e8e4bb790f6cb462d5d5425193cad874ac0deMichael Krufky		       __func__);
425265a6510629ab39f33ece43a857089dd37978184Steven Toth		return -1;
426265a6510629ab39f33ece43a857089dd37978184Steven Toth	}
427d7cba043d7ec840d67bd5143779d1febe7d83407Michael Krufky	/* define general-purpose callback pointer */
428d7cba043d7ec840d67bd5143779d1febe7d83407Michael Krufky	dvb->frontend->callback = au0828_tuner_callback;
429265a6510629ab39f33ece43a857089dd37978184Steven Toth
430265a6510629ab39f33ece43a857089dd37978184Steven Toth	/* register everything */
431265a6510629ab39f33ece43a857089dd37978184Steven Toth	ret = dvb_register(dev);
432265a6510629ab39f33ece43a857089dd37978184Steven Toth	if (ret < 0) {
433265a6510629ab39f33ece43a857089dd37978184Steven Toth		if (dvb->frontend->ops.release)
434265a6510629ab39f33ece43a857089dd37978184Steven Toth			dvb->frontend->ops.release(dvb->frontend);
435265a6510629ab39f33ece43a857089dd37978184Steven Toth		return ret;
436265a6510629ab39f33ece43a857089dd37978184Steven Toth	}
437265a6510629ab39f33ece43a857089dd37978184Steven Toth
438265a6510629ab39f33ece43a857089dd37978184Steven Toth	return 0;
439265a6510629ab39f33ece43a857089dd37978184Steven Toth}
440