aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media
diff options
context:
space:
mode:
authorJose Alberto Reguero <jareguero@telefonica.net>2012-03-04 17:22:05 -0500
committerMauro Carvalho Chehab <mchehab@redhat.com>2012-03-19 13:15:16 -0400
commit962f8f67e48693d110c26d06089406dd9931474d (patch)
tree5628eb5a09797b861b300fbdfa17b7f9caaf7610 /drivers/media
parent266e8ae37daa04fb3d89759305659f4e0acbc126 (diff)
[media] Add CI support to az6007 driver
This patch add CI support to az6007 driver. Signed-off-by: Jose Alberto Reguero <jareguero@telefonica.net> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media')
-rw-r--r--drivers/media/dvb/dvb-usb/az6007.c377
1 files changed, 376 insertions, 1 deletions
diff --git a/drivers/media/dvb/dvb-usb/az6007.c b/drivers/media/dvb/dvb-usb/az6007.c
index df4cbc0ed932..4008b9c50fbd 100644
--- a/drivers/media/dvb/dvb-usb/az6007.c
+++ b/drivers/media/dvb/dvb-usb/az6007.c
@@ -54,6 +54,7 @@ DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
54 54
55struct az6007_device_state { 55struct az6007_device_state {
56 struct mutex mutex; 56 struct mutex mutex;
57 struct mutex ca_mutex;
57 struct dvb_ca_en50221 ca; 58 struct dvb_ca_en50221 ca;
58 unsigned warm:1; 59 unsigned warm:1;
59 int (*gate_ctrl) (struct dvb_frontend *, int); 60 int (*gate_ctrl) (struct dvb_frontend *, int);
@@ -218,6 +219,371 @@ static int az6007_rc_query(struct dvb_usb_device *d)
218 return 0; 219 return 0;
219} 220}
220 221
222static int az6007_ci_read_attribute_mem(struct dvb_ca_en50221 *ca,
223 int slot,
224 int address)
225{
226 struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data;
227 struct az6007_device_state *state = (struct az6007_device_state *)d->priv;
228
229 int ret;
230 u8 req;
231 u16 value;
232 u16 index;
233 int blen;
234 u8 *b;
235
236 if (slot != 0)
237 return -EINVAL;
238
239 b = kmalloc(12, GFP_KERNEL);
240 if (!b)
241 return -ENOMEM;
242
243 mutex_lock(&state->ca_mutex);
244
245 req = 0xC1;
246 value = address;
247 index = 0;
248 blen = 1;
249
250 ret = az6007_read(d, req, value, index, b, blen);
251 if (ret < 0) {
252 warn("usb in operation failed. (%d)", ret);
253 ret = -EINVAL;
254 } else {
255 ret = b[0];
256 }
257
258 mutex_unlock(&state->ca_mutex);
259 kfree(b);
260 return ret;
261}
262
263static int az6007_ci_write_attribute_mem(struct dvb_ca_en50221 *ca,
264 int slot,
265 int address,
266 u8 value)
267{
268 struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data;
269 struct az6007_device_state *state = (struct az6007_device_state *)d->priv;
270
271 int ret;
272 u8 req;
273 u16 value1;
274 u16 index;
275 int blen;
276
277 deb_info("%s %d", __func__, slot);
278 if (slot != 0)
279 return -EINVAL;
280
281 mutex_lock(&state->ca_mutex);
282 req = 0xC2;
283 value1 = address;
284 index = value;
285 blen = 0;
286
287 ret = az6007_write(d, req, value1, index, NULL, blen);
288 if (ret != 0)
289 warn("usb out operation failed. (%d)", ret);
290
291 mutex_unlock(&state->ca_mutex);
292 return ret;
293}
294
295static int az6007_ci_read_cam_control(struct dvb_ca_en50221 *ca,
296 int slot,
297 u8 address)
298{
299 struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data;
300 struct az6007_device_state *state = (struct az6007_device_state *)d->priv;
301
302 int ret;
303 u8 req;
304 u16 value;
305 u16 index;
306 int blen;
307 u8 *b;
308
309 if (slot != 0)
310 return -EINVAL;
311
312 b = kmalloc(12, GFP_KERNEL);
313 if (!b)
314 return -ENOMEM;
315
316 mutex_lock(&state->ca_mutex);
317
318 req = 0xC3;
319 value = address;
320 index = 0;
321 blen = 2;
322
323 ret = az6007_read(d, req, value, index, b, blen);
324 if (ret < 0) {
325 warn("usb in operation failed. (%d)", ret);
326 ret = -EINVAL;
327 } else {
328 if (b[0] == 0)
329 warn("Read CI IO error");
330
331 ret = b[1];
332 deb_info("read cam data = %x from 0x%x", b[1], value);
333 }
334
335 mutex_unlock(&state->ca_mutex);
336 kfree(b);
337 return ret;
338}
339
340static int az6007_ci_write_cam_control(struct dvb_ca_en50221 *ca,
341 int slot,
342 u8 address,
343 u8 value)
344{
345 struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data;
346 struct az6007_device_state *state = (struct az6007_device_state *)d->priv;
347
348 int ret;
349 u8 req;
350 u16 value1;
351 u16 index;
352 int blen;
353
354 if (slot != 0)
355 return -EINVAL;
356
357 mutex_lock(&state->ca_mutex);
358 req = 0xC4;
359 value1 = address;
360 index = value;
361 blen = 0;
362
363 ret = az6007_write(d, req, value1, index, NULL, blen);
364 if (ret != 0) {
365 warn("usb out operation failed. (%d)", ret);
366 goto failed;
367 }
368
369failed:
370 mutex_unlock(&state->ca_mutex);
371 return ret;
372}
373
374static int CI_CamReady(struct dvb_ca_en50221 *ca, int slot)
375{
376 struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data;
377
378 int ret;
379 u8 req;
380 u16 value;
381 u16 index;
382 int blen;
383 u8 *b;
384
385 b = kmalloc(12, GFP_KERNEL);
386 if (!b)
387 return -ENOMEM;
388
389 req = 0xC8;
390 value = 0;
391 index = 0;
392 blen = 1;
393
394 ret = az6007_read(d, req, value, index, b, blen);
395 if (ret < 0) {
396 warn("usb in operation failed. (%d)", ret);
397 ret = -EIO;
398 } else{
399 ret = b[0];
400 }
401 kfree(b);
402 return ret;
403}
404
405static int az6007_ci_slot_reset(struct dvb_ca_en50221 *ca, int slot)
406{
407 struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data;
408 struct az6007_device_state *state = (struct az6007_device_state *)d->priv;
409
410 int ret, i;
411 u8 req;
412 u16 value;
413 u16 index;
414 int blen;
415
416 mutex_lock(&state->ca_mutex);
417
418 req = 0xC6;
419 value = 1;
420 index = 0;
421 blen = 0;
422
423 ret = az6007_write(d, req, value, index, NULL, blen);
424 if (ret != 0) {
425 warn("usb out operation failed. (%d)", ret);
426 goto failed;
427 }
428
429 msleep(500);
430 req = 0xC6;
431 value = 0;
432 index = 0;
433 blen = 0;
434
435 ret = az6007_write(d, req, value, index, NULL, blen);
436 if (ret != 0) {
437 warn("usb out operation failed. (%d)", ret);
438 goto failed;
439 }
440
441 for (i = 0; i < 15; i++) {
442 msleep(100);
443
444 if (CI_CamReady(ca, slot)) {
445 deb_info("CAM Ready");
446 break;
447 }
448 }
449 msleep(5000);
450
451failed:
452 mutex_unlock(&state->ca_mutex);
453 return ret;
454}
455
456static int az6007_ci_slot_shutdown(struct dvb_ca_en50221 *ca, int slot)
457{
458 return 0;
459}
460
461static int az6007_ci_slot_ts_enable(struct dvb_ca_en50221 *ca, int slot)
462{
463 struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data;
464 struct az6007_device_state *state = (struct az6007_device_state *)d->priv;
465
466 int ret;
467 u8 req;
468 u16 value;
469 u16 index;
470 int blen;
471
472 deb_info("%s", __func__);
473 mutex_lock(&state->ca_mutex);
474 req = 0xC7;
475 value = 1;
476 index = 0;
477 blen = 0;
478
479 ret = az6007_write(d, req, value, index, NULL, blen);
480 if (ret != 0) {
481 warn("usb out operation failed. (%d)", ret);
482 goto failed;
483 }
484
485failed:
486 mutex_unlock(&state->ca_mutex);
487 return ret;
488}
489
490static int az6007_ci_poll_slot_status(struct dvb_ca_en50221 *ca, int slot, int open)
491{
492 struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data;
493 struct az6007_device_state *state = (struct az6007_device_state *)d->priv;
494 int ret;
495 u8 req;
496 u16 value;
497 u16 index;
498 int blen;
499 u8 *b;
500
501 b = kmalloc(12, GFP_KERNEL);
502 if (!b)
503 return -ENOMEM;
504 mutex_lock(&state->ca_mutex);
505
506 req = 0xC5;
507 value = 0;
508 index = 0;
509 blen = 1;
510
511 ret = az6007_read(d, req, value, index, b, blen);
512 if (ret < 0) {
513 warn("usb in operation failed. (%d)", ret);
514 ret = -EIO;
515 } else
516 ret = 0;
517
518 if (!ret && b[0] == 1) {
519 ret = DVB_CA_EN50221_POLL_CAM_PRESENT |
520 DVB_CA_EN50221_POLL_CAM_READY;
521 }
522
523 mutex_unlock(&state->ca_mutex);
524 kfree(b);
525 return ret;
526}
527
528
529static void az6007_ci_uninit(struct dvb_usb_device *d)
530{
531 struct az6007_device_state *state;
532
533 deb_info("%s", __func__);
534
535 if (NULL == d)
536 return;
537
538 state = (struct az6007_device_state *)d->priv;
539 if (NULL == state)
540 return;
541
542 if (NULL == state->ca.data)
543 return;
544
545 dvb_ca_en50221_release(&state->ca);
546
547 memset(&state->ca, 0, sizeof(state->ca));
548}
549
550
551static int az6007_ci_init(struct dvb_usb_adapter *a)
552{
553 struct dvb_usb_device *d = a->dev;
554 struct az6007_device_state *state = (struct az6007_device_state *)d->priv;
555 int ret;
556
557 deb_info("%s", __func__);
558
559 mutex_init(&state->ca_mutex);
560
561 state->ca.owner = THIS_MODULE;
562 state->ca.read_attribute_mem = az6007_ci_read_attribute_mem;
563 state->ca.write_attribute_mem = az6007_ci_write_attribute_mem;
564 state->ca.read_cam_control = az6007_ci_read_cam_control;
565 state->ca.write_cam_control = az6007_ci_write_cam_control;
566 state->ca.slot_reset = az6007_ci_slot_reset;
567 state->ca.slot_shutdown = az6007_ci_slot_shutdown;
568 state->ca.slot_ts_enable = az6007_ci_slot_ts_enable;
569 state->ca.poll_slot_status = az6007_ci_poll_slot_status;
570 state->ca.data = d;
571
572 ret = dvb_ca_en50221_init(&a->dvb_adap,
573 &state->ca,
574 0, /* flags */
575 1);/* n_slots */
576 if (ret != 0) {
577 err("Cannot initialize CI: Error %d.", ret);
578 memset(&state->ca, 0, sizeof(state->ca));
579 return ret;
580 }
581
582 deb_info("CI initialized.");
583
584 return 0;
585}
586
221static int az6007_read_mac_addr(struct dvb_usb_device *d, u8 mac[6]) 587static int az6007_read_mac_addr(struct dvb_usb_device *d, u8 mac[6])
222{ 588{
223 struct az6007_device_state *st = d->priv; 589 struct az6007_device_state *st = d->priv;
@@ -249,6 +615,8 @@ static int az6007_frontend_attach(struct dvb_usb_adapter *adap)
249 st->gate_ctrl = adap->fe_adap[0].fe->ops.i2c_gate_ctrl; 615 st->gate_ctrl = adap->fe_adap[0].fe->ops.i2c_gate_ctrl;
250 adap->fe_adap[0].fe->ops.i2c_gate_ctrl = drxk_gate_ctrl; 616 adap->fe_adap[0].fe->ops.i2c_gate_ctrl = drxk_gate_ctrl;
251 617
618 az6007_ci_init(adap);
619
252 return 0; 620 return 0;
253} 621}
254 622
@@ -471,6 +839,13 @@ int az6007_identify_state(struct usb_device *udev,
471 839
472static struct dvb_usb_device_properties az6007_properties; 840static struct dvb_usb_device_properties az6007_properties;
473 841
842static void az6007_usb_disconnect(struct usb_interface *intf)
843{
844 struct dvb_usb_device *d = usb_get_intfdata(intf);
845 az6007_ci_uninit(d);
846 dvb_usb_device_exit(intf);
847}
848
474static int az6007_usb_probe(struct usb_interface *intf, 849static int az6007_usb_probe(struct usb_interface *intf,
475 const struct usb_device_id *id) 850 const struct usb_device_id *id)
476{ 851{
@@ -546,7 +921,7 @@ static struct dvb_usb_device_properties az6007_properties = {
546static struct usb_driver az6007_usb_driver = { 921static struct usb_driver az6007_usb_driver = {
547 .name = "dvb_usb_az6007", 922 .name = "dvb_usb_az6007",
548 .probe = az6007_usb_probe, 923 .probe = az6007_usb_probe,
549 .disconnect = dvb_usb_device_exit, 924 .disconnect = az6007_usb_disconnect,
550 .id_table = az6007_usb_table, 925 .id_table = az6007_usb_table,
551}; 926};
552 927