2 * FireDTV driver (formerly known as FireSAT)
4 * Copyright (C) 2004 Andreas Monitzer <andy@monitzer.com>
5 * Copyright (C) 2008 Ben Backx <ben@bbackx.com>
6 * Copyright (C) 2008 Henrik Kurelid <henrik@kurelid.se>
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License as
10 * published by the Free Software Foundation; either version 2 of
11 * the License, or (at your option) any later version.
14 #include <linux/bug.h>
15 #include <linux/crc32.h>
16 #include <linux/delay.h>
17 #include <linux/device.h>
18 #include <linux/jiffies.h>
19 #include <linux/kernel.h>
20 #include <linux/moduleparam.h>
21 #include <linux/mutex.h>
22 #include <linux/string.h>
23 #include <linux/stringify.h>
24 #include <linux/wait.h>
25 #include <linux/workqueue.h>
29 #define FCP_COMMAND_REGISTER 0xfffff0000b00ULL
31 #define AVC_CTYPE_CONTROL 0x0
32 #define AVC_CTYPE_STATUS 0x1
33 #define AVC_CTYPE_NOTIFY 0x3
35 #define AVC_RESPONSE_ACCEPTED 0x9
36 #define AVC_RESPONSE_STABLE 0xc
37 #define AVC_RESPONSE_CHANGED 0xd
38 #define AVC_RESPONSE_INTERIM 0xf
40 #define AVC_SUBUNIT_TYPE_TUNER (0x05 << 3)
41 #define AVC_SUBUNIT_TYPE_UNIT (0x1f << 3)
43 #define AVC_OPCODE_VENDOR 0x00
44 #define AVC_OPCODE_READ_DESCRIPTOR 0x09
45 #define AVC_OPCODE_DSIT 0xc8
46 #define AVC_OPCODE_DSD 0xcb
48 #define DESCRIPTOR_TUNER_STATUS 0x80
49 #define DESCRIPTOR_SUBUNIT_IDENTIFIER 0x00
51 #define SFE_VENDOR_DE_COMPANYID_0 0x00 /* OUI of Digital Everywhere */
52 #define SFE_VENDOR_DE_COMPANYID_1 0x12
53 #define SFE_VENDOR_DE_COMPANYID_2 0x87
55 #define SFE_VENDOR_OPCODE_REGISTER_REMOTE_CONTROL 0x0a
56 #define SFE_VENDOR_OPCODE_LNB_CONTROL 0x52
57 #define SFE_VENDOR_OPCODE_TUNE_QPSK 0x58 /* for DVB-S */
59 #define SFE_VENDOR_OPCODE_GET_FIRMWARE_VERSION 0x00
60 #define SFE_VENDOR_OPCODE_HOST2CA 0x56
61 #define SFE_VENDOR_OPCODE_CA2HOST 0x57
62 #define SFE_VENDOR_OPCODE_CISTATUS 0x59
63 #define SFE_VENDOR_OPCODE_TUNE_QPSK2 0x60 /* for DVB-S2 */
65 #define SFE_VENDOR_TAG_CA_RESET 0x00
66 #define SFE_VENDOR_TAG_CA_APPLICATION_INFO 0x01
67 #define SFE_VENDOR_TAG_CA_PMT 0x02
68 #define SFE_VENDOR_TAG_CA_DATE_TIME 0x04
69 #define SFE_VENDOR_TAG_CA_MMI 0x05
70 #define SFE_VENDOR_TAG_CA_ENTER_MENU 0x07
72 #define EN50221_LIST_MANAGEMENT_ONLY 0x03
73 #define EN50221_TAG_APP_INFO 0x9f8021
74 #define EN50221_TAG_CA_INFO 0x9f8031
76 struct avc_command_frame
{
83 struct avc_response_frame
{
90 #define LAST_OPERAND (509 - 1)
92 static inline void clear_operands(struct avc_command_frame
*c
, int from
, int to
)
94 memset(&c
->operand
[from
], 0, to
- from
+ 1);
97 static void pad_operands(struct avc_command_frame
*c
, int from
)
99 int to
= ALIGN(from
, 4);
101 if (from
<= to
&& to
<= LAST_OPERAND
)
102 clear_operands(c
, from
, to
);
105 #define AVC_DEBUG_READ_DESCRIPTOR 0x0001
106 #define AVC_DEBUG_DSIT 0x0002
107 #define AVC_DEBUG_DSD 0x0004
108 #define AVC_DEBUG_REGISTER_REMOTE_CONTROL 0x0008
109 #define AVC_DEBUG_LNB_CONTROL 0x0010
110 #define AVC_DEBUG_TUNE_QPSK 0x0020
111 #define AVC_DEBUG_TUNE_QPSK2 0x0040
112 #define AVC_DEBUG_HOST2CA 0x0080
113 #define AVC_DEBUG_CA2HOST 0x0100
114 #define AVC_DEBUG_APPLICATION_PMT 0x4000
115 #define AVC_DEBUG_FCP_PAYLOADS 0x8000
117 static int avc_debug
;
118 module_param_named(debug
, avc_debug
, int, 0644);
119 MODULE_PARM_DESC(debug
, "Verbose logging (none = 0"
121 ": READ DESCRIPTOR = " __stringify(AVC_DEBUG_READ_DESCRIPTOR
)
122 ", DSIT = " __stringify(AVC_DEBUG_DSIT
)
123 ", REGISTER_REMOTE_CONTROL = " __stringify(AVC_DEBUG_REGISTER_REMOTE_CONTROL
)
124 ", LNB CONTROL = " __stringify(AVC_DEBUG_LNB_CONTROL
)
125 ", TUNE QPSK = " __stringify(AVC_DEBUG_TUNE_QPSK
)
126 ", TUNE QPSK2 = " __stringify(AVC_DEBUG_TUNE_QPSK2
)
127 ", HOST2CA = " __stringify(AVC_DEBUG_HOST2CA
)
128 ", CA2HOST = " __stringify(AVC_DEBUG_CA2HOST
)
129 "; Application sent PMT = " __stringify(AVC_DEBUG_APPLICATION_PMT
)
130 ", FCP payloads = " __stringify(AVC_DEBUG_FCP_PAYLOADS
)
131 ", or a combination, or all = -1)");
133 static const char *debug_fcp_ctype(unsigned int ctype
)
135 static const char *ctypes
[] = {
136 [0x0] = "CONTROL", [0x1] = "STATUS",
137 [0x2] = "SPECIFIC INQUIRY", [0x3] = "NOTIFY",
138 [0x4] = "GENERAL INQUIRY", [0x8] = "NOT IMPLEMENTED",
139 [0x9] = "ACCEPTED", [0xa] = "REJECTED",
140 [0xb] = "IN TRANSITION", [0xc] = "IMPLEMENTED/STABLE",
141 [0xd] = "CHANGED", [0xf] = "INTERIM",
143 const char *ret
= ctype
< ARRAY_SIZE(ctypes
) ? ctypes
[ctype
] : NULL
;
145 return ret
? ret
: "?";
148 static const char *debug_fcp_opcode(unsigned int opcode
,
149 const u8
*data
, int length
)
152 case AVC_OPCODE_VENDOR
:
154 case AVC_OPCODE_READ_DESCRIPTOR
:
155 return avc_debug
& AVC_DEBUG_READ_DESCRIPTOR
?
156 "ReadDescriptor" : NULL
;
157 case AVC_OPCODE_DSIT
:
158 return avc_debug
& AVC_DEBUG_DSIT
?
159 "DirectSelectInfo.Type" : NULL
;
161 return avc_debug
& AVC_DEBUG_DSD
? "DirectSelectData" : NULL
;
167 data
[3] != SFE_VENDOR_DE_COMPANYID_0
||
168 data
[4] != SFE_VENDOR_DE_COMPANYID_1
||
169 data
[5] != SFE_VENDOR_DE_COMPANYID_2
)
170 return "Vendor/Unknown";
173 case SFE_VENDOR_OPCODE_REGISTER_REMOTE_CONTROL
:
174 return avc_debug
& AVC_DEBUG_REGISTER_REMOTE_CONTROL
?
176 case SFE_VENDOR_OPCODE_LNB_CONTROL
:
177 return avc_debug
& AVC_DEBUG_LNB_CONTROL
? "LNBControl" : NULL
;
178 case SFE_VENDOR_OPCODE_TUNE_QPSK
:
179 return avc_debug
& AVC_DEBUG_TUNE_QPSK
? "TuneQPSK" : NULL
;
180 case SFE_VENDOR_OPCODE_TUNE_QPSK2
:
181 return avc_debug
& AVC_DEBUG_TUNE_QPSK2
? "TuneQPSK2" : NULL
;
182 case SFE_VENDOR_OPCODE_HOST2CA
:
183 return avc_debug
& AVC_DEBUG_HOST2CA
? "Host2CA" : NULL
;
184 case SFE_VENDOR_OPCODE_CA2HOST
:
185 return avc_debug
& AVC_DEBUG_CA2HOST
? "CA2Host" : NULL
;
187 return "Vendor/Unknown";
190 static void debug_fcp(const u8
*data
, int length
)
192 unsigned int subunit_type
, subunit_id
, opcode
;
193 const char *op
, *prefix
;
195 prefix
= data
[0] > 7 ? "FCP <- " : "FCP -> ";
196 subunit_type
= data
[1] >> 3;
197 subunit_id
= data
[1] & 7;
198 opcode
= subunit_type
== 0x1e || subunit_id
== 5 ? ~0 : data
[2];
199 op
= debug_fcp_opcode(opcode
, data
, length
);
202 printk(KERN_INFO
"%ssu=%x.%x l=%d: %-8s - %s\n",
203 prefix
, subunit_type
, subunit_id
, length
,
204 debug_fcp_ctype(data
[0]), op
);
205 if (avc_debug
& AVC_DEBUG_FCP_PAYLOADS
)
206 print_hex_dump(KERN_INFO
, prefix
, DUMP_PREFIX_NONE
,
207 16, 1, data
, length
, false);
211 static void debug_pmt(char *msg
, int length
)
213 printk(KERN_INFO
"APP PMT -> l=%d\n", length
);
214 print_hex_dump(KERN_INFO
, "APP PMT -> ", DUMP_PREFIX_NONE
,
215 16, 1, msg
, length
, false);
218 static int avc_write(struct firedtv
*fdtv
)
222 fdtv
->avc_reply_received
= false;
224 for (retry
= 0; retry
< 6; retry
++) {
225 if (unlikely(avc_debug
))
226 debug_fcp(fdtv
->avc_data
, fdtv
->avc_data_length
);
228 err
= fdtv
->backend
->write(fdtv
, FCP_COMMAND_REGISTER
,
229 fdtv
->avc_data
, fdtv
->avc_data_length
);
231 dev_err(fdtv
->device
, "FCP command write failed\n");
237 * AV/C specs say that answers should be sent within 150 ms.
238 * Time out after 200 ms.
240 if (wait_event_timeout(fdtv
->avc_wait
,
241 fdtv
->avc_reply_received
,
242 msecs_to_jiffies(200)) != 0)
245 dev_err(fdtv
->device
, "FCP response timed out\n");
250 static bool is_register_rc(struct avc_response_frame
*r
)
252 return r
->opcode
== AVC_OPCODE_VENDOR
&&
253 r
->operand
[0] == SFE_VENDOR_DE_COMPANYID_0
&&
254 r
->operand
[1] == SFE_VENDOR_DE_COMPANYID_1
&&
255 r
->operand
[2] == SFE_VENDOR_DE_COMPANYID_2
&&
256 r
->operand
[3] == SFE_VENDOR_OPCODE_REGISTER_REMOTE_CONTROL
;
259 int avc_recv(struct firedtv
*fdtv
, void *data
, size_t length
)
261 struct avc_response_frame
*r
= data
;
263 if (unlikely(avc_debug
))
264 debug_fcp(data
, length
);
266 if (length
>= 8 && is_register_rc(r
)) {
267 switch (r
->response
) {
268 case AVC_RESPONSE_CHANGED
:
269 fdtv_handle_rc(fdtv
, r
->operand
[4] << 8 | r
->operand
[5]);
270 schedule_work(&fdtv
->remote_ctrl_work
);
272 case AVC_RESPONSE_INTERIM
:
273 if (is_register_rc((void *)fdtv
->avc_data
))
277 dev_info(fdtv
->device
,
278 "remote control result = %d\n", r
->response
);
283 if (fdtv
->avc_reply_received
) {
284 dev_err(fdtv
->device
, "out-of-order AVC response, ignored\n");
288 memcpy(fdtv
->avc_data
, data
, length
);
289 fdtv
->avc_data_length
= length
;
291 fdtv
->avc_reply_received
= true;
292 wake_up(&fdtv
->avc_wait
);
297 static int add_pid_filter(struct firedtv
*fdtv
, u8
*operand
)
301 for (i
= 0, n
= 0; i
< 16; i
++) {
302 if (test_bit(i
, &fdtv
->channel_active
)) {
303 operand
[pos
++] = 0x13; /* flowfunction relay */
304 operand
[pos
++] = 0x80; /* dsd_sel_spec_valid_flags -> PID */
305 operand
[pos
++] = (fdtv
->channel_pid
[i
] >> 8) & 0x1f;
306 operand
[pos
++] = fdtv
->channel_pid
[i
] & 0xff;
307 operand
[pos
++] = 0x00; /* tableID */
308 operand
[pos
++] = 0x00; /* filter_length */
318 * tuning command for setting the relative LNB frequency
319 * (not supported by the AVC standard)
321 static int avc_tuner_tuneqpsk(struct firedtv
*fdtv
,
322 struct dvb_frontend_parameters
*params
)
324 struct avc_command_frame
*c
= (void *)fdtv
->avc_data
;
326 c
->opcode
= AVC_OPCODE_VENDOR
;
328 c
->operand
[0] = SFE_VENDOR_DE_COMPANYID_0
;
329 c
->operand
[1] = SFE_VENDOR_DE_COMPANYID_1
;
330 c
->operand
[2] = SFE_VENDOR_DE_COMPANYID_2
;
331 if (fdtv
->type
== FIREDTV_DVB_S2
)
332 c
->operand
[3] = SFE_VENDOR_OPCODE_TUNE_QPSK2
;
334 c
->operand
[3] = SFE_VENDOR_OPCODE_TUNE_QPSK
;
336 c
->operand
[4] = (params
->frequency
>> 24) & 0xff;
337 c
->operand
[5] = (params
->frequency
>> 16) & 0xff;
338 c
->operand
[6] = (params
->frequency
>> 8) & 0xff;
339 c
->operand
[7] = params
->frequency
& 0xff;
341 c
->operand
[8] = ((params
->u
.qpsk
.symbol_rate
/ 1000) >> 8) & 0xff;
342 c
->operand
[9] = (params
->u
.qpsk
.symbol_rate
/ 1000) & 0xff;
344 switch (params
->u
.qpsk
.fec_inner
) {
345 case FEC_1_2
: c
->operand
[10] = 0x1; break;
346 case FEC_2_3
: c
->operand
[10] = 0x2; break;
347 case FEC_3_4
: c
->operand
[10] = 0x3; break;
348 case FEC_5_6
: c
->operand
[10] = 0x4; break;
349 case FEC_7_8
: c
->operand
[10] = 0x5; break;
353 default: c
->operand
[10] = 0x0;
356 if (fdtv
->voltage
== 0xff)
357 c
->operand
[11] = 0xff;
358 else if (fdtv
->voltage
== SEC_VOLTAGE_18
) /* polarisation */
363 if (fdtv
->tone
== 0xff)
364 c
->operand
[12] = 0xff;
365 else if (fdtv
->tone
== SEC_TONE_ON
) /* band */
370 if (fdtv
->type
== FIREDTV_DVB_S2
) {
371 c
->operand
[13] = 0x1;
372 c
->operand
[14] = 0xff;
373 c
->operand
[15] = 0xff;
381 static int avc_tuner_dsd_dvb_c(struct firedtv
*fdtv
,
382 struct dvb_frontend_parameters
*params
)
384 struct avc_command_frame
*c
= (void *)fdtv
->avc_data
;
386 c
->opcode
= AVC_OPCODE_DSD
;
388 c
->operand
[0] = 0; /* source plug */
389 c
->operand
[1] = 0xd2; /* subfunction replace */
390 c
->operand
[2] = 0x20; /* system id = DVB */
391 c
->operand
[3] = 0x00; /* antenna number */
392 c
->operand
[4] = 0x11; /* system_specific_multiplex selection_length */
394 /* multiplex_valid_flags, high byte */
395 c
->operand
[5] = 0 << 7 /* reserved */
396 | 0 << 6 /* Polarisation */
397 | 0 << 5 /* Orbital_Pos */
398 | 1 << 4 /* Frequency */
399 | 1 << 3 /* Symbol_Rate */
400 | 0 << 2 /* FEC_outer */
401 | (params
->u
.qam
.fec_inner
!= FEC_AUTO
? 1 << 1 : 0)
402 | (params
->u
.qam
.modulation
!= QAM_AUTO
? 1 << 0 : 0);
404 /* multiplex_valid_flags, low byte */
405 c
->operand
[6] = 0 << 7 /* NetworkID */
406 | 0 << 0 /* reserved */ ;
408 c
->operand
[7] = 0x00;
409 c
->operand
[8] = 0x00;
410 c
->operand
[9] = 0x00;
411 c
->operand
[10] = 0x00;
413 c
->operand
[11] = (((params
->frequency
/ 4000) >> 16) & 0xff) | (2 << 6);
414 c
->operand
[12] = ((params
->frequency
/ 4000) >> 8) & 0xff;
415 c
->operand
[13] = (params
->frequency
/ 4000) & 0xff;
416 c
->operand
[14] = ((params
->u
.qpsk
.symbol_rate
/ 1000) >> 12) & 0xff;
417 c
->operand
[15] = ((params
->u
.qpsk
.symbol_rate
/ 1000) >> 4) & 0xff;
418 c
->operand
[16] = ((params
->u
.qpsk
.symbol_rate
/ 1000) << 4) & 0xf0;
419 c
->operand
[17] = 0x00;
421 switch (params
->u
.qpsk
.fec_inner
) {
422 case FEC_1_2
: c
->operand
[18] = 0x1; break;
423 case FEC_2_3
: c
->operand
[18] = 0x2; break;
424 case FEC_3_4
: c
->operand
[18] = 0x3; break;
425 case FEC_5_6
: c
->operand
[18] = 0x4; break;
426 case FEC_7_8
: c
->operand
[18] = 0x5; break;
427 case FEC_8_9
: c
->operand
[18] = 0x6; break;
428 case FEC_4_5
: c
->operand
[18] = 0x8; break;
430 default: c
->operand
[18] = 0x0;
433 switch (params
->u
.qam
.modulation
) {
434 case QAM_16
: c
->operand
[19] = 0x08; break;
435 case QAM_32
: c
->operand
[19] = 0x10; break;
436 case QAM_64
: c
->operand
[19] = 0x18; break;
437 case QAM_128
: c
->operand
[19] = 0x20; break;
438 case QAM_256
: c
->operand
[19] = 0x28; break;
440 default: c
->operand
[19] = 0x00;
443 c
->operand
[20] = 0x00;
444 c
->operand
[21] = 0x00;
446 return 22 + add_pid_filter(fdtv
, &c
->operand
[22]);
449 static int avc_tuner_dsd_dvb_t(struct firedtv
*fdtv
,
450 struct dvb_frontend_parameters
*params
)
452 struct dvb_ofdm_parameters
*ofdm
= ¶ms
->u
.ofdm
;
453 struct avc_command_frame
*c
= (void *)fdtv
->avc_data
;
455 c
->opcode
= AVC_OPCODE_DSD
;
457 c
->operand
[0] = 0; /* source plug */
458 c
->operand
[1] = 0xd2; /* subfunction replace */
459 c
->operand
[2] = 0x20; /* system id = DVB */
460 c
->operand
[3] = 0x00; /* antenna number */
461 c
->operand
[4] = 0x0c; /* system_specific_multiplex selection_length */
463 /* multiplex_valid_flags, high byte */
465 0 << 7 /* reserved */
466 | 1 << 6 /* CenterFrequency */
467 | (ofdm
->bandwidth
!= BANDWIDTH_AUTO
? 1 << 5 : 0)
468 | (ofdm
->constellation
!= QAM_AUTO
? 1 << 4 : 0)
469 | (ofdm
->hierarchy_information
!= HIERARCHY_AUTO
? 1 << 3 : 0)
470 | (ofdm
->code_rate_HP
!= FEC_AUTO
? 1 << 2 : 0)
471 | (ofdm
->code_rate_LP
!= FEC_AUTO
? 1 << 1 : 0)
472 | (ofdm
->guard_interval
!= GUARD_INTERVAL_AUTO
? 1 << 0 : 0);
474 /* multiplex_valid_flags, low byte */
476 0 << 7 /* NetworkID */
477 | (ofdm
->transmission_mode
!= TRANSMISSION_MODE_AUTO
? 1 << 6 : 0)
478 | 0 << 5 /* OtherFrequencyFlag */
479 | 0 << 0 /* reserved */ ;
482 c
->operand
[8] = (params
->frequency
/ 10) >> 24;
483 c
->operand
[9] = ((params
->frequency
/ 10) >> 16) & 0xff;
484 c
->operand
[10] = ((params
->frequency
/ 10) >> 8) & 0xff;
485 c
->operand
[11] = (params
->frequency
/ 10) & 0xff;
487 switch (ofdm
->bandwidth
) {
488 case BANDWIDTH_7_MHZ
: c
->operand
[12] = 0x20; break;
489 case BANDWIDTH_8_MHZ
:
490 case BANDWIDTH_6_MHZ
: /* not defined by AVC spec */
492 default: c
->operand
[12] = 0x00;
495 switch (ofdm
->constellation
) {
496 case QAM_16
: c
->operand
[13] = 1 << 6; break;
497 case QAM_64
: c
->operand
[13] = 2 << 6; break;
499 default: c
->operand
[13] = 0x00;
502 switch (ofdm
->hierarchy_information
) {
503 case HIERARCHY_1
: c
->operand
[13] |= 1 << 3; break;
504 case HIERARCHY_2
: c
->operand
[13] |= 2 << 3; break;
505 case HIERARCHY_4
: c
->operand
[13] |= 3 << 3; break;
511 switch (ofdm
->code_rate_HP
) {
512 case FEC_2_3
: c
->operand
[13] |= 1; break;
513 case FEC_3_4
: c
->operand
[13] |= 2; break;
514 case FEC_5_6
: c
->operand
[13] |= 3; break;
515 case FEC_7_8
: c
->operand
[13] |= 4; break;
520 switch (ofdm
->code_rate_LP
) {
521 case FEC_2_3
: c
->operand
[14] = 1 << 5; break;
522 case FEC_3_4
: c
->operand
[14] = 2 << 5; break;
523 case FEC_5_6
: c
->operand
[14] = 3 << 5; break;
524 case FEC_7_8
: c
->operand
[14] = 4 << 5; break;
526 default: c
->operand
[14] = 0x00; break;
529 switch (ofdm
->guard_interval
) {
530 case GUARD_INTERVAL_1_16
: c
->operand
[14] |= 1 << 3; break;
531 case GUARD_INTERVAL_1_8
: c
->operand
[14] |= 2 << 3; break;
532 case GUARD_INTERVAL_1_4
: c
->operand
[14] |= 3 << 3; break;
533 case GUARD_INTERVAL_1_32
:
534 case GUARD_INTERVAL_AUTO
:
538 switch (ofdm
->transmission_mode
) {
539 case TRANSMISSION_MODE_8K
: c
->operand
[14] |= 1 << 1; break;
540 case TRANSMISSION_MODE_2K
:
541 case TRANSMISSION_MODE_AUTO
:
545 c
->operand
[15] = 0x00; /* network_ID[0] */
546 c
->operand
[16] = 0x00; /* network_ID[1] */
548 return 17 + add_pid_filter(fdtv
, &c
->operand
[17]);
551 int avc_tuner_dsd(struct firedtv
*fdtv
,
552 struct dvb_frontend_parameters
*params
)
554 struct avc_command_frame
*c
= (void *)fdtv
->avc_data
;
557 mutex_lock(&fdtv
->avc_mutex
);
559 c
->ctype
= AVC_CTYPE_CONTROL
;
560 c
->subunit
= AVC_SUBUNIT_TYPE_TUNER
| fdtv
->subunit
;
562 switch (fdtv
->type
) {
564 case FIREDTV_DVB_S2
: pos
= avc_tuner_tuneqpsk(fdtv
, params
); break;
565 case FIREDTV_DVB_C
: pos
= avc_tuner_dsd_dvb_c(fdtv
, params
); break;
566 case FIREDTV_DVB_T
: pos
= avc_tuner_dsd_dvb_t(fdtv
, params
); break;
570 pad_operands(c
, pos
);
572 fdtv
->avc_data_length
= ALIGN(3 + pos
, 4);
573 ret
= avc_write(fdtv
);
577 * u8 *status was an out-parameter of avc_tuner_dsd, unused by caller.
578 * Check for AVC_RESPONSE_ACCEPTED here instead?
581 *status
= r
->operand
[2];
583 mutex_unlock(&fdtv
->avc_mutex
);
591 int avc_tuner_set_pids(struct firedtv
*fdtv
, unsigned char pidc
, u16 pid
[])
593 struct avc_command_frame
*c
= (void *)fdtv
->avc_data
;
596 if (pidc
> 16 && pidc
!= 0xff)
599 mutex_lock(&fdtv
->avc_mutex
);
601 c
->ctype
= AVC_CTYPE_CONTROL
;
602 c
->subunit
= AVC_SUBUNIT_TYPE_TUNER
| fdtv
->subunit
;
603 c
->opcode
= AVC_OPCODE_DSD
;
605 c
->operand
[0] = 0; /* source plug */
606 c
->operand
[1] = 0xd2; /* subfunction replace */
607 c
->operand
[2] = 0x20; /* system id = DVB */
608 c
->operand
[3] = 0x00; /* antenna number */
609 c
->operand
[4] = 0x00; /* system_specific_multiplex selection_length */
610 c
->operand
[5] = pidc
; /* Nr_of_dsd_sel_specs */
614 for (k
= 0; k
< pidc
; k
++) {
615 c
->operand
[pos
++] = 0x13; /* flowfunction relay */
616 c
->operand
[pos
++] = 0x80; /* dsd_sel_spec_valid_flags -> PID */
617 c
->operand
[pos
++] = (pid
[k
] >> 8) & 0x1f;
618 c
->operand
[pos
++] = pid
[k
] & 0xff;
619 c
->operand
[pos
++] = 0x00; /* tableID */
620 c
->operand
[pos
++] = 0x00; /* filter_length */
622 pad_operands(c
, pos
);
624 fdtv
->avc_data_length
= ALIGN(3 + pos
, 4);
625 ret
= avc_write(fdtv
);
627 /* FIXME: check response code? */
629 mutex_unlock(&fdtv
->avc_mutex
);
637 int avc_tuner_get_ts(struct firedtv
*fdtv
)
639 struct avc_command_frame
*c
= (void *)fdtv
->avc_data
;
642 mutex_lock(&fdtv
->avc_mutex
);
644 c
->ctype
= AVC_CTYPE_CONTROL
;
645 c
->subunit
= AVC_SUBUNIT_TYPE_TUNER
| fdtv
->subunit
;
646 c
->opcode
= AVC_OPCODE_DSIT
;
648 sl
= fdtv
->type
== FIREDTV_DVB_T
? 0x0c : 0x11;
650 c
->operand
[0] = 0; /* source plug */
651 c
->operand
[1] = 0xd2; /* subfunction replace */
652 c
->operand
[2] = 0xff; /* status */
653 c
->operand
[3] = 0x20; /* system id = DVB */
654 c
->operand
[4] = 0x00; /* antenna number */
655 c
->operand
[5] = 0x0; /* system_specific_search_flags */
656 c
->operand
[6] = sl
; /* system_specific_multiplex selection_length */
658 * operand[7]: valid_flags[0]
659 * operand[8]: valid_flags[1]
660 * operand[7 + sl]: nr_of_dsit_sel_specs (always 0)
662 clear_operands(c
, 7, 24);
664 fdtv
->avc_data_length
= fdtv
->type
== FIREDTV_DVB_T
? 24 : 28;
665 ret
= avc_write(fdtv
);
667 /* FIXME: check response code? */
669 mutex_unlock(&fdtv
->avc_mutex
);
677 int avc_identify_subunit(struct firedtv
*fdtv
)
679 struct avc_command_frame
*c
= (void *)fdtv
->avc_data
;
680 struct avc_response_frame
*r
= (void *)fdtv
->avc_data
;
683 mutex_lock(&fdtv
->avc_mutex
);
685 c
->ctype
= AVC_CTYPE_CONTROL
;
686 c
->subunit
= AVC_SUBUNIT_TYPE_TUNER
| fdtv
->subunit
;
687 c
->opcode
= AVC_OPCODE_READ_DESCRIPTOR
;
689 c
->operand
[0] = DESCRIPTOR_SUBUNIT_IDENTIFIER
;
690 c
->operand
[1] = 0xff;
691 c
->operand
[2] = 0x00;
692 c
->operand
[3] = 0x00; /* length highbyte */
693 c
->operand
[4] = 0x08; /* length lowbyte */
694 c
->operand
[5] = 0x00; /* offset highbyte */
695 c
->operand
[6] = 0x0d; /* offset lowbyte */
696 clear_operands(c
, 7, 8); /* padding */
698 fdtv
->avc_data_length
= 12;
699 ret
= avc_write(fdtv
);
703 if ((r
->response
!= AVC_RESPONSE_STABLE
&&
704 r
->response
!= AVC_RESPONSE_ACCEPTED
) ||
705 (r
->operand
[3] << 8) + r
->operand
[4] != 8) {
706 dev_err(fdtv
->device
, "cannot read subunit identifier\n");
710 mutex_unlock(&fdtv
->avc_mutex
);
715 #define SIZEOF_ANTENNA_INPUT_INFO 22
717 int avc_tuner_status(struct firedtv
*fdtv
, struct firedtv_tuner_status
*stat
)
719 struct avc_command_frame
*c
= (void *)fdtv
->avc_data
;
720 struct avc_response_frame
*r
= (void *)fdtv
->avc_data
;
723 mutex_lock(&fdtv
->avc_mutex
);
725 c
->ctype
= AVC_CTYPE_CONTROL
;
726 c
->subunit
= AVC_SUBUNIT_TYPE_TUNER
| fdtv
->subunit
;
727 c
->opcode
= AVC_OPCODE_READ_DESCRIPTOR
;
729 c
->operand
[0] = DESCRIPTOR_TUNER_STATUS
;
730 c
->operand
[1] = 0xff; /* read_result_status */
732 * operand[2]: reserved
733 * operand[3]: SIZEOF_ANTENNA_INPUT_INFO >> 8
734 * operand[4]: SIZEOF_ANTENNA_INPUT_INFO & 0xff
736 clear_operands(c
, 2, 31);
738 fdtv
->avc_data_length
= 12;
739 ret
= avc_write(fdtv
);
743 if (r
->response
!= AVC_RESPONSE_STABLE
&&
744 r
->response
!= AVC_RESPONSE_ACCEPTED
) {
745 dev_err(fdtv
->device
, "cannot read tuner status\n");
750 length
= r
->operand
[9];
751 if (r
->operand
[1] != 0x10 || length
!= SIZEOF_ANTENNA_INPUT_INFO
) {
752 dev_err(fdtv
->device
, "got invalid tuner status\n");
757 stat
->active_system
= r
->operand
[10];
758 stat
->searching
= r
->operand
[11] >> 7 & 1;
759 stat
->moving
= r
->operand
[11] >> 6 & 1;
760 stat
->no_rf
= r
->operand
[11] >> 5 & 1;
761 stat
->input
= r
->operand
[12] >> 7 & 1;
762 stat
->selected_antenna
= r
->operand
[12] & 0x7f;
763 stat
->ber
= r
->operand
[13] << 24 |
764 r
->operand
[14] << 16 |
765 r
->operand
[15] << 8 |
767 stat
->signal_strength
= r
->operand
[17];
768 stat
->raster_frequency
= r
->operand
[18] >> 6 & 2;
769 stat
->rf_frequency
= (r
->operand
[18] & 0x3f) << 16 |
770 r
->operand
[19] << 8 |
772 stat
->man_dep_info_length
= r
->operand
[21];
773 stat
->front_end_error
= r
->operand
[22] >> 4 & 1;
774 stat
->antenna_error
= r
->operand
[22] >> 3 & 1;
775 stat
->front_end_power_status
= r
->operand
[22] >> 1 & 1;
776 stat
->power_supply
= r
->operand
[22] & 1;
777 stat
->carrier_noise_ratio
= r
->operand
[23] << 8 |
779 stat
->power_supply_voltage
= r
->operand
[27];
780 stat
->antenna_voltage
= r
->operand
[28];
781 stat
->firewire_bus_voltage
= r
->operand
[29];
782 stat
->ca_mmi
= r
->operand
[30] & 1;
783 stat
->ca_pmt_reply
= r
->operand
[31] >> 7 & 1;
784 stat
->ca_date_time_request
= r
->operand
[31] >> 6 & 1;
785 stat
->ca_application_info
= r
->operand
[31] >> 5 & 1;
786 stat
->ca_module_present_status
= r
->operand
[31] >> 4 & 1;
787 stat
->ca_dvb_flag
= r
->operand
[31] >> 3 & 1;
788 stat
->ca_error_flag
= r
->operand
[31] >> 2 & 1;
789 stat
->ca_initialization_status
= r
->operand
[31] >> 1 & 1;
791 mutex_unlock(&fdtv
->avc_mutex
);
796 int avc_lnb_control(struct firedtv
*fdtv
, char voltage
, char burst
,
797 char conttone
, char nrdiseq
,
798 struct dvb_diseqc_master_cmd
*diseqcmd
)
800 struct avc_command_frame
*c
= (void *)fdtv
->avc_data
;
801 struct avc_response_frame
*r
= (void *)fdtv
->avc_data
;
804 mutex_lock(&fdtv
->avc_mutex
);
806 c
->ctype
= AVC_CTYPE_CONTROL
;
807 c
->subunit
= AVC_SUBUNIT_TYPE_TUNER
| fdtv
->subunit
;
808 c
->opcode
= AVC_OPCODE_VENDOR
;
810 c
->operand
[0] = SFE_VENDOR_DE_COMPANYID_0
;
811 c
->operand
[1] = SFE_VENDOR_DE_COMPANYID_1
;
812 c
->operand
[2] = SFE_VENDOR_DE_COMPANYID_2
;
813 c
->operand
[3] = SFE_VENDOR_OPCODE_LNB_CONTROL
;
814 c
->operand
[4] = voltage
;
815 c
->operand
[5] = nrdiseq
;
818 for (j
= 0; j
< nrdiseq
; j
++) {
819 c
->operand
[pos
++] = diseqcmd
[j
].msg_len
;
821 for (k
= 0; k
< diseqcmd
[j
].msg_len
; k
++)
822 c
->operand
[pos
++] = diseqcmd
[j
].msg
[k
];
824 c
->operand
[pos
++] = burst
;
825 c
->operand
[pos
++] = conttone
;
826 pad_operands(c
, pos
);
828 fdtv
->avc_data_length
= ALIGN(3 + pos
, 4);
829 ret
= avc_write(fdtv
);
833 if (r
->response
!= AVC_RESPONSE_ACCEPTED
) {
834 dev_err(fdtv
->device
, "LNB control failed\n");
838 mutex_unlock(&fdtv
->avc_mutex
);
843 int avc_register_remote_control(struct firedtv
*fdtv
)
845 struct avc_command_frame
*c
= (void *)fdtv
->avc_data
;
848 mutex_lock(&fdtv
->avc_mutex
);
850 c
->ctype
= AVC_CTYPE_NOTIFY
;
851 c
->subunit
= AVC_SUBUNIT_TYPE_UNIT
| 7;
852 c
->opcode
= AVC_OPCODE_VENDOR
;
854 c
->operand
[0] = SFE_VENDOR_DE_COMPANYID_0
;
855 c
->operand
[1] = SFE_VENDOR_DE_COMPANYID_1
;
856 c
->operand
[2] = SFE_VENDOR_DE_COMPANYID_2
;
857 c
->operand
[3] = SFE_VENDOR_OPCODE_REGISTER_REMOTE_CONTROL
;
858 c
->operand
[4] = 0; /* padding */
860 fdtv
->avc_data_length
= 8;
861 ret
= avc_write(fdtv
);
863 /* FIXME: check response code? */
865 mutex_unlock(&fdtv
->avc_mutex
);
870 void avc_remote_ctrl_work(struct work_struct
*work
)
872 struct firedtv
*fdtv
=
873 container_of(work
, struct firedtv
, remote_ctrl_work
);
875 /* Should it be rescheduled in failure cases? */
876 avc_register_remote_control(fdtv
);
879 #if 0 /* FIXME: unused */
880 int avc_tuner_host2ca(struct firedtv
*fdtv
)
882 struct avc_command_frame
*c
= (void *)fdtv
->avc_data
;
885 mutex_lock(&fdtv
->avc_mutex
);
887 c
->ctype
= AVC_CTYPE_CONTROL
;
888 c
->subunit
= AVC_SUBUNIT_TYPE_TUNER
| fdtv
->subunit
;
889 c
->opcode
= AVC_OPCODE_VENDOR
;
891 c
->operand
[0] = SFE_VENDOR_DE_COMPANYID_0
;
892 c
->operand
[1] = SFE_VENDOR_DE_COMPANYID_1
;
893 c
->operand
[2] = SFE_VENDOR_DE_COMPANYID_2
;
894 c
->operand
[3] = SFE_VENDOR_OPCODE_HOST2CA
;
895 c
->operand
[4] = 0; /* slot */
896 c
->operand
[5] = SFE_VENDOR_TAG_CA_APPLICATION_INFO
; /* ca tag */
897 clear_operands(c
, 6, 8);
899 fdtv
->avc_data_length
= 12;
900 ret
= avc_write(fdtv
);
902 /* FIXME: check response code? */
904 mutex_unlock(&fdtv
->avc_mutex
);
910 static int get_ca_object_pos(struct avc_response_frame
*r
)
914 /* Check length of length field */
915 if (r
->operand
[7] & 0x80)
916 length
= (r
->operand
[7] & 0x7f) + 1;
920 static int get_ca_object_length(struct avc_response_frame
*r
)
922 #if 0 /* FIXME: unused */
926 if (r
->operand
[7] & 0x80)
927 for (i
= 0; i
< (r
->operand
[7] & 0x7f); i
++) {
929 size
+= r
->operand
[8 + i
];
932 return r
->operand
[7];
935 int avc_ca_app_info(struct firedtv
*fdtv
, char *app_info
, unsigned int *len
)
937 struct avc_command_frame
*c
= (void *)fdtv
->avc_data
;
938 struct avc_response_frame
*r
= (void *)fdtv
->avc_data
;
941 mutex_lock(&fdtv
->avc_mutex
);
943 c
->ctype
= AVC_CTYPE_STATUS
;
944 c
->subunit
= AVC_SUBUNIT_TYPE_TUNER
| fdtv
->subunit
;
945 c
->opcode
= AVC_OPCODE_VENDOR
;
947 c
->operand
[0] = SFE_VENDOR_DE_COMPANYID_0
;
948 c
->operand
[1] = SFE_VENDOR_DE_COMPANYID_1
;
949 c
->operand
[2] = SFE_VENDOR_DE_COMPANYID_2
;
950 c
->operand
[3] = SFE_VENDOR_OPCODE_CA2HOST
;
951 c
->operand
[4] = 0; /* slot */
952 c
->operand
[5] = SFE_VENDOR_TAG_CA_APPLICATION_INFO
; /* ca tag */
953 clear_operands(c
, 6, LAST_OPERAND
);
955 fdtv
->avc_data_length
= 12;
956 ret
= avc_write(fdtv
);
960 /* FIXME: check response code and validate response data */
962 pos
= get_ca_object_pos(r
);
963 app_info
[0] = (EN50221_TAG_APP_INFO
>> 16) & 0xff;
964 app_info
[1] = (EN50221_TAG_APP_INFO
>> 8) & 0xff;
965 app_info
[2] = (EN50221_TAG_APP_INFO
>> 0) & 0xff;
966 app_info
[3] = 6 + r
->operand
[pos
+ 4];
968 memcpy(&app_info
[5], &r
->operand
[pos
], 5 + r
->operand
[pos
+ 4]);
969 *len
= app_info
[3] + 4;
971 mutex_unlock(&fdtv
->avc_mutex
);
976 int avc_ca_info(struct firedtv
*fdtv
, char *app_info
, unsigned int *len
)
978 struct avc_command_frame
*c
= (void *)fdtv
->avc_data
;
979 struct avc_response_frame
*r
= (void *)fdtv
->avc_data
;
982 mutex_lock(&fdtv
->avc_mutex
);
984 c
->ctype
= AVC_CTYPE_STATUS
;
985 c
->subunit
= AVC_SUBUNIT_TYPE_TUNER
| fdtv
->subunit
;
986 c
->opcode
= AVC_OPCODE_VENDOR
;
988 c
->operand
[0] = SFE_VENDOR_DE_COMPANYID_0
;
989 c
->operand
[1] = SFE_VENDOR_DE_COMPANYID_1
;
990 c
->operand
[2] = SFE_VENDOR_DE_COMPANYID_2
;
991 c
->operand
[3] = SFE_VENDOR_OPCODE_CA2HOST
;
992 c
->operand
[4] = 0; /* slot */
993 c
->operand
[5] = SFE_VENDOR_TAG_CA_APPLICATION_INFO
; /* ca tag */
994 clear_operands(c
, 6, LAST_OPERAND
);
996 fdtv
->avc_data_length
= 12;
997 ret
= avc_write(fdtv
);
1001 /* FIXME: check response code and validate response data */
1003 pos
= get_ca_object_pos(r
);
1004 app_info
[0] = (EN50221_TAG_CA_INFO
>> 16) & 0xff;
1005 app_info
[1] = (EN50221_TAG_CA_INFO
>> 8) & 0xff;
1006 app_info
[2] = (EN50221_TAG_CA_INFO
>> 0) & 0xff;
1008 app_info
[4] = r
->operand
[pos
+ 0];
1009 app_info
[5] = r
->operand
[pos
+ 1];
1010 *len
= app_info
[3] + 4;
1012 mutex_unlock(&fdtv
->avc_mutex
);
1017 int avc_ca_reset(struct firedtv
*fdtv
)
1019 struct avc_command_frame
*c
= (void *)fdtv
->avc_data
;
1022 mutex_lock(&fdtv
->avc_mutex
);
1024 c
->ctype
= AVC_CTYPE_CONTROL
;
1025 c
->subunit
= AVC_SUBUNIT_TYPE_TUNER
| fdtv
->subunit
;
1026 c
->opcode
= AVC_OPCODE_VENDOR
;
1028 c
->operand
[0] = SFE_VENDOR_DE_COMPANYID_0
;
1029 c
->operand
[1] = SFE_VENDOR_DE_COMPANYID_1
;
1030 c
->operand
[2] = SFE_VENDOR_DE_COMPANYID_2
;
1031 c
->operand
[3] = SFE_VENDOR_OPCODE_HOST2CA
;
1032 c
->operand
[4] = 0; /* slot */
1033 c
->operand
[5] = SFE_VENDOR_TAG_CA_RESET
; /* ca tag */
1034 c
->operand
[6] = 0; /* more/last */
1035 c
->operand
[7] = 1; /* length */
1036 c
->operand
[8] = 0; /* force hardware reset */
1038 fdtv
->avc_data_length
= 12;
1039 ret
= avc_write(fdtv
);
1041 /* FIXME: check response code? */
1043 mutex_unlock(&fdtv
->avc_mutex
);
1048 int avc_ca_pmt(struct firedtv
*fdtv
, char *msg
, int length
)
1050 struct avc_command_frame
*c
= (void *)fdtv
->avc_data
;
1051 struct avc_response_frame
*r
= (void *)fdtv
->avc_data
;
1052 int list_management
;
1053 int program_info_length
;
1061 if (unlikely(avc_debug
& AVC_DEBUG_APPLICATION_PMT
))
1062 debug_pmt(msg
, length
);
1064 mutex_lock(&fdtv
->avc_mutex
);
1066 c
->ctype
= AVC_CTYPE_CONTROL
;
1067 c
->subunit
= AVC_SUBUNIT_TYPE_TUNER
| fdtv
->subunit
;
1068 c
->opcode
= AVC_OPCODE_VENDOR
;
1070 if (msg
[0] != EN50221_LIST_MANAGEMENT_ONLY
) {
1071 dev_info(fdtv
->device
, "forcing list_management to ONLY\n");
1072 msg
[0] = EN50221_LIST_MANAGEMENT_ONLY
;
1074 /* We take the cmd_id from the programme level only! */
1075 list_management
= msg
[0];
1076 program_info_length
= ((msg
[4] & 0x0f) << 8) + msg
[5];
1077 if (program_info_length
> 0)
1078 program_info_length
--; /* Remove pmt_cmd_id */
1079 pmt_cmd_id
= msg
[6];
1081 c
->operand
[0] = SFE_VENDOR_DE_COMPANYID_0
;
1082 c
->operand
[1] = SFE_VENDOR_DE_COMPANYID_1
;
1083 c
->operand
[2] = SFE_VENDOR_DE_COMPANYID_2
;
1084 c
->operand
[3] = SFE_VENDOR_OPCODE_HOST2CA
;
1085 c
->operand
[4] = 0; /* slot */
1086 c
->operand
[5] = SFE_VENDOR_TAG_CA_PMT
; /* ca tag */
1087 c
->operand
[6] = 0; /* more/last */
1088 /* Use three bytes for length field in case length > 127 */
1089 c
->operand
[10] = list_management
;
1090 c
->operand
[11] = 0x01; /* pmt_cmd=OK_descramble */
1092 /* TS program map table */
1094 c
->operand
[12] = 0x02; /* Table id=2 */
1095 c
->operand
[13] = 0x80; /* Section syntax + length */
1097 c
->operand
[15] = msg
[1]; /* Program number */
1098 c
->operand
[16] = msg
[2];
1099 c
->operand
[17] = 0x01; /* Version number=0 + current/next=1 */
1100 c
->operand
[18] = 0x00; /* Section number=0 */
1101 c
->operand
[19] = 0x00; /* Last section number=0 */
1102 c
->operand
[20] = 0x1f; /* PCR_PID=1FFF */
1103 c
->operand
[21] = 0xff;
1104 c
->operand
[22] = (program_info_length
>> 8); /* Program info length */
1105 c
->operand
[23] = (program_info_length
& 0xff);
1107 /* CA descriptors at programme level */
1110 if (program_info_length
> 0) {
1111 pmt_cmd_id
= msg
[read_pos
++];
1112 if (pmt_cmd_id
!= 1 && pmt_cmd_id
!= 4)
1113 dev_err(fdtv
->device
,
1114 "invalid pmt_cmd_id %d\n", pmt_cmd_id
);
1116 memcpy(&c
->operand
[write_pos
], &msg
[read_pos
],
1117 program_info_length
);
1118 read_pos
+= program_info_length
;
1119 write_pos
+= program_info_length
;
1121 while (read_pos
< length
) {
1122 c
->operand
[write_pos
++] = msg
[read_pos
++];
1123 c
->operand
[write_pos
++] = msg
[read_pos
++];
1124 c
->operand
[write_pos
++] = msg
[read_pos
++];
1126 ((msg
[read_pos
] & 0x0f) << 8) + msg
[read_pos
+ 1];
1128 if (es_info_length
> 0)
1129 es_info_length
--; /* Remove pmt_cmd_id */
1130 c
->operand
[write_pos
++] = es_info_length
>> 8;
1131 c
->operand
[write_pos
++] = es_info_length
& 0xff;
1132 if (es_info_length
> 0) {
1133 pmt_cmd_id
= msg
[read_pos
++];
1134 if (pmt_cmd_id
!= 1 && pmt_cmd_id
!= 4)
1135 dev_err(fdtv
->device
, "invalid pmt_cmd_id %d "
1136 "at stream level\n", pmt_cmd_id
);
1138 memcpy(&c
->operand
[write_pos
], &msg
[read_pos
],
1140 read_pos
+= es_info_length
;
1141 write_pos
+= es_info_length
;
1144 write_pos
+= 4; /* CRC */
1146 c
->operand
[7] = 0x82;
1147 c
->operand
[8] = (write_pos
- 10) >> 8;
1148 c
->operand
[9] = (write_pos
- 10) & 0xff;
1149 c
->operand
[14] = write_pos
- 15;
1151 crc32_csum
= crc32_be(0, &c
->operand
[10], c
->operand
[12] - 1);
1152 c
->operand
[write_pos
- 4] = (crc32_csum
>> 24) & 0xff;
1153 c
->operand
[write_pos
- 3] = (crc32_csum
>> 16) & 0xff;
1154 c
->operand
[write_pos
- 2] = (crc32_csum
>> 8) & 0xff;
1155 c
->operand
[write_pos
- 1] = (crc32_csum
>> 0) & 0xff;
1156 pad_operands(c
, write_pos
);
1158 fdtv
->avc_data_length
= ALIGN(3 + write_pos
, 4);
1159 ret
= avc_write(fdtv
);
1163 if (r
->response
!= AVC_RESPONSE_ACCEPTED
) {
1164 dev_err(fdtv
->device
,
1165 "CA PMT failed with response 0x%x\n", r
->response
);
1169 mutex_unlock(&fdtv
->avc_mutex
);
1174 int avc_ca_get_time_date(struct firedtv
*fdtv
, int *interval
)
1176 struct avc_command_frame
*c
= (void *)fdtv
->avc_data
;
1177 struct avc_response_frame
*r
= (void *)fdtv
->avc_data
;
1180 mutex_lock(&fdtv
->avc_mutex
);
1182 c
->ctype
= AVC_CTYPE_STATUS
;
1183 c
->subunit
= AVC_SUBUNIT_TYPE_TUNER
| fdtv
->subunit
;
1184 c
->opcode
= AVC_OPCODE_VENDOR
;
1186 c
->operand
[0] = SFE_VENDOR_DE_COMPANYID_0
;
1187 c
->operand
[1] = SFE_VENDOR_DE_COMPANYID_1
;
1188 c
->operand
[2] = SFE_VENDOR_DE_COMPANYID_2
;
1189 c
->operand
[3] = SFE_VENDOR_OPCODE_CA2HOST
;
1190 c
->operand
[4] = 0; /* slot */
1191 c
->operand
[5] = SFE_VENDOR_TAG_CA_DATE_TIME
; /* ca tag */
1192 clear_operands(c
, 6, LAST_OPERAND
);
1194 fdtv
->avc_data_length
= 12;
1195 ret
= avc_write(fdtv
);
1199 /* FIXME: check response code and validate response data */
1201 *interval
= r
->operand
[get_ca_object_pos(r
)];
1203 mutex_unlock(&fdtv
->avc_mutex
);
1208 int avc_ca_enter_menu(struct firedtv
*fdtv
)
1210 struct avc_command_frame
*c
= (void *)fdtv
->avc_data
;
1213 mutex_lock(&fdtv
->avc_mutex
);
1215 c
->ctype
= AVC_CTYPE_STATUS
;
1216 c
->subunit
= AVC_SUBUNIT_TYPE_TUNER
| fdtv
->subunit
;
1217 c
->opcode
= AVC_OPCODE_VENDOR
;
1219 c
->operand
[0] = SFE_VENDOR_DE_COMPANYID_0
;
1220 c
->operand
[1] = SFE_VENDOR_DE_COMPANYID_1
;
1221 c
->operand
[2] = SFE_VENDOR_DE_COMPANYID_2
;
1222 c
->operand
[3] = SFE_VENDOR_OPCODE_HOST2CA
;
1223 c
->operand
[4] = 0; /* slot */
1224 c
->operand
[5] = SFE_VENDOR_TAG_CA_ENTER_MENU
;
1225 clear_operands(c
, 6, 8);
1227 fdtv
->avc_data_length
= 12;
1228 ret
= avc_write(fdtv
);
1230 /* FIXME: check response code? */
1232 mutex_unlock(&fdtv
->avc_mutex
);
1237 int avc_ca_get_mmi(struct firedtv
*fdtv
, char *mmi_object
, unsigned int *len
)
1239 struct avc_command_frame
*c
= (void *)fdtv
->avc_data
;
1240 struct avc_response_frame
*r
= (void *)fdtv
->avc_data
;
1243 mutex_lock(&fdtv
->avc_mutex
);
1245 c
->ctype
= AVC_CTYPE_STATUS
;
1246 c
->subunit
= AVC_SUBUNIT_TYPE_TUNER
| fdtv
->subunit
;
1247 c
->opcode
= AVC_OPCODE_VENDOR
;
1249 c
->operand
[0] = SFE_VENDOR_DE_COMPANYID_0
;
1250 c
->operand
[1] = SFE_VENDOR_DE_COMPANYID_1
;
1251 c
->operand
[2] = SFE_VENDOR_DE_COMPANYID_2
;
1252 c
->operand
[3] = SFE_VENDOR_OPCODE_CA2HOST
;
1253 c
->operand
[4] = 0; /* slot */
1254 c
->operand
[5] = SFE_VENDOR_TAG_CA_MMI
;
1255 clear_operands(c
, 6, LAST_OPERAND
);
1257 fdtv
->avc_data_length
= 12;
1258 ret
= avc_write(fdtv
);
1262 /* FIXME: check response code and validate response data */
1264 *len
= get_ca_object_length(r
);
1265 memcpy(mmi_object
, &r
->operand
[get_ca_object_pos(r
)], *len
);
1267 mutex_unlock(&fdtv
->avc_mutex
);
1272 #define CMP_OUTPUT_PLUG_CONTROL_REG_0 0xfffff0000904ULL
1274 static int cmp_read(struct firedtv
*fdtv
, u64 addr
, __be32
*data
)
1278 mutex_lock(&fdtv
->avc_mutex
);
1280 ret
= fdtv
->backend
->read(fdtv
, addr
, data
);
1282 dev_err(fdtv
->device
, "CMP: read I/O error\n");
1284 mutex_unlock(&fdtv
->avc_mutex
);
1289 static int cmp_lock(struct firedtv
*fdtv
, u64 addr
, __be32 data
[])
1293 mutex_lock(&fdtv
->avc_mutex
);
1295 /* data[] is stack-allocated and should not be DMA-mapped. */
1296 memcpy(fdtv
->avc_data
, data
, 8);
1298 ret
= fdtv
->backend
->lock(fdtv
, addr
, fdtv
->avc_data
);
1300 dev_err(fdtv
->device
, "CMP: lock I/O error\n");
1302 memcpy(data
, fdtv
->avc_data
, 8);
1304 mutex_unlock(&fdtv
->avc_mutex
);
1309 static inline u32
get_opcr(__be32 opcr
, u32 mask
, u32 shift
)
1311 return (be32_to_cpu(opcr
) >> shift
) & mask
;
1314 static inline void set_opcr(__be32
*opcr
, u32 value
, u32 mask
, u32 shift
)
1316 *opcr
&= ~cpu_to_be32(mask
<< shift
);
1317 *opcr
|= cpu_to_be32((value
& mask
) << shift
);
1320 #define get_opcr_online(v) get_opcr((v), 0x1, 31)
1321 #define get_opcr_p2p_connections(v) get_opcr((v), 0x3f, 24)
1322 #define get_opcr_channel(v) get_opcr((v), 0x3f, 16)
1324 #define set_opcr_p2p_connections(p, v) set_opcr((p), (v), 0x3f, 24)
1325 #define set_opcr_channel(p, v) set_opcr((p), (v), 0x3f, 16)
1326 #define set_opcr_data_rate(p, v) set_opcr((p), (v), 0x3, 14)
1327 #define set_opcr_overhead_id(p, v) set_opcr((p), (v), 0xf, 10)
1329 int cmp_establish_pp_connection(struct firedtv
*fdtv
, int plug
, int channel
)
1331 __be32 old_opcr
, opcr
[2];
1332 u64 opcr_address
= CMP_OUTPUT_PLUG_CONTROL_REG_0
+ (plug
<< 2);
1336 ret
= cmp_read(fdtv
, opcr_address
, opcr
);
1341 if (!get_opcr_online(*opcr
)) {
1342 dev_err(fdtv
->device
, "CMP: output offline\n");
1348 if (get_opcr_p2p_connections(*opcr
)) {
1349 if (get_opcr_channel(*opcr
) != channel
) {
1350 dev_err(fdtv
->device
, "CMP: cannot change channel\n");
1353 dev_info(fdtv
->device
, "CMP: overlaying connection\n");
1355 /* We don't allocate isochronous resources. */
1357 set_opcr_channel(opcr
, channel
);
1358 set_opcr_data_rate(opcr
, 2); /* S400 */
1360 /* FIXME: this is for the worst case - optimize */
1361 set_opcr_overhead_id(opcr
, 0);
1364 * FIXME: allocate isochronous channel and bandwidth at IRM
1365 * fdtv->backend->alloc_resources(fdtv, channels_mask, bw);
1369 set_opcr_p2p_connections(opcr
, get_opcr_p2p_connections(*opcr
) + 1);
1374 ret
= cmp_lock(fdtv
, opcr_address
, opcr
);
1378 if (old_opcr
!= *opcr
) {
1380 * FIXME: if old_opcr.P2P_Connections > 0,
1381 * deallocate isochronous channel and bandwidth at IRM
1383 * fdtv->backend->dealloc_resources(fdtv, channel, bw);
1386 if (++attempts
< 6) /* arbitrary limit */
1394 void cmp_break_pp_connection(struct firedtv
*fdtv
, int plug
, int channel
)
1396 __be32 old_opcr
, opcr
[2];
1397 u64 opcr_address
= CMP_OUTPUT_PLUG_CONTROL_REG_0
+ (plug
<< 2);
1400 if (cmp_read(fdtv
, opcr_address
, opcr
) < 0)
1404 if (!get_opcr_online(*opcr
) || !get_opcr_p2p_connections(*opcr
) ||
1405 get_opcr_channel(*opcr
) != channel
) {
1406 dev_err(fdtv
->device
, "CMP: no connection to break\n");
1411 set_opcr_p2p_connections(opcr
, get_opcr_p2p_connections(*opcr
) - 1);
1416 if (cmp_lock(fdtv
, opcr_address
, opcr
) < 0)
1419 if (old_opcr
!= *opcr
) {
1421 * FIXME: if old_opcr.P2P_Connections == 1, i.e. we were last
1422 * owner, deallocate isochronous channel and bandwidth at IRM
1424 * fdtv->backend->dealloc_resources(fdtv, channel, bw);
1427 if (++attempts
< 6) /* arbitrary limit */