aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/dvb/firewire/firedtv-avc.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/dvb/firewire/firedtv-avc.c')
-rw-r--r--drivers/media/dvb/firewire/firedtv-avc.c514
1 files changed, 277 insertions, 237 deletions
diff --git a/drivers/media/dvb/firewire/firedtv-avc.c b/drivers/media/dvb/firewire/firedtv-avc.c
index 50c42a4b972b..1b31bebc27d6 100644
--- a/drivers/media/dvb/firewire/firedtv-avc.c
+++ b/drivers/media/dvb/firewire/firedtv-avc.c
@@ -74,7 +74,6 @@
74#define EN50221_TAG_CA_INFO 0x9f8031 74#define EN50221_TAG_CA_INFO 0x9f8031
75 75
76struct avc_command_frame { 76struct avc_command_frame {
77 int length;
78 u8 ctype; 77 u8 ctype;
79 u8 subunit; 78 u8 subunit;
80 u8 opcode; 79 u8 opcode;
@@ -82,13 +81,27 @@ struct avc_command_frame {
82}; 81};
83 82
84struct avc_response_frame { 83struct avc_response_frame {
85 int length;
86 u8 response; 84 u8 response;
87 u8 subunit; 85 u8 subunit;
88 u8 opcode; 86 u8 opcode;
89 u8 operand[509]; 87 u8 operand[509];
90}; 88};
91 89
90#define LAST_OPERAND (509 - 1)
91
92static inline void clear_operands(struct avc_command_frame *c, int from, int to)
93{
94 memset(&c->operand[from], 0, to - from + 1);
95}
96
97static void pad_operands(struct avc_command_frame *c, int from)
98{
99 int to = ALIGN(from, 4);
100
101 if (from <= to && to <= LAST_OPERAND)
102 clear_operands(c, from, to);
103}
104
92#define AVC_DEBUG_READ_DESCRIPTOR 0x0001 105#define AVC_DEBUG_READ_DESCRIPTOR 0x0001
93#define AVC_DEBUG_DSIT 0x0002 106#define AVC_DEBUG_DSIT 0x0002
94#define AVC_DEBUG_DSD 0x0004 107#define AVC_DEBUG_DSD 0x0004
@@ -202,78 +215,65 @@ static void debug_pmt(char *msg, int length)
202 16, 1, msg, length, false); 215 16, 1, msg, length, false);
203} 216}
204 217
205static int __avc_write(struct firedtv *fdtv, 218static int avc_write(struct firedtv *fdtv)
206 const struct avc_command_frame *c, struct avc_response_frame *r)
207{ 219{
208 int err, retry; 220 int err, retry;
209 221
210 if (r) 222 fdtv->avc_reply_received = false;
211 fdtv->avc_reply_received = false;
212 223
213 for (retry = 0; retry < 6; retry++) { 224 for (retry = 0; retry < 6; retry++) {
214 if (unlikely(avc_debug)) 225 if (unlikely(avc_debug))
215 debug_fcp(&c->ctype, c->length); 226 debug_fcp(fdtv->avc_data, fdtv->avc_data_length);
216 227
217 err = fdtv->backend->write(fdtv, FCP_COMMAND_REGISTER, 228 err = fdtv->backend->write(fdtv, FCP_COMMAND_REGISTER,
218 (void *)&c->ctype, c->length); 229 fdtv->avc_data, fdtv->avc_data_length);
219 if (err) { 230 if (err) {
220 fdtv->avc_reply_received = true;
221 dev_err(fdtv->device, "FCP command write failed\n"); 231 dev_err(fdtv->device, "FCP command write failed\n");
232
222 return err; 233 return err;
223 } 234 }
224 235
225 if (!r)
226 return 0;
227
228 /* 236 /*
229 * AV/C specs say that answers should be sent within 150 ms. 237 * AV/C specs say that answers should be sent within 150 ms.
230 * Time out after 200 ms. 238 * Time out after 200 ms.
231 */ 239 */
232 if (wait_event_timeout(fdtv->avc_wait, 240 if (wait_event_timeout(fdtv->avc_wait,
233 fdtv->avc_reply_received, 241 fdtv->avc_reply_received,
234 msecs_to_jiffies(200)) != 0) { 242 msecs_to_jiffies(200)) != 0)
235 r->length = fdtv->response_length;
236 memcpy(&r->response, fdtv->response, r->length);
237
238 return 0; 243 return 0;
239 }
240 } 244 }
241 dev_err(fdtv->device, "FCP response timed out\n"); 245 dev_err(fdtv->device, "FCP response timed out\n");
246
242 return -ETIMEDOUT; 247 return -ETIMEDOUT;
243} 248}
244 249
245static int avc_write(struct firedtv *fdtv, 250static bool is_register_rc(struct avc_response_frame *r)
246 const struct avc_command_frame *c, struct avc_response_frame *r)
247{ 251{
248 int ret; 252 return r->opcode == AVC_OPCODE_VENDOR &&
249 253 r->operand[0] == SFE_VENDOR_DE_COMPANYID_0 &&
250 if (mutex_lock_interruptible(&fdtv->avc_mutex)) 254 r->operand[1] == SFE_VENDOR_DE_COMPANYID_1 &&
251 return -EINTR; 255 r->operand[2] == SFE_VENDOR_DE_COMPANYID_2 &&
252 256 r->operand[3] == SFE_VENDOR_OPCODE_REGISTER_REMOTE_CONTROL;
253 ret = __avc_write(fdtv, c, r);
254
255 mutex_unlock(&fdtv->avc_mutex);
256 return ret;
257} 257}
258 258
259int avc_recv(struct firedtv *fdtv, void *data, size_t length) 259int avc_recv(struct firedtv *fdtv, void *data, size_t length)
260{ 260{
261 struct avc_response_frame *r = 261 struct avc_response_frame *r = data;
262 data - offsetof(struct avc_response_frame, response);
263 262
264 if (unlikely(avc_debug)) 263 if (unlikely(avc_debug))
265 debug_fcp(data, length); 264 debug_fcp(data, length);
266 265
267 if (length >= 8 && 266 if (length >= 8 && is_register_rc(r)) {
268 r->operand[0] == SFE_VENDOR_DE_COMPANYID_0 && 267 switch (r->response) {
269 r->operand[1] == SFE_VENDOR_DE_COMPANYID_1 && 268 case AVC_RESPONSE_CHANGED:
270 r->operand[2] == SFE_VENDOR_DE_COMPANYID_2 && 269 fdtv_handle_rc(fdtv, r->operand[4] << 8 | r->operand[5]);
271 r->operand[3] == SFE_VENDOR_OPCODE_REGISTER_REMOTE_CONTROL) {
272 if (r->response == AVC_RESPONSE_CHANGED) {
273 fdtv_handle_rc(fdtv,
274 r->operand[4] << 8 | r->operand[5]);
275 schedule_work(&fdtv->remote_ctrl_work); 270 schedule_work(&fdtv->remote_ctrl_work);
276 } else if (r->response != AVC_RESPONSE_INTERIM) { 271 break;
272 case AVC_RESPONSE_INTERIM:
273 if (is_register_rc((void *)fdtv->avc_data))
274 goto wake;
275 break;
276 default:
277 dev_info(fdtv->device, 277 dev_info(fdtv->device,
278 "remote control result = %d\n", r->response); 278 "remote control result = %d\n", r->response);
279 } 279 }
@@ -285,9 +285,9 @@ int avc_recv(struct firedtv *fdtv, void *data, size_t length)
285 return -EIO; 285 return -EIO;
286 } 286 }
287 287
288 memcpy(fdtv->response, data, length); 288 memcpy(fdtv->avc_data, data, length);
289 fdtv->response_length = length; 289 fdtv->avc_data_length = length;
290 290wake:
291 fdtv->avc_reply_received = true; 291 fdtv->avc_reply_received = true;
292 wake_up(&fdtv->avc_wait); 292 wake_up(&fdtv->avc_wait);
293 293
@@ -318,10 +318,11 @@ static int add_pid_filter(struct firedtv *fdtv, u8 *operand)
318 * tuning command for setting the relative LNB frequency 318 * tuning command for setting the relative LNB frequency
319 * (not supported by the AVC standard) 319 * (not supported by the AVC standard)
320 */ 320 */
321static void avc_tuner_tuneqpsk(struct firedtv *fdtv, 321static int avc_tuner_tuneqpsk(struct firedtv *fdtv,
322 struct dvb_frontend_parameters *params, 322 struct dvb_frontend_parameters *params)
323 struct avc_command_frame *c)
324{ 323{
324 struct avc_command_frame *c = (void *)fdtv->avc_data;
325
325 c->opcode = AVC_OPCODE_VENDOR; 326 c->opcode = AVC_OPCODE_VENDOR;
326 327
327 c->operand[0] = SFE_VENDOR_DE_COMPANYID_0; 328 c->operand[0] = SFE_VENDOR_DE_COMPANYID_0;
@@ -370,16 +371,18 @@ static void avc_tuner_tuneqpsk(struct firedtv *fdtv,
370 c->operand[13] = 0x1; 371 c->operand[13] = 0x1;
371 c->operand[14] = 0xff; 372 c->operand[14] = 0xff;
372 c->operand[15] = 0xff; 373 c->operand[15] = 0xff;
373 c->length = 20; 374
375 return 16;
374 } else { 376 } else {
375 c->length = 16; 377 return 13;
376 } 378 }
377} 379}
378 380
379static void avc_tuner_dsd_dvb_c(struct firedtv *fdtv, 381static int avc_tuner_dsd_dvb_c(struct firedtv *fdtv,
380 struct dvb_frontend_parameters *params, 382 struct dvb_frontend_parameters *params)
381 struct avc_command_frame *c)
382{ 383{
384 struct avc_command_frame *c = (void *)fdtv->avc_data;
385
383 c->opcode = AVC_OPCODE_DSD; 386 c->opcode = AVC_OPCODE_DSD;
384 387
385 c->operand[0] = 0; /* source plug */ 388 c->operand[0] = 0; /* source plug */
@@ -440,15 +443,14 @@ static void avc_tuner_dsd_dvb_c(struct firedtv *fdtv,
440 c->operand[20] = 0x00; 443 c->operand[20] = 0x00;
441 c->operand[21] = 0x00; 444 c->operand[21] = 0x00;
442 445
443 /* Add PIDs to filter */ 446 return 22 + add_pid_filter(fdtv, &c->operand[22]);
444 c->length = ALIGN(22 + add_pid_filter(fdtv, &c->operand[22]) + 3, 4);
445} 447}
446 448
447static void avc_tuner_dsd_dvb_t(struct firedtv *fdtv, 449static int avc_tuner_dsd_dvb_t(struct firedtv *fdtv,
448 struct dvb_frontend_parameters *params, 450 struct dvb_frontend_parameters *params)
449 struct avc_command_frame *c)
450{ 451{
451 struct dvb_ofdm_parameters *ofdm = &params->u.ofdm; 452 struct dvb_ofdm_parameters *ofdm = &params->u.ofdm;
453 struct avc_command_frame *c = (void *)fdtv->avc_data;
452 454
453 c->opcode = AVC_OPCODE_DSD; 455 c->opcode = AVC_OPCODE_DSD;
454 456
@@ -543,55 +545,58 @@ static void avc_tuner_dsd_dvb_t(struct firedtv *fdtv,
543 c->operand[15] = 0x00; /* network_ID[0] */ 545 c->operand[15] = 0x00; /* network_ID[0] */
544 c->operand[16] = 0x00; /* network_ID[1] */ 546 c->operand[16] = 0x00; /* network_ID[1] */
545 547
546 /* Add PIDs to filter */ 548 return 17 + add_pid_filter(fdtv, &c->operand[17]);
547 c->length = ALIGN(17 + add_pid_filter(fdtv, &c->operand[17]) + 3, 4);
548} 549}
549 550
550int avc_tuner_dsd(struct firedtv *fdtv, 551int avc_tuner_dsd(struct firedtv *fdtv,
551 struct dvb_frontend_parameters *params) 552 struct dvb_frontend_parameters *params)
552{ 553{
553 char buffer[sizeof(struct avc_command_frame)]; 554 struct avc_command_frame *c = (void *)fdtv->avc_data;
554 struct avc_command_frame *c = (void *)buffer; 555 int pos, ret;
555 struct avc_response_frame *r = (void *)buffer; /* FIXME: unused */
556 556
557 memset(c, 0, sizeof(*c)); 557 mutex_lock(&fdtv->avc_mutex);
558 558
559 c->ctype = AVC_CTYPE_CONTROL; 559 c->ctype = AVC_CTYPE_CONTROL;
560 c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit; 560 c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit;
561 561
562 switch (fdtv->type) { 562 switch (fdtv->type) {
563 case FIREDTV_DVB_S: 563 case FIREDTV_DVB_S:
564 case FIREDTV_DVB_S2: avc_tuner_tuneqpsk(fdtv, params, c); break; 564 case FIREDTV_DVB_S2: pos = avc_tuner_tuneqpsk(fdtv, params); break;
565 case FIREDTV_DVB_C: avc_tuner_dsd_dvb_c(fdtv, params, c); break; 565 case FIREDTV_DVB_C: pos = avc_tuner_dsd_dvb_c(fdtv, params); break;
566 case FIREDTV_DVB_T: avc_tuner_dsd_dvb_t(fdtv, params, c); break; 566 case FIREDTV_DVB_T: pos = avc_tuner_dsd_dvb_t(fdtv, params); break;
567 default: 567 default:
568 BUG(); 568 BUG();
569 } 569 }
570 pad_operands(c, pos);
570 571
571 if (avc_write(fdtv, c, r) < 0) 572 fdtv->avc_data_length = ALIGN(3 + pos, 4);
572 return -EIO; 573 ret = avc_write(fdtv);
573
574 msleep(500);
575#if 0 574#if 0
576 /* FIXME: */ 575 /*
577 /* u8 *status was an out-parameter of avc_tuner_dsd, unused by caller */ 576 * FIXME:
577 * u8 *status was an out-parameter of avc_tuner_dsd, unused by caller.
578 * Check for AVC_RESPONSE_ACCEPTED here instead?
579 */
578 if (status) 580 if (status)
579 *status = r->operand[2]; 581 *status = r->operand[2];
580#endif 582#endif
581 return 0; 583 mutex_unlock(&fdtv->avc_mutex);
584
585 if (ret == 0)
586 msleep(500);
587
588 return ret;
582} 589}
583 590
584int avc_tuner_set_pids(struct firedtv *fdtv, unsigned char pidc, u16 pid[]) 591int avc_tuner_set_pids(struct firedtv *fdtv, unsigned char pidc, u16 pid[])
585{ 592{
586 char buffer[sizeof(struct avc_command_frame)]; 593 struct avc_command_frame *c = (void *)fdtv->avc_data;
587 struct avc_command_frame *c = (void *)buffer; 594 int ret, pos, k;
588 struct avc_response_frame *r = (void *)buffer; /* FIXME: unused */
589 int pos, k;
590 595
591 if (pidc > 16 && pidc != 0xff) 596 if (pidc > 16 && pidc != 0xff)
592 return -EINVAL; 597 return -EINVAL;
593 598
594 memset(c, 0, sizeof(*c)); 599 mutex_lock(&fdtv->avc_mutex);
595 600
596 c->ctype = AVC_CTYPE_CONTROL; 601 c->ctype = AVC_CTYPE_CONTROL;
597 c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit; 602 c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit;
@@ -614,24 +619,27 @@ int avc_tuner_set_pids(struct firedtv *fdtv, unsigned char pidc, u16 pid[])
614 c->operand[pos++] = 0x00; /* tableID */ 619 c->operand[pos++] = 0x00; /* tableID */
615 c->operand[pos++] = 0x00; /* filter_length */ 620 c->operand[pos++] = 0x00; /* filter_length */
616 } 621 }
622 pad_operands(c, pos);
617 623
618 c->length = ALIGN(3 + pos, 4); 624 fdtv->avc_data_length = ALIGN(3 + pos, 4);
625 ret = avc_write(fdtv);
619 626
620 if (avc_write(fdtv, c, r) < 0) 627 /* FIXME: check response code? */
621 return -EIO;
622 628
623 msleep(50); 629 mutex_unlock(&fdtv->avc_mutex);
624 return 0; 630
631 if (ret == 0)
632 msleep(50);
633
634 return ret;
625} 635}
626 636
627int avc_tuner_get_ts(struct firedtv *fdtv) 637int avc_tuner_get_ts(struct firedtv *fdtv)
628{ 638{
629 char buffer[sizeof(struct avc_command_frame)]; 639 struct avc_command_frame *c = (void *)fdtv->avc_data;
630 struct avc_command_frame *c = (void *)buffer; 640 int ret, sl;
631 struct avc_response_frame *r = (void *)buffer; /* FIXME: unused */
632 int sl;
633 641
634 memset(c, 0, sizeof(*c)); 642 mutex_lock(&fdtv->avc_mutex);
635 643
636 c->ctype = AVC_CTYPE_CONTROL; 644 c->ctype = AVC_CTYPE_CONTROL;
637 c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit; 645 c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit;
@@ -646,26 +654,33 @@ int avc_tuner_get_ts(struct firedtv *fdtv)
646 c->operand[4] = 0x00; /* antenna number */ 654 c->operand[4] = 0x00; /* antenna number */
647 c->operand[5] = 0x0; /* system_specific_search_flags */ 655 c->operand[5] = 0x0; /* system_specific_search_flags */
648 c->operand[6] = sl; /* system_specific_multiplex selection_length */ 656 c->operand[6] = sl; /* system_specific_multiplex selection_length */
649 c->operand[7] = 0x00; /* valid_flags [0] */ 657 /*
650 c->operand[8] = 0x00; /* valid_flags [1] */ 658 * operand[7]: valid_flags[0]
651 c->operand[7 + sl] = 0x00; /* nr_of_dsit_sel_specs (always 0) */ 659 * operand[8]: valid_flags[1]
660 * operand[7 + sl]: nr_of_dsit_sel_specs (always 0)
661 */
662 clear_operands(c, 7, 24);
652 663
653 c->length = fdtv->type == FIREDTV_DVB_T ? 24 : 28; 664 fdtv->avc_data_length = fdtv->type == FIREDTV_DVB_T ? 24 : 28;
665 ret = avc_write(fdtv);
654 666
655 if (avc_write(fdtv, c, r) < 0) 667 /* FIXME: check response code? */
656 return -EIO;
657 668
658 msleep(250); 669 mutex_unlock(&fdtv->avc_mutex);
659 return 0; 670
671 if (ret == 0)
672 msleep(250);
673
674 return ret;
660} 675}
661 676
662int avc_identify_subunit(struct firedtv *fdtv) 677int avc_identify_subunit(struct firedtv *fdtv)
663{ 678{
664 char buffer[sizeof(struct avc_command_frame)]; 679 struct avc_command_frame *c = (void *)fdtv->avc_data;
665 struct avc_command_frame *c = (void *)buffer; 680 struct avc_response_frame *r = (void *)fdtv->avc_data;
666 struct avc_response_frame *r = (void *)buffer; 681 int ret;
667 682
668 memset(c, 0, sizeof(*c)); 683 mutex_lock(&fdtv->avc_mutex);
669 684
670 c->ctype = AVC_CTYPE_CONTROL; 685 c->ctype = AVC_CTYPE_CONTROL;
671 c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit; 686 c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit;
@@ -678,31 +693,34 @@ int avc_identify_subunit(struct firedtv *fdtv)
678 c->operand[4] = 0x08; /* length lowbyte */ 693 c->operand[4] = 0x08; /* length lowbyte */
679 c->operand[5] = 0x00; /* offset highbyte */ 694 c->operand[5] = 0x00; /* offset highbyte */
680 c->operand[6] = 0x0d; /* offset lowbyte */ 695 c->operand[6] = 0x0d; /* offset lowbyte */
696 clear_operands(c, 7, 8); /* padding */
681 697
682 c->length = 12; 698 fdtv->avc_data_length = 12;
683 699 ret = avc_write(fdtv);
684 if (avc_write(fdtv, c, r) < 0) 700 if (ret < 0)
685 return -EIO; 701 goto out;
686 702
687 if ((r->response != AVC_RESPONSE_STABLE && 703 if ((r->response != AVC_RESPONSE_STABLE &&
688 r->response != AVC_RESPONSE_ACCEPTED) || 704 r->response != AVC_RESPONSE_ACCEPTED) ||
689 (r->operand[3] << 8) + r->operand[4] != 8) { 705 (r->operand[3] << 8) + r->operand[4] != 8) {
690 dev_err(fdtv->device, "cannot read subunit identifier\n"); 706 dev_err(fdtv->device, "cannot read subunit identifier\n");
691 return -EINVAL; 707 ret = -EINVAL;
692 } 708 }
693 return 0; 709out:
710 mutex_unlock(&fdtv->avc_mutex);
711
712 return ret;
694} 713}
695 714
696#define SIZEOF_ANTENNA_INPUT_INFO 22 715#define SIZEOF_ANTENNA_INPUT_INFO 22
697 716
698int avc_tuner_status(struct firedtv *fdtv, struct firedtv_tuner_status *stat) 717int avc_tuner_status(struct firedtv *fdtv, struct firedtv_tuner_status *stat)
699{ 718{
700 char buffer[sizeof(struct avc_command_frame)]; 719 struct avc_command_frame *c = (void *)fdtv->avc_data;
701 struct avc_command_frame *c = (void *)buffer; 720 struct avc_response_frame *r = (void *)fdtv->avc_data;
702 struct avc_response_frame *r = (void *)buffer; 721 int length, ret;
703 int length;
704 722
705 memset(c, 0, sizeof(*c)); 723 mutex_lock(&fdtv->avc_mutex);
706 724
707 c->ctype = AVC_CTYPE_CONTROL; 725 c->ctype = AVC_CTYPE_CONTROL;
708 c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit; 726 c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit;
@@ -710,27 +728,30 @@ int avc_tuner_status(struct firedtv *fdtv, struct firedtv_tuner_status *stat)
710 728
711 c->operand[0] = DESCRIPTOR_TUNER_STATUS; 729 c->operand[0] = DESCRIPTOR_TUNER_STATUS;
712 c->operand[1] = 0xff; /* read_result_status */ 730 c->operand[1] = 0xff; /* read_result_status */
713 c->operand[2] = 0x00; /* reserved */ 731 /*
714 c->operand[3] = 0; /* SIZEOF_ANTENNA_INPUT_INFO >> 8; */ 732 * operand[2]: reserved
715 c->operand[4] = 0; /* SIZEOF_ANTENNA_INPUT_INFO & 0xff; */ 733 * operand[3]: SIZEOF_ANTENNA_INPUT_INFO >> 8
716 c->operand[5] = 0x00; 734 * operand[4]: SIZEOF_ANTENNA_INPUT_INFO & 0xff
717 c->operand[6] = 0x00; 735 */
718 736 clear_operands(c, 2, 31);
719 c->length = 12; 737
720 738 fdtv->avc_data_length = 12;
721 if (avc_write(fdtv, c, r) < 0) 739 ret = avc_write(fdtv);
722 return -EIO; 740 if (ret < 0)
741 goto out;
723 742
724 if (r->response != AVC_RESPONSE_STABLE && 743 if (r->response != AVC_RESPONSE_STABLE &&
725 r->response != AVC_RESPONSE_ACCEPTED) { 744 r->response != AVC_RESPONSE_ACCEPTED) {
726 dev_err(fdtv->device, "cannot read tuner status\n"); 745 dev_err(fdtv->device, "cannot read tuner status\n");
727 return -EINVAL; 746 ret = -EINVAL;
747 goto out;
728 } 748 }
729 749
730 length = r->operand[9]; 750 length = r->operand[9];
731 if (r->operand[1] != 0x10 || length != SIZEOF_ANTENNA_INPUT_INFO) { 751 if (r->operand[1] != 0x10 || length != SIZEOF_ANTENNA_INPUT_INFO) {
732 dev_err(fdtv->device, "got invalid tuner status\n"); 752 dev_err(fdtv->device, "got invalid tuner status\n");
733 return -EINVAL; 753 ret = -EINVAL;
754 goto out;
734 } 755 }
735 756
736 stat->active_system = r->operand[10]; 757 stat->active_system = r->operand[10];
@@ -766,20 +787,21 @@ int avc_tuner_status(struct firedtv *fdtv, struct firedtv_tuner_status *stat)
766 stat->ca_dvb_flag = r->operand[31] >> 3 & 1; 787 stat->ca_dvb_flag = r->operand[31] >> 3 & 1;
767 stat->ca_error_flag = r->operand[31] >> 2 & 1; 788 stat->ca_error_flag = r->operand[31] >> 2 & 1;
768 stat->ca_initialization_status = r->operand[31] >> 1 & 1; 789 stat->ca_initialization_status = r->operand[31] >> 1 & 1;
790out:
791 mutex_unlock(&fdtv->avc_mutex);
769 792
770 return 0; 793 return ret;
771} 794}
772 795
773int avc_lnb_control(struct firedtv *fdtv, char voltage, char burst, 796int avc_lnb_control(struct firedtv *fdtv, char voltage, char burst,
774 char conttone, char nrdiseq, 797 char conttone, char nrdiseq,
775 struct dvb_diseqc_master_cmd *diseqcmd) 798 struct dvb_diseqc_master_cmd *diseqcmd)
776{ 799{
777 char buffer[sizeof(struct avc_command_frame)]; 800 struct avc_command_frame *c = (void *)fdtv->avc_data;
778 struct avc_command_frame *c = (void *)buffer; 801 struct avc_response_frame *r = (void *)fdtv->avc_data;
779 struct avc_response_frame *r = (void *)buffer; 802 int pos, j, k, ret;
780 int i, j, k;
781 803
782 memset(c, 0, sizeof(*c)); 804 mutex_lock(&fdtv->avc_mutex);
783 805
784 c->ctype = AVC_CTYPE_CONTROL; 806 c->ctype = AVC_CTYPE_CONTROL;
785 c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit; 807 c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit;
@@ -789,41 +811,41 @@ int avc_lnb_control(struct firedtv *fdtv, char voltage, char burst,
789 c->operand[1] = SFE_VENDOR_DE_COMPANYID_1; 811 c->operand[1] = SFE_VENDOR_DE_COMPANYID_1;
790 c->operand[2] = SFE_VENDOR_DE_COMPANYID_2; 812 c->operand[2] = SFE_VENDOR_DE_COMPANYID_2;
791 c->operand[3] = SFE_VENDOR_OPCODE_LNB_CONTROL; 813 c->operand[3] = SFE_VENDOR_OPCODE_LNB_CONTROL;
792
793 c->operand[4] = voltage; 814 c->operand[4] = voltage;
794 c->operand[5] = nrdiseq; 815 c->operand[5] = nrdiseq;
795 816
796 i = 6; 817 pos = 6;
797
798 for (j = 0; j < nrdiseq; j++) { 818 for (j = 0; j < nrdiseq; j++) {
799 c->operand[i++] = diseqcmd[j].msg_len; 819 c->operand[pos++] = diseqcmd[j].msg_len;
800 820
801 for (k = 0; k < diseqcmd[j].msg_len; k++) 821 for (k = 0; k < diseqcmd[j].msg_len; k++)
802 c->operand[i++] = diseqcmd[j].msg[k]; 822 c->operand[pos++] = diseqcmd[j].msg[k];
803 } 823 }
824 c->operand[pos++] = burst;
825 c->operand[pos++] = conttone;
826 pad_operands(c, pos);
804 827
805 c->operand[i++] = burst; 828 fdtv->avc_data_length = ALIGN(3 + pos, 4);
806 c->operand[i++] = conttone; 829 ret = avc_write(fdtv);
807 830 if (ret < 0)
808 c->length = ALIGN(3 + i, 4); 831 goto out;
809
810 if (avc_write(fdtv, c, r) < 0)
811 return -EIO;
812 832
813 if (r->response != AVC_RESPONSE_ACCEPTED) { 833 if (r->response != AVC_RESPONSE_ACCEPTED) {
814 dev_err(fdtv->device, "LNB control failed\n"); 834 dev_err(fdtv->device, "LNB control failed\n");
815 return -EINVAL; 835 ret = -EINVAL;
816 } 836 }
837out:
838 mutex_unlock(&fdtv->avc_mutex);
817 839
818 return 0; 840 return ret;
819} 841}
820 842
821int avc_register_remote_control(struct firedtv *fdtv) 843int avc_register_remote_control(struct firedtv *fdtv)
822{ 844{
823 char buffer[sizeof(struct avc_command_frame)]; 845 struct avc_command_frame *c = (void *)fdtv->avc_data;
824 struct avc_command_frame *c = (void *)buffer; 846 int ret;
825 847
826 memset(c, 0, sizeof(*c)); 848 mutex_lock(&fdtv->avc_mutex);
827 849
828 c->ctype = AVC_CTYPE_NOTIFY; 850 c->ctype = AVC_CTYPE_NOTIFY;
829 c->subunit = AVC_SUBUNIT_TYPE_UNIT | 7; 851 c->subunit = AVC_SUBUNIT_TYPE_UNIT | 7;
@@ -833,10 +855,16 @@ int avc_register_remote_control(struct firedtv *fdtv)
833 c->operand[1] = SFE_VENDOR_DE_COMPANYID_1; 855 c->operand[1] = SFE_VENDOR_DE_COMPANYID_1;
834 c->operand[2] = SFE_VENDOR_DE_COMPANYID_2; 856 c->operand[2] = SFE_VENDOR_DE_COMPANYID_2;
835 c->operand[3] = SFE_VENDOR_OPCODE_REGISTER_REMOTE_CONTROL; 857 c->operand[3] = SFE_VENDOR_OPCODE_REGISTER_REMOTE_CONTROL;
858 c->operand[4] = 0; /* padding */
859
860 fdtv->avc_data_length = 8;
861 ret = avc_write(fdtv);
836 862
837 c->length = 8; 863 /* FIXME: check response code? */
838 864
839 return avc_write(fdtv, c, NULL); 865 mutex_unlock(&fdtv->avc_mutex);
866
867 return ret;
840} 868}
841 869
842void avc_remote_ctrl_work(struct work_struct *work) 870void avc_remote_ctrl_work(struct work_struct *work)
@@ -851,11 +879,10 @@ void avc_remote_ctrl_work(struct work_struct *work)
851#if 0 /* FIXME: unused */ 879#if 0 /* FIXME: unused */
852int avc_tuner_host2ca(struct firedtv *fdtv) 880int avc_tuner_host2ca(struct firedtv *fdtv)
853{ 881{
854 char buffer[sizeof(struct avc_command_frame)]; 882 struct avc_command_frame *c = (void *)fdtv->avc_data;
855 struct avc_command_frame *c = (void *)buffer; 883 int ret;
856 struct avc_response_frame *r = (void *)buffer; /* FIXME: unused */
857 884
858 memset(c, 0, sizeof(*c)); 885 mutex_lock(&fdtv->avc_mutex);
859 886
860 c->ctype = AVC_CTYPE_CONTROL; 887 c->ctype = AVC_CTYPE_CONTROL;
861 c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit; 888 c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit;
@@ -867,15 +894,16 @@ int avc_tuner_host2ca(struct firedtv *fdtv)
867 c->operand[3] = SFE_VENDOR_OPCODE_HOST2CA; 894 c->operand[3] = SFE_VENDOR_OPCODE_HOST2CA;
868 c->operand[4] = 0; /* slot */ 895 c->operand[4] = 0; /* slot */
869 c->operand[5] = SFE_VENDOR_TAG_CA_APPLICATION_INFO; /* ca tag */ 896 c->operand[5] = SFE_VENDOR_TAG_CA_APPLICATION_INFO; /* ca tag */
870 c->operand[6] = 0; /* more/last */ 897 clear_operands(c, 6, 8);
871 c->operand[7] = 0; /* length */
872 898
873 c->length = 12; 899 fdtv->avc_data_length = 12;
900 ret = avc_write(fdtv);
874 901
875 if (avc_write(fdtv, c, r) < 0) 902 /* FIXME: check response code? */
876 return -EIO;
877 903
878 return 0; 904 mutex_unlock(&fdtv->avc_mutex);
905
906 return ret;
879} 907}
880#endif 908#endif
881 909
@@ -906,12 +934,11 @@ static int get_ca_object_length(struct avc_response_frame *r)
906 934
907int avc_ca_app_info(struct firedtv *fdtv, char *app_info, unsigned int *len) 935int avc_ca_app_info(struct firedtv *fdtv, char *app_info, unsigned int *len)
908{ 936{
909 char buffer[sizeof(struct avc_command_frame)]; 937 struct avc_command_frame *c = (void *)fdtv->avc_data;
910 struct avc_command_frame *c = (void *)buffer; 938 struct avc_response_frame *r = (void *)fdtv->avc_data;
911 struct avc_response_frame *r = (void *)buffer; 939 int pos, ret;
912 int pos;
913 940
914 memset(c, 0, sizeof(*c)); 941 mutex_lock(&fdtv->avc_mutex);
915 942
916 c->ctype = AVC_CTYPE_STATUS; 943 c->ctype = AVC_CTYPE_STATUS;
917 c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit; 944 c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit;
@@ -923,11 +950,12 @@ int avc_ca_app_info(struct firedtv *fdtv, char *app_info, unsigned int *len)
923 c->operand[3] = SFE_VENDOR_OPCODE_CA2HOST; 950 c->operand[3] = SFE_VENDOR_OPCODE_CA2HOST;
924 c->operand[4] = 0; /* slot */ 951 c->operand[4] = 0; /* slot */
925 c->operand[5] = SFE_VENDOR_TAG_CA_APPLICATION_INFO; /* ca tag */ 952 c->operand[5] = SFE_VENDOR_TAG_CA_APPLICATION_INFO; /* ca tag */
953 clear_operands(c, 6, LAST_OPERAND);
926 954
927 c->length = 12; 955 fdtv->avc_data_length = 12;
928 956 ret = avc_write(fdtv);
929 if (avc_write(fdtv, c, r) < 0) 957 if (ret < 0)
930 return -EIO; 958 goto out;
931 959
932 /* FIXME: check response code and validate response data */ 960 /* FIXME: check response code and validate response data */
933 961
@@ -939,18 +967,19 @@ int avc_ca_app_info(struct firedtv *fdtv, char *app_info, unsigned int *len)
939 app_info[4] = 0x01; 967 app_info[4] = 0x01;
940 memcpy(&app_info[5], &r->operand[pos], 5 + r->operand[pos + 4]); 968 memcpy(&app_info[5], &r->operand[pos], 5 + r->operand[pos + 4]);
941 *len = app_info[3] + 4; 969 *len = app_info[3] + 4;
970out:
971 mutex_unlock(&fdtv->avc_mutex);
942 972
943 return 0; 973 return ret;
944} 974}
945 975
946int avc_ca_info(struct firedtv *fdtv, char *app_info, unsigned int *len) 976int avc_ca_info(struct firedtv *fdtv, char *app_info, unsigned int *len)
947{ 977{
948 char buffer[sizeof(struct avc_command_frame)]; 978 struct avc_command_frame *c = (void *)fdtv->avc_data;
949 struct avc_command_frame *c = (void *)buffer; 979 struct avc_response_frame *r = (void *)fdtv->avc_data;
950 struct avc_response_frame *r = (void *)buffer; 980 int pos, ret;
951 int pos;
952 981
953 memset(c, 0, sizeof(*c)); 982 mutex_lock(&fdtv->avc_mutex);
954 983
955 c->ctype = AVC_CTYPE_STATUS; 984 c->ctype = AVC_CTYPE_STATUS;
956 c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit; 985 c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit;
@@ -962,11 +991,14 @@ int avc_ca_info(struct firedtv *fdtv, char *app_info, unsigned int *len)
962 c->operand[3] = SFE_VENDOR_OPCODE_CA2HOST; 991 c->operand[3] = SFE_VENDOR_OPCODE_CA2HOST;
963 c->operand[4] = 0; /* slot */ 992 c->operand[4] = 0; /* slot */
964 c->operand[5] = SFE_VENDOR_TAG_CA_APPLICATION_INFO; /* ca tag */ 993 c->operand[5] = SFE_VENDOR_TAG_CA_APPLICATION_INFO; /* ca tag */
994 clear_operands(c, 6, LAST_OPERAND);
965 995
966 c->length = 12; 996 fdtv->avc_data_length = 12;
997 ret = avc_write(fdtv);
998 if (ret < 0)
999 goto out;
967 1000
968 if (avc_write(fdtv, c, r) < 0) 1001 /* FIXME: check response code and validate response data */
969 return -EIO;
970 1002
971 pos = get_ca_object_pos(r); 1003 pos = get_ca_object_pos(r);
972 app_info[0] = (EN50221_TAG_CA_INFO >> 16) & 0xff; 1004 app_info[0] = (EN50221_TAG_CA_INFO >> 16) & 0xff;
@@ -976,17 +1008,18 @@ int avc_ca_info(struct firedtv *fdtv, char *app_info, unsigned int *len)
976 app_info[4] = r->operand[pos + 0]; 1008 app_info[4] = r->operand[pos + 0];
977 app_info[5] = r->operand[pos + 1]; 1009 app_info[5] = r->operand[pos + 1];
978 *len = app_info[3] + 4; 1010 *len = app_info[3] + 4;
1011out:
1012 mutex_unlock(&fdtv->avc_mutex);
979 1013
980 return 0; 1014 return ret;
981} 1015}
982 1016
983int avc_ca_reset(struct firedtv *fdtv) 1017int avc_ca_reset(struct firedtv *fdtv)
984{ 1018{
985 char buffer[sizeof(struct avc_command_frame)]; 1019 struct avc_command_frame *c = (void *)fdtv->avc_data;
986 struct avc_command_frame *c = (void *)buffer; 1020 int ret;
987 struct avc_response_frame *r = (void *)buffer; /* FIXME: unused */
988 1021
989 memset(c, 0, sizeof(*c)); 1022 mutex_lock(&fdtv->avc_mutex);
990 1023
991 c->ctype = AVC_CTYPE_CONTROL; 1024 c->ctype = AVC_CTYPE_CONTROL;
992 c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit; 1025 c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit;
@@ -1002,19 +1035,20 @@ int avc_ca_reset(struct firedtv *fdtv)
1002 c->operand[7] = 1; /* length */ 1035 c->operand[7] = 1; /* length */
1003 c->operand[8] = 0; /* force hardware reset */ 1036 c->operand[8] = 0; /* force hardware reset */
1004 1037
1005 c->length = 12; 1038 fdtv->avc_data_length = 12;
1039 ret = avc_write(fdtv);
1006 1040
1007 if (avc_write(fdtv, c, r) < 0) 1041 /* FIXME: check response code? */
1008 return -EIO;
1009 1042
1010 return 0; 1043 mutex_unlock(&fdtv->avc_mutex);
1044
1045 return ret;
1011} 1046}
1012 1047
1013int avc_ca_pmt(struct firedtv *fdtv, char *msg, int length) 1048int avc_ca_pmt(struct firedtv *fdtv, char *msg, int length)
1014{ 1049{
1015 char buffer[sizeof(struct avc_command_frame)]; 1050 struct avc_command_frame *c = (void *)fdtv->avc_data;
1016 struct avc_command_frame *c = (void *)buffer; 1051 struct avc_response_frame *r = (void *)fdtv->avc_data;
1017 struct avc_response_frame *r = (void *)buffer;
1018 int list_management; 1052 int list_management;
1019 int program_info_length; 1053 int program_info_length;
1020 int pmt_cmd_id; 1054 int pmt_cmd_id;
@@ -1022,11 +1056,12 @@ int avc_ca_pmt(struct firedtv *fdtv, char *msg, int length)
1022 int write_pos; 1056 int write_pos;
1023 int es_info_length; 1057 int es_info_length;
1024 int crc32_csum; 1058 int crc32_csum;
1059 int ret;
1025 1060
1026 if (unlikely(avc_debug & AVC_DEBUG_APPLICATION_PMT)) 1061 if (unlikely(avc_debug & AVC_DEBUG_APPLICATION_PMT))
1027 debug_pmt(msg, length); 1062 debug_pmt(msg, length);
1028 1063
1029 memset(c, 0, sizeof(*c)); 1064 mutex_lock(&fdtv->avc_mutex);
1030 1065
1031 c->ctype = AVC_CTYPE_CONTROL; 1066 c->ctype = AVC_CTYPE_CONTROL;
1032 c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit; 1067 c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit;
@@ -1058,7 +1093,7 @@ int avc_ca_pmt(struct firedtv *fdtv, char *msg, int length)
1058 1093
1059 c->operand[12] = 0x02; /* Table id=2 */ 1094 c->operand[12] = 0x02; /* Table id=2 */
1060 c->operand[13] = 0x80; /* Section syntax + length */ 1095 c->operand[13] = 0x80; /* Section syntax + length */
1061 /* c->operand[14] = XXXprogram_info_length + 12; */ 1096
1062 c->operand[15] = msg[1]; /* Program number */ 1097 c->operand[15] = msg[1]; /* Program number */
1063 c->operand[16] = msg[2]; 1098 c->operand[16] = msg[2];
1064 c->operand[17] = 0x01; /* Version number=0 + current/next=1 */ 1099 c->operand[17] = 0x01; /* Version number=0 + current/next=1 */
@@ -1106,12 +1141,7 @@ int avc_ca_pmt(struct firedtv *fdtv, char *msg, int length)
1106 write_pos += es_info_length; 1141 write_pos += es_info_length;
1107 } 1142 }
1108 } 1143 }
1109 1144 write_pos += 4; /* CRC */
1110 /* CRC */
1111 c->operand[write_pos++] = 0x00;
1112 c->operand[write_pos++] = 0x00;
1113 c->operand[write_pos++] = 0x00;
1114 c->operand[write_pos++] = 0x00;
1115 1145
1116 c->operand[7] = 0x82; 1146 c->operand[7] = 0x82;
1117 c->operand[8] = (write_pos - 10) >> 8; 1147 c->operand[8] = (write_pos - 10) >> 8;
@@ -1123,28 +1153,31 @@ int avc_ca_pmt(struct firedtv *fdtv, char *msg, int length)
1123 c->operand[write_pos - 3] = (crc32_csum >> 16) & 0xff; 1153 c->operand[write_pos - 3] = (crc32_csum >> 16) & 0xff;
1124 c->operand[write_pos - 2] = (crc32_csum >> 8) & 0xff; 1154 c->operand[write_pos - 2] = (crc32_csum >> 8) & 0xff;
1125 c->operand[write_pos - 1] = (crc32_csum >> 0) & 0xff; 1155 c->operand[write_pos - 1] = (crc32_csum >> 0) & 0xff;
1156 pad_operands(c, write_pos);
1126 1157
1127 c->length = ALIGN(3 + write_pos, 4); 1158 fdtv->avc_data_length = ALIGN(3 + write_pos, 4);
1128 1159 ret = avc_write(fdtv);
1129 if (avc_write(fdtv, c, r) < 0) 1160 if (ret < 0)
1130 return -EIO; 1161 goto out;
1131 1162
1132 if (r->response != AVC_RESPONSE_ACCEPTED) { 1163 if (r->response != AVC_RESPONSE_ACCEPTED) {
1133 dev_err(fdtv->device, 1164 dev_err(fdtv->device,
1134 "CA PMT failed with response 0x%x\n", r->response); 1165 "CA PMT failed with response 0x%x\n", r->response);
1135 return -EFAULT; 1166 ret = -EFAULT;
1136 } 1167 }
1168out:
1169 mutex_unlock(&fdtv->avc_mutex);
1137 1170
1138 return 0; 1171 return ret;
1139} 1172}
1140 1173
1141int avc_ca_get_time_date(struct firedtv *fdtv, int *interval) 1174int avc_ca_get_time_date(struct firedtv *fdtv, int *interval)
1142{ 1175{
1143 char buffer[sizeof(struct avc_command_frame)]; 1176 struct avc_command_frame *c = (void *)fdtv->avc_data;
1144 struct avc_command_frame *c = (void *)buffer; 1177 struct avc_response_frame *r = (void *)fdtv->avc_data;
1145 struct avc_response_frame *r = (void *)buffer; 1178 int ret;
1146 1179
1147 memset(c, 0, sizeof(*c)); 1180 mutex_lock(&fdtv->avc_mutex);
1148 1181
1149 c->ctype = AVC_CTYPE_STATUS; 1182 c->ctype = AVC_CTYPE_STATUS;
1150 c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit; 1183 c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit;
@@ -1156,28 +1189,28 @@ int avc_ca_get_time_date(struct firedtv *fdtv, int *interval)
1156 c->operand[3] = SFE_VENDOR_OPCODE_CA2HOST; 1189 c->operand[3] = SFE_VENDOR_OPCODE_CA2HOST;
1157 c->operand[4] = 0; /* slot */ 1190 c->operand[4] = 0; /* slot */
1158 c->operand[5] = SFE_VENDOR_TAG_CA_DATE_TIME; /* ca tag */ 1191 c->operand[5] = SFE_VENDOR_TAG_CA_DATE_TIME; /* ca tag */
1159 c->operand[6] = 0; /* more/last */ 1192 clear_operands(c, 6, LAST_OPERAND);
1160 c->operand[7] = 0; /* length */
1161 1193
1162 c->length = 12; 1194 fdtv->avc_data_length = 12;
1163 1195 ret = avc_write(fdtv);
1164 if (avc_write(fdtv, c, r) < 0) 1196 if (ret < 0)
1165 return -EIO; 1197 goto out;
1166 1198
1167 /* FIXME: check response code and validate response data */ 1199 /* FIXME: check response code and validate response data */
1168 1200
1169 *interval = r->operand[get_ca_object_pos(r)]; 1201 *interval = r->operand[get_ca_object_pos(r)];
1202out:
1203 mutex_unlock(&fdtv->avc_mutex);
1170 1204
1171 return 0; 1205 return ret;
1172} 1206}
1173 1207
1174int avc_ca_enter_menu(struct firedtv *fdtv) 1208int avc_ca_enter_menu(struct firedtv *fdtv)
1175{ 1209{
1176 char buffer[sizeof(struct avc_command_frame)]; 1210 struct avc_command_frame *c = (void *)fdtv->avc_data;
1177 struct avc_command_frame *c = (void *)buffer; 1211 int ret;
1178 struct avc_response_frame *r = (void *)buffer; /* FIXME: unused */
1179 1212
1180 memset(c, 0, sizeof(*c)); 1213 mutex_lock(&fdtv->avc_mutex);
1181 1214
1182 c->ctype = AVC_CTYPE_STATUS; 1215 c->ctype = AVC_CTYPE_STATUS;
1183 c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit; 1216 c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit;
@@ -1189,24 +1222,25 @@ int avc_ca_enter_menu(struct firedtv *fdtv)
1189 c->operand[3] = SFE_VENDOR_OPCODE_HOST2CA; 1222 c->operand[3] = SFE_VENDOR_OPCODE_HOST2CA;
1190 c->operand[4] = 0; /* slot */ 1223 c->operand[4] = 0; /* slot */
1191 c->operand[5] = SFE_VENDOR_TAG_CA_ENTER_MENU; 1224 c->operand[5] = SFE_VENDOR_TAG_CA_ENTER_MENU;
1192 c->operand[6] = 0; /* more/last */ 1225 clear_operands(c, 6, 8);
1193 c->operand[7] = 0; /* length */
1194 1226
1195 c->length = 12; 1227 fdtv->avc_data_length = 12;
1228 ret = avc_write(fdtv);
1196 1229
1197 if (avc_write(fdtv, c, r) < 0) 1230 /* FIXME: check response code? */
1198 return -EIO;
1199 1231
1200 return 0; 1232 mutex_unlock(&fdtv->avc_mutex);
1233
1234 return ret;
1201} 1235}
1202 1236
1203int avc_ca_get_mmi(struct firedtv *fdtv, char *mmi_object, unsigned int *len) 1237int avc_ca_get_mmi(struct firedtv *fdtv, char *mmi_object, unsigned int *len)
1204{ 1238{
1205 char buffer[sizeof(struct avc_command_frame)]; 1239 struct avc_command_frame *c = (void *)fdtv->avc_data;
1206 struct avc_command_frame *c = (void *)buffer; 1240 struct avc_response_frame *r = (void *)fdtv->avc_data;
1207 struct avc_response_frame *r = (void *)buffer; 1241 int ret;
1208 1242
1209 memset(c, 0, sizeof(*c)); 1243 mutex_lock(&fdtv->avc_mutex);
1210 1244
1211 c->ctype = AVC_CTYPE_STATUS; 1245 c->ctype = AVC_CTYPE_STATUS;
1212 c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit; 1246 c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit;
@@ -1218,20 +1252,21 @@ int avc_ca_get_mmi(struct firedtv *fdtv, char *mmi_object, unsigned int *len)
1218 c->operand[3] = SFE_VENDOR_OPCODE_CA2HOST; 1252 c->operand[3] = SFE_VENDOR_OPCODE_CA2HOST;
1219 c->operand[4] = 0; /* slot */ 1253 c->operand[4] = 0; /* slot */
1220 c->operand[5] = SFE_VENDOR_TAG_CA_MMI; 1254 c->operand[5] = SFE_VENDOR_TAG_CA_MMI;
1221 c->operand[6] = 0; /* more/last */ 1255 clear_operands(c, 6, LAST_OPERAND);
1222 c->operand[7] = 0; /* length */
1223 1256
1224 c->length = 12; 1257 fdtv->avc_data_length = 12;
1225 1258 ret = avc_write(fdtv);
1226 if (avc_write(fdtv, c, r) < 0) 1259 if (ret < 0)
1227 return -EIO; 1260 goto out;
1228 1261
1229 /* FIXME: check response code and validate response data */ 1262 /* FIXME: check response code and validate response data */
1230 1263
1231 *len = get_ca_object_length(r); 1264 *len = get_ca_object_length(r);
1232 memcpy(mmi_object, &r->operand[get_ca_object_pos(r)], *len); 1265 memcpy(mmi_object, &r->operand[get_ca_object_pos(r)], *len);
1266out:
1267 mutex_unlock(&fdtv->avc_mutex);
1233 1268
1234 return 0; 1269 return ret;
1235} 1270}
1236 1271
1237#define CMP_OUTPUT_PLUG_CONTROL_REG_0 0xfffff0000904ULL 1272#define CMP_OUTPUT_PLUG_CONTROL_REG_0 0xfffff0000904ULL
@@ -1240,14 +1275,14 @@ static int cmp_read(struct firedtv *fdtv, u64 addr, __be32 *data)
1240{ 1275{
1241 int ret; 1276 int ret;
1242 1277
1243 if (mutex_lock_interruptible(&fdtv->avc_mutex)) 1278 mutex_lock(&fdtv->avc_mutex);
1244 return -EINTR;
1245 1279
1246 ret = fdtv->backend->read(fdtv, addr, data); 1280 ret = fdtv->backend->read(fdtv, addr, data);
1247 if (ret < 0) 1281 if (ret < 0)
1248 dev_err(fdtv->device, "CMP: read I/O error\n"); 1282 dev_err(fdtv->device, "CMP: read I/O error\n");
1249 1283
1250 mutex_unlock(&fdtv->avc_mutex); 1284 mutex_unlock(&fdtv->avc_mutex);
1285
1251 return ret; 1286 return ret;
1252} 1287}
1253 1288
@@ -1255,14 +1290,19 @@ static int cmp_lock(struct firedtv *fdtv, u64 addr, __be32 data[])
1255{ 1290{
1256 int ret; 1291 int ret;
1257 1292
1258 if (mutex_lock_interruptible(&fdtv->avc_mutex)) 1293 mutex_lock(&fdtv->avc_mutex);
1259 return -EINTR; 1294
1295 /* data[] is stack-allocated and should not be DMA-mapped. */
1296 memcpy(fdtv->avc_data, data, 8);
1260 1297
1261 ret = fdtv->backend->lock(fdtv, addr, data); 1298 ret = fdtv->backend->lock(fdtv, addr, fdtv->avc_data);
1262 if (ret < 0) 1299 if (ret < 0)
1263 dev_err(fdtv->device, "CMP: lock I/O error\n"); 1300 dev_err(fdtv->device, "CMP: lock I/O error\n");
1301 else
1302 memcpy(data, fdtv->avc_data, 8);
1264 1303
1265 mutex_unlock(&fdtv->avc_mutex); 1304 mutex_unlock(&fdtv->avc_mutex);
1305
1266 return ret; 1306 return ret;
1267} 1307}
1268 1308