diff options
author | Malcolm Priestley <tvboxspy@gmail.com> | 2010-10-16 15:44:43 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2010-10-22 20:22:47 -0400 |
commit | ab599a6d474e0dd4db3557a46dd15cff6e126d0b (patch) | |
tree | f1271d31ecd1c247f76cab8cec18f03714c7acbe /drivers/media | |
parent | dda7ae789f1d9b0c2528f7abc37f4316f8fa1e0f (diff) |
[media] lmedm04: driver for DM04/QQBOX updated to version 1.60
These include
-later kill of usb_buffer to avoid kernel crash on hot unplugging.
-DiSEqC functions.
-LNB Power switch
-Faster channel change.
-support for LG tuner on LME2510C.
-firmware switching for LG tuner.
Signed-off-by: Malcolm Priestley <tvboxspy@gmail.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media')
-rw-r--r-- | drivers/media/dvb/dvb-usb/Kconfig | 1 | ||||
-rw-r--r-- | drivers/media/dvb/dvb-usb/lmedm04.c | 292 | ||||
-rw-r--r-- | drivers/media/dvb/dvb-usb/lmedm04.h | 44 |
3 files changed, 237 insertions, 100 deletions
diff --git a/drivers/media/dvb/dvb-usb/Kconfig b/drivers/media/dvb/dvb-usb/Kconfig index ce60c1e46e15..2525d3b3c88d 100644 --- a/drivers/media/dvb/dvb-usb/Kconfig +++ b/drivers/media/dvb/dvb-usb/Kconfig | |||
@@ -356,6 +356,5 @@ config DVB_USB_LME2510 | |||
356 | select DVB_TDA826X if !DVB_FE_CUSTOMISE | 356 | select DVB_TDA826X if !DVB_FE_CUSTOMISE |
357 | select DVB_STV0288 if !DVB_FE_CUSTOMISE | 357 | select DVB_STV0288 if !DVB_FE_CUSTOMISE |
358 | select DVB_IX2505V if !DVB_FE_CUSTOMISE | 358 | select DVB_IX2505V if !DVB_FE_CUSTOMISE |
359 | depends on IR_CORE | ||
360 | help | 359 | help |
361 | Say Y here to support the LME DM04/QQBOX DVB-S USB2.0 . | 360 | Say Y here to support the LME DM04/QQBOX DVB-S USB2.0 . |
diff --git a/drivers/media/dvb/dvb-usb/lmedm04.c b/drivers/media/dvb/dvb-usb/lmedm04.c index d5374ac075d3..d939fbbf9fe6 100644 --- a/drivers/media/dvb/dvb-usb/lmedm04.c +++ b/drivers/media/dvb/dvb-usb/lmedm04.c | |||
@@ -1,14 +1,17 @@ | |||
1 | /* DVB USB compliant linux driver for | 1 | /* DVB USB compliant linux driver for |
2 | * | 2 | * |
3 | * DM04/QQBOX DVB-S USB BOX LME2510C + SHARP:BS2F7HZ7395 | 3 | * DM04/QQBOX DVB-S USB BOX LME2510C + SHARP:BS2F7HZ7395 |
4 | * LME2510 + LGTDQT-P001F | 4 | * LME2510C + LG TDQY-P001F |
5 | * LME2510 + LG TDQY-P001F | ||
5 | * | 6 | * |
6 | * MVB7395 (LME2510C+SHARP:BS2F7HZ7395) | 7 | * MVB7395 (LME2510C+SHARP:BS2F7HZ7395) |
7 | * SHARP:BS2F7HZ7395 = (STV0288+Sharp IX2505V) | 8 | * SHARP:BS2F7HZ7395 = (STV0288+Sharp IX2505V) |
8 | * | 9 | * |
9 | * MV001F (LME2510 +LGTDQY-P001F) | 10 | * MV001F (LME2510+LGTDQY-P001F) |
10 | * LG TDQY - P001F =(TDA8263 + TDA10086H) | 11 | * LG TDQY - P001F =(TDA8263 + TDA10086H) |
11 | * | 12 | * |
13 | * MVB0001F (LME2510C+LGTDQT-P001F) | ||
14 | * | ||
12 | * For firmware see Documentation/dvb/lmedm04.txt | 15 | * For firmware see Documentation/dvb/lmedm04.txt |
13 | * | 16 | * |
14 | * I2C addresses: | 17 | * I2C addresses: |
@@ -21,7 +24,6 @@ | |||
21 | * ***Please Note*** | 24 | * ***Please Note*** |
22 | * There are other variants of the DM04 | 25 | * There are other variants of the DM04 |
23 | * ***NOT SUPPORTED*** | 26 | * ***NOT SUPPORTED*** |
24 | * MVB0001F (LME2510C+LGTDQT-P001F) | ||
25 | * MV0194 (LME2510+SHARP0194) | 27 | * MV0194 (LME2510+SHARP0194) |
26 | * MVB0194 (LME2510C+SHARP0194) | 28 | * MVB0194 (LME2510C+SHARP0194) |
27 | * | 29 | * |
@@ -51,10 +53,7 @@ | |||
51 | * LME2510: Non Intel USB chipsets fail to maintain High Speed on | 53 | * LME2510: Non Intel USB chipsets fail to maintain High Speed on |
52 | * Boot or Hot Plug. | 54 | * Boot or Hot Plug. |
53 | * | 55 | * |
54 | * DiSEqC functions are not fully supported in this driver. The main | 56 | * QQbox suffers from noise on LNB voltage. |
55 | * reason is the frontend is cut off during streaming. Allowing frontend | ||
56 | * access will stall the driver. Applications that attempt to this, the | ||
57 | * commands are ignored. | ||
58 | * | 57 | * |
59 | * PID functions have been removed from this driver version due to | 58 | * PID functions have been removed from this driver version due to |
60 | * problems with different firmware and application versions. | 59 | * problems with different firmware and application versions. |
@@ -91,9 +90,14 @@ module_param_named(debug, dvb_usb_lme2510_debug, int, 0644); | |||
91 | MODULE_PARM_DESC(debug, "set debugging level (1=info (or-able))." | 90 | MODULE_PARM_DESC(debug, "set debugging level (1=info (or-able))." |
92 | DVB_USB_DEBUG_STATUS); | 91 | DVB_USB_DEBUG_STATUS); |
93 | 92 | ||
93 | static int dvb_usb_lme2510_firmware; | ||
94 | module_param_named(firmware, dvb_usb_lme2510_firmware, int, 0644); | ||
95 | MODULE_PARM_DESC(firmware, "set default firmware 0=Sharp7395 1=LG"); | ||
96 | |||
97 | |||
94 | DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); | 98 | DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); |
95 | #define TUNER_LG 0x1 | 99 | #define TUNER_LG 0x1 |
96 | #define TUNER_S7395 0x2 | 100 | #define TUNER_S7395 0x2 |
97 | 101 | ||
98 | struct lme2510_state { | 102 | struct lme2510_state { |
99 | u8 id; | 103 | u8 id; |
@@ -107,6 +111,8 @@ struct lme2510_state { | |||
107 | u8 i2c_tuner_gate_w; | 111 | u8 i2c_tuner_gate_w; |
108 | u8 i2c_tuner_gate_r; | 112 | u8 i2c_tuner_gate_r; |
109 | u8 i2c_tuner_addr; | 113 | u8 i2c_tuner_addr; |
114 | u8 stream_on; | ||
115 | u8 one_tune; | ||
110 | void *buffer; | 116 | void *buffer; |
111 | struct urb *lme_urb; | 117 | struct urb *lme_urb; |
112 | void *usb_buffer; | 118 | void *usb_buffer; |
@@ -117,6 +123,7 @@ static int lme2510_bulk_write(struct usb_device *dev, | |||
117 | u8 *snd, int len, u8 pipe) | 123 | u8 *snd, int len, u8 pipe) |
118 | { | 124 | { |
119 | int ret, actual_l; | 125 | int ret, actual_l; |
126 | |||
120 | ret = usb_bulk_msg(dev, usb_sndbulkpipe(dev, pipe), | 127 | ret = usb_bulk_msg(dev, usb_sndbulkpipe(dev, pipe), |
121 | snd, len , &actual_l, 500); | 128 | snd, len , &actual_l, 500); |
122 | return ret; | 129 | return ret; |
@@ -151,22 +158,21 @@ static int lme2510_usb_talk(struct dvb_usb_device *d, | |||
151 | /* the read/write capped at 512 */ | 158 | /* the read/write capped at 512 */ |
152 | memcpy(buff, wbuf, (wlen > 512) ? 512 : wlen); | 159 | memcpy(buff, wbuf, (wlen > 512) ? 512 : wlen); |
153 | 160 | ||
154 | |||
155 | ret = mutex_lock_interruptible(&d->usb_mutex); | 161 | ret = mutex_lock_interruptible(&d->usb_mutex); |
156 | 162 | ||
157 | if (ret < 0) | 163 | if (ret < 0) |
158 | return -EAGAIN; | 164 | return -EAGAIN; |
159 | 165 | ||
160 | ret |= usb_clear_halt(d->udev, usb_sndbulkpipe(d->udev, 0x01)); | 166 | ret |= usb_clear_halt(d->udev, usb_sndbulkpipe(d->udev, 0x01)); |
161 | msleep(5); | ||
162 | ret |= lme2510_bulk_write(d->udev, buff, wlen , 0x1); | ||
163 | 167 | ||
164 | msleep(5); | 168 | ret |= lme2510_bulk_write(d->udev, buff, wlen , 0x01); |
165 | ret |= usb_clear_halt(d->udev, usb_rcvbulkpipe(d->udev, 0x1)); | 169 | |
170 | msleep(12); | ||
171 | |||
172 | ret |= usb_clear_halt(d->udev, usb_rcvbulkpipe(d->udev, 0x01)); | ||
166 | 173 | ||
167 | msleep(5); | ||
168 | ret |= lme2510_bulk_read(d->udev, buff, (rlen > 512) ? | 174 | ret |= lme2510_bulk_read(d->udev, buff, (rlen > 512) ? |
169 | 512 : rlen , 0x1); | 175 | 512 : rlen , 0x01); |
170 | 176 | ||
171 | if (rlen > 0) | 177 | if (rlen > 0) |
172 | memcpy(rbuf, buff, rlen); | 178 | memcpy(rbuf, buff, rlen); |
@@ -176,6 +182,18 @@ static int lme2510_usb_talk(struct dvb_usb_device *d, | |||
176 | return (ret < 0) ? -ENODEV : 0; | 182 | return (ret < 0) ? -ENODEV : 0; |
177 | } | 183 | } |
178 | 184 | ||
185 | static int lme2510_usb_talk_restart(struct dvb_usb_device *d, | ||
186 | u8 *wbuf, int wlen, u8 *rbuf, int rlen) { | ||
187 | static u8 stream_on[] = LME_ST_ON_W; | ||
188 | int ret; | ||
189 | u8 rbuff[10]; | ||
190 | /*Send Normal Command*/ | ||
191 | ret = lme2510_usb_talk(d, wbuf, wlen, rbuf, rlen); | ||
192 | /*Restart Stream Command*/ | ||
193 | ret |= lme2510_usb_talk(d, stream_on, sizeof(stream_on), | ||
194 | rbuff, sizeof(rbuff)); | ||
195 | return ret; | ||
196 | } | ||
179 | static int lme2510_remote_keypress(struct dvb_usb_adapter *adap, u16 keypress) | 197 | static int lme2510_remote_keypress(struct dvb_usb_adapter *adap, u16 keypress) |
180 | { | 198 | { |
181 | struct dvb_usb_device *d = adap->dev; | 199 | struct dvb_usb_device *d = adap->dev; |
@@ -213,7 +231,6 @@ static void lme2510_int_response(struct urb *lme_urb) | |||
213 | offset = ((lme_urb->actual_length/8) > 4) | 231 | offset = ((lme_urb->actual_length/8) > 4) |
214 | ? 4 : (lme_urb->actual_length/8) ; | 232 | ? 4 : (lme_urb->actual_length/8) ; |
215 | 233 | ||
216 | |||
217 | for (i = 0; i < offset; ++i) { | 234 | for (i = 0; i < offset; ++i) { |
218 | ibuf = (u8 *)&rbuf[i*8]; | 235 | ibuf = (u8 *)&rbuf[i*8]; |
219 | deb_info(5, "INT O/S C =%02x C/O=%02x Type =%02x%02x", | 236 | deb_info(5, "INT O/S C =%02x C/O=%02x Type =%02x%02x", |
@@ -228,7 +245,8 @@ static void lme2510_int_response(struct urb *lme_urb) | |||
228 | case 0xbb: | 245 | case 0xbb: |
229 | switch (st->tuner_config) { | 246 | switch (st->tuner_config) { |
230 | case TUNER_LG: | 247 | case TUNER_LG: |
231 | st->signal_lock = ibuf[2]; | 248 | if (ibuf[2] > 0) |
249 | st->signal_lock = ibuf[2]; | ||
232 | st->signal_level = ibuf[4]; | 250 | st->signal_level = ibuf[4]; |
233 | st->signal_sn = ibuf[3]; | 251 | st->signal_sn = ibuf[3]; |
234 | st->time_key = ibuf[7]; | 252 | st->time_key = ibuf[7]; |
@@ -237,7 +255,7 @@ static void lme2510_int_response(struct urb *lme_urb) | |||
237 | /* Tweak for earlier firmware*/ | 255 | /* Tweak for earlier firmware*/ |
238 | if (ibuf[1] == 0x03) { | 256 | if (ibuf[1] == 0x03) { |
239 | st->signal_level = ibuf[3]; | 257 | st->signal_level = ibuf[3]; |
240 | st->signal_sn = ibuf[2]; | 258 | st->signal_sn = ibuf[4]; |
241 | } else { | 259 | } else { |
242 | st->signal_level = ibuf[4]; | 260 | st->signal_level = ibuf[4]; |
243 | st->signal_sn = ibuf[5]; | 261 | st->signal_sn = ibuf[5]; |
@@ -295,6 +313,7 @@ static int lme2510_return_status(struct usb_device *dev) | |||
295 | { | 313 | { |
296 | int ret = 0; | 314 | int ret = 0; |
297 | u8 data[10] = {0}; | 315 | u8 data[10] = {0}; |
316 | |||
298 | ret |= usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), | 317 | ret |= usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), |
299 | 0x06, 0x80, 0x0302, 0x00, data, 0x0006, 200); | 318 | 0x06, 0x80, 0x0302, 0x00, data, 0x0006, 200); |
300 | info("Firmware Status: %x (%x)", ret , data[2]); | 319 | info("Firmware Status: %x (%x)", ret , data[2]); |
@@ -308,25 +327,48 @@ static int lme2510_msg(struct dvb_usb_device *d, | |||
308 | int ret = 0; | 327 | int ret = 0; |
309 | struct lme2510_state *st = d->priv; | 328 | struct lme2510_state *st = d->priv; |
310 | 329 | ||
311 | if (st->i2c_talk_onoff == 1) { | 330 | if (mutex_lock_interruptible(&d->i2c_mutex) < 0) |
312 | if ((wbuf[2] == 0x1c) & (wbuf[3] == 0x0e)) | ||
313 | msleep(80); /*take your time when waiting for tune*/ | ||
314 | |||
315 | if (mutex_lock_interruptible(&d->i2c_mutex) < 0) | ||
316 | return -EAGAIN; | 331 | return -EAGAIN; |
317 | 332 | ||
333 | if (st->i2c_talk_onoff == 1) { | ||
334 | |||
318 | ret = lme2510_usb_talk(d, wbuf, wlen, rbuf, rlen); | 335 | ret = lme2510_usb_talk(d, wbuf, wlen, rbuf, rlen); |
319 | 336 | ||
320 | mutex_unlock(&d->i2c_mutex); | ||
321 | switch (st->tuner_config) { | 337 | switch (st->tuner_config) { |
338 | case TUNER_LG: | ||
339 | if (wbuf[2] == 0x1c) { | ||
340 | if (wbuf[3] == 0x0e) { | ||
341 | st->signal_lock = rbuf[1]; | ||
342 | if ((st->stream_on & 1) && | ||
343 | (st->signal_lock & 0x10)) { | ||
344 | lme2510_usb_talk_restart(d, | ||
345 | wbuf, wlen, rbuf, rlen); | ||
346 | st->i2c_talk_onoff = 0; | ||
347 | } | ||
348 | msleep(80); | ||
349 | } | ||
350 | } | ||
351 | break; | ||
322 | case TUNER_S7395: | 352 | case TUNER_S7395: |
323 | if (wbuf[3] == 0x24) | 353 | if (wbuf[2] == 0xd0) { |
324 | st->signal_lock = rbuf[1]; | 354 | if (wbuf[3] == 0x24) { |
355 | st->signal_lock = rbuf[1]; | ||
356 | if ((st->stream_on & 1) && | ||
357 | (st->signal_lock & 0x8)) { | ||
358 | lme2510_usb_talk_restart(d, | ||
359 | wbuf, wlen, rbuf, rlen); | ||
360 | st->i2c_talk_onoff = 0; | ||
361 | } | ||
362 | } | ||
363 | if ((wbuf[3] != 0x6) & (wbuf[3] != 0x5)) | ||
364 | msleep(5); | ||
365 | |||
366 | |||
367 | } | ||
325 | break; | 368 | break; |
326 | default: | 369 | default: |
327 | break; | 370 | break; |
328 | } | 371 | } |
329 | |||
330 | } else { | 372 | } else { |
331 | switch (st->tuner_config) { | 373 | switch (st->tuner_config) { |
332 | case TUNER_LG: | 374 | case TUNER_LG: |
@@ -343,6 +385,17 @@ static int lme2510_msg(struct dvb_usb_device *d, | |||
343 | rbuf[0] = 0x55; | 385 | rbuf[0] = 0x55; |
344 | rbuf[1] = st->signal_sn; | 386 | rbuf[1] = st->signal_sn; |
345 | break; | 387 | break; |
388 | /*DiSEqC functions as per TDA10086*/ | ||
389 | case 0x36: | ||
390 | case 0x48: | ||
391 | case 0x49: | ||
392 | case 0x4a: | ||
393 | case 0x4b: | ||
394 | case 0x4c: | ||
395 | case 0x4d: | ||
396 | if (wbuf[2] == 0x1c) | ||
397 | lme2510_usb_talk_restart(d, | ||
398 | wbuf, wlen, rbuf, rlen); | ||
346 | default: | 399 | default: |
347 | break; | 400 | break; |
348 | } | 401 | } |
@@ -362,7 +415,31 @@ static int lme2510_msg(struct dvb_usb_device *d, | |||
362 | rbuf[0] = 0x55; | 415 | rbuf[0] = 0x55; |
363 | rbuf[1] = (st->signal_level & 0x80) | 416 | rbuf[1] = (st->signal_level & 0x80) |
364 | ? 0 : st->signal_lock; | 417 | ? 0 : st->signal_lock; |
418 | break; | ||
419 | case 0x6: | ||
420 | if (wbuf[2] == 0xd0) | ||
421 | lme2510_usb_talk(d, | ||
422 | wbuf, wlen, rbuf, rlen); | ||
423 | break; | ||
424 | case 0x1: | ||
425 | if (st->one_tune > 0) | ||
426 | break; | ||
427 | st->one_tune++; | ||
428 | st->i2c_talk_onoff = 1; | ||
429 | /*DiSEqC functions as per STV0288*/ | ||
430 | case 0x5: | ||
431 | case 0x7: | ||
432 | case 0x8: | ||
433 | case 0x9: | ||
434 | case 0xa: | ||
435 | case 0xb: | ||
436 | if (wbuf[2] == 0xd0) | ||
437 | lme2510_usb_talk_restart(d, | ||
438 | wbuf, wlen, rbuf, rlen); | ||
439 | break; | ||
365 | default: | 440 | default: |
441 | rbuf[0] = 0x55; | ||
442 | rbuf[1] = 0x00; | ||
366 | break; | 443 | break; |
367 | } | 444 | } |
368 | break; | 445 | break; |
@@ -376,6 +453,8 @@ static int lme2510_msg(struct dvb_usb_device *d, | |||
376 | 453 | ||
377 | } | 454 | } |
378 | 455 | ||
456 | mutex_unlock(&d->i2c_mutex); | ||
457 | |||
379 | return ret; | 458 | return ret; |
380 | } | 459 | } |
381 | 460 | ||
@@ -469,29 +548,34 @@ static int lme2510_identify_state(struct usb_device *udev, | |||
469 | static int lme2510_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff) | 548 | static int lme2510_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff) |
470 | { | 549 | { |
471 | struct lme2510_state *st = adap->dev->priv; | 550 | struct lme2510_state *st = adap->dev->priv; |
472 | static u8 reset[] = LME_RESET; | ||
473 | static u8 stream_on[] = LME_ST_ON_W; | 551 | static u8 stream_on[] = LME_ST_ON_W; |
474 | static u8 clear_reg_3[] = LME_CLEAR_PID; | 552 | static u8 clear_reg_3[] = LME_CLEAR_PID; |
475 | static u8 rbuf[1]; | 553 | static u8 rbuf[1]; |
554 | static u8 timeout; | ||
476 | int ret = 0, len = 2, rlen = sizeof(rbuf); | 555 | int ret = 0, len = 2, rlen = sizeof(rbuf); |
477 | 556 | ||
478 | deb_info(1, "STM (%02x)", onoff); | 557 | deb_info(1, "STM (%02x)", onoff); |
479 | 558 | ||
480 | if (onoff == 1) { | 559 | if (onoff == 1) { |
481 | st->i2c_talk_onoff = 0; | 560 | st->i2c_talk_onoff = 0; |
482 | msleep(400); /* give enough time for i2c to stop */ | 561 | timeout = 0; |
562 | /* wait for i2C to be free */ | ||
563 | while (mutex_lock_interruptible(&adap->dev->i2c_mutex) < 0) { | ||
564 | timeout++; | ||
565 | if (timeout > 5) | ||
566 | return -ENODEV; | ||
567 | } | ||
568 | msleep(100); | ||
483 | ret |= lme2510_usb_talk(adap->dev, | 569 | ret |= lme2510_usb_talk(adap->dev, |
484 | stream_on, len, rbuf, rlen); | 570 | stream_on, len, rbuf, rlen); |
571 | st->stream_on = 1; | ||
572 | st->one_tune = 0; | ||
573 | mutex_unlock(&adap->dev->i2c_mutex); | ||
485 | } else { | 574 | } else { |
486 | deb_info(1, "STM Steam Off"); | 575 | deb_info(1, "STM Steam Off"); |
487 | if (st->tuner_config == TUNER_LG) | 576 | ret |= lme2510_usb_talk(adap->dev, clear_reg_3, |
488 | ret |= lme2510_usb_talk(adap->dev, clear_reg_3, | ||
489 | sizeof(clear_reg_3), rbuf, rlen); | 577 | sizeof(clear_reg_3), rbuf, rlen); |
490 | else | 578 | st->stream_on = 0; |
491 | ret |= lme2510_usb_talk(adap->dev, | ||
492 | reset, sizeof(reset), rbuf, rlen); | ||
493 | |||
494 | msleep(400); | ||
495 | st->i2c_talk_onoff = 1; | 579 | st->i2c_talk_onoff = 1; |
496 | } | 580 | } |
497 | 581 | ||
@@ -604,6 +688,63 @@ static int lme2510_download_firmware(struct usb_device *dev, | |||
604 | return (ret < 0) ? -ENODEV : 0; | 688 | return (ret < 0) ? -ENODEV : 0; |
605 | } | 689 | } |
606 | 690 | ||
691 | /* Default firmware for LME2510C */ | ||
692 | const char lme_firmware[50] = "dvb-usb-lme2510c-s7395.fw"; | ||
693 | |||
694 | static void lme_coldreset(struct usb_device *dev) | ||
695 | { | ||
696 | int ret = 0, len_in; | ||
697 | u8 data[512] = {0}; | ||
698 | |||
699 | data[0] = 0x0a; | ||
700 | len_in = 1; | ||
701 | info("FRM Firmware Cold Reset"); | ||
702 | ret |= lme2510_bulk_write(dev, data , len_in, 1); /*Cold Resetting*/ | ||
703 | ret |= lme2510_bulk_read(dev, data, len_in, 1); | ||
704 | return; | ||
705 | } | ||
706 | |||
707 | static void lme_firmware_switch(struct usb_device *udev, int cold) | ||
708 | { | ||
709 | const struct firmware *fw = NULL; | ||
710 | char lme2510c_s7395[] = "dvb-usb-lme2510c-s7395.fw"; | ||
711 | char lme2510c_lg[] = "dvb-usb-lme2510c-lg.fw"; | ||
712 | char *firm_msg[] = {"Loading", "Switching to"}; | ||
713 | int ret; | ||
714 | |||
715 | if (udev->descriptor.idProduct == 0x1122) | ||
716 | return; | ||
717 | |||
718 | switch (dvb_usb_lme2510_firmware) { | ||
719 | case 0: | ||
720 | default: | ||
721 | memcpy(&lme_firmware, lme2510c_s7395, sizeof(lme2510c_s7395)); | ||
722 | ret = request_firmware(&fw, lme_firmware, &udev->dev); | ||
723 | if (ret == 0) { | ||
724 | info("FRM %s S7395 Firmware", firm_msg[cold]); | ||
725 | break; | ||
726 | } | ||
727 | if (cold == 0) | ||
728 | dvb_usb_lme2510_firmware = 1; | ||
729 | else | ||
730 | cold = 0; | ||
731 | case 1: | ||
732 | memcpy(&lme_firmware, lme2510c_lg, sizeof(lme2510c_lg)); | ||
733 | ret = request_firmware(&fw, lme_firmware, &udev->dev); | ||
734 | if (ret == 0) { | ||
735 | info("FRM %s LG Firmware", firm_msg[cold]); | ||
736 | break; | ||
737 | } | ||
738 | info("FRM No Firmware Found - please install"); | ||
739 | dvb_usb_lme2510_firmware = 0; | ||
740 | cold = 0; | ||
741 | break; | ||
742 | } | ||
743 | release_firmware(fw); | ||
744 | if (cold) | ||
745 | lme_coldreset(udev); | ||
746 | return; | ||
747 | } | ||
607 | 748 | ||
608 | static int lme2510_kill_urb(struct usb_data_stream *stream) | 749 | static int lme2510_kill_urb(struct usb_data_stream *stream) |
609 | { | 750 | { |
@@ -638,7 +779,6 @@ static struct ix2505v_config lme_tuner = { | |||
638 | .tuner_chargepump = 0x3, | 779 | .tuner_chargepump = 0x3, |
639 | }; | 780 | }; |
640 | 781 | ||
641 | |||
642 | static int dm04_lme2510_set_voltage(struct dvb_frontend *fe, | 782 | static int dm04_lme2510_set_voltage(struct dvb_frontend *fe, |
643 | fe_sec_voltage_t voltage) | 783 | fe_sec_voltage_t voltage) |
644 | { | 784 | { |
@@ -646,35 +786,28 @@ static int dm04_lme2510_set_voltage(struct dvb_frontend *fe, | |||
646 | struct lme2510_state *st = adap->dev->priv; | 786 | struct lme2510_state *st = adap->dev->priv; |
647 | static u8 voltage_low[] = LME_VOLTAGE_L; | 787 | static u8 voltage_low[] = LME_VOLTAGE_L; |
648 | static u8 voltage_high[] = LME_VOLTAGE_H; | 788 | static u8 voltage_high[] = LME_VOLTAGE_H; |
649 | static u8 reset[] = LME_RESET; | 789 | static u8 lnb_on[] = LNB_ON; |
650 | static u8 clear_reg_3[] = LME_CLEAR_PID; | 790 | static u8 lnb_off[] = LNB_OFF; |
651 | static u8 rbuf[1]; | 791 | static u8 rbuf[1]; |
652 | int ret = 0, len = 3, rlen = 1; | 792 | int ret = 0, len = 3, rlen = 1; |
653 | 793 | ||
654 | msleep(100); | 794 | if (st->stream_on == 1) |
655 | 795 | return 0; | |
656 | if (st->tuner_config == TUNER_LG) | ||
657 | ret |= lme2510_usb_talk(adap->dev, clear_reg_3, | ||
658 | sizeof(clear_reg_3), rbuf, rlen); | ||
659 | else | ||
660 | ret |= lme2510_usb_talk(adap->dev, | ||
661 | reset, sizeof(reset), rbuf, rlen); | ||
662 | |||
663 | /*always check & stop streaming*/ | ||
664 | lme2510_kill_urb(&adap->stream); | ||
665 | adap->feedcount = 0; | ||
666 | 796 | ||
667 | switch (voltage) { | 797 | ret |= lme2510_usb_talk(adap->dev, lnb_on, len, rbuf, rlen); |
668 | 798 | ||
669 | case SEC_VOLTAGE_18: | 799 | switch (voltage) { |
670 | ret |= lme2510_usb_talk(adap->dev, | 800 | case SEC_VOLTAGE_18: |
671 | voltage_high, len, rbuf, rlen); | 801 | ret |= lme2510_usb_talk(adap->dev, |
802 | voltage_high, len, rbuf, rlen); | ||
672 | break; | 803 | break; |
673 | 804 | ||
674 | case SEC_VOLTAGE_OFF: | 805 | case SEC_VOLTAGE_OFF: |
675 | case SEC_VOLTAGE_13: | 806 | ret |= lme2510_usb_talk(adap->dev, |
676 | default: | 807 | lnb_off, len, rbuf, rlen); |
677 | ret |= lme2510_usb_talk(adap->dev, | 808 | case SEC_VOLTAGE_13: |
809 | default: | ||
810 | ret |= lme2510_usb_talk(adap->dev, | ||
678 | voltage_low, len, rbuf, rlen); | 811 | voltage_low, len, rbuf, rlen); |
679 | break; | 812 | break; |
680 | 813 | ||
@@ -714,6 +847,10 @@ static int dm04_lme2510_frontend_attach(struct dvb_usb_adapter *adap) | |||
714 | &adap->dev->i2c_adap, 1)) { | 847 | &adap->dev->i2c_adap, 1)) { |
715 | info("TUN TDA8263 Found"); | 848 | info("TUN TDA8263 Found"); |
716 | st->tuner_config = TUNER_LG; | 849 | st->tuner_config = TUNER_LG; |
850 | if (dvb_usb_lme2510_firmware != 1) { | ||
851 | dvb_usb_lme2510_firmware = 1; | ||
852 | lme_firmware_switch(adap->dev->udev, 1); | ||
853 | } | ||
717 | return 0; | 854 | return 0; |
718 | } | 855 | } |
719 | kfree(adap->fe); | 856 | kfree(adap->fe); |
@@ -735,6 +872,10 @@ static int dm04_lme2510_frontend_attach(struct dvb_usb_adapter *adap) | |||
735 | &adap->dev->i2c_adap)) { | 872 | &adap->dev->i2c_adap)) { |
736 | st->tuner_config = TUNER_S7395; | 873 | st->tuner_config = TUNER_S7395; |
737 | info("TUN Sharp IX2505V silicon tuner"); | 874 | info("TUN Sharp IX2505V silicon tuner"); |
875 | if (dvb_usb_lme2510_firmware != 0) { | ||
876 | dvb_usb_lme2510_firmware = 0; | ||
877 | lme_firmware_switch(adap->dev->udev, 1); | ||
878 | } | ||
738 | return 0; | 879 | return 0; |
739 | } | 880 | } |
740 | kfree(adap->fe); | 881 | kfree(adap->fe); |
@@ -772,6 +913,8 @@ static int lme2510_probe(struct usb_interface *intf, | |||
772 | return -ENODEV; | 913 | return -ENODEV; |
773 | } | 914 | } |
774 | 915 | ||
916 | lme_firmware_switch(udev, 0); | ||
917 | |||
775 | if (0 == dvb_usb_device_init(intf, &lme2510_properties, | 918 | if (0 == dvb_usb_device_init(intf, &lme2510_properties, |
776 | THIS_MODULE, NULL, adapter_nr)) { | 919 | THIS_MODULE, NULL, adapter_nr)) { |
777 | info("DEV registering device driver"); | 920 | info("DEV registering device driver"); |
@@ -839,7 +982,7 @@ static struct dvb_usb_device_properties lme2510c_properties = { | |||
839 | .caps = DVB_USB_IS_AN_I2C_ADAPTER, | 982 | .caps = DVB_USB_IS_AN_I2C_ADAPTER, |
840 | .usb_ctrl = DEVICE_SPECIFIC, | 983 | .usb_ctrl = DEVICE_SPECIFIC, |
841 | .download_firmware = lme2510_download_firmware, | 984 | .download_firmware = lme2510_download_firmware, |
842 | .firmware = "dvb-usb-lme2510c-s7395.fw", | 985 | .firmware = lme_firmware, |
843 | .size_of_priv = sizeof(struct lme2510_state), | 986 | .size_of_priv = sizeof(struct lme2510_state), |
844 | .num_adapters = 1, | 987 | .num_adapters = 1, |
845 | .adapter = { | 988 | .adapter = { |
@@ -849,7 +992,7 @@ static struct dvb_usb_device_properties lme2510c_properties = { | |||
849 | /* parameter for the MPEG2-data transfer */ | 992 | /* parameter for the MPEG2-data transfer */ |
850 | .stream = { | 993 | .stream = { |
851 | .type = USB_BULK, | 994 | .type = USB_BULK, |
852 | .count = 8, | 995 | .count = 10, |
853 | .endpoint = 0x8, | 996 | .endpoint = 0x8, |
854 | .u = { | 997 | .u = { |
855 | .bulk = { | 998 | .bulk = { |
@@ -872,15 +1015,23 @@ static struct dvb_usb_device_properties lme2510c_properties = { | |||
872 | } | 1015 | } |
873 | }; | 1016 | }; |
874 | 1017 | ||
875 | void lme2510_exit_int(struct dvb_usb_device *d) | 1018 | void *lme2510_exit_int(struct dvb_usb_device *d) |
876 | { | 1019 | { |
877 | struct lme2510_state *st = d->priv; | 1020 | struct lme2510_state *st = d->priv; |
1021 | struct dvb_usb_adapter *adap = &d->adapter[0]; | ||
1022 | void *buffer = NULL; | ||
1023 | |||
1024 | if (adap != NULL) { | ||
1025 | lme2510_kill_urb(&adap->stream); | ||
1026 | adap->feedcount = 0; | ||
1027 | } | ||
1028 | |||
878 | if (st->lme_urb != NULL) { | 1029 | if (st->lme_urb != NULL) { |
879 | st->i2c_talk_onoff = 0; | 1030 | st->i2c_talk_onoff = 1; |
880 | st->signal_lock = 0; | 1031 | st->signal_lock = 0; |
881 | st->signal_level = 0; | 1032 | st->signal_level = 0; |
882 | st->signal_sn = 0; | 1033 | st->signal_sn = 0; |
883 | kfree(st->usb_buffer); | 1034 | buffer = st->usb_buffer; |
884 | usb_kill_urb(st->lme_urb); | 1035 | usb_kill_urb(st->lme_urb); |
885 | usb_free_coherent(d->udev, 5000, st->buffer, | 1036 | usb_free_coherent(d->udev, 5000, st->buffer, |
886 | st->lme_urb->transfer_dma); | 1037 | st->lme_urb->transfer_dma); |
@@ -888,18 +1039,19 @@ void lme2510_exit_int(struct dvb_usb_device *d) | |||
888 | ir_input_unregister(d->rc_input_dev); | 1039 | ir_input_unregister(d->rc_input_dev); |
889 | info("Remote Stopped"); | 1040 | info("Remote Stopped"); |
890 | } | 1041 | } |
891 | return; | 1042 | return buffer; |
892 | } | 1043 | } |
893 | 1044 | ||
894 | void lme2510_exit(struct usb_interface *intf) | 1045 | void lme2510_exit(struct usb_interface *intf) |
895 | { | 1046 | { |
896 | struct dvb_usb_device *d = usb_get_intfdata(intf); | 1047 | struct dvb_usb_device *d = usb_get_intfdata(intf); |
1048 | void *usb_buffer; | ||
1049 | |||
897 | if (d != NULL) { | 1050 | if (d != NULL) { |
898 | d->adapter[0].feedcount = 0; | 1051 | usb_buffer = lme2510_exit_int(d); |
899 | lme2510_exit_int(d); | ||
900 | dvb_usb_device_exit(intf); | 1052 | dvb_usb_device_exit(intf); |
1053 | kfree(usb_buffer); | ||
901 | } | 1054 | } |
902 | |||
903 | } | 1055 | } |
904 | 1056 | ||
905 | static struct usb_driver lme2510_driver = { | 1057 | static struct usb_driver lme2510_driver = { |
@@ -932,5 +1084,5 @@ module_exit(lme2510_module_exit); | |||
932 | 1084 | ||
933 | MODULE_AUTHOR("Malcolm Priestley <tvboxspy@gmail.com>"); | 1085 | MODULE_AUTHOR("Malcolm Priestley <tvboxspy@gmail.com>"); |
934 | MODULE_DESCRIPTION("LM2510(C) DVB-S USB2.0"); | 1086 | MODULE_DESCRIPTION("LM2510(C) DVB-S USB2.0"); |
935 | MODULE_VERSION("1.4"); | 1087 | MODULE_VERSION("1.60"); |
936 | MODULE_LICENSE("GPL"); | 1088 | MODULE_LICENSE("GPL"); |
diff --git a/drivers/media/dvb/dvb-usb/lmedm04.h b/drivers/media/dvb/dvb-usb/lmedm04.h index 5a66c7ec4511..e6af16c1e3e5 100644 --- a/drivers/media/dvb/dvb-usb/lmedm04.h +++ b/drivers/media/dvb/dvb-usb/lmedm04.h | |||
@@ -1,14 +1,16 @@ | |||
1 | /* DVB USB compliant linux driver for | 1 | /* DVB USB compliant linux driver for |
2 | * | 2 | * |
3 | * DM04/QQBOX DVB-S USB BOX LME2510C + SHARP:BS2F7HZ7395 | 3 | * DM04/QQBOX DVB-S USB BOX LME2510C + SHARP:BS2F7HZ7395 |
4 | * LME2510C + LGTDQT-P001F | 4 | * LME2510C + LG TDQY-P001F |
5 | * LME2510 + LG TDQY-P001F | ||
5 | * | 6 | * |
6 | * MVB7395 (LME2510C+SHARP:BS2F7HZ7395) | 7 | * MVB7395 (LME2510C+SHARP:BS2F7HZ7395) |
7 | * SHARP:BS2F7HZ7395 = (STV0288+Sharp IX2505V) | 8 | * SHARP:BS2F7HZ7395 = (STV0288+Sharp IX2505V) |
8 | * | 9 | * |
9 | * MVB0001F (LME2510C+LGTDQT-P001F) | 10 | * MVB001F (LME2510+LGTDQT-P001F) |
10 | * LG TDQY - P001F =(TDA8263 + TDA10086H) | 11 | * LG TDQY - P001F =(TDA8263 + TDA10086H) |
11 | * | 12 | * |
13 | * MVB0001F (LME2510C+LGTDQT-P001F) | ||
12 | * | 14 | * |
13 | * This program is free software; you can redistribute it and/or modify it | 15 | * This program is free software; you can redistribute it and/or modify it |
14 | * under the terms of the GNU General Public License as published by the Free | 16 | * under the terms of the GNU General Public License as published by the Free |
@@ -35,35 +37,33 @@ | |||
35 | * end byte -1 = 20 | 37 | * end byte -1 = 20 |
36 | * end byte = clear pid always a0, other wise 9c, 9a ?? | 38 | * end byte = clear pid always a0, other wise 9c, 9a ?? |
37 | * | 39 | * |
38 | * RESET (also clears PID filter) | ||
39 | * 3a 01 00 | ||
40 | */ | 40 | */ |
41 | #define LME_ST_ON_W {0x06, 0x00} | 41 | #define LME_ST_ON_W {0x06, 0x00} |
42 | #define LME_RESET {0x3a, 0x01, 0x00} | ||
43 | #define LME_CLEAR_PID {0x03, 0x02, 0x20, 0xa0} | 42 | #define LME_CLEAR_PID {0x03, 0x02, 0x20, 0xa0} |
44 | 43 | ||
45 | 44 | /* LNB Voltage | |
46 | /* LME Power Control | ||
47 | * 07 XX XX | 45 | * 07 XX XX |
48 | * offset 1 = 01 Power? my device cannot be powered down | 46 | * offset 1 = 01 |
49 | * offset 2 = 00=Voltage low 01=Voltage high | 47 | * offset 2 = 00=Voltage low 01=Voltage high |
48 | * | ||
49 | * LNB Power | ||
50 | * 03 01 XX | ||
51 | * offset 2 = 00=ON 01=OFF | ||
50 | */ | 52 | */ |
51 | 53 | ||
52 | #define LME_VOLTAGE_L {0x07, 0x01, 0x00} | 54 | #define LME_VOLTAGE_L {0x07, 0x01, 0x00} |
53 | #define LME_VOLTAGE_H {0x07, 0x01, 0x01} | 55 | #define LME_VOLTAGE_H {0x07, 0x01, 0x01} |
54 | 56 | #define LNB_ON {0x3a, 0x01, 0x00} | |
57 | #define LNB_OFF {0x3a, 0x01, 0x01} | ||
55 | 58 | ||
56 | /* Initial stv0288 settings for 7395 Frontend */ | 59 | /* Initial stv0288 settings for 7395 Frontend */ |
57 | static u8 s7395_inittab[] = { | 60 | static u8 s7395_inittab[] = { |
58 | 0x00, 0x11, | ||
59 | 0x01, 0x15, | 61 | 0x01, 0x15, |
60 | 0x02, 0x20, | 62 | 0x02, 0x20, |
61 | 0x03, 0x8e, | 63 | 0x03, 0xa0, |
62 | 0x04, 0x8e, | 64 | 0x04, 0xa0, |
63 | 0x05, 0x12, | 65 | 0x05, 0x12, |
64 | 0x06, 0xff, | 66 | 0x06, 0x00, |
65 | 0x07, 0x20, | ||
66 | 0x08, 0x00, | ||
67 | 0x09, 0x00, | 67 | 0x09, 0x00, |
68 | 0x0a, 0x04, | 68 | 0x0a, 0x04, |
69 | 0x0b, 0x00, | 69 | 0x0b, 0x00, |
@@ -71,7 +71,6 @@ static u8 s7395_inittab[] = { | |||
71 | 0x0d, 0x00, | 71 | 0x0d, 0x00, |
72 | 0x0e, 0xc1, | 72 | 0x0e, 0xc1, |
73 | 0x0f, 0x54, | 73 | 0x0f, 0x54, |
74 | 0x10, 0x40, | ||
75 | 0x11, 0x7a, | 74 | 0x11, 0x7a, |
76 | 0x12, 0x03, | 75 | 0x12, 0x03, |
77 | 0x13, 0x48, | 76 | 0x13, 0x48, |
@@ -84,23 +83,15 @@ static u8 s7395_inittab[] = { | |||
84 | 0x1a, 0x88, | 83 | 0x1a, 0x88, |
85 | 0x1b, 0x8f, | 84 | 0x1b, 0x8f, |
86 | 0x1c, 0xf0, | 85 | 0x1c, 0xf0, |
87 | 0x1e, 0x80, | ||
88 | 0x20, 0x0b, | 86 | 0x20, 0x0b, |
89 | 0x21, 0x54, | 87 | 0x21, 0x54, |
90 | 0x22, 0xff, | 88 | 0x22, 0xff, |
91 | 0x23, 0x01, | 89 | 0x23, 0x01, |
92 | 0x24, 0x9a, | ||
93 | 0x25, 0x7f, | ||
94 | 0x26, 0x00, | ||
95 | 0x27, 0x00, | ||
96 | 0x28, 0x46, | 90 | 0x28, 0x46, |
97 | 0x29, 0x66, | 91 | 0x29, 0x66, |
98 | 0x2a, 0x90, | 92 | 0x2a, 0x90, |
99 | 0x2b, 0xfa, | 93 | 0x2b, 0xfa, |
100 | 0x2c, 0xd9, | 94 | 0x2c, 0xd9, |
101 | 0x2d, 0x02, | ||
102 | 0x2e, 0xb1, | ||
103 | 0x2f, 0x00, | ||
104 | 0x30, 0x0, | 95 | 0x30, 0x0, |
105 | 0x31, 0x1e, | 96 | 0x31, 0x1e, |
106 | 0x32, 0x14, | 97 | 0x32, 0x14, |
@@ -115,8 +106,6 @@ static u8 s7395_inittab[] = { | |||
115 | 0x3b, 0x13, | 106 | 0x3b, 0x13, |
116 | 0x3c, 0x11, | 107 | 0x3c, 0x11, |
117 | 0x3d, 0x30, | 108 | 0x3d, 0x30, |
118 | 0x3e, 0x00, | ||
119 | 0x3f, 0x00, | ||
120 | 0x40, 0x63, | 109 | 0x40, 0x63, |
121 | 0x41, 0x04, | 110 | 0x41, 0x04, |
122 | 0x42, 0x60, | 111 | 0x42, 0x60, |
@@ -126,8 +115,6 @@ static u8 s7395_inittab[] = { | |||
126 | 0x46, 0x00, | 115 | 0x46, 0x00, |
127 | 0x47, 0x00, | 116 | 0x47, 0x00, |
128 | 0x4a, 0x00, | 117 | 0x4a, 0x00, |
129 | 0x4b, 0xd1, | ||
130 | 0x4c, 0x33, | ||
131 | 0x50, 0x12, | 118 | 0x50, 0x12, |
132 | 0x51, 0x36, | 119 | 0x51, 0x36, |
133 | 0x52, 0x21, | 120 | 0x52, 0x21, |
@@ -183,5 +170,4 @@ static u8 s7395_inittab[] = { | |||
183 | 0xf2, 0xc0, | 170 | 0xf2, 0xc0, |
184 | 0xff, 0xff, | 171 | 0xff, 0xff, |
185 | }; | 172 | }; |
186 | |||
187 | #endif | 173 | #endif |