diff options
author | Mauro Carvalho Chehab <mchehab@redhat.com> | 2011-07-22 09:31:25 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2012-01-21 10:44:39 -0500 |
commit | caa1a700ed2a06a831e6a7db5d9f213fc63caee3 (patch) | |
tree | 6f9d226518fddb9fb7d417e8083df345c0f15e01 /drivers/media/dvb/dvb-usb/az6007.c | |
parent | 6da347065062d28de035c01b298c6aebab2723fb (diff) |
[media] az6007: Fix it to allow loading it without crash
Add some fixes to allow frontend attachment. The patch is not
complete yet, as just the frontend 0 is initialized. So, more
changes will be needed, including some changes at dvb-usb core.
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/dvb/dvb-usb/az6007.c')
-rw-r--r-- | drivers/media/dvb/dvb-usb/az6007.c | 190 |
1 files changed, 98 insertions, 92 deletions
diff --git a/drivers/media/dvb/dvb-usb/az6007.c b/drivers/media/dvb/dvb-usb/az6007.c index 5873759f5db4..6a21f928550a 100644 --- a/drivers/media/dvb/dvb-usb/az6007.c +++ b/drivers/media/dvb/dvb-usb/az6007.c | |||
@@ -49,12 +49,20 @@ struct drxk_config terratec_h7_drxk = { | |||
49 | static int drxk_gate_ctrl(struct dvb_frontend *fe, int enable) | 49 | static int drxk_gate_ctrl(struct dvb_frontend *fe, int enable) |
50 | { | 50 | { |
51 | struct dvb_usb_adapter *adap = fe->sec_priv; | 51 | struct dvb_usb_adapter *adap = fe->sec_priv; |
52 | struct az6007_device_state *st = adap->priv; | 52 | struct az6007_device_state *st; |
53 | int status; | 53 | int status; |
54 | 54 | ||
55 | if (!adap || !st) | 55 | info("%s", __func__); |
56 | |||
57 | if (!adap) | ||
58 | return -EINVAL; | ||
59 | |||
60 | st = adap->priv; | ||
61 | |||
62 | if (!st) | ||
56 | return -EINVAL; | 63 | return -EINVAL; |
57 | 64 | ||
65 | |||
58 | if (enable) { | 66 | if (enable) { |
59 | down(&st->pll_mutex); | 67 | down(&st->pll_mutex); |
60 | status = st->gate_ctrl(fe, 1); | 68 | status = st->gate_ctrl(fe, 1); |
@@ -66,7 +74,7 @@ static int drxk_gate_ctrl(struct dvb_frontend *fe, int enable) | |||
66 | } | 74 | } |
67 | 75 | ||
68 | struct mt2063_config az6007_mt2063_config = { | 76 | struct mt2063_config az6007_mt2063_config = { |
69 | .tuner_address = 0xc0, | 77 | .tuner_address = 0x60, |
70 | .refclock = 36125000, | 78 | .refclock = 36125000, |
71 | }; | 79 | }; |
72 | 80 | ||
@@ -84,10 +92,8 @@ int az6007_usb_in_op(struct dvb_usb_device *d, u8 req, u16 value, u16 index, u8 | |||
84 | 92 | ||
85 | if (ret < 0) { | 93 | if (ret < 0) { |
86 | warn("usb in operation failed. (%d)", ret); | 94 | warn("usb in operation failed. (%d)", ret); |
87 | ret = -EIO; | 95 | return -EIO; |
88 | } else | 96 | } |
89 | ret = 0; | ||
90 | |||
91 | 97 | ||
92 | deb_xfer("in: req. %02x, val: %04x, ind: %04x, buffer: ",req,value,index); | 98 | deb_xfer("in: req. %02x, val: %04x, ind: %04x, buffer: ",req,value,index); |
93 | debug_dump(b,blen,deb_xfer); | 99 | debug_dump(b,blen,deb_xfer); |
@@ -219,7 +225,7 @@ static int az6007_frontend_poweron(struct dvb_usb_adapter *adap) | |||
219 | u16 index; | 225 | u16 index; |
220 | int blen; | 226 | int blen; |
221 | 227 | ||
222 | info("az6007_frontend_poweron adap=%p adap->dev=%p\n", adap, adap->dev); | 228 | info("az6007_frontend_poweron adap=%p adap->dev=%p", adap, adap->dev); |
223 | 229 | ||
224 | req = 0xBC; | 230 | req = 0xBC; |
225 | value = 1;//power on | 231 | value = 1;//power on |
@@ -257,7 +263,8 @@ static int az6007_frontend_poweron(struct dvb_usb_adapter *adap) | |||
257 | err("az6007_frontend_poweron failed!!!"); | 263 | err("az6007_frontend_poweron failed!!!"); |
258 | return -EIO; | 264 | return -EIO; |
259 | } | 265 | } |
260 | info("az6007_frontend_poweron\n"); | 266 | info("az6007_frontend_poweron: OK"); |
267 | |||
261 | return 0; | 268 | return 0; |
262 | } | 269 | } |
263 | 270 | ||
@@ -269,7 +276,7 @@ static int az6007_frontend_reset(struct dvb_usb_adapter *adap) | |||
269 | u16 index; | 276 | u16 index; |
270 | int blen; | 277 | int blen; |
271 | 278 | ||
272 | info("az6007_frontend_reset adap=%p adap->dev=%p\n", adap, adap->dev); | 279 | info("az6007_frontend_reset adap=%p adap->dev=%p", adap, adap->dev); |
273 | 280 | ||
274 | //reset demodulator | 281 | //reset demodulator |
275 | req = 0xC0; | 282 | req = 0xC0; |
@@ -306,7 +313,7 @@ static int az6007_frontend_reset(struct dvb_usb_adapter *adap) | |||
306 | 313 | ||
307 | msleep_interruptible(200); | 314 | msleep_interruptible(200); |
308 | 315 | ||
309 | info("reset az6007 frontend\n"); | 316 | info("reset az6007 frontend"); |
310 | 317 | ||
311 | return 0; | 318 | return 0; |
312 | } | 319 | } |
@@ -367,10 +374,12 @@ static int az6007_frontend_attach(struct dvb_usb_adapter *adap) | |||
367 | 374 | ||
368 | int result; | 375 | int result; |
369 | 376 | ||
377 | BUG_ON(!st); | ||
378 | |||
370 | az6007_frontend_poweron(adap); | 379 | az6007_frontend_poweron(adap); |
371 | az6007_frontend_reset(adap); | 380 | az6007_frontend_reset(adap); |
372 | 381 | ||
373 | info("az6007_frontend_attach\n"); | 382 | info("az6007_frontend_attach: drxk"); |
374 | 383 | ||
375 | adap->fe = dvb_attach(drxk_attach, &terratec_h7_drxk, | 384 | adap->fe = dvb_attach(drxk_attach, &terratec_h7_drxk, |
376 | &adap->dev->i2c_adap, &adap->fe2); | 385 | &adap->dev->i2c_adap, &adap->fe2); |
@@ -379,6 +388,8 @@ static int az6007_frontend_attach(struct dvb_usb_adapter *adap) | |||
379 | goto out_free; | 388 | goto out_free; |
380 | } | 389 | } |
381 | 390 | ||
391 | info("Setting hacks"); | ||
392 | |||
382 | /* FIXME: do we need a pll semaphore? */ | 393 | /* FIXME: do we need a pll semaphore? */ |
383 | adap->fe->sec_priv = adap; | 394 | adap->fe->sec_priv = adap; |
384 | sema_init(&st->pll_mutex, 1); | 395 | sema_init(&st->pll_mutex, 1); |
@@ -386,6 +397,7 @@ static int az6007_frontend_attach(struct dvb_usb_adapter *adap) | |||
386 | adap->fe->ops.i2c_gate_ctrl = drxk_gate_ctrl; | 397 | adap->fe->ops.i2c_gate_ctrl = drxk_gate_ctrl; |
387 | adap->fe2->id = 1; | 398 | adap->fe2->id = 1; |
388 | 399 | ||
400 | info("az6007_frontend_attach: mt2063"); | ||
389 | /* Attach mt2063 to DVB-C frontend */ | 401 | /* Attach mt2063 to DVB-C frontend */ |
390 | if (adap->fe->ops.i2c_gate_ctrl) | 402 | if (adap->fe->ops.i2c_gate_ctrl) |
391 | adap->fe->ops.i2c_gate_ctrl(adap->fe, 1); | 403 | adap->fe->ops.i2c_gate_ctrl(adap->fe, 1); |
@@ -423,100 +435,95 @@ az6007_usb_disconnect(struct usb_interface *intf) | |||
423 | } | 435 | } |
424 | 436 | ||
425 | /* I2C */ | 437 | /* I2C */ |
426 | static int az6007_i2c_xfer(struct i2c_adapter *adap,struct i2c_msg msg[],int num) | 438 | static int az6007_i2c_xfer(struct i2c_adapter *adap,struct i2c_msg msgs[],int num) |
427 | { | 439 | { |
428 | struct dvb_usb_device *d = i2c_get_adapdata(adap); | 440 | struct dvb_usb_device *d = i2c_get_adapdata(adap); |
429 | int j=0,len=0; | 441 | int i, j, len; |
430 | int ret=0; | 442 | int ret = 0; |
431 | u16 index; | 443 | u16 index; |
432 | u16 value; | 444 | u16 value; |
433 | int length; | 445 | int length; |
434 | u8 req; | 446 | u8 req, addr; |
435 | u8 data[512]; | 447 | u8 data[512]; |
436 | 448 | ||
437 | if (mutex_lock_interruptible(&d->i2c_mutex) < 0) | 449 | if (mutex_lock_interruptible(&d->i2c_mutex) < 0) |
438 | return -EAGAIN; | 450 | return -EAGAIN; |
439 | if (num > 2) | ||
440 | warn("more than 2 i2c messages at a time is not handled yet. TODO."); | ||
441 | 451 | ||
442 | 452 | for (i = 0; i < num; i++) { | |
443 | if (msg[0].addr == 0xc0) //MT2063 | 453 | addr = msgs[i].addr << 1; |
444 | { | 454 | |
445 | if (msg[0].flags != I2C_M_RD) //write | 455 | if (((i + 1) < num) |
446 | { | 456 | && (msgs[i].len == 1) |
447 | //printk("Tuner Tuner Write DevAddr=%02x RegAddr=%d\n", msg[0].addr, msg[0].buf[0]); | 457 | && (!msgs[i].flags & I2C_M_RD) |
448 | req = 0xBD; | 458 | && (msgs[i + 1].flags & I2C_M_RD) |
449 | index = msg[0].buf[0]; | 459 | && (msgs[i].addr == msgs[i + 1].addr)) { |
450 | value = msg[0].addr | (1<<8); | 460 | /* |
451 | length = msg[0].len - 1; | 461 | * A write + read xfer for the same address, where |
452 | len = msg[0].len - 1; | 462 | * the first xfer has just 1 byte length. |
453 | //printk("Tuner Tuner WriteDATA len=%d ", len); | 463 | * Need to join both into one operation |
454 | for(j=0;j<len;j++) | 464 | */ |
455 | { | 465 | printk("az6007 I2C xfer write+read addr=0x%x len=%d/%d: ", |
456 | data[j] = msg[0].buf[j+1]; | 466 | addr, msgs[i].len, msgs[i + 1].len); |
457 | //printk("data[%d]=%02x ", j, data[j]); | 467 | req = 0xb9; |
458 | } | 468 | index = 0; |
459 | //printk("\n"); | 469 | value = addr; |
460 | ret = az6007_usb_out_op(d,req,value,index,data,length); | 470 | for (j = 0; j < msgs[i].len; j++) |
461 | //ret = az6007_usb_out_op(d,req,value,index,&(msg[0].buf[1]),length); | 471 | data[j] = msgs[i].buf[j]; |
462 | } | 472 | length = 6 + msgs[i + 1].len; |
463 | else //read | 473 | len = msgs[i + 1].len; |
464 | { | ||
465 | //printk("Tuner Tuner Read DevAddr=%02x RegAddr=%02x\n", msg[0].addr, msg[0].buf[0]); | ||
466 | req = 0xB9; | ||
467 | index = msg[0].buf[0]; | ||
468 | value = msg[0].addr + (1 << 8); | ||
469 | length = msg[1].len + 6; | ||
470 | ret = az6007_usb_in_op(d,req,value,index,data,length); | 474 | ret = az6007_usb_in_op(d,req,value,index,data,length); |
471 | len = msg[1].len; | 475 | if (ret >= len) { |
472 | //printk("Tuner Tuner ReadDATA len=%d ", len); | 476 | for (j = 0; j < len; j++) { |
473 | for (j=0; j<len; j++) | 477 | msgs[i + 1].buf[j] = data[j + 5]; |
474 | { | 478 | printk("0x%02x ", msgs[i + 1].buf[j]); |
475 | msg[1].buf[j] = data[j+5]; | 479 | } |
476 | //printk("data[%d]=%02x ", j, data[j+5]); | 480 | } else |
477 | } | 481 | ret = -EIO; |
478 | //printk("\n"); | 482 | i++; |
479 | } | 483 | } else if (!(msgs[i].flags & I2C_M_RD)) { |
480 | } | 484 | /* write bytes */ |
481 | else | 485 | // printk("az6007 I2C xfer write addr=0x%x len=%d: ", |
482 | { //Demodulator | 486 | // addr, msgs[i].len); |
483 | if (msg[0].flags != I2C_M_RD) //write | 487 | req = 0xbd; |
484 | { | 488 | index = msgs[i].buf[0]; |
485 | //printk("Demodulator Write DevAddr=%02x RegAddr=%d\n", msg[0].addr, msg[0].buf[0]); | 489 | value = addr | (1 << 8); |
486 | req = 0xBD; | 490 | length = msgs[i].len - 1; |
487 | index = msg[0].buf[0]; | 491 | len = msgs[i].len - 1; |
488 | value = msg[0].addr | (1<<8); | 492 | // printk("(0x%02x) ", msgs[i].buf[0]); |
489 | length = msg[0].len - 1; | 493 | for (j = 0; j < len; j++) |
490 | len = msg[0].len - 1; | ||
491 | //printk("Demodulator WriteDATA len=%d ", len); | ||
492 | for(j=0;j<len;j++) | ||
493 | { | 494 | { |
494 | data[j] = msg[0].buf[j+1]; | 495 | data[j] = msgs[i].buf[j + 1]; |
495 | //printk("data[%d]=%02x ", j, data[j]); | 496 | // printk("0x%02x ", data[j]); |
496 | } | 497 | } |
497 | //printk("\n"); | ||
498 | ret = az6007_usb_out_op(d,req,value,index,data,length); | 498 | ret = az6007_usb_out_op(d,req,value,index,data,length); |
499 | } | 499 | } else { |
500 | else //read | 500 | /* read bytes */ |
501 | { | 501 | // printk("az6007 I2C xfer read addr=0x%x len=%d: ", |
502 | //printk("Demodulator Read DevAddr=%02x RegAddr=%02x\n", msg[0].addr, msg[0].buf[0]); | 502 | // addr, msgs[i].len); |
503 | req = 0xB9; | 503 | req = 0xb9; |
504 | index = 0; | 504 | index = msgs[i].buf[0]; |
505 | value = msg[0].addr + (0 << 8); | 505 | value = addr; |
506 | length = msg[0].len + 6; | 506 | length = msgs[i].len + 6; |
507 | len = msgs[i].len; | ||
507 | ret = az6007_usb_in_op(d,req,value,index,data,length); | 508 | ret = az6007_usb_in_op(d,req,value,index,data,length); |
508 | len = msg[0].len; | 509 | for (j = 0; j < len; j++) |
509 | //printk("Demodulator ReadDATA len=%d ", len); | ||
510 | for (j=0; j<len; j++) | ||
511 | { | 510 | { |
512 | msg[0].buf[j] = data[j+5]; | 511 | msgs[i].buf[j] = data[j + 5]; |
513 | //printk("data[%d]=%02x ", j, data[j+5]); | 512 | // printk("0x%02x ", data[j + 5]); |
514 | } | 513 | } |
515 | //printk("\n"); | ||
516 | } | 514 | } |
515 | // printk("\n"); | ||
516 | if (ret < 0) | ||
517 | goto err; | ||
517 | } | 518 | } |
519 | err: | ||
518 | mutex_unlock(&d->i2c_mutex); | 520 | mutex_unlock(&d->i2c_mutex); |
519 | return ret; | 521 | |
522 | if (ret < 0) { | ||
523 | info("%s ERROR: %i\n", __func__, ret); | ||
524 | return ret; | ||
525 | } | ||
526 | return num; | ||
520 | } | 527 | } |
521 | 528 | ||
522 | 529 | ||
@@ -540,11 +547,11 @@ int az6007_identify_state(struct usb_device *udev, struct dvb_usb_device_propert | |||
540 | s16 ret = usb_control_msg(udev, usb_rcvctrlpipe(udev,0), | 547 | s16 ret = usb_control_msg(udev, usb_rcvctrlpipe(udev,0), |
541 | 0xb7, USB_TYPE_VENDOR | USB_DIR_IN, 6, 0, b, 6, USB_CTRL_GET_TIMEOUT); | 548 | 0xb7, USB_TYPE_VENDOR | USB_DIR_IN, 6, 0, b, 6, USB_CTRL_GET_TIMEOUT); |
542 | 549 | ||
543 | info("FW GET_VERSION length: %d\n",ret); | 550 | info("FW GET_VERSION length: %d",ret); |
544 | 551 | ||
545 | *cold = ret <= 0; | 552 | *cold = ret <= 0; |
546 | 553 | ||
547 | info("cold: %d\n", *cold); | 554 | info("cold: %d", *cold); |
548 | return 0; | 555 | return 0; |
549 | } | 556 | } |
550 | 557 | ||
@@ -572,7 +579,6 @@ static struct dvb_usb_device_properties az6007_properties = { | |||
572 | .firmware = "dvb-usb-az6007-03.fw", | 579 | .firmware = "dvb-usb-az6007-03.fw", |
573 | .no_reconnect = 1, | 580 | .no_reconnect = 1, |
574 | 581 | ||
575 | .size_of_priv = sizeof(struct az6007_device_state), | ||
576 | .identify_state = az6007_identify_state, | 582 | .identify_state = az6007_identify_state, |
577 | .num_adapters = 1, | 583 | .num_adapters = 1, |
578 | .adapter = { | 584 | .adapter = { |
@@ -593,7 +599,7 @@ static struct dvb_usb_device_properties az6007_properties = { | |||
593 | } | 599 | } |
594 | } | 600 | } |
595 | }, | 601 | }, |
596 | .size_of_priv = 0,//sizeof(struct az6007_state), | 602 | .size_of_priv = sizeof(struct az6007_device_state), |
597 | } | 603 | } |
598 | }, | 604 | }, |
599 | //.power_ctrl = az6007_power_ctrl, | 605 | //.power_ctrl = az6007_power_ctrl, |
@@ -634,7 +640,7 @@ static struct usb_driver az6007_usb_driver = { | |||
634 | static int __init az6007_usb_module_init(void) | 640 | static int __init az6007_usb_module_init(void) |
635 | { | 641 | { |
636 | int result; | 642 | int result; |
637 | info("henry :: az6007 usb module init"); | 643 | info("az6007 usb module init"); |
638 | if ((result = usb_register(&az6007_usb_driver))) { | 644 | if ((result = usb_register(&az6007_usb_driver))) { |
639 | err("usb_register failed. (%d)",result); | 645 | err("usb_register failed. (%d)",result); |
640 | return result; | 646 | return result; |
@@ -646,7 +652,7 @@ static int __init az6007_usb_module_init(void) | |||
646 | static void __exit az6007_usb_module_exit(void) | 652 | static void __exit az6007_usb_module_exit(void) |
647 | { | 653 | { |
648 | /* deregister this driver from the USB subsystem */ | 654 | /* deregister this driver from the USB subsystem */ |
649 | info("henry :: az6007 usb module exit"); | 655 | info("az6007 usb module exit"); |
650 | usb_deregister(&az6007_usb_driver); | 656 | usb_deregister(&az6007_usb_driver); |
651 | } | 657 | } |
652 | 658 | ||