diff options
Diffstat (limited to 'drivers/media/dvb/firewire/firedtv-avc.c')
-rw-r--r-- | drivers/media/dvb/firewire/firedtv-avc.c | 514 |
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 | ||
76 | struct avc_command_frame { | 76 | struct 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 | ||
84 | struct avc_response_frame { | 83 | struct 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 | |||
92 | static 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 | |||
97 | static 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 | ||
205 | static int __avc_write(struct firedtv *fdtv, | 218 | static 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 | ||
245 | static int avc_write(struct firedtv *fdtv, | 250 | static 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 | ||
259 | int avc_recv(struct firedtv *fdtv, void *data, size_t length) | 259 | int 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 | 290 | wake: | |
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 | */ |
321 | static void avc_tuner_tuneqpsk(struct firedtv *fdtv, | 321 | static 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 | ||
379 | static void avc_tuner_dsd_dvb_c(struct firedtv *fdtv, | 381 | static 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 | ||
447 | static void avc_tuner_dsd_dvb_t(struct firedtv *fdtv, | 449 | static 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 = ¶ms->u.ofdm; | 452 | struct dvb_ofdm_parameters *ofdm = ¶ms->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 | ||
550 | int avc_tuner_dsd(struct firedtv *fdtv, | 551 | int 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 | ||
584 | int avc_tuner_set_pids(struct firedtv *fdtv, unsigned char pidc, u16 pid[]) | 591 | int 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 | ||
627 | int avc_tuner_get_ts(struct firedtv *fdtv) | 637 | int 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 | ||
662 | int avc_identify_subunit(struct firedtv *fdtv) | 677 | int 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; | 709 | out: |
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 | ||
698 | int avc_tuner_status(struct firedtv *fdtv, struct firedtv_tuner_status *stat) | 717 | int 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; |
790 | out: | ||
791 | mutex_unlock(&fdtv->avc_mutex); | ||
769 | 792 | ||
770 | return 0; | 793 | return ret; |
771 | } | 794 | } |
772 | 795 | ||
773 | int avc_lnb_control(struct firedtv *fdtv, char voltage, char burst, | 796 | int 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 | } |
837 | out: | ||
838 | mutex_unlock(&fdtv->avc_mutex); | ||
817 | 839 | ||
818 | return 0; | 840 | return ret; |
819 | } | 841 | } |
820 | 842 | ||
821 | int avc_register_remote_control(struct firedtv *fdtv) | 843 | int 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 | ||
842 | void avc_remote_ctrl_work(struct work_struct *work) | 870 | void 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 */ |
852 | int avc_tuner_host2ca(struct firedtv *fdtv) | 880 | int 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 | ||
907 | int avc_ca_app_info(struct firedtv *fdtv, char *app_info, unsigned int *len) | 935 | int 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; |
970 | out: | ||
971 | mutex_unlock(&fdtv->avc_mutex); | ||
942 | 972 | ||
943 | return 0; | 973 | return ret; |
944 | } | 974 | } |
945 | 975 | ||
946 | int avc_ca_info(struct firedtv *fdtv, char *app_info, unsigned int *len) | 976 | int 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; |
1011 | out: | ||
1012 | mutex_unlock(&fdtv->avc_mutex); | ||
979 | 1013 | ||
980 | return 0; | 1014 | return ret; |
981 | } | 1015 | } |
982 | 1016 | ||
983 | int avc_ca_reset(struct firedtv *fdtv) | 1017 | int 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 | ||
1013 | int avc_ca_pmt(struct firedtv *fdtv, char *msg, int length) | 1048 | int 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 | } |
1168 | out: | ||
1169 | mutex_unlock(&fdtv->avc_mutex); | ||
1137 | 1170 | ||
1138 | return 0; | 1171 | return ret; |
1139 | } | 1172 | } |
1140 | 1173 | ||
1141 | int avc_ca_get_time_date(struct firedtv *fdtv, int *interval) | 1174 | int 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)]; |
1202 | out: | ||
1203 | mutex_unlock(&fdtv->avc_mutex); | ||
1170 | 1204 | ||
1171 | return 0; | 1205 | return ret; |
1172 | } | 1206 | } |
1173 | 1207 | ||
1174 | int avc_ca_enter_menu(struct firedtv *fdtv) | 1208 | int 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 | ||
1203 | int avc_ca_get_mmi(struct firedtv *fdtv, char *mmi_object, unsigned int *len) | 1237 | int 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); |
1266 | out: | ||
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 | ||