• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /netgear-R7000-V1.0.7.12_1.2.5/components/opensource/linux/linux-2.6.36/drivers/media/video/hdpvr/
1
2/*
3 * Hauppauge HD PVR USB driver
4 *
5 * Copyright (C) 2008      Janne Grunau (j@jannau.net)
6 *
7 *	This program is free software; you can redistribute it and/or
8 *	modify it under the terms of the GNU General Public License as
9 *	published by the Free Software Foundation, version 2.
10 *
11 */
12
13#include <linux/i2c.h>
14#include <linux/slab.h>
15
16#include "hdpvr.h"
17
18#define CTRL_READ_REQUEST	0xb8
19#define CTRL_WRITE_REQUEST	0x38
20
21#define REQTYPE_I2C_READ	0xb1
22#define REQTYPE_I2C_WRITE	0xb0
23#define REQTYPE_I2C_WRITE_STATT	0xd0
24
25static int hdpvr_i2c_read(struct hdpvr_device *dev, unsigned char addr,
26			  char *data, int len)
27{
28	int ret;
29	char *buf = kmalloc(len, GFP_KERNEL);
30	if (!buf)
31		return -ENOMEM;
32
33	ret = usb_control_msg(dev->udev,
34			      usb_rcvctrlpipe(dev->udev, 0),
35			      REQTYPE_I2C_READ, CTRL_READ_REQUEST,
36			      0x100|addr, 0, buf, len, 1000);
37
38	if (ret == len) {
39		memcpy(data, buf, len);
40		ret = 0;
41	} else if (ret >= 0)
42		ret = -EIO;
43
44	kfree(buf);
45
46	return ret;
47}
48
49static int hdpvr_i2c_write(struct hdpvr_device *dev, unsigned char addr,
50			   char *data, int len)
51{
52	int ret;
53	char *buf = kmalloc(len, GFP_KERNEL);
54	if (!buf)
55		return -ENOMEM;
56
57	memcpy(buf, data, len);
58	ret = usb_control_msg(dev->udev,
59			      usb_sndctrlpipe(dev->udev, 0),
60			      REQTYPE_I2C_WRITE, CTRL_WRITE_REQUEST,
61			      0x100|addr, 0, buf, len, 1000);
62
63	if (ret < 0)
64		goto error;
65
66	ret = usb_control_msg(dev->udev,
67			      usb_rcvctrlpipe(dev->udev, 0),
68			      REQTYPE_I2C_WRITE_STATT, CTRL_READ_REQUEST,
69			      0, 0, buf, 2, 1000);
70
71	if (ret == 2)
72		ret = 0;
73	else if (ret >= 0)
74		ret = -EIO;
75
76error:
77	kfree(buf);
78	return ret;
79}
80
81static int hdpvr_transfer(struct i2c_adapter *i2c_adapter, struct i2c_msg *msgs,
82			  int num)
83{
84	struct hdpvr_device *dev = i2c_get_adapdata(i2c_adapter);
85	int retval = 0, i, addr;
86
87	if (num <= 0)
88		return 0;
89
90	mutex_lock(&dev->i2c_mutex);
91
92	for (i = 0; i < num && !retval; i++) {
93		addr = msgs[i].addr << 1;
94
95		if (msgs[i].flags & I2C_M_RD)
96			retval = hdpvr_i2c_read(dev, addr, msgs[i].buf,
97						msgs[i].len);
98		else
99			retval = hdpvr_i2c_write(dev, addr, msgs[i].buf,
100						 msgs[i].len);
101	}
102
103	mutex_unlock(&dev->i2c_mutex);
104
105	return retval ? retval : num;
106}
107
108static u32 hdpvr_functionality(struct i2c_adapter *adapter)
109{
110	return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
111}
112
113static struct i2c_algorithm hdpvr_algo = {
114	.master_xfer   = hdpvr_transfer,
115	.functionality = hdpvr_functionality,
116};
117
118int hdpvr_register_i2c_adapter(struct hdpvr_device *dev)
119{
120	struct i2c_adapter *i2c_adap;
121	int retval = -ENOMEM;
122
123	i2c_adap = kzalloc(sizeof(struct i2c_adapter), GFP_KERNEL);
124	if (i2c_adap == NULL)
125		goto error;
126
127	strlcpy(i2c_adap->name, "Hauppauge HD PVR I2C",
128		sizeof(i2c_adap->name));
129	i2c_adap->algo  = &hdpvr_algo;
130	i2c_adap->class = I2C_CLASS_TV_ANALOG;
131	i2c_adap->owner = THIS_MODULE;
132	i2c_adap->dev.parent = &dev->udev->dev;
133
134	i2c_set_adapdata(i2c_adap, dev);
135
136	retval = i2c_add_adapter(i2c_adap);
137
138	if (!retval)
139		dev->i2c_adapter = i2c_adap;
140	else
141		kfree(i2c_adap);
142
143error:
144	return retval;
145}
146