~ubuntu-branches/ubuntu/precise/linux-ti-omap4/precise

« back to all changes in this revision

Viewing changes to drivers/media/dvb/dvb-usb/technisat-usb2.c

  • Committer: Bazaar Package Importer
  • Author(s): Paolo Pisati
  • Date: 2011-06-29 15:23:51 UTC
  • mfrom: (26.1.1 natty-proposed)
  • Revision ID: james.westby@ubuntu.com-20110629152351-xs96tm303d95rpbk
Tags: 3.0.0-1200.2
* Rebased against 3.0.0-6.7
* BSP from TI based on 3.0.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Linux driver for Technisat DVB-S/S2 USB 2.0 device
 
3
 *
 
4
 * Copyright (C) 2010 Patrick Boettcher,
 
5
 *                    Kernel Labs Inc. PO Box 745, St James, NY 11780
 
6
 *
 
7
 * Development was sponsored by Technisat Digital UK Limited, whose
 
8
 * registered office is Witan Gate House 500 - 600 Witan Gate West,
 
9
 * Milton Keynes, MK9 1SH
 
10
 *
 
11
 * This program is free software; you can redistribute it and/or
 
12
 * modify it under the terms of the GNU General Public License as
 
13
 * published by the Free Software Foundation; either version 2 of the
 
14
 * License, or (at your option) any later version.
 
15
 *
 
16
 *
 
17
 * You should have received a copy of the GNU General Public License
 
18
 * along with this program; if not, write to the Free Software
 
19
 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 
20
 *
 
21
 * THIS PROGRAM IS PROVIDED "AS IS" AND BOTH THE COPYRIGHT HOLDER AND
 
22
 * TECHNISAT DIGITAL UK LTD DISCLAIM ALL WARRANTIES WITH REGARD TO
 
23
 * THIS PROGRAM INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY OR
 
24
 * FITNESS FOR A PARTICULAR PURPOSE.  NEITHER THE COPYRIGHT HOLDER
 
25
 * NOR TECHNISAT DIGITAL UK LIMITED SHALL BE LIABLE FOR ANY SPECIAL,
 
26
 * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
 
27
 * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
 
28
 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
 
29
 * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS PROGRAM. See the
 
30
 * GNU General Public License for more details.
 
31
 */
 
32
 
 
33
#define DVB_USB_LOG_PREFIX "technisat-usb2"
 
34
#include "dvb-usb.h"
 
35
 
 
36
#include "stv6110x.h"
 
37
#include "stv090x.h"
 
38
 
 
39
/* module parameters */
 
40
DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
 
41
 
 
42
static int debug;
 
43
module_param(debug, int, 0644);
 
44
MODULE_PARM_DESC(debug,
 
45
                "set debugging level (bit-mask: 1=info,2=eeprom,4=i2c,8=rc)." \
 
46
                DVB_USB_DEBUG_STATUS);
 
47
 
 
48
/* disables all LED control command and
 
49
 * also does not start the signal polling thread */
 
50
static int disable_led_control;
 
51
module_param(disable_led_control, int, 0444);
 
52
MODULE_PARM_DESC(disable_led_control,
 
53
                "disable LED control of the device "
 
54
                "(default: 0 - LED control is active).");
 
55
 
 
56
/* device private data */
 
57
struct technisat_usb2_state {
 
58
        struct dvb_usb_device *dev;
 
59
        struct delayed_work green_led_work;
 
60
        u8 power_state;
 
61
 
 
62
        u16 last_scan_code;
 
63
};
 
64
 
 
65
/* debug print helpers */
 
66
#define deb_info(args...)    dprintk(debug, 0x01, args)
 
67
#define deb_eeprom(args...)  dprintk(debug, 0x02, args)
 
68
#define deb_i2c(args...)     dprintk(debug, 0x04, args)
 
69
#define deb_rc(args...)      dprintk(debug, 0x08, args)
 
70
 
 
71
/* vendor requests */
 
72
#define SET_IFCLK_TO_EXTERNAL_TSCLK_VENDOR_REQUEST 0xB3
 
73
#define SET_FRONT_END_RESET_VENDOR_REQUEST         0xB4
 
74
#define GET_VERSION_INFO_VENDOR_REQUEST            0xB5
 
75
#define SET_GREEN_LED_VENDOR_REQUEST               0xB6
 
76
#define SET_RED_LED_VENDOR_REQUEST                 0xB7
 
77
#define GET_IR_DATA_VENDOR_REQUEST                 0xB8
 
78
#define SET_LED_TIMER_DIVIDER_VENDOR_REQUEST       0xB9
 
79
#define SET_USB_REENUMERATION                      0xBA
 
80
 
 
81
/* i2c-access methods */
 
82
#define I2C_SPEED_100KHZ_BIT 0x40
 
83
 
 
84
#define I2C_STATUS_NAK 7
 
85
#define I2C_STATUS_OK 8
 
86
 
 
87
static int technisat_usb2_i2c_access(struct usb_device *udev,
 
88
                u8 device_addr, u8 *tx, u8 txlen, u8 *rx, u8 rxlen)
 
89
{
 
90
        u8 b[64];
 
91
        int ret, actual_length;
 
92
 
 
93
        deb_i2c("i2c-access: %02x, tx: ", device_addr);
 
94
        debug_dump(tx, txlen, deb_i2c);
 
95
        deb_i2c(" ");
 
96
 
 
97
        if (txlen > 62) {
 
98
                err("i2c TX buffer can't exceed 62 bytes (dev 0x%02x)",
 
99
                                device_addr);
 
100
                txlen = 62;
 
101
        }
 
102
        if (rxlen > 62) {
 
103
                err("i2c RX buffer can't exceed 62 bytes (dev 0x%02x)",
 
104
                                device_addr);
 
105
                txlen = 62;
 
106
        }
 
107
 
 
108
        b[0] = I2C_SPEED_100KHZ_BIT;
 
109
        b[1] = device_addr << 1;
 
110
 
 
111
        if (rx != NULL) {
 
112
                b[0] |= rxlen;
 
113
                b[1] |= 1;
 
114
        }
 
115
 
 
116
        memcpy(&b[2], tx, txlen);
 
117
        ret = usb_bulk_msg(udev,
 
118
                        usb_sndbulkpipe(udev, 0x01),
 
119
                        b, 2 + txlen,
 
120
                        NULL, 1000);
 
121
 
 
122
        if (ret < 0) {
 
123
                err("i2c-error: out failed %02x = %d", device_addr, ret);
 
124
                return -ENODEV;
 
125
        }
 
126
 
 
127
        ret = usb_bulk_msg(udev,
 
128
                        usb_rcvbulkpipe(udev, 0x01),
 
129
                        b, 64, &actual_length, 1000);
 
130
        if (ret < 0) {
 
131
                err("i2c-error: in failed %02x = %d", device_addr, ret);
 
132
                return -ENODEV;
 
133
        }
 
134
 
 
135
        if (b[0] != I2C_STATUS_OK) {
 
136
                err("i2c-error: %02x = %d", device_addr, b[0]);
 
137
                /* handle tuner-i2c-nak */
 
138
                if (!(b[0] == I2C_STATUS_NAK &&
 
139
                                device_addr == 0x60
 
140
                                /* && device_is_technisat_usb2 */))
 
141
                        return -ENODEV;
 
142
        }
 
143
 
 
144
        deb_i2c("status: %d, ", b[0]);
 
145
 
 
146
        if (rx != NULL) {
 
147
                memcpy(rx, &b[2], rxlen);
 
148
 
 
149
                deb_i2c("rx (%d): ", rxlen);
 
150
                debug_dump(rx, rxlen, deb_i2c);
 
151
        }
 
152
 
 
153
        deb_i2c("\n");
 
154
 
 
155
        return 0;
 
156
}
 
157
 
 
158
static int technisat_usb2_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msg,
 
159
                                int num)
 
160
{
 
161
        int ret = 0, i;
 
162
        struct dvb_usb_device *d = i2c_get_adapdata(adap);
 
163
 
 
164
        /* Ensure nobody else hits the i2c bus while we're sending our
 
165
           sequence of messages, (such as the remote control thread) */
 
166
        if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
 
167
                return -EAGAIN;
 
168
 
 
169
        for (i = 0; i < num; i++) {
 
170
                if (i+1 < num && msg[i+1].flags & I2C_M_RD) {
 
171
                        ret = technisat_usb2_i2c_access(d->udev, msg[i+1].addr,
 
172
                                                msg[i].buf, msg[i].len,
 
173
                                                msg[i+1].buf, msg[i+1].len);
 
174
                        if (ret != 0)
 
175
                                break;
 
176
                        i++;
 
177
                } else {
 
178
                        ret = technisat_usb2_i2c_access(d->udev, msg[i].addr,
 
179
                                                msg[i].buf, msg[i].len,
 
180
                                                NULL, 0);
 
181
                        if (ret != 0)
 
182
                                break;
 
183
                }
 
184
        }
 
185
 
 
186
        if (ret == 0)
 
187
                ret = i;
 
188
 
 
189
        mutex_unlock(&d->i2c_mutex);
 
190
 
 
191
        return ret;
 
192
}
 
193
 
 
194
static u32 technisat_usb2_i2c_func(struct i2c_adapter *adapter)
 
195
{
 
196
        return I2C_FUNC_I2C;
 
197
}
 
198
 
 
199
static struct i2c_algorithm technisat_usb2_i2c_algo = {
 
200
        .master_xfer   = technisat_usb2_i2c_xfer,
 
201
        .functionality = technisat_usb2_i2c_func,
 
202
};
 
203
 
 
204
#if 0
 
205
static void technisat_usb2_frontend_reset(struct usb_device *udev)
 
206
{
 
207
        usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
 
208
                        SET_FRONT_END_RESET_VENDOR_REQUEST,
 
209
                        USB_TYPE_VENDOR | USB_DIR_OUT,
 
210
                        10, 0,
 
211
                        NULL, 0, 500);
 
212
}
 
213
#endif
 
214
 
 
215
/* LED control */
 
216
enum technisat_usb2_led_state {
 
217
        LED_OFF,
 
218
        LED_BLINK,
 
219
        LED_ON,
 
220
        LED_UNDEFINED
 
221
};
 
222
 
 
223
static int technisat_usb2_set_led(struct dvb_usb_device *d, int red, enum technisat_usb2_led_state state)
 
224
{
 
225
        int ret;
 
226
 
 
227
        u8 led[8] = {
 
228
                red ? SET_RED_LED_VENDOR_REQUEST : SET_GREEN_LED_VENDOR_REQUEST,
 
229
                0
 
230
        };
 
231
 
 
232
        if (disable_led_control && state != LED_OFF)
 
233
                return 0;
 
234
 
 
235
        switch (state) {
 
236
        case LED_ON:
 
237
                led[1] = 0x82;
 
238
                break;
 
239
        case LED_BLINK:
 
240
                led[1] = 0x82;
 
241
                if (red) {
 
242
                        led[2] = 0x02;
 
243
                        led[3] = 10;
 
244
                        led[4] = 10;
 
245
                } else {
 
246
                        led[2] = 0xff;
 
247
                        led[3] = 50;
 
248
                        led[4] = 50;
 
249
                }
 
250
                led[5] = 1;
 
251
                break;
 
252
 
 
253
        default:
 
254
        case LED_OFF:
 
255
                led[1] = 0x80;
 
256
                break;
 
257
        }
 
258
 
 
259
        if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
 
260
                return -EAGAIN;
 
261
 
 
262
        ret = usb_control_msg(d->udev, usb_sndctrlpipe(d->udev, 0),
 
263
                red ? SET_RED_LED_VENDOR_REQUEST : SET_GREEN_LED_VENDOR_REQUEST,
 
264
                USB_TYPE_VENDOR | USB_DIR_OUT,
 
265
                0, 0,
 
266
                led, sizeof(led), 500);
 
267
 
 
268
        mutex_unlock(&d->i2c_mutex);
 
269
        return ret;
 
270
}
 
271
 
 
272
static int technisat_usb2_set_led_timer(struct dvb_usb_device *d, u8 red, u8 green)
 
273
{
 
274
        int ret;
 
275
        u8 b = 0;
 
276
 
 
277
        if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
 
278
                return -EAGAIN;
 
279
 
 
280
        ret = usb_control_msg(d->udev, usb_sndctrlpipe(d->udev, 0),
 
281
                SET_LED_TIMER_DIVIDER_VENDOR_REQUEST,
 
282
                USB_TYPE_VENDOR | USB_DIR_OUT,
 
283
                (red << 8) | green, 0,
 
284
                &b, 1, 500);
 
285
 
 
286
        mutex_unlock(&d->i2c_mutex);
 
287
 
 
288
        return ret;
 
289
}
 
290
 
 
291
static void technisat_usb2_green_led_control(struct work_struct *work)
 
292
{
 
293
        struct technisat_usb2_state *state =
 
294
                container_of(work, struct technisat_usb2_state, green_led_work.work);
 
295
        struct dvb_frontend *fe = state->dev->adapter[0].fe;
 
296
 
 
297
        if (state->power_state == 0)
 
298
                goto schedule;
 
299
 
 
300
        if (fe != NULL) {
 
301
                enum fe_status status;
 
302
 
 
303
                if (fe->ops.read_status(fe, &status) != 0)
 
304
                        goto schedule;
 
305
 
 
306
                if (status & FE_HAS_LOCK) {
 
307
                        u32 ber;
 
308
 
 
309
                        if (fe->ops.read_ber(fe, &ber) != 0)
 
310
                                goto schedule;
 
311
 
 
312
                        if (ber > 1000)
 
313
                                technisat_usb2_set_led(state->dev, 0, LED_BLINK);
 
314
                        else
 
315
                                technisat_usb2_set_led(state->dev, 0, LED_ON);
 
316
                } else
 
317
                        technisat_usb2_set_led(state->dev, 0, LED_OFF);
 
318
        }
 
319
 
 
320
schedule:
 
321
        schedule_delayed_work(&state->green_led_work,
 
322
                        msecs_to_jiffies(500));
 
323
}
 
324
 
 
325
/* method to find out whether the firmware has to be downloaded or not */
 
326
static int technisat_usb2_identify_state(struct usb_device *udev,
 
327
                struct dvb_usb_device_properties *props,
 
328
                struct dvb_usb_device_description **desc, int *cold)
 
329
{
 
330
        int ret;
 
331
        u8 version[3];
 
332
 
 
333
        /* first select the interface */
 
334
        if (usb_set_interface(udev, 0, 1) != 0)
 
335
                err("could not set alternate setting to 0");
 
336
        else
 
337
                info("set alternate setting");
 
338
 
 
339
        *cold = 0; /* by default do not download a firmware - just in case something is wrong */
 
340
 
 
341
        ret = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
 
342
                GET_VERSION_INFO_VENDOR_REQUEST,
 
343
                USB_TYPE_VENDOR | USB_DIR_IN,
 
344
                0, 0,
 
345
                version, sizeof(version), 500);
 
346
 
 
347
        if (ret < 0)
 
348
                *cold = 1;
 
349
        else {
 
350
                info("firmware version: %d.%d", version[1], version[2]);
 
351
                *cold = 0;
 
352
        }
 
353
 
 
354
        return 0;
 
355
}
 
356
 
 
357
/* power control */
 
358
static int technisat_usb2_power_ctrl(struct dvb_usb_device *d, int level)
 
359
{
 
360
        struct technisat_usb2_state *state = d->priv;
 
361
 
 
362
        state->power_state = level;
 
363
 
 
364
        if (disable_led_control)
 
365
                return 0;
 
366
 
 
367
        /* green led is turned off in any case - will be turned on when tuning */
 
368
        technisat_usb2_set_led(d, 0, LED_OFF);
 
369
        /* red led is turned on all the time */
 
370
        technisat_usb2_set_led(d, 1, LED_ON);
 
371
        return 0;
 
372
}
 
373
 
 
374
/* mac address reading - from the eeprom */
 
375
#if 0
 
376
static void technisat_usb2_eeprom_dump(struct dvb_usb_device *d)
 
377
{
 
378
        u8 reg;
 
379
        u8 b[16];
 
380
        int i, j;
 
381
 
 
382
        /* full EEPROM dump */
 
383
        for (j = 0; j < 256 * 4; j += 16) {
 
384
                reg = j;
 
385
                if (technisat_usb2_i2c_access(d->udev, 0x50 + j / 256, &reg, 1, b, 16) != 0)
 
386
                        break;
 
387
 
 
388
                deb_eeprom("EEPROM: %01x%02x: ", j / 256, reg);
 
389
                for (i = 0; i < 16; i++)
 
390
                        deb_eeprom("%02x ", b[i]);
 
391
                deb_eeprom("\n");
 
392
        }
 
393
}
 
394
#endif
 
395
 
 
396
static u8 technisat_usb2_calc_lrc(const u8 *b, u16 length)
 
397
{
 
398
        u8 lrc = 0;
 
399
        while (--length)
 
400
                lrc ^= *b++;
 
401
        return lrc;
 
402
}
 
403
 
 
404
static int technisat_usb2_eeprom_lrc_read(struct dvb_usb_device *d,
 
405
        u16 offset, u8 *b, u16 length, u8 tries)
 
406
{
 
407
        u8 bo = offset & 0xff;
 
408
        struct i2c_msg msg[] = {
 
409
                {
 
410
                        .addr = 0x50 | ((offset >> 8) & 0x3),
 
411
                        .buf = &bo,
 
412
                        .len = 1
 
413
                }, {
 
414
                        .addr = 0x50 | ((offset >> 8) & 0x3),
 
415
                        .flags  = I2C_M_RD,
 
416
                        .buf = b,
 
417
                        .len = length
 
418
                }
 
419
        };
 
420
 
 
421
        while (tries--) {
 
422
                int status;
 
423
 
 
424
                if (i2c_transfer(&d->i2c_adap, msg, 2) != 2)
 
425
                        break;
 
426
 
 
427
                status =
 
428
                        technisat_usb2_calc_lrc(b, length - 1) == b[length - 1];
 
429
 
 
430
                if (status)
 
431
                        return 0;
 
432
        }
 
433
 
 
434
        return -EREMOTEIO;
 
435
}
 
436
 
 
437
#define EEPROM_MAC_START 0x3f8
 
438
#define EEPROM_MAC_TOTAL 8
 
439
static int technisat_usb2_read_mac_address(struct dvb_usb_device *d,
 
440
                u8 mac[])
 
441
{
 
442
        u8 buf[EEPROM_MAC_TOTAL];
 
443
 
 
444
        if (technisat_usb2_eeprom_lrc_read(d, EEPROM_MAC_START,
 
445
                                buf, EEPROM_MAC_TOTAL, 4) != 0)
 
446
                return -ENODEV;
 
447
 
 
448
        memcpy(mac, buf, 6);
 
449
        return 0;
 
450
}
 
451
 
 
452
/* frontend attach */
 
453
static int technisat_usb2_set_voltage(struct dvb_frontend *fe,
 
454
                fe_sec_voltage_t voltage)
 
455
{
 
456
        int i;
 
457
        u8 gpio[3] = { 0 }; /* 0 = 2, 1 = 3, 2 = 4 */
 
458
 
 
459
        gpio[2] = 1; /* high - voltage ? */
 
460
 
 
461
        switch (voltage) {
 
462
        case SEC_VOLTAGE_13:
 
463
                gpio[0] = 1;
 
464
                break;
 
465
        case SEC_VOLTAGE_18:
 
466
                gpio[0] = 1;
 
467
                gpio[1] = 1;
 
468
                break;
 
469
        default:
 
470
        case SEC_VOLTAGE_OFF:
 
471
                break;
 
472
        }
 
473
 
 
474
        for (i = 0; i < 3; i++)
 
475
                if (stv090x_set_gpio(fe, i+2, 0, gpio[i], 0) != 0)
 
476
                        return -EREMOTEIO;
 
477
        return 0;
 
478
}
 
479
 
 
480
static struct stv090x_config technisat_usb2_stv090x_config = {
 
481
        .device         = STV0903,
 
482
        .demod_mode     = STV090x_SINGLE,
 
483
        .clk_mode       = STV090x_CLK_EXT,
 
484
 
 
485
        .xtal           = 8000000,
 
486
        .address        = 0x68,
 
487
 
 
488
        .ts1_mode       = STV090x_TSMODE_DVBCI,
 
489
        .ts1_clk        = 13400000,
 
490
        .ts1_tei        = 1,
 
491
 
 
492
        .repeater_level = STV090x_RPTLEVEL_64,
 
493
 
 
494
        .tuner_bbgain   = 6,
 
495
};
 
496
 
 
497
static struct stv6110x_config technisat_usb2_stv6110x_config = {
 
498
        .addr           = 0x60,
 
499
        .refclk         = 16000000,
 
500
        .clk_div        = 2,
 
501
};
 
502
 
 
503
static int technisat_usb2_frontend_attach(struct dvb_usb_adapter *a)
 
504
{
 
505
        struct usb_device *udev = a->dev->udev;
 
506
        int ret;
 
507
 
 
508
        a->fe = dvb_attach(stv090x_attach, &technisat_usb2_stv090x_config,
 
509
                        &a->dev->i2c_adap, STV090x_DEMODULATOR_0);
 
510
 
 
511
        if (a->fe) {
 
512
                struct stv6110x_devctl *ctl;
 
513
 
 
514
                ctl = dvb_attach(stv6110x_attach,
 
515
                                a->fe,
 
516
                                &technisat_usb2_stv6110x_config,
 
517
                                &a->dev->i2c_adap);
 
518
 
 
519
                if (ctl) {
 
520
                        technisat_usb2_stv090x_config.tuner_init          = ctl->tuner_init;
 
521
                        technisat_usb2_stv090x_config.tuner_sleep         = ctl->tuner_sleep;
 
522
                        technisat_usb2_stv090x_config.tuner_set_mode      = ctl->tuner_set_mode;
 
523
                        technisat_usb2_stv090x_config.tuner_set_frequency = ctl->tuner_set_frequency;
 
524
                        technisat_usb2_stv090x_config.tuner_get_frequency = ctl->tuner_get_frequency;
 
525
                        technisat_usb2_stv090x_config.tuner_set_bandwidth = ctl->tuner_set_bandwidth;
 
526
                        technisat_usb2_stv090x_config.tuner_get_bandwidth = ctl->tuner_get_bandwidth;
 
527
                        technisat_usb2_stv090x_config.tuner_set_bbgain    = ctl->tuner_set_bbgain;
 
528
                        technisat_usb2_stv090x_config.tuner_get_bbgain    = ctl->tuner_get_bbgain;
 
529
                        technisat_usb2_stv090x_config.tuner_set_refclk    = ctl->tuner_set_refclk;
 
530
                        technisat_usb2_stv090x_config.tuner_get_status    = ctl->tuner_get_status;
 
531
 
 
532
                        /* call the init function once to initialize
 
533
                           tuner's clock output divider and demod's
 
534
                           master clock */
 
535
                        if (a->fe->ops.init)
 
536
                                a->fe->ops.init(a->fe);
 
537
 
 
538
                        if (mutex_lock_interruptible(&a->dev->i2c_mutex) < 0)
 
539
                                return -EAGAIN;
 
540
 
 
541
                        ret = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
 
542
                                        SET_IFCLK_TO_EXTERNAL_TSCLK_VENDOR_REQUEST,
 
543
                                        USB_TYPE_VENDOR | USB_DIR_OUT,
 
544
                                        0, 0,
 
545
                                        NULL, 0, 500);
 
546
                        mutex_unlock(&a->dev->i2c_mutex);
 
547
 
 
548
                        if (ret != 0)
 
549
                                err("could not set IF_CLK to external");
 
550
 
 
551
                        a->fe->ops.set_voltage = technisat_usb2_set_voltage;
 
552
 
 
553
                        /* if everything was successful assign a nice name to the frontend */
 
554
                        strlcpy(a->fe->ops.info.name, a->dev->desc->name,
 
555
                                        sizeof(a->fe->ops.info.name));
 
556
                } else {
 
557
                        dvb_frontend_detach(a->fe);
 
558
                        a->fe = NULL;
 
559
                }
 
560
        }
 
561
 
 
562
        technisat_usb2_set_led_timer(a->dev, 1, 1);
 
563
 
 
564
        return a->fe == NULL ? -ENODEV : 0;
 
565
}
 
566
 
 
567
/* Remote control */
 
568
 
 
569
/* the device is giving providing raw IR-signals to the host mapping
 
570
 * it only to one remote control is just the default implementation
 
571
 */
 
572
#define NOMINAL_IR_BIT_TRANSITION_TIME_US 889
 
573
#define NOMINAL_IR_BIT_TIME_US (2 * NOMINAL_IR_BIT_TRANSITION_TIME_US)
 
574
 
 
575
#define FIRMWARE_CLOCK_TICK 83333
 
576
#define FIRMWARE_CLOCK_DIVISOR 256
 
577
 
 
578
#define IR_PERCENT_TOLERANCE 15
 
579
 
 
580
#define NOMINAL_IR_BIT_TRANSITION_TICKS ((NOMINAL_IR_BIT_TRANSITION_TIME_US * 1000 * 1000) / FIRMWARE_CLOCK_TICK)
 
581
#define NOMINAL_IR_BIT_TRANSITION_TICK_COUNT (NOMINAL_IR_BIT_TRANSITION_TICKS / FIRMWARE_CLOCK_DIVISOR)
 
582
 
 
583
#define NOMINAL_IR_BIT_TIME_TICKS ((NOMINAL_IR_BIT_TIME_US * 1000 * 1000) / FIRMWARE_CLOCK_TICK)
 
584
#define NOMINAL_IR_BIT_TIME_TICK_COUNT (NOMINAL_IR_BIT_TIME_TICKS / FIRMWARE_CLOCK_DIVISOR)
 
585
 
 
586
#define MINIMUM_IR_BIT_TRANSITION_TICK_COUNT (NOMINAL_IR_BIT_TRANSITION_TICK_COUNT - ((NOMINAL_IR_BIT_TRANSITION_TICK_COUNT * IR_PERCENT_TOLERANCE) / 100))
 
587
#define MAXIMUM_IR_BIT_TRANSITION_TICK_COUNT (NOMINAL_IR_BIT_TRANSITION_TICK_COUNT + ((NOMINAL_IR_BIT_TRANSITION_TICK_COUNT * IR_PERCENT_TOLERANCE) / 100))
 
588
 
 
589
#define MINIMUM_IR_BIT_TIME_TICK_COUNT (NOMINAL_IR_BIT_TIME_TICK_COUNT - ((NOMINAL_IR_BIT_TIME_TICK_COUNT * IR_PERCENT_TOLERANCE) / 100))
 
590
#define MAXIMUM_IR_BIT_TIME_TICK_COUNT (NOMINAL_IR_BIT_TIME_TICK_COUNT + ((NOMINAL_IR_BIT_TIME_TICK_COUNT * IR_PERCENT_TOLERANCE) / 100))
 
591
 
 
592
static int technisat_usb2_get_ir(struct dvb_usb_device *d)
 
593
{
 
594
        u8 buf[62], *b;
 
595
        int ret;
 
596
        struct ir_raw_event ev;
 
597
 
 
598
        buf[0] = GET_IR_DATA_VENDOR_REQUEST;
 
599
        buf[1] = 0x08;
 
600
        buf[2] = 0x8f;
 
601
        buf[3] = MINIMUM_IR_BIT_TRANSITION_TICK_COUNT;
 
602
        buf[4] = MAXIMUM_IR_BIT_TIME_TICK_COUNT;
 
603
 
 
604
        if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
 
605
                return -EAGAIN;
 
606
        ret = usb_control_msg(d->udev, usb_sndctrlpipe(d->udev, 0),
 
607
                        GET_IR_DATA_VENDOR_REQUEST,
 
608
                        USB_TYPE_VENDOR | USB_DIR_OUT,
 
609
                        0, 0,
 
610
                        buf, 5, 500);
 
611
        if (ret < 0)
 
612
                goto unlock;
 
613
 
 
614
        buf[1] = 0;
 
615
        buf[2] = 0;
 
616
        ret = usb_control_msg(d->udev, usb_rcvctrlpipe(d->udev, 0),
 
617
                        GET_IR_DATA_VENDOR_REQUEST,
 
618
                        USB_TYPE_VENDOR | USB_DIR_IN,
 
619
                        0x8080, 0,
 
620
                        buf, sizeof(buf), 500);
 
621
 
 
622
unlock:
 
623
        mutex_unlock(&d->i2c_mutex);
 
624
 
 
625
        if (ret < 0)
 
626
                return ret;
 
627
 
 
628
        if (ret == 1)
 
629
                return 0; /* no key pressed */
 
630
 
 
631
        /* decoding */
 
632
        b = buf+1;
 
633
 
 
634
#if 0
 
635
        deb_rc("RC: %d ", ret);
 
636
        debug_dump(b, ret, deb_rc);
 
637
#endif
 
638
 
 
639
        ev.pulse = 0;
 
640
        while (1) {
 
641
                ev.pulse = !ev.pulse;
 
642
                ev.duration = (*b * FIRMWARE_CLOCK_DIVISOR * FIRMWARE_CLOCK_TICK) / 1000;
 
643
                ir_raw_event_store(d->rc_dev, &ev);
 
644
 
 
645
                b++;
 
646
                if (*b == 0xff) {
 
647
                        ev.pulse = 0;
 
648
                        ev.duration = 888888*2;
 
649
                        ir_raw_event_store(d->rc_dev, &ev);
 
650
                        break;
 
651
                }
 
652
        }
 
653
 
 
654
        ir_raw_event_handle(d->rc_dev);
 
655
 
 
656
        return 1;
 
657
}
 
658
 
 
659
static int technisat_usb2_rc_query(struct dvb_usb_device *d)
 
660
{
 
661
        int ret = technisat_usb2_get_ir(d);
 
662
 
 
663
        if (ret < 0)
 
664
                return ret;
 
665
 
 
666
        if (ret == 0)
 
667
                return 0;
 
668
 
 
669
        if (!disable_led_control)
 
670
                technisat_usb2_set_led(d, 1, LED_BLINK);
 
671
 
 
672
        return 0;
 
673
}
 
674
 
 
675
/* DVB-USB and USB stuff follows */
 
676
static struct usb_device_id technisat_usb2_id_table[] = {
 
677
        { USB_DEVICE(USB_VID_TECHNISAT, USB_PID_TECHNISAT_USB2_DVB_S2) },
 
678
        { 0 }           /* Terminating entry */
 
679
};
 
680
 
 
681
/* device description */
 
682
static struct dvb_usb_device_properties technisat_usb2_devices = {
 
683
        .caps              = DVB_USB_IS_AN_I2C_ADAPTER,
 
684
 
 
685
        .usb_ctrl          = CYPRESS_FX2,
 
686
 
 
687
        .identify_state    = technisat_usb2_identify_state,
 
688
        .firmware          = "dvb-usb-SkyStar_USB_HD_FW_v17_63.HEX.fw",
 
689
 
 
690
        .size_of_priv      = sizeof(struct technisat_usb2_state),
 
691
 
 
692
        .i2c_algo          = &technisat_usb2_i2c_algo,
 
693
 
 
694
        .power_ctrl        = technisat_usb2_power_ctrl,
 
695
        .read_mac_address  = technisat_usb2_read_mac_address,
 
696
 
 
697
        .num_adapters = 1,
 
698
        .adapter = {
 
699
                {
 
700
                        .frontend_attach  = technisat_usb2_frontend_attach,
 
701
 
 
702
                        .stream = {
 
703
                                .type = USB_ISOC,
 
704
                                .count = 8,
 
705
                                .endpoint = 0x2,
 
706
                                .u = {
 
707
                                        .isoc = {
 
708
                                                .framesperurb = 32,
 
709
                                                .framesize = 2048,
 
710
                                                .interval = 3,
 
711
                                        }
 
712
                                }
 
713
                        },
 
714
 
 
715
                        .size_of_priv = 0,
 
716
                },
 
717
        },
 
718
 
 
719
        .num_device_descs = 1,
 
720
        .devices = {
 
721
                {   "Technisat SkyStar USB HD (DVB-S/S2)",
 
722
                        { &technisat_usb2_id_table[0], NULL },
 
723
                        { NULL },
 
724
                },
 
725
        },
 
726
 
 
727
        .rc.core = {
 
728
                .rc_interval = 100,
 
729
                .rc_codes    = RC_MAP_TECHNISAT_USB2,
 
730
                .module_name = "technisat-usb2",
 
731
                .rc_query    = technisat_usb2_rc_query,
 
732
                .allowed_protos = RC_TYPE_ALL,
 
733
                .driver_type    = RC_DRIVER_IR_RAW,
 
734
        }
 
735
};
 
736
 
 
737
static int technisat_usb2_probe(struct usb_interface *intf,
 
738
                const struct usb_device_id *id)
 
739
{
 
740
        struct dvb_usb_device *dev;
 
741
 
 
742
        if (dvb_usb_device_init(intf, &technisat_usb2_devices, THIS_MODULE,
 
743
                                &dev, adapter_nr) != 0)
 
744
                return -ENODEV;
 
745
 
 
746
        if (dev) {
 
747
                struct technisat_usb2_state *state = dev->priv;
 
748
                state->dev = dev;
 
749
 
 
750
                if (!disable_led_control) {
 
751
                        INIT_DELAYED_WORK(&state->green_led_work,
 
752
                                        technisat_usb2_green_led_control);
 
753
                        schedule_delayed_work(&state->green_led_work,
 
754
                                        msecs_to_jiffies(500));
 
755
                }
 
756
        }
 
757
 
 
758
        return 0;
 
759
}
 
760
 
 
761
static void technisat_usb2_disconnect(struct usb_interface *intf)
 
762
{
 
763
        struct dvb_usb_device *dev = usb_get_intfdata(intf);
 
764
 
 
765
        /* work and stuff was only created when the device is is hot-state */
 
766
        if (dev != NULL) {
 
767
                struct technisat_usb2_state *state = dev->priv;
 
768
                if (state != NULL) {
 
769
                        cancel_delayed_work_sync(&state->green_led_work);
 
770
                        flush_scheduled_work();
 
771
                }
 
772
        }
 
773
 
 
774
        dvb_usb_device_exit(intf);
 
775
}
 
776
 
 
777
static struct usb_driver technisat_usb2_driver = {
 
778
        .name       = "dvb_usb_technisat_usb2",
 
779
        .probe      = technisat_usb2_probe,
 
780
        .disconnect = technisat_usb2_disconnect,
 
781
        .id_table   = technisat_usb2_id_table,
 
782
};
 
783
 
 
784
/* module stuff */
 
785
static int __init technisat_usb2_module_init(void)
 
786
{
 
787
        int result = usb_register(&technisat_usb2_driver);
 
788
        if (result) {
 
789
                err("usb_register failed. Code %d", result);
 
790
                return result;
 
791
        }
 
792
 
 
793
        return 0;
 
794
}
 
795
 
 
796
static void __exit technisat_usb2_module_exit(void)
 
797
{
 
798
        usb_deregister(&technisat_usb2_driver);
 
799
}
 
800
 
 
801
module_init(technisat_usb2_module_init);
 
802
module_exit(technisat_usb2_module_exit);
 
803
 
 
804
MODULE_AUTHOR("Patrick Boettcher <pboettcher@kernellabs.com>");
 
805
MODULE_DESCRIPTION("Driver for Technisat DVB-S/S2 USB 2.0 device");
 
806
MODULE_VERSION("1.0");
 
807
MODULE_LICENSE("GPL");