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 | } |