aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/dvb/dvb-usb/vp7045.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/dvb/dvb-usb/vp7045.c')
-rw-r--r--drivers/media/dvb/dvb-usb/vp7045.c263
1 files changed, 263 insertions, 0 deletions
diff --git a/drivers/media/dvb/dvb-usb/vp7045.c b/drivers/media/dvb/dvb-usb/vp7045.c
new file mode 100644
index 000000000000..02ecc9a8e3b6
--- /dev/null
+++ b/drivers/media/dvb/dvb-usb/vp7045.c
@@ -0,0 +1,263 @@
1/* DVB USB compliant Linux driver for the
2 * - TwinhanDTV Alpha/MagicBoxII USB2.0 DVB-T receiver
3 * - DigitalNow TinyUSB2 DVB-t receiver
4 *
5 * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de)
6 *
7 * Thanks to Twinhan who kindly provided hardware and information.
8 *
9 * This program is free software; you can redistribute it and/or modify it
10 * under the terms of the GNU General Public License as published by the Free
11 * Software Foundation, version 2.
12 *
13 * see Documentation/dvb/README.dvb-usb for more information
14 */
15#include "vp7045.h"
16
17/* debug */
18int dvb_usb_vp7045_debug;
19module_param_named(debug,dvb_usb_vp7045_debug, int, 0644);
20MODULE_PARM_DESC(debug, "set debugging level (1=info,xfer=2,rc=4 (or-able))." DVB_USB_DEBUG_STATUS);
21
22int vp7045_usb_op(struct dvb_usb_device *d, u8 cmd, u8 *out, int outlen, u8 *in, int inlen, int msec)
23{
24 int ret = 0;
25 u8 inbuf[12] = { 0 }, outbuf[20] = { 0 };
26
27 outbuf[0] = cmd;
28
29 if (outlen > 19)
30 outlen = 19;
31
32 if (inlen > 11)
33 inlen = 11;
34
35 if (out != NULL && outlen > 0)
36 memcpy(&outbuf[1], out, outlen);
37
38 deb_xfer("out buffer: ");
39 debug_dump(outbuf,outlen+1,deb_xfer);
40
41 if ((ret = down_interruptible(&d->usb_sem)))
42 return ret;
43
44 if (usb_control_msg(d->udev,
45 usb_sndctrlpipe(d->udev,0),
46 TH_COMMAND_OUT, USB_TYPE_VENDOR | USB_DIR_OUT, 0, 0,
47 outbuf, 20, 2*HZ) != 20) {
48 err("USB control message 'out' went wrong.");
49 ret = -EIO;
50 goto unlock;
51 }
52
53 msleep(msec);
54
55 if (usb_control_msg(d->udev,
56 usb_rcvctrlpipe(d->udev,0),
57 TH_COMMAND_IN, USB_TYPE_VENDOR | USB_DIR_IN, 0, 0,
58 inbuf, 12, 2*HZ) != 12) {
59 err("USB control message 'in' went wrong.");
60 ret = -EIO;
61 goto unlock;
62 }
63
64 deb_xfer("in buffer: ");
65 debug_dump(inbuf,12,deb_xfer);
66
67 if (in != NULL && inlen > 0)
68 memcpy(in,&inbuf[1],inlen);
69
70unlock:
71 up(&d->usb_sem);
72
73 return ret;
74}
75
76u8 vp7045_read_reg(struct dvb_usb_device *d, u8 reg)
77{
78 u8 obuf[2] = { 0 },v;
79 obuf[1] = reg;
80
81 vp7045_usb_op(d,TUNER_REG_READ,obuf,2,&v,1,30);
82
83 return v;
84}
85
86static int vp7045_power_ctrl(struct dvb_usb_device *d, int onoff)
87{
88 u8 v = onoff;
89 return vp7045_usb_op(d,SET_TUNER_POWER,&v,1,NULL,0,150);
90}
91
92/* remote control stuff */
93
94/* The keymapping struct. Somehow this should be loaded to the driver, but
95 * currently it is hardcoded. */
96static struct dvb_usb_rc_key vp7045_rc_keys[] = {
97 /* insert the keys like this. to make the raw keys visible, enable
98 * debug=0x04 when loading dvb-usb-vp7045. */
99
100 /* these keys are probably wrong. I don't have a working IR-receiver on my
101 * vp7045, so I can't test it. Patches are welcome. */
102 { 0x00, 0x01, KEY_1 },
103 { 0x00, 0x02, KEY_2 },
104};
105
106static int vp7045_rc_query(struct dvb_usb_device *d, u32 *key_buf, int *state)
107{
108 u8 key;
109 int i;
110 vp7045_usb_op(d,RC_VAL_READ,NULL,0,&key,1,20);
111
112 deb_rc("remote query key: %x %d\n",key,key);
113
114 if (key == 0x44) {
115 *state = REMOTE_NO_KEY_PRESSED;
116 return 0;
117 }
118
119 for (i = 0; i < sizeof(vp7045_rc_keys)/sizeof(struct dvb_usb_rc_key); i++)
120 if (vp7045_rc_keys[i].data == key) {
121 *state = REMOTE_KEY_PRESSED;
122 *key_buf = vp7045_rc_keys[i].event;
123 break;
124 }
125 return 0;
126}
127
128static int vp7045_read_eeprom(struct dvb_usb_device *d,u8 *buf, int len, int offset)
129{
130 int i = 0;
131 u8 v,br[2];
132 for (i=0; i < len; i++) {
133 v = offset + i;
134 vp7045_usb_op(d,GET_EE_VALUE,&v,1,br,2,5);
135 buf[i] = br[1];
136 }
137 deb_info("VP7045 EEPROM read (offs: %d, len: %d) : ",offset, i);
138 debug_dump(buf,i,deb_info);
139 return 0;
140}
141
142
143static int vp7045_read_mac_addr(struct dvb_usb_device *d,u8 mac[6])
144{
145 return vp7045_read_eeprom(d,mac, 6, MAC_0_ADDR);
146}
147
148static int vp7045_frontend_attach(struct dvb_usb_device *d)
149{
150 u8 buf[255] = { 0 };
151
152 vp7045_usb_op(d,VENDOR_STRING_READ,NULL,0,buf,20,0);
153 buf[10] = '\0';
154 deb_info("firmware says: %s ",buf);
155
156 vp7045_usb_op(d,PRODUCT_STRING_READ,NULL,0,buf,20,0);
157 buf[10] = '\0';
158 deb_info("%s ",buf);
159
160 vp7045_usb_op(d,FW_VERSION_READ,NULL,0,buf,20,0);
161 buf[10] = '\0';
162 deb_info("v%s\n",buf);
163
164/* Dump the EEPROM */
165/* vp7045_read_eeprom(d,buf, 255, FX2_ID_ADDR); */
166
167 d->fe = vp7045_fe_attach(d);
168
169 return 0;
170}
171
172static struct dvb_usb_properties vp7045_properties;
173
174static int vp7045_usb_probe(struct usb_interface *intf,
175 const struct usb_device_id *id)
176{
177 return dvb_usb_device_init(intf,&vp7045_properties,THIS_MODULE);
178}
179
180static struct usb_device_id vp7045_usb_table [] = {
181 { USB_DEVICE(USB_VID_VISIONPLUS, USB_PID_TWINHAN_VP7045_COLD) },
182 { USB_DEVICE(USB_VID_VISIONPLUS, USB_PID_TWINHAN_VP7045_WARM) },
183 { USB_DEVICE(USB_VID_VISIONPLUS, USB_PID_DNTV_TINYUSB2_COLD) },
184 { USB_DEVICE(USB_VID_VISIONPLUS, USB_PID_DNTV_TINYUSB2_WARM) },
185 { 0 },
186};
187MODULE_DEVICE_TABLE(usb, vp7045_usb_table);
188
189static struct dvb_usb_properties vp7045_properties = {
190 .caps = 0,
191
192 .usb_ctrl = CYPRESS_FX2,
193 .firmware = "dvb-usb-vp7045-01.fw",
194
195 .power_ctrl = vp7045_power_ctrl,
196 .frontend_attach = vp7045_frontend_attach,
197 .read_mac_address = vp7045_read_mac_addr,
198
199 .rc_interval = 400,
200 .rc_key_map = vp7045_rc_keys,
201 .rc_key_map_size = ARRAY_SIZE(vp7045_rc_keys),
202 .rc_query = vp7045_rc_query,
203
204 /* parameter for the MPEG2-data transfer */
205 .urb = {
206 .type = DVB_USB_BULK,
207 .count = 7,
208 .endpoint = 0x02,
209 .u = {
210 .bulk = {
211 .buffersize = 4096,
212 }
213 }
214 },
215
216 .num_device_descs = 2,
217 .devices = {
218 { .name = "Twinhan USB2.0 DVB-T receiver (TwinhanDTV Alpha/MagicBox II)",
219 .cold_ids = { &vp7045_usb_table[0], NULL },
220 .warm_ids = { &vp7045_usb_table[1], NULL },
221 },
222 { .name = "DigitalNow TinyUSB 2 DVB-t Receiver",
223 .cold_ids = { &vp7045_usb_table[2], NULL },
224 .warm_ids = { &vp7045_usb_table[3], NULL },
225 },
226 { 0 },
227 }
228};
229
230/* usb specific object needed to register this driver with the usb subsystem */
231static struct usb_driver vp7045_usb_driver = {
232 .owner = THIS_MODULE,
233 .name = "dvb-usb-vp7045",
234 .probe = vp7045_usb_probe,
235 .disconnect = dvb_usb_device_exit,
236 .id_table = vp7045_usb_table,
237};
238
239/* module stuff */
240static int __init vp7045_usb_module_init(void)
241{
242 int result;
243 if ((result = usb_register(&vp7045_usb_driver))) {
244 err("usb_register failed. (%d)",result);
245 return result;
246 }
247
248 return 0;
249}
250
251static void __exit vp7045_usb_module_exit(void)
252{
253 /* deregister this driver from the USB subsystem */
254 usb_deregister(&vp7045_usb_driver);
255}
256
257module_init(vp7045_usb_module_init);
258module_exit(vp7045_usb_module_exit);
259
260MODULE_AUTHOR("Patrick Boettcher <patrick.boettcher@desy.de>");
261MODULE_DESCRIPTION("Driver for Twinhan MagicBox/Alpha and DNTV tinyUSB2 DVB-T USB2.0");
262MODULE_VERSION("1.0");
263MODULE_LICENSE("GPL");