blob: 89b71faeaac2dce9f2216fadc8dd7b5987e702b2 [file] [log] [blame]
Janne Grunau9aba42e2009-03-18 18:10:04 -03001
2/*
Janne Grunaue86da6f2009-03-19 19:00:35 -03003 * Hauppauge HD PVR USB driver
Janne Grunau9aba42e2009-03-18 18:10:04 -03004 *
5 * Copyright (C) 2008 Janne Grunau (j@jannau.net)
6 *
Andy Wallsea6c0602010-12-28 22:46:13 -03007 * IR device registration code is
8 * Copyright (C) 2010 Andy Walls <awalls@md.metrocast.net>
9 *
Janne Grunau9aba42e2009-03-18 18:10:04 -030010 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License as
12 * published by the Free Software Foundation, version 2.
13 *
14 */
15
Jarod Wilson324b04b2011-01-14 16:25:21 -030016#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
17
Janne Grunau9aba42e2009-03-18 18:10:04 -030018#include <linux/i2c.h>
Tejun Heo5a0e3ad2010-03-24 17:04:11 +090019#include <linux/slab.h>
Janne Grunau9aba42e2009-03-18 18:10:04 -030020
21#include "hdpvr.h"
22
23#define CTRL_READ_REQUEST 0xb8
24#define CTRL_WRITE_REQUEST 0x38
25
26#define REQTYPE_I2C_READ 0xb1
27#define REQTYPE_I2C_WRITE 0xb0
28#define REQTYPE_I2C_WRITE_STATT 0xd0
29
Andy Wallsea6c0602010-12-28 22:46:13 -030030#define Z8F0811_IR_TX_I2C_ADDR 0x70
31#define Z8F0811_IR_RX_I2C_ADDR 0x71
32
Jarod Wilson324b04b2011-01-14 16:25:21 -030033
34static struct i2c_board_info hdpvr_i2c_board_info = {
35 I2C_BOARD_INFO("ir_tx_z8f0811_hdpvr", Z8F0811_IR_TX_I2C_ADDR),
36 I2C_BOARD_INFO("ir_rx_z8f0811_hdpvr", Z8F0811_IR_RX_I2C_ADDR),
Andy Wallsea6c0602010-12-28 22:46:13 -030037};
38
Andy Wallsea6c0602010-12-28 22:46:13 -030039int hdpvr_register_i2c_ir(struct hdpvr_device *dev)
40{
Jarod Wilson324b04b2011-01-14 16:25:21 -030041 struct i2c_client *c;
42 struct IR_i2c_init_data *init_data = &dev->ir_i2c_init_data;
Andy Wallsea6c0602010-12-28 22:46:13 -030043
Jarod Wilson324b04b2011-01-14 16:25:21 -030044 /* Our default information for ir-kbd-i2c.c to use */
45 init_data->ir_codes = RC_MAP_HAUPPAUGE_NEW;
46 init_data->internal_get_key_func = IR_KBD_GET_KEY_HAUP_XVR;
47 init_data->type = RC_TYPE_RC5;
48 init_data->name = "HD PVR";
49 hdpvr_i2c_board_info.platform_data = init_data;
Andy Wallsea6c0602010-12-28 22:46:13 -030050
Jarod Wilson324b04b2011-01-14 16:25:21 -030051 c = i2c_new_device(&dev->i2c_adapter, &hdpvr_i2c_board_info);
52
53 return (c == NULL) ? -ENODEV : 0;
Andy Wallsea6c0602010-12-28 22:46:13 -030054}
55
Jarod Wilson324b04b2011-01-14 16:25:21 -030056static int hdpvr_i2c_read(struct hdpvr_device *dev, int bus,
57 unsigned char addr, char *data, int len)
Janne Grunau9aba42e2009-03-18 18:10:04 -030058{
59 int ret;
Jarod Wilson559d1622011-01-14 16:40:32 -030060
61 if (len > sizeof(dev->i2c_buf))
62 return -EINVAL;
Janne Grunau9aba42e2009-03-18 18:10:04 -030063
64 ret = usb_control_msg(dev->udev,
65 usb_rcvctrlpipe(dev->udev, 0),
66 REQTYPE_I2C_READ, CTRL_READ_REQUEST,
Jarod Wilson559d1622011-01-14 16:40:32 -030067 (bus << 8) | addr, 0, &dev->i2c_buf, len, 1000);
Janne Grunau9aba42e2009-03-18 18:10:04 -030068
69 if (ret == len) {
Jarod Wilson559d1622011-01-14 16:40:32 -030070 memcpy(data, &dev->i2c_buf, len);
Janne Grunau9aba42e2009-03-18 18:10:04 -030071 ret = 0;
72 } else if (ret >= 0)
73 ret = -EIO;
74
Janne Grunau9aba42e2009-03-18 18:10:04 -030075 return ret;
76}
77
Jarod Wilson324b04b2011-01-14 16:25:21 -030078static int hdpvr_i2c_write(struct hdpvr_device *dev, int bus,
79 unsigned char addr, char *data, int len)
Janne Grunau9aba42e2009-03-18 18:10:04 -030080{
81 int ret;
Janne Grunau9aba42e2009-03-18 18:10:04 -030082
Jarod Wilson559d1622011-01-14 16:40:32 -030083 if (len > sizeof(dev->i2c_buf))
84 return -EINVAL;
85
86 memcpy(&dev->i2c_buf, data, len);
Janne Grunau9aba42e2009-03-18 18:10:04 -030087 ret = usb_control_msg(dev->udev,
88 usb_sndctrlpipe(dev->udev, 0),
89 REQTYPE_I2C_WRITE, CTRL_WRITE_REQUEST,
Jarod Wilson559d1622011-01-14 16:40:32 -030090 (bus << 8) | addr, 0, &dev->i2c_buf, len, 1000);
Janne Grunau9aba42e2009-03-18 18:10:04 -030091
92 if (ret < 0)
Jarod Wilson559d1622011-01-14 16:40:32 -030093 return ret;
Janne Grunau9aba42e2009-03-18 18:10:04 -030094
95 ret = usb_control_msg(dev->udev,
96 usb_rcvctrlpipe(dev->udev, 0),
97 REQTYPE_I2C_WRITE_STATT, CTRL_READ_REQUEST,
Jarod Wilson559d1622011-01-14 16:40:32 -030098 0, 0, &dev->i2c_buf, 2, 1000);
Janne Grunau9aba42e2009-03-18 18:10:04 -030099
Jarod Wilson559d1622011-01-14 16:40:32 -0300100 if ((ret == 2) && (dev->i2c_buf[1] == (len - 1)))
Janne Grunau9aba42e2009-03-18 18:10:04 -0300101 ret = 0;
102 else if (ret >= 0)
103 ret = -EIO;
104
Janne Grunau9aba42e2009-03-18 18:10:04 -0300105 return ret;
106}
107
108static int hdpvr_transfer(struct i2c_adapter *i2c_adapter, struct i2c_msg *msgs,
109 int num)
110{
111 struct hdpvr_device *dev = i2c_get_adapdata(i2c_adapter);
112 int retval = 0, i, addr;
113
114 if (num <= 0)
115 return 0;
116
117 mutex_lock(&dev->i2c_mutex);
118
119 for (i = 0; i < num && !retval; i++) {
120 addr = msgs[i].addr << 1;
121
122 if (msgs[i].flags & I2C_M_RD)
Jarod Wilson324b04b2011-01-14 16:25:21 -0300123 retval = hdpvr_i2c_read(dev, 1, addr, msgs[i].buf,
Janne Grunau9aba42e2009-03-18 18:10:04 -0300124 msgs[i].len);
125 else
Jarod Wilson324b04b2011-01-14 16:25:21 -0300126 retval = hdpvr_i2c_write(dev, 1, addr, msgs[i].buf,
Janne Grunau9aba42e2009-03-18 18:10:04 -0300127 msgs[i].len);
128 }
129
130 mutex_unlock(&dev->i2c_mutex);
131
132 return retval ? retval : num;
133}
134
135static u32 hdpvr_functionality(struct i2c_adapter *adapter)
136{
137 return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
138}
139
140static struct i2c_algorithm hdpvr_algo = {
141 .master_xfer = hdpvr_transfer,
142 .functionality = hdpvr_functionality,
143};
144
Jarod Wilson324b04b2011-01-14 16:25:21 -0300145static struct i2c_adapter hdpvr_i2c_adapter_template = {
146 .name = "Hauppage HD PVR I2C",
147 .owner = THIS_MODULE,
148 .algo = &hdpvr_algo,
149};
150
151static int hdpvr_activate_ir(struct hdpvr_device *dev)
152{
153 char buffer[8];
154
155 mutex_lock(&dev->i2c_mutex);
156
157 hdpvr_i2c_read(dev, 0, 0x54, buffer, 1);
158
159 buffer[0] = 0;
160 buffer[1] = 0x8;
161 hdpvr_i2c_write(dev, 1, 0x54, buffer, 2);
162
163 buffer[1] = 0x18;
164 hdpvr_i2c_write(dev, 1, 0x54, buffer, 2);
165
166 mutex_unlock(&dev->i2c_mutex);
167
168 return 0;
169}
170
Janne Grunau9aba42e2009-03-18 18:10:04 -0300171int hdpvr_register_i2c_adapter(struct hdpvr_device *dev)
172{
Janne Grunau9aba42e2009-03-18 18:10:04 -0300173 int retval = -ENOMEM;
174
Jarod Wilson324b04b2011-01-14 16:25:21 -0300175 hdpvr_activate_ir(dev);
Janne Grunau9aba42e2009-03-18 18:10:04 -0300176
Jarod Wilson324b04b2011-01-14 16:25:21 -0300177 memcpy(&dev->i2c_adapter, &hdpvr_i2c_adapter_template,
178 sizeof(struct i2c_adapter));
179 dev->i2c_adapter.dev.parent = &dev->udev->dev;
Janne Grunau9aba42e2009-03-18 18:10:04 -0300180
Jarod Wilson324b04b2011-01-14 16:25:21 -0300181 i2c_set_adapdata(&dev->i2c_adapter, dev);
Janne Grunau9aba42e2009-03-18 18:10:04 -0300182
Jarod Wilson324b04b2011-01-14 16:25:21 -0300183 retval = i2c_add_adapter(&dev->i2c_adapter);
Janne Grunau9aba42e2009-03-18 18:10:04 -0300184
Janne Grunau9aba42e2009-03-18 18:10:04 -0300185 return retval;
186}
Jarod Wilson324b04b2011-01-14 16:25:21 -0300187
188#endif