Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

V4L/DVB (4863): Adding support for Pinnacle PCTV 400e DVB-S

Adding support for Pinnacle PCTV 400e DVB-S. The module name is called ttusb2,
because it this device (and other Pinnacle devices) is using the USB-protocol
originally used by Technotrend device. I'm suspecting Technotrend as the
device-designer.

Signed-off-by: Patrick Boettcher <pb@linuxtv.org>
Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>

authored by

Patrick Boettcher and committed by
Mauro Carvalho Chehab
bc2e3913 8949f1a2

+354
+11
drivers/media/dvb/dvb-usb/Kconfig
··· 160 160 help 161 161 Say Y here to support the Hauppauge WinTV-NOVA-T usb2 DVB-T USB2.0 receiver. 162 162 163 + config DVB_USB_TTUSB2 164 + tristate "Pinnacle 400e DVB-S USB2.0 support" 165 + depends on DVB_USB 166 + select DVB_TDA10086 if !DVB_FE_CUSTOMISE 167 + select DVB_LNBP21 if !DVB_FE_CUSTOMISE 168 + select DVB_TDA826X if !DVB_FE_CUSTOMISE 169 + help 170 + Say Y here to support the Pinnacle 400e DVB-S USB2.0 receiver. The 171 + firmware protocol used by this module is similar to the one used by the 172 + old ttusb-driver - that's why the module is called dvb-usb-ttusb2.ko. 173 + 163 174 config DVB_USB_DTT200U 164 175 tristate "WideView WT-200U and WT-220U (pen) DVB-T USB2.0 support (Yakumo/Hama/Typhoon/Yuan)" 165 176 depends on DVB_USB
+3
drivers/media/dvb/dvb-usb/Makefile
··· 36 36 dvb-usb-cxusb-objs = cxusb.o 37 37 obj-$(CONFIG_DVB_USB_CXUSB) += dvb-usb-cxusb.o 38 38 39 + dvb-usb-ttusb2-objs = ttusb2.o 40 + obj-$(CONFIG_DVB_USB_TTUSB2) += dvb-usb-ttusb2.o 41 + 39 42 dvb-usb-dib0700-objs = dib0700_core.o dib0700_devices.o 40 43 obj-$(CONFIG_DVB_USB_DIB0700) += dvb-usb-dib0700.o 41 44
+270
drivers/media/dvb/dvb-usb/ttusb2.c
··· 1 + /* DVB USB compliant linux driver for Technotrend DVB USB boxes and clones 2 + * (e.g. Pinnacle 400e DVB-S USB2.0). 3 + * 4 + * The Pinnacle 400e uses the same protocol as the Technotrend USB1.1 boxes. 5 + * 6 + * TDA8263 + TDA10086 7 + * 8 + * I2C addresses: 9 + * 0x08 - LNBP21PD - LNB power supply 10 + * 0x0e - TDA10086 - Demodulator 11 + * 0x50 - FX2 eeprom 12 + * 0x60 - TDA8263 - Tuner 13 + * 0x78 ??? 14 + * 15 + * Copyright (c) 2002 Holger Waechtler <holger@convergence.de> 16 + * Copyright (c) 2003 Felix Domke <tmbinc@elitedvb.net> 17 + * Copyright (C) 2005-6 Patrick Boettcher <pb@linuxtv.org> 18 + * 19 + * This program is free software; you can redistribute it and/or modify it 20 + * under the terms of the GNU General Public License as published by the Free 21 + * Software Foundation, version 2. 22 + * 23 + * see Documentation/dvb/README.dvb-usb for more information 24 + */ 25 + #define DVB_USB_LOG_PREFIX "ttusb2" 26 + #include "dvb-usb.h" 27 + 28 + #include "ttusb2.h" 29 + 30 + #include "tda826x.h" 31 + #include "tda10086.h" 32 + #include "lnbp21.h" 33 + 34 + /* debug */ 35 + static int dvb_usb_ttusb2_debug; 36 + #define deb_info(args...) dprintk(dvb_usb_ttusb2_debug,0x01,args) 37 + module_param_named(debug,dvb_usb_ttusb2_debug, int, 0644); 38 + MODULE_PARM_DESC(debug, "set debugging level (1=info (or-able))." DVB_USB_DEBUG_STATUS); 39 + 40 + struct ttusb2_state { 41 + u8 id; 42 + }; 43 + 44 + static int ttusb2_msg(struct dvb_usb_device *d, u8 cmd, 45 + u8 *wbuf, int wlen, u8 *rbuf, int rlen) 46 + { 47 + struct ttusb2_state *st = d->priv; 48 + u8 s[wlen+4],r[64] = { 0 }; 49 + int ret = 0; 50 + 51 + memset(s,0,wlen+4); 52 + 53 + s[0] = 0xaa; 54 + s[1] = ++st->id; 55 + s[2] = cmd; 56 + s[3] = wlen; 57 + memcpy(&s[4],wbuf,wlen); 58 + 59 + ret = dvb_usb_generic_rw(d, s, wlen+4, r, 64, 0); 60 + 61 + if (ret != 0 || 62 + r[0] != 0x55 || 63 + r[1] != s[1] || 64 + r[2] != cmd || 65 + (rlen > 0 && r[3] != rlen)) { 66 + warn("there might have been an error during control message transfer. (rlen = %d, was %d)",rlen,r[3]); 67 + return -EIO; 68 + } 69 + 70 + if (rlen > 0) 71 + memcpy(rbuf, &r[4], rlen); 72 + 73 + return 0; 74 + } 75 + 76 + static int ttusb2_i2c_xfer(struct i2c_adapter *adap,struct i2c_msg msg[],int num) 77 + { 78 + struct dvb_usb_device *d = i2c_get_adapdata(adap); 79 + static u8 obuf[60], ibuf[60]; 80 + int i,read; 81 + 82 + if (mutex_lock_interruptible(&d->i2c_mutex) < 0) 83 + return -EAGAIN; 84 + 85 + if (num > 2) 86 + warn("more than 2 i2c messages at a time is not handled yet. TODO."); 87 + 88 + for (i = 0; i < num; i++) { 89 + read = i+1 < num && (msg[i+1].flags & I2C_M_RD); 90 + 91 + obuf[0] = (msg[i].addr << 1) | read; 92 + obuf[1] = msg[i].len; 93 + 94 + /* read request */ 95 + if (read) 96 + obuf[2] = msg[i+1].len; 97 + else 98 + obuf[2] = 0; 99 + 100 + memcpy(&obuf[3],msg[i].buf,msg[i].len); 101 + 102 + if (ttusb2_msg(d, CMD_I2C_XFER, obuf, msg[i].len+3, ibuf, obuf[2] + 3) < 0) { 103 + err("i2c transfer failed."); 104 + break; 105 + } 106 + 107 + if (read) { 108 + memcpy(msg[i+1].buf,&ibuf[3],msg[i+1].len); 109 + i++; 110 + } 111 + } 112 + 113 + mutex_unlock(&d->i2c_mutex); 114 + return i; 115 + } 116 + 117 + static u32 ttusb2_i2c_func(struct i2c_adapter *adapter) 118 + { 119 + return I2C_FUNC_I2C; 120 + } 121 + 122 + static struct i2c_algorithm ttusb2_i2c_algo = { 123 + .master_xfer = ttusb2_i2c_xfer, 124 + .functionality = ttusb2_i2c_func, 125 + }; 126 + 127 + /* Callbacks for DVB USB */ 128 + static int ttusb2_identify_state (struct usb_device *udev, struct 129 + dvb_usb_device_properties *props, struct dvb_usb_device_description **desc, 130 + int *cold) 131 + { 132 + *cold = udev->descriptor.iManufacturer == 0 && udev->descriptor.iProduct == 0; 133 + return 0; 134 + } 135 + 136 + static int ttusb2_power_ctrl(struct dvb_usb_device *d, int onoff) 137 + { 138 + u8 b = onoff; 139 + ttusb2_msg(d, CMD_POWER, &b, 0, NULL, 0); 140 + return ttusb2_msg(d, CMD_POWER, &b, 1, NULL, 0); 141 + } 142 + 143 + 144 + static struct tda10086_config tda10086_config = { 145 + .demod_address = 0x0e, 146 + .invert = 0, 147 + }; 148 + 149 + static int ttusb2_frontend_attach(struct dvb_usb_adapter *adap) 150 + { 151 + if (usb_set_interface(adap->dev->udev,0,3) < 0) 152 + err("set interface to alts=3 failed"); 153 + 154 + if ((adap->fe = dvb_attach(tda10086_attach, &tda10086_config, &adap->dev->i2c_adap)) == NULL) { 155 + deb_info("TDA10086 attach failed\n"); 156 + return -ENODEV; 157 + } 158 + 159 + return 0; 160 + } 161 + 162 + static int ttusb2_tuner_attach(struct dvb_usb_adapter *adap) 163 + { 164 + if (dvb_attach(tda826x_attach, adap->fe, 0x60, &adap->dev->i2c_adap, 0) == NULL) { 165 + deb_info("TDA8263 attach failed\n"); 166 + return -ENODEV; 167 + } 168 + 169 + if (dvb_attach(lnbp21_attach, adap->fe, &adap->dev->i2c_adap, 0, 0) == NULL) { 170 + deb_info("LNBP21 attach failed\n"); 171 + return -ENODEV; 172 + } 173 + return 0; 174 + } 175 + 176 + /* DVB USB Driver stuff */ 177 + static struct dvb_usb_device_properties ttusb2_properties; 178 + 179 + static int ttusb2_probe(struct usb_interface *intf, 180 + const struct usb_device_id *id) 181 + { 182 + return dvb_usb_device_init(intf,&ttusb2_properties,THIS_MODULE,NULL); 183 + } 184 + 185 + static struct usb_device_id ttusb2_table [] = { 186 + { USB_DEVICE(USB_VID_PINNACLE, USB_PID_PCTV_400E) }, 187 + {} /* Terminating entry */ 188 + }; 189 + MODULE_DEVICE_TABLE (usb, ttusb2_table); 190 + 191 + static struct dvb_usb_device_properties ttusb2_properties = { 192 + .caps = DVB_USB_IS_AN_I2C_ADAPTER, 193 + 194 + .usb_ctrl = CYPRESS_FX2, 195 + .firmware = "dvb-usb-pctv-400e-01.fw", 196 + 197 + .size_of_priv = sizeof(struct ttusb2_state), 198 + 199 + .num_adapters = 1, 200 + .adapter = { 201 + { 202 + .streaming_ctrl = NULL, // ttusb2_streaming_ctrl, 203 + 204 + .frontend_attach = ttusb2_frontend_attach, 205 + .tuner_attach = ttusb2_tuner_attach, 206 + 207 + /* parameter for the MPEG2-data transfer */ 208 + .stream = { 209 + .type = USB_ISOC, 210 + .count = 5, 211 + .endpoint = 0x02, 212 + .u = { 213 + .isoc = { 214 + .framesperurb = 4, 215 + .framesize = 940, 216 + .interval = 1, 217 + } 218 + } 219 + } 220 + } 221 + }, 222 + 223 + .power_ctrl = ttusb2_power_ctrl, 224 + .identify_state = ttusb2_identify_state, 225 + 226 + .i2c_algo = &ttusb2_i2c_algo, 227 + 228 + .generic_bulk_ctrl_endpoint = 0x01, 229 + 230 + .num_device_descs = 1, 231 + .devices = { 232 + { "Pinnacle 400e DVB-S USB2.0", 233 + { &ttusb2_table[0], NULL }, 234 + { NULL }, 235 + }, 236 + } 237 + }; 238 + 239 + static struct usb_driver ttusb2_driver = { 240 + .name = "dvb_usb_ttusb2", 241 + .probe = ttusb2_probe, 242 + .disconnect = dvb_usb_device_exit, 243 + .id_table = ttusb2_table, 244 + }; 245 + 246 + /* module stuff */ 247 + static int __init ttusb2_module_init(void) 248 + { 249 + int result; 250 + if ((result = usb_register(&ttusb2_driver))) { 251 + err("usb_register failed. Error number %d",result); 252 + return result; 253 + } 254 + 255 + return 0; 256 + } 257 + 258 + static void __exit ttusb2_module_exit(void) 259 + { 260 + /* deregister this driver from the USB subsystem */ 261 + usb_deregister(&ttusb2_driver); 262 + } 263 + 264 + module_init (ttusb2_module_init); 265 + module_exit (ttusb2_module_exit); 266 + 267 + MODULE_AUTHOR("Patrick Boettcher <patrick.boettcher@desy.de>"); 268 + MODULE_DESCRIPTION("Driver for Pinnacle PCTV 400e DVB-S USB2.0"); 269 + MODULE_VERSION("1.0"); 270 + MODULE_LICENSE("GPL");
+70
drivers/media/dvb/dvb-usb/ttusb2.h
··· 1 + /* DVB USB compliant linux driver for Technotrend DVB USB boxes and clones 2 + * (e.g. Pinnacle 400e DVB-S USB2.0). 3 + * 4 + * Copyright (c) 2002 Holger Waechtler <holger@convergence.de> 5 + * Copyright (c) 2003 Felix Domke <tmbinc@elitedvb.net> 6 + * Copyright (C) 2005-6 Patrick Boettcher <pb@linuxtv.de> 7 + * 8 + * This program is free software; you can redistribute it and/or modify it 9 + * under the terms of the GNU General Public License as published by the Free 10 + * Software Foundation, version 2. 11 + * 12 + * see Documentation/dvb/README.dvb-usb for more information 13 + */ 14 + #ifndef _DVB_USB_TTUSB2_H_ 15 + #define _DVB_USB_TTUSB2_H_ 16 + 17 + /* TTUSB protocol 18 + * 19 + * always to messages (out/in) 20 + * out message: 21 + * 0xaa <id> <cmdbyte> <datalen> <data...> 22 + * 23 + * in message (complete block is always 0x40 bytes long) 24 + * 0x55 <id> <cmdbyte> <datalen> <data...> 25 + * 26 + * id is incremented for each transaction 27 + */ 28 + 29 + #define CMD_DSP_DOWNLOAD 0x13 30 + /* out data: <byte>[28] 31 + * last block must be empty */ 32 + 33 + #define CMD_DSP_BOOT 0x14 34 + /* out data: nothing */ 35 + 36 + #define CMD_POWER 0x15 37 + /* out data: <on=1/off=0> */ 38 + 39 + #define CMD_LNB 0x16 40 + /* out data: <power=1> <18V=0,13V=1> <tone> <??=1> <??=1> */ 41 + 42 + #define CMD_GET_VERSION 0x17 43 + /* in data: <version_byte>[5] */ 44 + 45 + #define CMD_DISEQC 0x18 46 + /* out data: <master=0xff/burst=??> <cmdlen> <cmdbytes>[cmdlen] */ 47 + 48 + #define CMD_PID_ENABLE 0x22 49 + /* out data: <index> <type: ts=1/sec=2> <pid msb> <pid lsb> */ 50 + 51 + #define CMD_PID_DISABLE 0x23 52 + /* out data: <index> */ 53 + 54 + #define CMD_FILTER_ENABLE 0x24 55 + /* out data: <index> <pid_idx> <filter>[12] <mask>[12] */ 56 + 57 + #define CMD_FILTER_DISABLE 0x25 58 + /* out data: <index> */ 59 + 60 + #define CMD_GET_DSP_VERSION 0x26 61 + /* in data: <version_byte>[28] */ 62 + 63 + #define CMD_I2C_XFER 0x31 64 + /* out data: <addr << 1> <sndlen> <rcvlen> <data>[sndlen] 65 + * in data: <addr << 1> <sndlen> <rcvlen> <data>[rcvlen] */ 66 + 67 + #define CMD_I2C_BITRATE 0x32 68 + /* out data: <default=0> */ 69 + 70 + #endif