diff options
| -rw-r--r-- | drivers/media/dvb/dvb-usb/az6007.c | 148 |
1 files changed, 83 insertions, 65 deletions
diff --git a/drivers/media/dvb/dvb-usb/az6007.c b/drivers/media/dvb/dvb-usb/az6007.c index 81fdc90be449..f0e4c013bb5d 100644 --- a/drivers/media/dvb/dvb-usb/az6007.c +++ b/drivers/media/dvb/dvb-usb/az6007.c | |||
| @@ -54,12 +54,16 @@ DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); | |||
| 54 | struct az6007_device_state { | 54 | struct az6007_device_state { |
| 55 | struct dvb_ca_en50221 ca; | 55 | struct dvb_ca_en50221 ca; |
| 56 | struct mutex ca_mutex; | 56 | struct mutex ca_mutex; |
| 57 | u8 power_state; | 57 | unsigned warm : 1; |
| 58 | 58 | ||
| 59 | /* Due to DRX-K - probably need changes */ | 59 | /* Due to DRX-K - probably need changes */ |
| 60 | int (*gate_ctrl) (struct dvb_frontend *, int); | 60 | int (*gate_ctrl) (struct dvb_frontend *, int); |
| 61 | struct semaphore pll_mutex; | 61 | struct semaphore pll_mutex; |
| 62 | bool tuner_attached; | 62 | bool tuner_attached; |
| 63 | |||
| 64 | unsigned char data[4096]; | ||
| 65 | |||
| 66 | struct usb_data_stream *stream; | ||
| 63 | }; | 67 | }; |
| 64 | 68 | ||
| 65 | static struct drxk_config terratec_h7_drxk = { | 69 | static struct drxk_config terratec_h7_drxk = { |
| @@ -71,7 +75,7 @@ static struct drxk_config terratec_h7_drxk = { | |||
| 71 | .no_i2c_bridge = false, | 75 | .no_i2c_bridge = false, |
| 72 | .chunk_size = 64, | 76 | .chunk_size = 64, |
| 73 | .mpeg_out_clk_strength = 0x02, | 77 | .mpeg_out_clk_strength = 0x02, |
| 74 | .microcode_name = "dvb-usb-terratec-h7-az6007.fw", | 78 | .microcode_name = "dvb-usb-terratec-h7-drxk.fw", |
| 75 | }; | 79 | }; |
| 76 | 80 | ||
| 77 | static int drxk_gate_ctrl(struct dvb_frontend *fe, int enable) | 81 | static int drxk_gate_ctrl(struct dvb_frontend *fe, int enable) |
| @@ -162,7 +166,9 @@ static int az6007_write(struct usb_device *udev, u8 req, u16 value, | |||
| 162 | 166 | ||
| 163 | static int az6007_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff) | 167 | static int az6007_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff) |
| 164 | { | 168 | { |
| 165 | return 0; | 169 | deb_info("%s: %s", __func__, onoff ? "enable" : "disable"); |
| 170 | |||
| 171 | return az6007_write(adap->dev->udev, 0xbc, onoff, 0, NULL, 0); | ||
| 166 | } | 172 | } |
| 167 | 173 | ||
| 168 | /* keys for the enclosed remote control */ | 174 | /* keys for the enclosed remote control */ |
| @@ -236,46 +242,6 @@ static int az6007_read_mac_addr(struct dvb_usb_device *d, u8 mac[6]) | |||
| 236 | return ret; | 242 | return ret; |
| 237 | } | 243 | } |
| 238 | 244 | ||
| 239 | static int az6007_frontend_poweron(struct dvb_usb_adapter *adap) | ||
| 240 | { | ||
| 241 | int ret; | ||
| 242 | struct usb_device *udev = adap->dev->udev; | ||
| 243 | |||
| 244 | deb_info("%s: adap=%p adap->dev=%p\n", __func__, adap, adap->dev); | ||
| 245 | |||
| 246 | ret = az6007_write(udev, AZ6007_POWER, 0, 2, NULL, 0); | ||
| 247 | if (ret < 0) | ||
| 248 | goto error; | ||
| 249 | msleep(150); | ||
| 250 | ret = az6007_write(udev, AZ6007_POWER, 1, 4, NULL, 0); | ||
| 251 | if (ret < 0) | ||
| 252 | goto error; | ||
| 253 | msleep(100); | ||
| 254 | ret = az6007_write(udev, AZ6007_POWER, 1, 3, NULL, 0); | ||
| 255 | if (ret < 0) | ||
| 256 | goto error; | ||
| 257 | msleep(100); | ||
| 258 | ret = az6007_write(udev, AZ6007_POWER, 1, 4, NULL, 0); | ||
| 259 | if (ret < 0) | ||
| 260 | goto error; | ||
| 261 | msleep(100); | ||
| 262 | ret = az6007_write(udev, FX2_SCON1, 0, 3, NULL, 0); | ||
| 263 | if (ret < 0) | ||
| 264 | goto error; | ||
| 265 | msleep (10); | ||
| 266 | ret = az6007_write(udev, FX2_SCON1, 1, 3, NULL, 0); | ||
| 267 | if (ret < 0) | ||
| 268 | goto error; | ||
| 269 | msleep (10); | ||
| 270 | ret = az6007_write(udev, AZ6007_POWER, 0, 0, NULL, 0); | ||
| 271 | |||
| 272 | error: | ||
| 273 | if (ret < 0) | ||
| 274 | err("%s failed with error %d", __func__, ret); | ||
| 275 | |||
| 276 | return ret; | ||
| 277 | } | ||
| 278 | |||
| 279 | static int az6007_led_on_off(struct usb_interface *intf, int onoff) | 245 | static int az6007_led_on_off(struct usb_interface *intf, int onoff) |
| 280 | { | 246 | { |
| 281 | struct usb_device *udev = interface_to_usbdev(intf); | 247 | struct usb_device *udev = interface_to_usbdev(intf); |
| @@ -293,9 +259,8 @@ static int az6007_frontend_attach(struct dvb_usb_adapter *adap) | |||
| 293 | 259 | ||
| 294 | BUG_ON(!st); | 260 | BUG_ON(!st); |
| 295 | 261 | ||
| 296 | az6007_frontend_poweron(adap); | 262 | deb_info("attaching demod drxk"); |
| 297 | 263 | ||
| 298 | info("attaching demod drxk"); | ||
| 299 | adap->fe_adap[0].fe = dvb_attach(drxk_attach, &terratec_h7_drxk, | 264 | adap->fe_adap[0].fe = dvb_attach(drxk_attach, &terratec_h7_drxk, |
| 300 | &adap->dev->i2c_adap); | 265 | &adap->dev->i2c_adap); |
| 301 | if (!adap->fe_adap[0].fe) | 266 | if (!adap->fe_adap[0].fe) |
| @@ -319,11 +284,11 @@ static int az6007_tuner_attach(struct dvb_usb_adapter *adap) | |||
| 319 | 284 | ||
| 320 | st->tuner_attached = true; | 285 | st->tuner_attached = true; |
| 321 | 286 | ||
| 322 | info("attaching tuner mt2063"); | 287 | deb_info("attaching tuner mt2063"); |
| 323 | /* Attach mt2063 to DVB-C frontend */ | 288 | /* Attach mt2063 to DVB-C frontend */ |
| 324 | if (adap->fe_adap[0].fe->ops.i2c_gate_ctrl) | 289 | if (adap->fe_adap[0].fe->ops.i2c_gate_ctrl) |
| 325 | adap->fe_adap[0].fe->ops.i2c_gate_ctrl(adap->fe_adap[0].fe, 1); | 290 | adap->fe_adap[0].fe->ops.i2c_gate_ctrl(adap->fe_adap[0].fe, 1); |
| 326 | if (!dvb_attach(mt2063_attach, adap->fe_adap[0].fe, | 291 | if (!dvb_attach(mt2063_attach, adap->fe_adap[0].fe, |
| 327 | &az6007_mt2063_config, | 292 | &az6007_mt2063_config, |
| 328 | &adap->dev->i2c_adap)) | 293 | &adap->dev->i2c_adap)) |
| 329 | return -EINVAL; | 294 | return -EINVAL; |
| @@ -336,22 +301,69 @@ static int az6007_tuner_attach(struct dvb_usb_adapter *adap) | |||
| 336 | 301 | ||
| 337 | int az6007_power_ctrl(struct dvb_usb_device *d, int onoff) | 302 | int az6007_power_ctrl(struct dvb_usb_device *d, int onoff) |
| 338 | { | 303 | { |
| 339 | if (!onoff) | 304 | struct az6007_device_state *st = d->priv; |
| 340 | return 0; | 305 | struct usb_device *udev = d->udev; |
| 306 | int ret; | ||
| 307 | |||
| 308 | deb_info("%s()\n", __func__); | ||
| 309 | |||
| 310 | if (!st->warm) { | ||
| 311 | u8 data[6]; | ||
| 312 | |||
| 313 | az6007_read(udev, FX2_OED, 1, 0, data, 1); /* {0x01} */ | ||
| 314 | az6007_read(udev, AZ6007_READ_DATA, 0, 8160, data, 1); /* {0x20} */ | ||
| 315 | az6007_read(udev, AZ6007_READ_DATA, 0, 0, data, 5); /* {0x00, 0x00, 0x00, 0x00, 0x0a} */ | ||
| 316 | az6007_read(udev, AZ6007_READ_DATA, 0, 4080, data, 6); /* {0x00, 0x08, 0x00, 0x0c, 0x22, 0x38} */ | ||
| 317 | |||
| 318 | ret = az6007_write(udev, AZ6007_POWER, 0, 2, NULL, 0); | ||
| 319 | if (ret < 0) | ||
| 320 | return ret; | ||
| 321 | msleep(60); | ||
| 322 | ret = az6007_write(udev, AZ6007_POWER, 1, 4, NULL, 0); | ||
| 323 | if (ret < 0) | ||
| 324 | return ret; | ||
| 325 | msleep(100); | ||
| 326 | ret = az6007_write(udev, AZ6007_POWER, 1, 3, NULL, 0); | ||
| 327 | if (ret < 0) | ||
| 328 | return ret; | ||
| 329 | msleep(20); | ||
| 330 | ret = az6007_write(udev, AZ6007_POWER, 1, 4, NULL, 0); | ||
| 331 | if (ret < 0) | ||
| 332 | return ret; | ||
| 333 | |||
| 334 | msleep(400); | ||
| 335 | ret = az6007_write(udev, FX2_SCON1, 0, 3, NULL, 0); | ||
| 336 | if (ret < 0) | ||
| 337 | return ret; | ||
| 338 | msleep (150); | ||
| 339 | ret = az6007_write(udev, FX2_SCON1, 1, 3, NULL, 0); | ||
| 340 | if (ret < 0) | ||
| 341 | return ret; | ||
| 342 | msleep (430); | ||
| 343 | ret = az6007_write(udev, AZ6007_POWER, 0, 0, NULL, 0); | ||
| 344 | if (ret < 0) | ||
| 345 | return ret; | ||
| 341 | 346 | ||
| 347 | st->warm = true; | ||
| 342 | 348 | ||
| 343 | info("Sending poweron sequence"); | 349 | return 0; |
| 350 | } | ||
| 344 | 351 | ||
| 345 | az6007_write(d->udev, AZ6007_TS_THROUGH, 0, 0, NULL, 0); | 352 | if (!onoff) |
| 353 | return 0; | ||
| 354 | |||
| 355 | az6007_write(udev, AZ6007_POWER, 0, 0, NULL, 0); | ||
| 356 | az6007_write(udev, AZ6007_TS_THROUGH, 0, 0, NULL, 0); | ||
| 346 | 357 | ||
| 347 | #if 0 | 358 | #if 0 |
| 348 | // Seems to be a poweroff sequence | 359 | // Seems to be a poweroff sequence |
| 349 | az6007_write(d->udev, 0xbc, 1, 3, NULL, 0); | 360 | az6007_write(udev, 0xbc, 1, 3, NULL, 0); |
| 350 | az6007_write(d->udev, 0xbc, 1, 4, NULL, 0); | 361 | az6007_write(udev, 0xbc, 1, 4, NULL, 0); |
| 351 | az6007_write(d->udev, 0xc0, 0, 3, NULL, 0); | 362 | az6007_write(udev, 0xc0, 0, 3, NULL, 0); |
| 352 | az6007_write(d->udev, 0xc0, 1, 3, NULL, 0); | 363 | az6007_write(udev, 0xc0, 1, 3, NULL, 0); |
| 353 | az6007_write(d->udev, 0xbc, 0, 1, NULL, 0); | 364 | az6007_write(udev, 0xbc, 0, 1, NULL, 0); |
| 354 | #endif | 365 | #endif |
| 366 | |||
| 355 | return 0; | 367 | return 0; |
| 356 | } | 368 | } |
| 357 | 369 | ||
| @@ -367,13 +379,13 @@ static int az6007_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], | |||
| 367 | int num) | 379 | int num) |
| 368 | { | 380 | { |
| 369 | struct dvb_usb_device *d = i2c_get_adapdata(adap); | 381 | struct dvb_usb_device *d = i2c_get_adapdata(adap); |
| 382 | struct az6007_device_state *st = d->priv; | ||
| 370 | int i, j, len; | 383 | int i, j, len; |
| 371 | int ret = 0; | 384 | int ret = 0; |
| 372 | u16 index; | 385 | u16 index; |
| 373 | u16 value; | 386 | u16 value; |
| 374 | int length; | 387 | int length; |
| 375 | u8 req, addr; | 388 | u8 req, addr; |
| 376 | u8 data[512]; | ||
| 377 | 389 | ||
| 378 | if (mutex_lock_interruptible(&d->i2c_mutex) < 0) | 390 | if (mutex_lock_interruptible(&d->i2c_mutex) < 0) |
| 379 | return -EAGAIN; | 391 | return -EAGAIN; |
| @@ -399,11 +411,11 @@ static int az6007_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], | |||
| 399 | value = addr | (1 << 8); | 411 | value = addr | (1 << 8); |
| 400 | length = 6 + msgs[i + 1].len; | 412 | length = 6 + msgs[i + 1].len; |
| 401 | len = msgs[i + 1].len; | 413 | len = msgs[i + 1].len; |
| 402 | ret = az6007_read(d->udev, req, value, index, data, | 414 | ret = az6007_read(d->udev, req, value, index, st->data, |
| 403 | length); | 415 | length); |
| 404 | if (ret >= len) { | 416 | if (ret >= len) { |
| 405 | for (j = 0; j < len; j++) { | 417 | for (j = 0; j < len; j++) { |
| 406 | msgs[i + 1].buf[j] = data[j + 5]; | 418 | msgs[i + 1].buf[j] = st->data[j + 5]; |
| 407 | if (dvb_usb_az6007_debug & 2) | 419 | if (dvb_usb_az6007_debug & 2) |
| 408 | printk(KERN_CONT | 420 | printk(KERN_CONT |
| 409 | "0x%02x ", | 421 | "0x%02x ", |
| @@ -426,11 +438,11 @@ static int az6007_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], | |||
| 426 | if (dvb_usb_az6007_debug & 2) | 438 | if (dvb_usb_az6007_debug & 2) |
| 427 | printk(KERN_CONT "(0x%02x) ", msgs[i].buf[0]); | 439 | printk(KERN_CONT "(0x%02x) ", msgs[i].buf[0]); |
| 428 | for (j = 0; j < len; j++) { | 440 | for (j = 0; j < len; j++) { |
| 429 | data[j] = msgs[i].buf[j + 1]; | 441 | st->data[j] = msgs[i].buf[j + 1]; |
| 430 | if (dvb_usb_az6007_debug & 2) | 442 | if (dvb_usb_az6007_debug & 2) |
| 431 | printk(KERN_CONT "0x%02x ", data[j]); | 443 | printk(KERN_CONT "0x%02x ", st->data[j]); |
| 432 | } | 444 | } |
| 433 | ret = az6007_write(d->udev, req, value, index, data, | 445 | ret = az6007_write(d->udev, req, value, index, st->data, |
| 434 | length); | 446 | length); |
| 435 | } else { | 447 | } else { |
| 436 | /* read bytes */ | 448 | /* read bytes */ |
| @@ -443,13 +455,13 @@ static int az6007_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], | |||
| 443 | value = addr; | 455 | value = addr; |
| 444 | length = msgs[i].len + 6; | 456 | length = msgs[i].len + 6; |
| 445 | len = msgs[i].len; | 457 | len = msgs[i].len; |
| 446 | ret = az6007_read(d->udev, req, value, index, data, | 458 | ret = az6007_read(d->udev, req, value, index, st->data, |
| 447 | length); | 459 | length); |
| 448 | for (j = 0; j < len; j++) { | 460 | for (j = 0; j < len; j++) { |
| 449 | msgs[i].buf[j] = data[j + 5]; | 461 | msgs[i].buf[j] = st->data[j + 5]; |
| 450 | if (dvb_usb_az6007_debug & 2) | 462 | if (dvb_usb_az6007_debug & 2) |
| 451 | printk(KERN_CONT | 463 | printk(KERN_CONT |
| 452 | "0x%02x ", data[j + 5]); | 464 | "0x%02x ", st->data[j + 5]); |
| 453 | } | 465 | } |
| 454 | } | 466 | } |
| 455 | if (dvb_usb_az6007_debug & 2) | 467 | if (dvb_usb_az6007_debug & 2) |
| @@ -491,6 +503,12 @@ int az6007_identify_state(struct usb_device *udev, | |||
| 491 | else | 503 | else |
| 492 | *cold = 1; | 504 | *cold = 1; |
| 493 | 505 | ||
| 506 | if (*cold) { | ||
| 507 | az6007_write(udev, 0x09, 1, 0, NULL, 0); | ||
| 508 | az6007_write(udev, 0x00, 0, 0, NULL, 0); | ||
| 509 | az6007_write(udev, 0x00, 0, 0, NULL, 0); | ||
| 510 | } | ||
| 511 | |||
| 494 | deb_info("Device is on %s state\n", *cold? "warm" : "cold"); | 512 | deb_info("Device is on %s state\n", *cold? "warm" : "cold"); |
| 495 | return 0; | 513 | return 0; |
| 496 | } | 514 | } |
