au0828-core.c 8.7 KB
Newer Older
1 2 3
/*
 *  Driver for the Auvitek USB bridge
 *
4
 *  Copyright (c) 2008 Steven Toth <stoth@linuxtv.org>
5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */

#include <linux/module.h>
23
#include <linux/slab.h>
24 25 26 27 28 29
#include <linux/videodev2.h>
#include <media/v4l2-common.h>
#include <linux/mutex.h>

#include "au0828.h"

S
Steven Toth 已提交
30 31 32 33 34
/*
 * 1 = General debug messages
 * 2 = USB handling
 * 4 = I2C related
 * 8 = Bridge related
35
 * 16 = IR related
S
Steven Toth 已提交
36
 */
37 38
int au0828_debug;
module_param_named(debug, au0828_debug, int, 0644);
39 40
MODULE_PARM_DESC(debug,
		 "set debug bitmask: 1=general, 2=USB, 4=I2C, 8=bridge, 16=IR");
41

42 43 44 45 46
static unsigned int disable_usb_speed_check;
module_param(disable_usb_speed_check, int, 0444);
MODULE_PARM_DESC(disable_usb_speed_check,
		 "override min bandwidth requirement of 480M bps");

47 48 49 50
#define _AU0828_BULKPIPE 0x03
#define _BULKPIPESIZE 0xffff

static int send_control_msg(struct au0828_dev *dev, u16 request, u32 value,
51
			    u16 index);
52 53 54 55 56 57 58 59 60
static int recv_control_msg(struct au0828_dev *dev, u16 request, u32 value,
	u16 index, unsigned char *cp, u16 size);

/* USB Direction */
#define CMD_REQUEST_IN		0x00
#define CMD_REQUEST_OUT		0x01

u32 au0828_readreg(struct au0828_dev *dev, u16 reg)
{
61 62 63 64 65 66
	u8 result = 0;

	recv_control_msg(dev, CMD_REQUEST_IN, 0, reg, &result, 1);
	dprintk(8, "%s(0x%04x) = 0x%02x\n", __func__, reg, result);

	return result;
67 68 69 70
}

u32 au0828_writereg(struct au0828_dev *dev, u16 reg, u32 val)
{
71
	dprintk(8, "%s(0x%04x, 0x%02x)\n", __func__, reg, val);
72
	return send_control_msg(dev, CMD_REQUEST_OUT, val, reg);
73 74 75
}

static int send_control_msg(struct au0828_dev *dev, u16 request, u32 value,
76
	u16 index)
77 78
{
	int status = -ENODEV;
79

80 81 82 83 84 85
	if (dev->usbdev) {

		/* cp must be memory that has been allocated by kmalloc */
		status = usb_control_msg(dev->usbdev,
				usb_sndctrlpipe(dev->usbdev, 0),
				request,
86 87
				USB_DIR_OUT | USB_TYPE_VENDOR |
					USB_RECIP_DEVICE,
88
				value, index, NULL, 0, 1000);
89 90 91 92

		status = min(status, 0);

		if (status < 0) {
S
Steven Toth 已提交
93
			printk(KERN_ERR "%s() Failed sending control message, error %d.\n",
94
				__func__, status);
95 96 97
		}

	}
98

99 100 101 102 103 104 105 106 107 108 109 110 111 112
	return status;
}

static int recv_control_msg(struct au0828_dev *dev, u16 request, u32 value,
	u16 index, unsigned char *cp, u16 size)
{
	int status = -ENODEV;
	mutex_lock(&dev->mutex);
	if (dev->usbdev) {
		status = usb_control_msg(dev->usbdev,
				usb_rcvctrlpipe(dev->usbdev, 0),
				request,
				USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
				value, index,
113
				dev->ctrlmsg, size, 1000);
114 115 116 117

		status = min(status, 0);

		if (status < 0) {
S
Steven Toth 已提交
118
			printk(KERN_ERR "%s() Failed receiving control message, error %d.\n",
119
				__func__, status);
120 121 122 123 124
		}

		/* the host controller requires heap allocated memory, which
		   is why we didn't just pass "cp" into usb_control_msg */
		memcpy(cp, dev->ctrlmsg, size);
125 126 127 128
	}
	mutex_unlock(&dev->mutex);
	return status;
}
S
Steven Toth 已提交
129

130
static void au0828_usb_release(struct au0828_dev *dev)
131 132 133 134
{
	/* I2C */
	au0828_i2c_unregister(dev);

135 136 137
	kfree(dev);
}

138
#ifdef CONFIG_VIDEO_AU0828_V4L2
139 140 141 142 143
static void au0828_usb_v4l2_release(struct v4l2_device *v4l2_dev)
{
	struct au0828_dev *dev =
		container_of(v4l2_dev, struct au0828_dev, v4l2_dev);

144
	v4l2_ctrl_handler_free(&dev->v4l2_ctrl_hdl);
145
	v4l2_device_unregister(&dev->v4l2_dev);
146 147
	au0828_usb_release(dev);
}
148
#endif
149

150 151 152 153 154 155
static void au0828_usb_disconnect(struct usb_interface *interface)
{
	struct au0828_dev *dev = usb_get_intfdata(interface);

	dprintk(1, "%s()\n", __func__);

156
	au0828_rc_unregister(dev);
157 158
	/* Digital TV */
	au0828_dvb_unregister(dev);
159

160
	usb_set_intfdata(interface, NULL);
161 162 163
	mutex_lock(&dev->mutex);
	dev->usbdev = NULL;
	mutex_unlock(&dev->mutex);
164 165 166 167 168 169 170 171 172
#ifdef CONFIG_VIDEO_AU0828_V4L2
	if (AUVI_INPUT(0).type != AU0828_VMUX_UNDEFINED) {
		au0828_analog_unregister(dev);
		v4l2_device_disconnect(&dev->v4l2_dev);
		v4l2_device_put(&dev->v4l2_dev);
		return;
	}
#endif
	au0828_usb_release(dev);
173 174
}

175
static int au0828_usb_probe(struct usb_interface *interface,
176 177
	const struct usb_device_id *id)
{
178
	int ifnum;
179 180
	int retval = 0;

181 182 183 184 185 186 187 188
	struct au0828_dev *dev;
	struct usb_device *usbdev = interface_to_usbdev(interface);

	ifnum = interface->altsetting->desc.bInterfaceNumber;

	if (ifnum != 0)
		return -ENODEV;

S
Steven Toth 已提交
189
	dprintk(1, "%s() vendor id 0x%x device id 0x%x ifnum:%d\n", __func__,
190 191 192 193
		le16_to_cpu(usbdev->descriptor.idVendor),
		le16_to_cpu(usbdev->descriptor.idProduct),
		ifnum);

194 195 196 197 198
	/*
	 * Make sure we have 480 Mbps of bandwidth, otherwise things like
	 * video stream wouldn't likely work, since 12 Mbps is generally
	 * not enough even for most Digital TV streams.
	 */
199
	if (usbdev->speed != USB_SPEED_HIGH && disable_usb_speed_check == 0) {
200 201 202 203 204 205
		printk(KERN_ERR "au0828: Device initialization failed.\n");
		printk(KERN_ERR "au0828: Device must be connected to a "
		       "high-speed USB 2.0 port.\n");
		return -ENODEV;
	}

206 207
	dev = kzalloc(sizeof(*dev), GFP_KERNEL);
	if (dev == NULL) {
208
		printk(KERN_ERR "%s() Unable to allocate memory\n", __func__);
209 210 211
		return -ENOMEM;
	}

212 213
	mutex_init(&dev->lock);
	mutex_lock(&dev->lock);
214 215 216
	mutex_init(&dev->mutex);
	mutex_init(&dev->dvb.lock);
	dev->usbdev = usbdev;
217
	dev->boardnr = id->driver_info;
218

219
#ifdef CONFIG_VIDEO_AU0828_V4L2
220 221
	dev->v4l2_dev.release = au0828_usb_v4l2_release;

222
	/* Create the v4l2_device */
223
	retval = v4l2_device_register(&interface->dev, &dev->v4l2_dev);
224
	if (retval) {
225
		pr_err("%s() v4l2_device_register failed\n",
226
		       __func__);
227
		mutex_unlock(&dev->lock);
228
		kfree(dev);
229
		return retval;
230
	}
231 232 233 234 235 236 237 238 239 240
	/* This control handler will inherit the controls from au8522 */
	retval = v4l2_ctrl_handler_init(&dev->v4l2_ctrl_hdl, 4);
	if (retval) {
		pr_err("%s() v4l2_ctrl_handler_init failed\n",
		       __func__);
		mutex_unlock(&dev->lock);
		kfree(dev);
		return retval;
	}
	dev->v4l2_dev.ctrl_handler = &dev->v4l2_ctrl_hdl;
241
#endif
242

243 244 245 246 247 248 249 250 251
	/* Power Up the bridge */
	au0828_write(dev, REG_600, 1 << 4);

	/* Bring up the GPIO's and supporting devices */
	au0828_gpio_setup(dev);

	/* I2C */
	au0828_i2c_register(dev);

252 253 254
	/* Setup */
	au0828_card_setup(dev);

255
#ifdef CONFIG_VIDEO_AU0828_V4L2
256
	/* Analog TV */
257
	if (AUVI_INPUT(0).type != AU0828_VMUX_UNDEFINED)
258
		au0828_analog_register(dev, interface);
259
#endif
260

261
	/* Digital TV */
262 263 264 265 266
	retval = au0828_dvb_register(dev);
	if (retval)
		pr_err("%s() au0282_dev_register failed\n",
		       __func__);

267 268
	/* Remote controller */
	au0828_rc_register(dev);
269

270 271 272 273
	/*
	 * Store the pointer to the au0828_dev so it can be accessed in
	 * au0828_usb_disconnect
	 */
274 275
	usb_set_intfdata(interface, dev);

S
Steven Toth 已提交
276
	printk(KERN_INFO "Registered device AU0828 [%s]\n",
277
		dev->board.name == NULL ? "Unset" : dev->board.name);
278

279 280
	mutex_unlock(&dev->lock);

281
	return retval;
282 283
}

284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311
static int au0828_suspend(struct usb_interface *interface,
				pm_message_t message)
{
	struct au0828_dev *dev = usb_get_intfdata(interface);

	if (!dev)
		return 0;

	au0828_rc_suspend(dev);

	/* FIXME: should suspend also ATV/DTV */

	return 0;
}

static int au0828_resume(struct usb_interface *interface)
{
	struct au0828_dev *dev = usb_get_intfdata(interface);
	if (!dev)
		return 0;

	au0828_rc_resume(dev);

	/* FIXME: should resume also ATV/DTV */

	return 0;
}

312 313 314 315 316
static struct usb_driver au0828_usb_driver = {
	.name		= DRIVER_NAME,
	.probe		= au0828_usb_probe,
	.disconnect	= au0828_usb_disconnect,
	.id_table	= au0828_usb_id_table,
317 318 319
	.suspend	= au0828_suspend,
	.resume		= au0828_resume,
	.reset_resume	= au0828_resume,
320 321 322 323 324 325
};

static int __init au0828_init(void)
{
	int ret;

326
	if (au0828_debug & 1)
327
		printk(KERN_INFO "%s() Debugging is enabled\n", __func__);
S
Steven Toth 已提交
328

329
	if (au0828_debug & 2)
330
		printk(KERN_INFO "%s() USB Debugging is enabled\n", __func__);
S
Steven Toth 已提交
331

332
	if (au0828_debug & 4)
333
		printk(KERN_INFO "%s() I2C Debugging is enabled\n", __func__);
S
Steven Toth 已提交
334

335
	if (au0828_debug & 8)
336 337
		printk(KERN_INFO "%s() Bridge Debugging is enabled\n",
		       __func__);
S
Steven Toth 已提交
338

339 340 341 342
	if (au0828_debug & 16)
		printk(KERN_INFO "%s() IR Debugging is enabled\n",
		       __func__);

S
Steven Toth 已提交
343
	printk(KERN_INFO "au0828 driver loaded\n");
344 345 346

	ret = usb_register(&au0828_usb_driver);
	if (ret)
S
Steven Toth 已提交
347
		printk(KERN_ERR "usb_register failed, error = %d\n", ret);
348 349 350 351 352 353 354 355 356 357 358 359 360

	return ret;
}

static void __exit au0828_exit(void)
{
	usb_deregister(&au0828_usb_driver);
}

module_init(au0828_init);
module_exit(au0828_exit);

MODULE_DESCRIPTION("Driver for Auvitek AU0828 based products");
361
MODULE_AUTHOR("Steven Toth <stoth@linuxtv.org>");
362
MODULE_LICENSE("GPL");
363
MODULE_VERSION("0.0.3");