blob: 7e32d11f32b0fd6e4ddc41714d7dd3242bacc819 [file] [log] [blame]
Marco Gittler941491f2007-04-19 11:26:47 -03001/* DVB USB framework compliant Linux driver for the Opera1 DVB-S Card
2*
3* Copyright (C) 2006 Mario Hlawitschka (dh1pa@amsat.org)
4* Copyright (C) 2006 Marco Gittler (g.marco@freenet.de)
5*
6* This program is free software; you can redistribute it and/or modify it
7* under the terms of the GNU General Public License as published by the Free
8* Software Foundation, version 2.
9*
10* see Documentation/dvb/README.dvb-usb for more information
11*/
12
Adrian Bunk53133af2007-11-05 14:07:06 -030013#define DVB_USB_LOG_PREFIX "opera"
14
15#include "dvb-usb.h"
Marco Gittler941491f2007-04-19 11:26:47 -030016#include "stv0299.h"
17
18#define OPERA_READ_MSG 0
19#define OPERA_WRITE_MSG 1
20#define OPERA_I2C_TUNER 0xd1
21
22#define READ_FX2_REG_REQ 0xba
23#define READ_MAC_ADDR 0x08
24#define OPERA_WRITE_FX2 0xbb
25#define OPERA_TUNER_REQ 0xb1
26#define REG_1F_SYMBOLRATE_BYTE0 0x1f
27#define REG_20_SYMBOLRATE_BYTE1 0x20
28#define REG_21_SYMBOLRATE_BYTE2 0x21
29
Marco Gittler86534e52007-04-23 17:52:58 -030030#define ADDR_B600_VOLTAGE_13V (0x02)
31#define ADDR_B601_VOLTAGE_18V (0x03)
32#define ADDR_B1A6_STREAM_CTRL (0x04)
33#define ADDR_B880_READ_REMOTE (0x05)
34
Marco Gittler941491f2007-04-19 11:26:47 -030035struct opera1_state {
36 u32 last_key_pressed;
37};
38struct opera_rc_keys {
39 u32 keycode;
40 u32 event;
41};
42
Adrian Bunk53133af2007-11-05 14:07:06 -030043static int dvb_usb_opera1_debug;
Marco Gittler941491f2007-04-19 11:26:47 -030044module_param_named(debug, dvb_usb_opera1_debug, int, 0644);
45MODULE_PARM_DESC(debug,
46 "set debugging level (1=info,xfer=2,pll=4,ts=8,err=16,rc=32,fw=64 (or-able))."
47 DVB_USB_DEBUG_STATUS);
48
Janne Grunau78e920062008-04-09 19:13:13 -030049DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
50
51
Marco Gittler941491f2007-04-19 11:26:47 -030052static int opera1_xilinx_rw(struct usb_device *dev, u8 request, u16 value,
53 u8 * data, u16 len, int flags)
54{
55 int ret;
56 u8 r;
57 u8 u8buf[len];
58
59 unsigned int pipe = (flags == OPERA_READ_MSG) ?
60 usb_rcvctrlpipe(dev,0) : usb_sndctrlpipe(dev, 0);
61 u8 request_type = (flags == OPERA_READ_MSG) ? USB_DIR_IN : USB_DIR_OUT;
62
63 if (flags == OPERA_WRITE_MSG)
64 memcpy(u8buf, data, len);
65 ret =
66 usb_control_msg(dev, pipe, request, request_type | USB_TYPE_VENDOR,
67 value, 0x0, u8buf, len, 2000);
68
69 if (request == OPERA_TUNER_REQ) {
70 if (usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
71 OPERA_TUNER_REQ, USB_DIR_IN | USB_TYPE_VENDOR,
72 0x01, 0x0, &r, 1, 2000)<1 || r!=0x08)
73 return 0;
74 }
75 if (flags == OPERA_READ_MSG)
76 memcpy(data, u8buf, len);
77 return ret;
78}
79
80/* I2C */
81
82static int opera1_usb_i2c_msgxfer(struct dvb_usb_device *dev, u16 addr,
Marco Gittler86534e52007-04-23 17:52:58 -030083 u8 * buf, u16 len)
Marco Gittler941491f2007-04-19 11:26:47 -030084{
85 int ret = 0;
86 u8 request;
87 u16 value;
88
89 if (!dev) {
90 info("no usb_device");
91 return -EINVAL;
92 }
93 if (mutex_lock_interruptible(&dev->usb_mutex) < 0)
94 return -EAGAIN;
95
Marco Gittler86534e52007-04-23 17:52:58 -030096 switch (addr>>1){
97 case ADDR_B600_VOLTAGE_13V:
98 request=0xb6;
99 value=0x00;
100 break;
101 case ADDR_B601_VOLTAGE_18V:
102 request=0xb6;
103 value=0x01;
104 break;
105 case ADDR_B1A6_STREAM_CTRL:
106 request=0xb1;
107 value=0xa6;
108 break;
109 case ADDR_B880_READ_REMOTE:
110 request=0xb8;
111 value=0x80;
112 break;
113 default:
114 request=0xb1;
115 value=addr;
Marco Gittler941491f2007-04-19 11:26:47 -0300116 }
Marco Gittler86534e52007-04-23 17:52:58 -0300117 ret = opera1_xilinx_rw(dev->udev, request,
118 value, buf, len,
119 addr&0x01?OPERA_READ_MSG:OPERA_WRITE_MSG);
Marco Gittler941491f2007-04-19 11:26:47 -0300120
121 mutex_unlock(&dev->usb_mutex);
122 return ret;
123}
124
125static int opera1_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[],
126 int num)
127{
128 struct dvb_usb_device *d = i2c_get_adapdata(adap);
129 int i = 0, tmp = 0;
130
131 if (!d)
132 return -ENODEV;
133 if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
134 return -EAGAIN;
135
136 for (i = 0; i < num; i++) {
137 if ((tmp = opera1_usb_i2c_msgxfer(d,
Marco Gittler86534e52007-04-23 17:52:58 -0300138 (msg[i].addr<<1)|(msg[i].flags&I2C_M_RD?0x01:0),
Marco Gittler941491f2007-04-19 11:26:47 -0300139 msg[i].buf,
Marco Gittler86534e52007-04-23 17:52:58 -0300140 msg[i].len
141 )!= msg[i].len)) {
Marco Gittler941491f2007-04-19 11:26:47 -0300142 break;
143 }
144 if (dvb_usb_opera1_debug & 0x10)
145 info("sending i2c mesage %d %d", tmp, msg[i].len);
146 }
147 mutex_unlock(&d->i2c_mutex);
148 return num;
149}
150
151static u32 opera1_i2c_func(struct i2c_adapter *adapter)
152{
153 return I2C_FUNC_I2C;
154}
155
156static struct i2c_algorithm opera1_i2c_algo = {
157 .master_xfer = opera1_i2c_xfer,
158 .functionality = opera1_i2c_func,
159};
160
161static int opera1_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage)
162{
163 static u8 command_13v[1]={0x00};
164 static u8 command_18v[1]={0x01};
165 struct i2c_msg msg[] = {
Marco Gittler86534e52007-04-23 17:52:58 -0300166 {.addr = ADDR_B600_VOLTAGE_13V,.flags = 0,.buf = command_13v,.len = 1},
Marco Gittler941491f2007-04-19 11:26:47 -0300167 };
168 struct dvb_usb_adapter *udev_adap =
169 (struct dvb_usb_adapter *)(fe->dvb->priv);
170 if (voltage == SEC_VOLTAGE_18) {
Marco Gittler86534e52007-04-23 17:52:58 -0300171 msg[0].addr = ADDR_B601_VOLTAGE_18V;
Marco Gittler941491f2007-04-19 11:26:47 -0300172 msg[0].buf = command_18v;
173 }
174 i2c_transfer(&udev_adap->dev->i2c_adap, msg, 1);
175 return 0;
176}
177
178static int opera1_stv0299_set_symbol_rate(struct dvb_frontend *fe, u32 srate,
179 u32 ratio)
180{
181 stv0299_writereg(fe, 0x13, 0x98);
182 stv0299_writereg(fe, 0x14, 0x95);
183 stv0299_writereg(fe, REG_1F_SYMBOLRATE_BYTE0, (ratio >> 16) & 0xff);
184 stv0299_writereg(fe, REG_20_SYMBOLRATE_BYTE1, (ratio >> 8) & 0xff);
185 stv0299_writereg(fe, REG_21_SYMBOLRATE_BYTE2, (ratio) & 0xf0);
186 return 0;
187
188}
189static u8 opera1_inittab[] = {
190 0x00, 0xa1,
191 0x01, 0x15,
192 0x02, 0x00,
193 0x03, 0x00,
194 0x04, 0x7d,
195 0x05, 0x05,
196 0x06, 0x02,
197 0x07, 0x00,
198 0x0b, 0x00,
199 0x0c, 0x01,
200 0x0d, 0x81,
201 0x0e, 0x44,
202 0x0f, 0x19,
203 0x10, 0x3f,
204 0x11, 0x84,
205 0x12, 0xda,
206 0x13, 0x98,
207 0x14, 0x95,
208 0x15, 0xc9,
209 0x16, 0xeb,
210 0x17, 0x00,
211 0x18, 0x19,
212 0x19, 0x8b,
213 0x1a, 0x00,
214 0x1b, 0x82,
215 0x1c, 0x7f,
216 0x1d, 0x00,
217 0x1e, 0x00,
218 REG_1F_SYMBOLRATE_BYTE0, 0x06,
219 REG_20_SYMBOLRATE_BYTE1, 0x50,
220 REG_21_SYMBOLRATE_BYTE2, 0x10,
221 0x22, 0x00,
222 0x23, 0x00,
223 0x24, 0x37,
224 0x25, 0xbc,
225 0x26, 0x00,
226 0x27, 0x00,
227 0x28, 0x00,
228 0x29, 0x1e,
229 0x2a, 0x14,
230 0x2b, 0x1f,
231 0x2c, 0x09,
232 0x2d, 0x0a,
233 0x2e, 0x00,
234 0x2f, 0x00,
235 0x30, 0x00,
236 0x31, 0x1f,
237 0x32, 0x19,
238 0x33, 0xfc,
239 0x34, 0x13,
240 0xff, 0xff,
241};
242
243static struct stv0299_config opera1_stv0299_config = {
Marco Gittler86534e52007-04-23 17:52:58 -0300244 .demod_address = 0xd0>>1,
Marco Gittler941491f2007-04-19 11:26:47 -0300245 .min_delay_ms = 100,
246 .mclk = 88000000UL,
247 .invert = 1,
248 .skip_reinit = 0,
Oliver Endrissda2c7f62008-04-20 22:13:37 -0300249 .lock_output = STV0299_LOCKOUTPUT_0,
Marco Gittler941491f2007-04-19 11:26:47 -0300250 .volt13_op0_op1 = STV0299_VOLT13_OP0,
251 .inittab = opera1_inittab,
252 .set_symbol_rate = opera1_stv0299_set_symbol_rate,
253};
254
255static int opera1_frontend_attach(struct dvb_usb_adapter *d)
256{
257 if ((d->fe =
258 dvb_attach(stv0299_attach, &opera1_stv0299_config,
259 &d->dev->i2c_adap)) != NULL) {
260 d->fe->ops.set_voltage = opera1_set_voltage;
261 return 0;
262 }
263 info("not attached stv0299");
264 return -EIO;
265}
266
267static int opera1_tuner_attach(struct dvb_usb_adapter *adap)
268{
Marco Gittler86534e52007-04-23 17:52:58 -0300269 dvb_attach(
270 dvb_pll_attach, adap->fe, 0xc0>>1,
Michael Krufky47a99912007-06-12 16:10:51 -0300271 &adap->dev->i2c_adap, DVB_PLL_OPERA1
Marco Gittler86534e52007-04-23 17:52:58 -0300272 );
Marco Gittler941491f2007-04-19 11:26:47 -0300273 return 0;
274}
275
276static int opera1_power_ctrl(struct dvb_usb_device *d, int onoff)
277{
Marco Gittler941491f2007-04-19 11:26:47 -0300278 u8 val = onoff ? 0x01 : 0x00;
Marco Gittler86534e52007-04-23 17:52:58 -0300279
Marco Gittler941491f2007-04-19 11:26:47 -0300280 if (dvb_usb_opera1_debug)
281 info("power %s", onoff ? "on" : "off");
Marco Gittler86534e52007-04-23 17:52:58 -0300282 return opera1_xilinx_rw(d->udev, 0xb7, val,
283 &val, 1, OPERA_WRITE_MSG);
Marco Gittler941491f2007-04-19 11:26:47 -0300284}
285
286static int opera1_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff)
287{
288 static u8 buf_start[2] = { 0xff, 0x03 };
289 static u8 buf_stop[2] = { 0xff, 0x00 };
290 struct i2c_msg start_tuner[] = {
Marco Gittler86534e52007-04-23 17:52:58 -0300291 {.addr = ADDR_B1A6_STREAM_CTRL,.buf = onoff ? buf_start : buf_stop,.len = 2},
Marco Gittler941491f2007-04-19 11:26:47 -0300292 };
293 if (dvb_usb_opera1_debug)
294 info("streaming %s", onoff ? "on" : "off");
295 i2c_transfer(&adap->dev->i2c_adap, start_tuner, 1);
296 return 0;
297}
298
299static int opera1_pid_filter(struct dvb_usb_adapter *adap, int index, u16 pid,
300 int onoff)
301{
302 u8 b_pid[3];
303 struct i2c_msg msg[] = {
Marco Gittler86534e52007-04-23 17:52:58 -0300304 {.addr = ADDR_B1A6_STREAM_CTRL,.buf = b_pid,.len = 3},
Marco Gittler941491f2007-04-19 11:26:47 -0300305 };
306 if (dvb_usb_opera1_debug)
307 info("pidfilter index: %d pid: %d %s", index, pid,
308 onoff ? "on" : "off");
309 b_pid[0] = (2 * index) + 4;
310 b_pid[1] = onoff ? (pid & 0xff) : (0x00);
311 b_pid[2] = onoff ? ((pid >> 8) & 0xff) : (0x00);
312 i2c_transfer(&adap->dev->i2c_adap, msg, 1);
313 return 0;
314}
315
316static int opera1_pid_filter_control(struct dvb_usb_adapter *adap, int onoff)
317{
318 int u = 0x04;
319 u8 b_pid[3];
320 struct i2c_msg msg[] = {
Marco Gittler86534e52007-04-23 17:52:58 -0300321 {.addr = ADDR_B1A6_STREAM_CTRL,.buf = b_pid,.len = 3},
Marco Gittler941491f2007-04-19 11:26:47 -0300322 };
323 if (dvb_usb_opera1_debug)
324 info("%s hw-pidfilter", onoff ? "enable" : "disable");
325 for (; u < 0x7e; u += 2) {
326 b_pid[0] = u;
327 b_pid[1] = 0;
328 b_pid[2] = 0x80;
329 i2c_transfer(&adap->dev->i2c_adap, msg, 1);
330 }
331 return 0;
332}
333
334static struct dvb_usb_rc_key opera1_rc_keys[] = {
335 {0x5f, 0xa0, KEY_1},
336 {0x51, 0xaf, KEY_2},
337 {0x5d, 0xa2, KEY_3},
338 {0x41, 0xbe, KEY_4},
339 {0x0b, 0xf5, KEY_5},
340 {0x43, 0xbd, KEY_6},
341 {0x47, 0xb8, KEY_7},
342 {0x49, 0xb6, KEY_8},
343 {0x05, 0xfa, KEY_9},
344 {0x45, 0xba, KEY_0},
345 {0x09, 0xf6, KEY_UP}, /*chanup */
346 {0x1b, 0xe5, KEY_DOWN}, /*chandown */
347 {0x5d, 0xa3, KEY_LEFT}, /*voldown */
348 {0x5f, 0xa1, KEY_RIGHT}, /*volup */
349 {0x07, 0xf8, KEY_SPACE}, /*tab */
350 {0x1f, 0xe1, KEY_ENTER}, /*play ok */
351 {0x1b, 0xe4, KEY_Z}, /*zoom */
352 {0x59, 0xa6, KEY_M}, /*mute */
353 {0x5b, 0xa5, KEY_F}, /*tv/f */
354 {0x19, 0xe7, KEY_R}, /*rec */
355 {0x01, 0xfe, KEY_S}, /*Stop */
356 {0x03, 0xfd, KEY_P}, /*pause */
357 {0x03, 0xfc, KEY_W}, /*<- -> */
358 {0x07, 0xf9, KEY_C}, /*capture */
359 {0x47, 0xb9, KEY_Q}, /*exit */
360 {0x43, 0xbc, KEY_O}, /*power */
361
362};
363
364static int opera1_rc_query(struct dvb_usb_device *dev, u32 * event, int *state)
365{
366 struct opera1_state *opst = dev->priv;
367 u8 rcbuffer[32];
368 const u16 startmarker1 = 0x10ed;
369 const u16 startmarker2 = 0x11ec;
370 struct i2c_msg read_remote[] = {
Marco Gittler86534e52007-04-23 17:52:58 -0300371 {.addr = ADDR_B880_READ_REMOTE,.buf = rcbuffer,.flags = I2C_M_RD,.len = 32},
Marco Gittler941491f2007-04-19 11:26:47 -0300372 };
373 int i = 0;
374 u32 send_key = 0;
375
376 if (i2c_transfer(&dev->i2c_adap, read_remote, 1) == 1) {
377 for (i = 0; i < 32; i++) {
378 if (rcbuffer[i])
379 send_key |= 1;
380 if (i < 31)
381 send_key = send_key << 1;
382 }
383 if (send_key & 0x8000)
384 send_key = (send_key << 1) | (send_key >> 15 & 0x01);
385
386 if (send_key == 0xffff && opst->last_key_pressed != 0) {
387 *state = REMOTE_KEY_REPEAT;
388 *event = opst->last_key_pressed;
389 return 0;
390 }
391 for (; send_key != 0;) {
392 if (send_key >> 16 == startmarker2) {
393 break;
394 } else if (send_key >> 16 == startmarker1) {
395 send_key =
396 (send_key & 0xfffeffff) | (startmarker1 << 16);
397 break;
398 } else
399 send_key >>= 1;
400 }
401
402 if (send_key == 0)
403 return 0;
404
405 send_key = (send_key & 0xffff) | 0x0100;
406
407 for (i = 0; i < ARRAY_SIZE(opera1_rc_keys); i++) {
408 if ((opera1_rc_keys[i].custom * 256 +
409 opera1_rc_keys[i].data) == (send_key & 0xffff)) {
410 *state = REMOTE_KEY_PRESSED;
411 *event = opera1_rc_keys[i].event;
412 opst->last_key_pressed =
413 opera1_rc_keys[i].event;
414 break;
415 }
416 opst->last_key_pressed = 0;
417 }
418 } else
419 *state = REMOTE_NO_KEY_PRESSED;
420 return 0;
421}
422
423static struct usb_device_id opera1_table[] = {
424 {USB_DEVICE(USB_VID_CYPRESS, USB_PID_OPERA1_COLD)},
425 {USB_DEVICE(USB_VID_OPERA1, USB_PID_OPERA1_WARM)},
426 {}
427};
428
429MODULE_DEVICE_TABLE(usb, opera1_table);
430
431static int opera1_read_mac_address(struct dvb_usb_device *d, u8 mac[6])
432{
433 u8 command[] = { READ_MAC_ADDR };
434 opera1_xilinx_rw(d->udev, 0xb1, 0xa0, command, 1, OPERA_WRITE_MSG);
435 opera1_xilinx_rw(d->udev, 0xb1, 0xa1, mac, 6, OPERA_READ_MSG);
436 return 0;
437}
438static int opera1_xilinx_load_firmware(struct usb_device *dev,
439 const char *filename)
440{
441 const struct firmware *fw = NULL;
442 u8 *b, *p;
Marco Gittler59800552007-07-04 19:18:34 -0300443 int ret = 0, i,fpgasize=40;
Marco Gittler941491f2007-04-19 11:26:47 -0300444 u8 testval;
Marco Gittler59800552007-07-04 19:18:34 -0300445 info("start downloading fpga firmware %s",filename);
Marco Gittler941491f2007-04-19 11:26:47 -0300446
447 if ((ret = request_firmware(&fw, filename, &dev->dev)) != 0) {
448 err("did not find the firmware file. (%s) "
449 "Please see linux/Documentation/dvb/ for more details on firmware-problems.",
450 filename);
451 return ret;
452 } else {
453 p = kmalloc(fw->size, GFP_KERNEL);
454 opera1_xilinx_rw(dev, 0xbc, 0x00, &testval, 1, OPERA_READ_MSG);
455 if (p != NULL && testval != 0x67) {
456
457 u8 reset = 0, fpga_command = 0;
458 memcpy(p, fw->data, fw->size);
459 /* clear fpga ? */
460 opera1_xilinx_rw(dev, 0xbc, 0xaa, &fpga_command, 1,
461 OPERA_WRITE_MSG);
Marco Gittler59800552007-07-04 19:18:34 -0300462 for (i = 0; i < fw->size;) {
463 if ( (fw->size - i) <fpgasize){
464 fpgasize=fw->size-i;
465 }
Marco Gittler941491f2007-04-19 11:26:47 -0300466 b = (u8 *) p + i;
467 if (opera1_xilinx_rw
Marco Gittler59800552007-07-04 19:18:34 -0300468 (dev, OPERA_WRITE_FX2, 0x0, b , fpgasize,
469 OPERA_WRITE_MSG) != fpgasize
Marco Gittler941491f2007-04-19 11:26:47 -0300470 ) {
471 err("error while transferring firmware");
472 ret = -EINVAL;
473 break;
474 }
Marco Gittler59800552007-07-04 19:18:34 -0300475 i = i + fpgasize;
Marco Gittler941491f2007-04-19 11:26:47 -0300476 }
477 /* restart the CPU */
478 if (ret || opera1_xilinx_rw
479 (dev, 0xa0, 0xe600, &reset, 1,
480 OPERA_WRITE_MSG) != 1) {
481 err("could not restart the USB controller CPU.");
482 ret = -EINVAL;
483 }
Marco Gittler941491f2007-04-19 11:26:47 -0300484 }
485 }
Adrian Bunk77596052008-02-27 21:21:15 -0300486 kfree(p);
Marco Gittler941491f2007-04-19 11:26:47 -0300487 if (fw) {
488 release_firmware(fw);
489 }
490 return ret;
491}
492
493static struct dvb_usb_device_properties opera1_properties = {
494 .caps = DVB_USB_IS_AN_I2C_ADAPTER,
495 .usb_ctrl = CYPRESS_FX2,
Marco Gittler86534e52007-04-23 17:52:58 -0300496 .firmware = "dvb-usb-opera-01.fw",
Marco Gittler941491f2007-04-19 11:26:47 -0300497 .size_of_priv = sizeof(struct opera1_state),
498
499 .power_ctrl = opera1_power_ctrl,
500 .i2c_algo = &opera1_i2c_algo,
501
502 .rc_key_map = opera1_rc_keys,
503 .rc_key_map_size = ARRAY_SIZE(opera1_rc_keys),
504 .rc_interval = 200,
505 .rc_query = opera1_rc_query,
506 .read_mac_address = opera1_read_mac_address,
507 .generic_bulk_ctrl_endpoint = 0x00,
508 /* parameter for the MPEG2-data transfer */
509 .num_adapters = 1,
510 .adapter = {
511 {
512 .frontend_attach = opera1_frontend_attach,
513 .streaming_ctrl = opera1_streaming_ctrl,
514 .tuner_attach = opera1_tuner_attach,
515 .caps =
516 DVB_USB_ADAP_HAS_PID_FILTER |
517 DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
518 .pid_filter = opera1_pid_filter,
519 .pid_filter_ctrl = opera1_pid_filter_control,
520 .pid_filter_count = 252,
521 .stream = {
522 .type = USB_BULK,
523 .count = 10,
524 .endpoint = 0x82,
525 .u = {
526 .bulk = {
527 .buffersize = 4096,
528 }
529 }
530 },
531 }
532 },
533 .num_device_descs = 1,
534 .devices = {
535 {"Opera1 DVB-S USB2.0",
536 {&opera1_table[0], NULL},
537 {&opera1_table[1], NULL},
538 },
539 }
540};
541
542static int opera1_probe(struct usb_interface *intf,
543 const struct usb_device_id *id)
544{
Marco Gittler941491f2007-04-19 11:26:47 -0300545 struct usb_device *udev = interface_to_usbdev(intf);
546
547 if (udev->descriptor.idProduct == USB_PID_OPERA1_WARM &&
548 udev->descriptor.idVendor == USB_VID_OPERA1 &&
Marco Gittler59800552007-07-04 19:18:34 -0300549 opera1_xilinx_load_firmware(udev, "dvb-usb-opera1-fpga-01.fw") != 0
Marco Gittlerd06cdbe2007-06-28 10:10:00 -0300550 ) {
Marco Gittler941491f2007-04-19 11:26:47 -0300551 return -EINVAL;
552 }
553
Janne Grunau78e920062008-04-09 19:13:13 -0300554 if (0 != dvb_usb_device_init(intf, &opera1_properties,
555 THIS_MODULE, NULL, adapter_nr))
Marco Gittler941491f2007-04-19 11:26:47 -0300556 return -EINVAL;
557 return 0;
558}
559
560static struct usb_driver opera1_driver = {
561 .name = "opera1",
562 .probe = opera1_probe,
563 .disconnect = dvb_usb_device_exit,
564 .id_table = opera1_table,
565};
566
567static int __init opera1_module_init(void)
568{
569 int result = 0;
570 if ((result = usb_register(&opera1_driver))) {
571 err("usb_register failed. Error number %d", result);
572 }
573 return result;
574}
575
576static void __exit opera1_module_exit(void)
577{
578 usb_deregister(&opera1_driver);
579}
580
581module_init(opera1_module_init);
582module_exit(opera1_module_exit);
583
584MODULE_AUTHOR("Mario Hlawitschka (c) dh1pa@amsat.org");
585MODULE_AUTHOR("Marco Gittler (c) g.marco@freenet.de");
586MODULE_DESCRIPTION("Driver for Opera1 DVB-S device");
587MODULE_VERSION("0.1");
588MODULE_LICENSE("GPL");