Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  * FireDTV driver (formerly known as FireSAT)
0004  *
0005  * Copyright (C) 2004 Andreas Monitzer <andy@monitzer.com>
0006  * Copyright (C) 2008 Ben Backx <ben@bbackx.com>
0007  * Copyright (C) 2008 Henrik Kurelid <henrik@kurelid.se>
0008  */
0009 
0010 #include <linux/bug.h>
0011 #include <linux/crc32.h>
0012 #include <linux/delay.h>
0013 #include <linux/device.h>
0014 #include <linux/jiffies.h>
0015 #include <linux/kernel.h>
0016 #include <linux/moduleparam.h>
0017 #include <linux/mutex.h>
0018 #include <linux/string.h>
0019 #include <linux/stringify.h>
0020 #include <linux/wait.h>
0021 #include <linux/workqueue.h>
0022 
0023 #include <media/dvb_frontend.h>
0024 
0025 #include "firedtv.h"
0026 
0027 #define FCP_COMMAND_REGISTER        0xfffff0000b00ULL
0028 
0029 #define AVC_CTYPE_CONTROL       0x0
0030 #define AVC_CTYPE_STATUS        0x1
0031 #define AVC_CTYPE_NOTIFY        0x3
0032 
0033 #define AVC_RESPONSE_ACCEPTED       0x9
0034 #define AVC_RESPONSE_STABLE     0xc
0035 #define AVC_RESPONSE_CHANGED        0xd
0036 #define AVC_RESPONSE_INTERIM        0xf
0037 
0038 #define AVC_SUBUNIT_TYPE_TUNER      (0x05 << 3)
0039 #define AVC_SUBUNIT_TYPE_UNIT       (0x1f << 3)
0040 
0041 #define AVC_OPCODE_VENDOR       0x00
0042 #define AVC_OPCODE_READ_DESCRIPTOR  0x09
0043 #define AVC_OPCODE_DSIT         0xc8
0044 #define AVC_OPCODE_DSD          0xcb
0045 
0046 #define DESCRIPTOR_TUNER_STATUS     0x80
0047 #define DESCRIPTOR_SUBUNIT_IDENTIFIER   0x00
0048 
0049 #define SFE_VENDOR_DE_COMPANYID_0   0x00 /* OUI of Digital Everywhere */
0050 #define SFE_VENDOR_DE_COMPANYID_1   0x12
0051 #define SFE_VENDOR_DE_COMPANYID_2   0x87
0052 
0053 #define SFE_VENDOR_OPCODE_REGISTER_REMOTE_CONTROL 0x0a
0054 #define SFE_VENDOR_OPCODE_LNB_CONTROL       0x52
0055 #define SFE_VENDOR_OPCODE_TUNE_QPSK     0x58 /* for DVB-S */
0056 
0057 #define SFE_VENDOR_OPCODE_GET_FIRMWARE_VERSION  0x00
0058 #define SFE_VENDOR_OPCODE_HOST2CA       0x56
0059 #define SFE_VENDOR_OPCODE_CA2HOST       0x57
0060 #define SFE_VENDOR_OPCODE_CISTATUS      0x59
0061 #define SFE_VENDOR_OPCODE_TUNE_QPSK2        0x60 /* for DVB-S2 */
0062 
0063 #define SFE_VENDOR_TAG_CA_RESET         0x00
0064 #define SFE_VENDOR_TAG_CA_APPLICATION_INFO  0x01
0065 #define SFE_VENDOR_TAG_CA_PMT           0x02
0066 #define SFE_VENDOR_TAG_CA_DATE_TIME     0x04
0067 #define SFE_VENDOR_TAG_CA_MMI           0x05
0068 #define SFE_VENDOR_TAG_CA_ENTER_MENU        0x07
0069 
0070 #define EN50221_LIST_MANAGEMENT_ONLY    0x03
0071 #define EN50221_TAG_APP_INFO        0x9f8021
0072 #define EN50221_TAG_CA_INFO     0x9f8031
0073 
0074 struct avc_command_frame {
0075     u8 ctype;
0076     u8 subunit;
0077     u8 opcode;
0078     u8 operand[509];
0079 };
0080 
0081 struct avc_response_frame {
0082     u8 response;
0083     u8 subunit;
0084     u8 opcode;
0085     u8 operand[509];
0086 };
0087 
0088 #define LAST_OPERAND (509 - 1)
0089 
0090 static inline void clear_operands(struct avc_command_frame *c, int from, int to)
0091 {
0092     memset(&c->operand[from], 0, to - from + 1);
0093 }
0094 
0095 static void pad_operands(struct avc_command_frame *c, int from)
0096 {
0097     int to = ALIGN(from, 4);
0098 
0099     if (from <= to && to <= LAST_OPERAND)
0100         clear_operands(c, from, to);
0101 }
0102 
0103 #define AVC_DEBUG_READ_DESCRIPTOR              0x0001
0104 #define AVC_DEBUG_DSIT                         0x0002
0105 #define AVC_DEBUG_DSD                          0x0004
0106 #define AVC_DEBUG_REGISTER_REMOTE_CONTROL      0x0008
0107 #define AVC_DEBUG_LNB_CONTROL                  0x0010
0108 #define AVC_DEBUG_TUNE_QPSK                    0x0020
0109 #define AVC_DEBUG_TUNE_QPSK2                   0x0040
0110 #define AVC_DEBUG_HOST2CA                      0x0080
0111 #define AVC_DEBUG_CA2HOST                      0x0100
0112 #define AVC_DEBUG_APPLICATION_PMT              0x4000
0113 #define AVC_DEBUG_FCP_PAYLOADS                 0x8000
0114 
0115 static int avc_debug;
0116 module_param_named(debug, avc_debug, int, 0644);
0117 MODULE_PARM_DESC(debug, "Verbose logging (none = 0"
0118     ", FCP subactions"
0119     ": READ DESCRIPTOR = "      __stringify(AVC_DEBUG_READ_DESCRIPTOR)
0120     ", DSIT = "         __stringify(AVC_DEBUG_DSIT)
0121     ", REGISTER_REMOTE_CONTROL = "  __stringify(AVC_DEBUG_REGISTER_REMOTE_CONTROL)
0122     ", LNB CONTROL = "      __stringify(AVC_DEBUG_LNB_CONTROL)
0123     ", TUNE QPSK = "        __stringify(AVC_DEBUG_TUNE_QPSK)
0124     ", TUNE QPSK2 = "       __stringify(AVC_DEBUG_TUNE_QPSK2)
0125     ", HOST2CA = "          __stringify(AVC_DEBUG_HOST2CA)
0126     ", CA2HOST = "          __stringify(AVC_DEBUG_CA2HOST)
0127     "; Application sent PMT = " __stringify(AVC_DEBUG_APPLICATION_PMT)
0128     ", FCP payloads = "     __stringify(AVC_DEBUG_FCP_PAYLOADS)
0129     ", or a combination, or all = -1)");
0130 
0131 /*
0132  * This is a workaround since there is no vendor specific command to retrieve
0133  * ca_info using AVC. If this parameter is not used, ca_system_id will be
0134  * filled with application_manufacturer from ca_app_info.
0135  * Digital Everywhere have said that adding ca_info is on their TODO list.
0136  */
0137 static unsigned int num_fake_ca_system_ids;
0138 static int fake_ca_system_ids[4] = { -1, -1, -1, -1 };
0139 module_param_array(fake_ca_system_ids, int, &num_fake_ca_system_ids, 0644);
0140 MODULE_PARM_DESC(fake_ca_system_ids, "If your CAM application manufacturer "
0141          "does not have the same ca_system_id as your CAS, you can "
0142          "override what ca_system_ids are presented to the "
0143          "application by setting this field to an array of ids.");
0144 
0145 static const char *debug_fcp_ctype(unsigned int ctype)
0146 {
0147     static const char *ctypes[] = {
0148         [0x0] = "CONTROL",      [0x1] = "STATUS",
0149         [0x2] = "SPECIFIC INQUIRY", [0x3] = "NOTIFY",
0150         [0x4] = "GENERAL INQUIRY",  [0x8] = "NOT IMPLEMENTED",
0151         [0x9] = "ACCEPTED",     [0xa] = "REJECTED",
0152         [0xb] = "IN TRANSITION",    [0xc] = "IMPLEMENTED/STABLE",
0153         [0xd] = "CHANGED",      [0xf] = "INTERIM",
0154     };
0155     const char *ret = ctype < ARRAY_SIZE(ctypes) ? ctypes[ctype] : NULL;
0156 
0157     return ret ? ret : "?";
0158 }
0159 
0160 static const char *debug_fcp_opcode(unsigned int opcode,
0161                     const u8 *data, int length)
0162 {
0163     switch (opcode) {
0164     case AVC_OPCODE_VENDOR:
0165         break;
0166     case AVC_OPCODE_READ_DESCRIPTOR:
0167         return avc_debug & AVC_DEBUG_READ_DESCRIPTOR ?
0168                 "ReadDescriptor" : NULL;
0169     case AVC_OPCODE_DSIT:
0170         return avc_debug & AVC_DEBUG_DSIT ?
0171                 "DirectSelectInfo.Type" : NULL;
0172     case AVC_OPCODE_DSD:
0173         return avc_debug & AVC_DEBUG_DSD ? "DirectSelectData" : NULL;
0174     default:
0175         return "Unknown";
0176     }
0177 
0178     if (length < 7 ||
0179         data[3] != SFE_VENDOR_DE_COMPANYID_0 ||
0180         data[4] != SFE_VENDOR_DE_COMPANYID_1 ||
0181         data[5] != SFE_VENDOR_DE_COMPANYID_2)
0182         return "Vendor/Unknown";
0183 
0184     switch (data[6]) {
0185     case SFE_VENDOR_OPCODE_REGISTER_REMOTE_CONTROL:
0186         return avc_debug & AVC_DEBUG_REGISTER_REMOTE_CONTROL ?
0187                 "RegisterRC" : NULL;
0188     case SFE_VENDOR_OPCODE_LNB_CONTROL:
0189         return avc_debug & AVC_DEBUG_LNB_CONTROL ? "LNBControl" : NULL;
0190     case SFE_VENDOR_OPCODE_TUNE_QPSK:
0191         return avc_debug & AVC_DEBUG_TUNE_QPSK ? "TuneQPSK" : NULL;
0192     case SFE_VENDOR_OPCODE_TUNE_QPSK2:
0193         return avc_debug & AVC_DEBUG_TUNE_QPSK2 ? "TuneQPSK2" : NULL;
0194     case SFE_VENDOR_OPCODE_HOST2CA:
0195         return avc_debug & AVC_DEBUG_HOST2CA ? "Host2CA" : NULL;
0196     case SFE_VENDOR_OPCODE_CA2HOST:
0197         return avc_debug & AVC_DEBUG_CA2HOST ? "CA2Host" : NULL;
0198     }
0199     return "Vendor/Unknown";
0200 }
0201 
0202 static void debug_fcp(const u8 *data, int length)
0203 {
0204     unsigned int subunit_type, subunit_id, opcode;
0205     const char *op, *prefix;
0206 
0207     prefix       = data[0] > 7 ? "FCP <- " : "FCP -> ";
0208     subunit_type = data[1] >> 3;
0209     subunit_id   = data[1] & 7;
0210     opcode       = subunit_type == 0x1e || subunit_id == 5 ? ~0 : data[2];
0211     op           = debug_fcp_opcode(opcode, data, length);
0212 
0213     if (op) {
0214         printk(KERN_INFO "%ssu=%x.%x l=%d: %-8s - %s\n",
0215                prefix, subunit_type, subunit_id, length,
0216                debug_fcp_ctype(data[0]), op);
0217         if (avc_debug & AVC_DEBUG_FCP_PAYLOADS)
0218             print_hex_dump(KERN_INFO, prefix, DUMP_PREFIX_NONE,
0219                        16, 1, data, length, false);
0220     }
0221 }
0222 
0223 static void debug_pmt(char *msg, int length)
0224 {
0225     printk(KERN_INFO "APP PMT -> l=%d\n", length);
0226     print_hex_dump(KERN_INFO, "APP PMT -> ", DUMP_PREFIX_NONE,
0227                16, 1, msg, length, false);
0228 }
0229 
0230 static int avc_write(struct firedtv *fdtv)
0231 {
0232     int err, retry;
0233 
0234     fdtv->avc_reply_received = false;
0235 
0236     for (retry = 0; retry < 6; retry++) {
0237         if (unlikely(avc_debug))
0238             debug_fcp(fdtv->avc_data, fdtv->avc_data_length);
0239 
0240         err = fdtv_write(fdtv, FCP_COMMAND_REGISTER,
0241                  fdtv->avc_data, fdtv->avc_data_length);
0242         if (err) {
0243             dev_err(fdtv->device, "FCP command write failed\n");
0244 
0245             return err;
0246         }
0247 
0248         /*
0249          * AV/C specs say that answers should be sent within 150 ms.
0250          * Time out after 200 ms.
0251          */
0252         if (wait_event_timeout(fdtv->avc_wait,
0253                        fdtv->avc_reply_received,
0254                        msecs_to_jiffies(200)) != 0)
0255             return 0;
0256     }
0257     dev_err(fdtv->device, "FCP response timed out\n");
0258 
0259     return -ETIMEDOUT;
0260 }
0261 
0262 static bool is_register_rc(struct avc_response_frame *r)
0263 {
0264     return r->opcode     == AVC_OPCODE_VENDOR &&
0265            r->operand[0] == SFE_VENDOR_DE_COMPANYID_0 &&
0266            r->operand[1] == SFE_VENDOR_DE_COMPANYID_1 &&
0267            r->operand[2] == SFE_VENDOR_DE_COMPANYID_2 &&
0268            r->operand[3] == SFE_VENDOR_OPCODE_REGISTER_REMOTE_CONTROL;
0269 }
0270 
0271 int avc_recv(struct firedtv *fdtv, void *data, size_t length)
0272 {
0273     struct avc_response_frame *r = data;
0274 
0275     if (unlikely(avc_debug))
0276         debug_fcp(data, length);
0277 
0278     if (length >= 8 && is_register_rc(r)) {
0279         switch (r->response) {
0280         case AVC_RESPONSE_CHANGED:
0281             fdtv_handle_rc(fdtv, r->operand[4] << 8 | r->operand[5]);
0282             schedule_work(&fdtv->remote_ctrl_work);
0283             break;
0284         case AVC_RESPONSE_INTERIM:
0285             if (is_register_rc((void *)fdtv->avc_data))
0286                 goto wake;
0287             break;
0288         default:
0289             dev_info(fdtv->device,
0290                  "remote control result = %d\n", r->response);
0291         }
0292         return 0;
0293     }
0294 
0295     if (fdtv->avc_reply_received) {
0296         dev_err(fdtv->device, "out-of-order AVC response, ignored\n");
0297         return -EIO;
0298     }
0299 
0300     memcpy(fdtv->avc_data, data, length);
0301     fdtv->avc_data_length = length;
0302 wake:
0303     fdtv->avc_reply_received = true;
0304     wake_up(&fdtv->avc_wait);
0305 
0306     return 0;
0307 }
0308 
0309 static int add_pid_filter(struct firedtv *fdtv, u8 *operand)
0310 {
0311     int i, n, pos = 1;
0312 
0313     for (i = 0, n = 0; i < 16; i++) {
0314         if (test_bit(i, &fdtv->channel_active)) {
0315             operand[pos++] = 0x13; /* flowfunction relay */
0316             operand[pos++] = 0x80; /* dsd_sel_spec_valid_flags -> PID */
0317             operand[pos++] = (fdtv->channel_pid[i] >> 8) & 0x1f;
0318             operand[pos++] = fdtv->channel_pid[i] & 0xff;
0319             operand[pos++] = 0x00; /* tableID */
0320             operand[pos++] = 0x00; /* filter_length */
0321             n++;
0322         }
0323     }
0324     operand[0] = n;
0325 
0326     return pos;
0327 }
0328 
0329 /*
0330  * tuning command for setting the relative LNB frequency
0331  * (not supported by the AVC standard)
0332  */
0333 static int avc_tuner_tuneqpsk(struct firedtv *fdtv,
0334                   struct dtv_frontend_properties *p)
0335 {
0336     struct avc_command_frame *c = (void *)fdtv->avc_data;
0337 
0338     c->opcode = AVC_OPCODE_VENDOR;
0339 
0340     c->operand[0] = SFE_VENDOR_DE_COMPANYID_0;
0341     c->operand[1] = SFE_VENDOR_DE_COMPANYID_1;
0342     c->operand[2] = SFE_VENDOR_DE_COMPANYID_2;
0343     if (fdtv->type == FIREDTV_DVB_S2)
0344         c->operand[3] = SFE_VENDOR_OPCODE_TUNE_QPSK2;
0345     else
0346         c->operand[3] = SFE_VENDOR_OPCODE_TUNE_QPSK;
0347 
0348     c->operand[4] = (p->frequency >> 24) & 0xff;
0349     c->operand[5] = (p->frequency >> 16) & 0xff;
0350     c->operand[6] = (p->frequency >> 8) & 0xff;
0351     c->operand[7] = p->frequency & 0xff;
0352 
0353     c->operand[8] = ((p->symbol_rate / 1000) >> 8) & 0xff;
0354     c->operand[9] = (p->symbol_rate / 1000) & 0xff;
0355 
0356     switch (p->fec_inner) {
0357     case FEC_1_2:   c->operand[10] = 0x1; break;
0358     case FEC_2_3:   c->operand[10] = 0x2; break;
0359     case FEC_3_4:   c->operand[10] = 0x3; break;
0360     case FEC_5_6:   c->operand[10] = 0x4; break;
0361     case FEC_7_8:   c->operand[10] = 0x5; break;
0362     case FEC_4_5:
0363     case FEC_8_9:
0364     case FEC_AUTO:
0365     default:    c->operand[10] = 0x0;
0366     }
0367 
0368     if (fdtv->voltage == 0xff)
0369         c->operand[11] = 0xff;
0370     else if (fdtv->voltage == SEC_VOLTAGE_18) /* polarisation */
0371         c->operand[11] = 0;
0372     else
0373         c->operand[11] = 1;
0374 
0375     if (fdtv->tone == 0xff)
0376         c->operand[12] = 0xff;
0377     else if (fdtv->tone == SEC_TONE_ON) /* band */
0378         c->operand[12] = 1;
0379     else
0380         c->operand[12] = 0;
0381 
0382     if (fdtv->type == FIREDTV_DVB_S2) {
0383         if (fdtv->fe.dtv_property_cache.delivery_system == SYS_DVBS2) {
0384             switch (fdtv->fe.dtv_property_cache.modulation) {
0385             case QAM_16:        c->operand[13] = 0x1; break;
0386             case QPSK:      c->operand[13] = 0x2; break;
0387             case PSK_8:     c->operand[13] = 0x3; break;
0388             default:        c->operand[13] = 0x2; break;
0389             }
0390             switch (fdtv->fe.dtv_property_cache.rolloff) {
0391             case ROLLOFF_35:    c->operand[14] = 0x2; break;
0392             case ROLLOFF_20:    c->operand[14] = 0x0; break;
0393             case ROLLOFF_25:    c->operand[14] = 0x1; break;
0394             case ROLLOFF_AUTO:
0395             default:        c->operand[14] = 0x2; break;
0396             /* case ROLLOFF_NONE:   c->operand[14] = 0xff; break; */
0397             }
0398             switch (fdtv->fe.dtv_property_cache.pilot) {
0399             case PILOT_AUTO:    c->operand[15] = 0x0; break;
0400             case PILOT_OFF:     c->operand[15] = 0x0; break;
0401             case PILOT_ON:      c->operand[15] = 0x1; break;
0402             }
0403         } else {
0404             c->operand[13] = 0x1;  /* auto modulation */
0405             c->operand[14] = 0xff; /* disable rolloff */
0406             c->operand[15] = 0xff; /* disable pilot */
0407         }
0408         return 16;
0409     } else {
0410         return 13;
0411     }
0412 }
0413 
0414 static int avc_tuner_dsd_dvb_c(struct firedtv *fdtv,
0415                    struct dtv_frontend_properties *p)
0416 {
0417     struct avc_command_frame *c = (void *)fdtv->avc_data;
0418 
0419     c->opcode = AVC_OPCODE_DSD;
0420 
0421     c->operand[0] = 0;    /* source plug */
0422     c->operand[1] = 0xd2; /* subfunction replace */
0423     c->operand[2] = 0x20; /* system id = DVB */
0424     c->operand[3] = 0x00; /* antenna number */
0425     c->operand[4] = 0x11; /* system_specific_multiplex selection_length */
0426 
0427     /* multiplex_valid_flags, high byte */
0428     c->operand[5] =   0 << 7 /* reserved */
0429             | 0 << 6 /* Polarisation */
0430             | 0 << 5 /* Orbital_Pos */
0431             | 1 << 4 /* Frequency */
0432             | 1 << 3 /* Symbol_Rate */
0433             | 0 << 2 /* FEC_outer */
0434             | (p->fec_inner  != FEC_AUTO ? 1 << 1 : 0)
0435             | (p->modulation != QAM_AUTO ? 1 << 0 : 0);
0436 
0437     /* multiplex_valid_flags, low byte */
0438     c->operand[6] =   0 << 7 /* NetworkID */
0439             | 0 << 0 /* reserved */ ;
0440 
0441     c->operand[7]  = 0x00;
0442     c->operand[8]  = 0x00;
0443     c->operand[9]  = 0x00;
0444     c->operand[10] = 0x00;
0445 
0446     c->operand[11] = (((p->frequency / 4000) >> 16) & 0xff) | (2 << 6);
0447     c->operand[12] = ((p->frequency / 4000) >> 8) & 0xff;
0448     c->operand[13] = (p->frequency / 4000) & 0xff;
0449     c->operand[14] = ((p->symbol_rate / 1000) >> 12) & 0xff;
0450     c->operand[15] = ((p->symbol_rate / 1000) >> 4) & 0xff;
0451     c->operand[16] = ((p->symbol_rate / 1000) << 4) & 0xf0;
0452     c->operand[17] = 0x00;
0453 
0454     switch (p->fec_inner) {
0455     case FEC_1_2:   c->operand[18] = 0x1; break;
0456     case FEC_2_3:   c->operand[18] = 0x2; break;
0457     case FEC_3_4:   c->operand[18] = 0x3; break;
0458     case FEC_5_6:   c->operand[18] = 0x4; break;
0459     case FEC_7_8:   c->operand[18] = 0x5; break;
0460     case FEC_8_9:   c->operand[18] = 0x6; break;
0461     case FEC_4_5:   c->operand[18] = 0x8; break;
0462     case FEC_AUTO:
0463     default:    c->operand[18] = 0x0;
0464     }
0465 
0466     switch (p->modulation) {
0467     case QAM_16:    c->operand[19] = 0x08; break;
0468     case QAM_32:    c->operand[19] = 0x10; break;
0469     case QAM_64:    c->operand[19] = 0x18; break;
0470     case QAM_128:   c->operand[19] = 0x20; break;
0471     case QAM_256:   c->operand[19] = 0x28; break;
0472     case QAM_AUTO:
0473     default:    c->operand[19] = 0x00;
0474     }
0475 
0476     c->operand[20] = 0x00;
0477     c->operand[21] = 0x00;
0478 
0479     return 22 + add_pid_filter(fdtv, &c->operand[22]);
0480 }
0481 
0482 static int avc_tuner_dsd_dvb_t(struct firedtv *fdtv,
0483                    struct dtv_frontend_properties *p)
0484 {
0485     struct avc_command_frame *c = (void *)fdtv->avc_data;
0486 
0487     c->opcode = AVC_OPCODE_DSD;
0488 
0489     c->operand[0] = 0;    /* source plug */
0490     c->operand[1] = 0xd2; /* subfunction replace */
0491     c->operand[2] = 0x20; /* system id = DVB */
0492     c->operand[3] = 0x00; /* antenna number */
0493     c->operand[4] = 0x0c; /* system_specific_multiplex selection_length */
0494 
0495     /* multiplex_valid_flags, high byte */
0496     c->operand[5] =
0497           0 << 7 /* reserved */
0498         | 1 << 6 /* CenterFrequency */
0499         | (p->bandwidth_hz != 0        ? 1 << 5 : 0)
0500         | (p->modulation  != QAM_AUTO              ? 1 << 4 : 0)
0501         | (p->hierarchy != HIERARCHY_AUTO ? 1 << 3 : 0)
0502         | (p->code_rate_HP   != FEC_AUTO              ? 1 << 2 : 0)
0503         | (p->code_rate_LP   != FEC_AUTO              ? 1 << 1 : 0)
0504         | (p->guard_interval != GUARD_INTERVAL_AUTO   ? 1 << 0 : 0);
0505 
0506     /* multiplex_valid_flags, low byte */
0507     c->operand[6] =
0508           0 << 7 /* NetworkID */
0509         | (p->transmission_mode != TRANSMISSION_MODE_AUTO ? 1 << 6 : 0)
0510         | 0 << 5 /* OtherFrequencyFlag */
0511         | 0 << 0 /* reserved */ ;
0512 
0513     c->operand[7]  = 0x0;
0514     c->operand[8]  = (p->frequency / 10) >> 24;
0515     c->operand[9]  = ((p->frequency / 10) >> 16) & 0xff;
0516     c->operand[10] = ((p->frequency / 10) >>  8) & 0xff;
0517     c->operand[11] = (p->frequency / 10) & 0xff;
0518 
0519     switch (p->bandwidth_hz) {
0520     case 7000000:   c->operand[12] = 0x20; break;
0521     case 8000000:
0522     case 6000000:   /* not defined by AVC spec */
0523     case 0:
0524     default:        c->operand[12] = 0x00;
0525     }
0526 
0527     switch (p->modulation) {
0528     case QAM_16:    c->operand[13] = 1 << 6; break;
0529     case QAM_64:    c->operand[13] = 2 << 6; break;
0530     case QPSK:
0531     default:    c->operand[13] = 0x00;
0532     }
0533 
0534     switch (p->hierarchy) {
0535     case HIERARCHY_1:   c->operand[13] |= 1 << 3; break;
0536     case HIERARCHY_2:   c->operand[13] |= 2 << 3; break;
0537     case HIERARCHY_4:   c->operand[13] |= 3 << 3; break;
0538     case HIERARCHY_AUTO:
0539     case HIERARCHY_NONE:
0540     default:        break;
0541     }
0542 
0543     switch (p->code_rate_HP) {
0544     case FEC_2_3:   c->operand[13] |= 1; break;
0545     case FEC_3_4:   c->operand[13] |= 2; break;
0546     case FEC_5_6:   c->operand[13] |= 3; break;
0547     case FEC_7_8:   c->operand[13] |= 4; break;
0548     case FEC_1_2:
0549     default:    break;
0550     }
0551 
0552     switch (p->code_rate_LP) {
0553     case FEC_2_3:   c->operand[14] = 1 << 5; break;
0554     case FEC_3_4:   c->operand[14] = 2 << 5; break;
0555     case FEC_5_6:   c->operand[14] = 3 << 5; break;
0556     case FEC_7_8:   c->operand[14] = 4 << 5; break;
0557     case FEC_1_2:
0558     default:    c->operand[14] = 0x00; break;
0559     }
0560 
0561     switch (p->guard_interval) {
0562     case GUARD_INTERVAL_1_16:   c->operand[14] |= 1 << 3; break;
0563     case GUARD_INTERVAL_1_8:    c->operand[14] |= 2 << 3; break;
0564     case GUARD_INTERVAL_1_4:    c->operand[14] |= 3 << 3; break;
0565     case GUARD_INTERVAL_1_32:
0566     case GUARD_INTERVAL_AUTO:
0567     default:            break;
0568     }
0569 
0570     switch (p->transmission_mode) {
0571     case TRANSMISSION_MODE_8K:  c->operand[14] |= 1 << 1; break;
0572     case TRANSMISSION_MODE_2K:
0573     case TRANSMISSION_MODE_AUTO:
0574     default:            break;
0575     }
0576 
0577     c->operand[15] = 0x00; /* network_ID[0] */
0578     c->operand[16] = 0x00; /* network_ID[1] */
0579 
0580     return 17 + add_pid_filter(fdtv, &c->operand[17]);
0581 }
0582 
0583 int avc_tuner_dsd(struct firedtv *fdtv,
0584           struct dtv_frontend_properties *p)
0585 {
0586     struct avc_command_frame *c = (void *)fdtv->avc_data;
0587     int pos, ret;
0588 
0589     mutex_lock(&fdtv->avc_mutex);
0590 
0591     c->ctype   = AVC_CTYPE_CONTROL;
0592     c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit;
0593 
0594     switch (fdtv->type) {
0595     case FIREDTV_DVB_S:
0596     case FIREDTV_DVB_S2: pos = avc_tuner_tuneqpsk(fdtv, p); break;
0597     case FIREDTV_DVB_C: pos = avc_tuner_dsd_dvb_c(fdtv, p); break;
0598     case FIREDTV_DVB_T: pos = avc_tuner_dsd_dvb_t(fdtv, p); break;
0599     default:
0600         BUG();
0601     }
0602     pad_operands(c, pos);
0603 
0604     fdtv->avc_data_length = ALIGN(3 + pos, 4);
0605     ret = avc_write(fdtv);
0606 #if 0
0607     /*
0608      * FIXME:
0609      * u8 *status was an out-parameter of avc_tuner_dsd, unused by caller.
0610      * Check for AVC_RESPONSE_ACCEPTED here instead?
0611      */
0612     if (status)
0613         *status = r->operand[2];
0614 #endif
0615     mutex_unlock(&fdtv->avc_mutex);
0616 
0617     if (ret == 0)
0618         msleep(500);
0619 
0620     return ret;
0621 }
0622 
0623 int avc_tuner_set_pids(struct firedtv *fdtv, unsigned char pidc, u16 pid[])
0624 {
0625     struct avc_command_frame *c = (void *)fdtv->avc_data;
0626     int ret, pos, k;
0627 
0628     if (pidc > 16 && pidc != 0xff)
0629         return -EINVAL;
0630 
0631     mutex_lock(&fdtv->avc_mutex);
0632 
0633     c->ctype   = AVC_CTYPE_CONTROL;
0634     c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit;
0635     c->opcode  = AVC_OPCODE_DSD;
0636 
0637     c->operand[0] = 0;  /* source plug */
0638     c->operand[1] = 0xd2;   /* subfunction replace */
0639     c->operand[2] = 0x20;   /* system id = DVB */
0640     c->operand[3] = 0x00;   /* antenna number */
0641     c->operand[4] = 0x00;   /* system_specific_multiplex selection_length */
0642     c->operand[5] = pidc;   /* Nr_of_dsd_sel_specs */
0643 
0644     pos = 6;
0645     if (pidc != 0xff)
0646         for (k = 0; k < pidc; k++) {
0647             c->operand[pos++] = 0x13; /* flowfunction relay */
0648             c->operand[pos++] = 0x80; /* dsd_sel_spec_valid_flags -> PID */
0649             c->operand[pos++] = (pid[k] >> 8) & 0x1f;
0650             c->operand[pos++] = pid[k] & 0xff;
0651             c->operand[pos++] = 0x00; /* tableID */
0652             c->operand[pos++] = 0x00; /* filter_length */
0653         }
0654     pad_operands(c, pos);
0655 
0656     fdtv->avc_data_length = ALIGN(3 + pos, 4);
0657     ret = avc_write(fdtv);
0658 
0659     /* FIXME: check response code? */
0660 
0661     mutex_unlock(&fdtv->avc_mutex);
0662 
0663     if (ret == 0)
0664         msleep(50);
0665 
0666     return ret;
0667 }
0668 
0669 int avc_tuner_get_ts(struct firedtv *fdtv)
0670 {
0671     struct avc_command_frame *c = (void *)fdtv->avc_data;
0672     int ret, sl;
0673 
0674     mutex_lock(&fdtv->avc_mutex);
0675 
0676     c->ctype   = AVC_CTYPE_CONTROL;
0677     c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit;
0678     c->opcode  = AVC_OPCODE_DSIT;
0679 
0680     sl = fdtv->type == FIREDTV_DVB_T ? 0x0c : 0x11;
0681 
0682     c->operand[0] = 0;  /* source plug */
0683     c->operand[1] = 0xd2;   /* subfunction replace */
0684     c->operand[2] = 0xff;   /* status */
0685     c->operand[3] = 0x20;   /* system id = DVB */
0686     c->operand[4] = 0x00;   /* antenna number */
0687     c->operand[5] = 0x0;    /* system_specific_search_flags */
0688     c->operand[6] = sl; /* system_specific_multiplex selection_length */
0689     /*
0690      * operand[7]: valid_flags[0]
0691      * operand[8]: valid_flags[1]
0692      * operand[7 + sl]: nr_of_dsit_sel_specs (always 0)
0693      */
0694     clear_operands(c, 7, 24);
0695 
0696     fdtv->avc_data_length = fdtv->type == FIREDTV_DVB_T ? 24 : 28;
0697     ret = avc_write(fdtv);
0698 
0699     /* FIXME: check response code? */
0700 
0701     mutex_unlock(&fdtv->avc_mutex);
0702 
0703     if (ret == 0)
0704         msleep(250);
0705 
0706     return ret;
0707 }
0708 
0709 int avc_identify_subunit(struct firedtv *fdtv)
0710 {
0711     struct avc_command_frame *c = (void *)fdtv->avc_data;
0712     struct avc_response_frame *r = (void *)fdtv->avc_data;
0713     int ret;
0714 
0715     mutex_lock(&fdtv->avc_mutex);
0716 
0717     c->ctype   = AVC_CTYPE_CONTROL;
0718     c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit;
0719     c->opcode  = AVC_OPCODE_READ_DESCRIPTOR;
0720 
0721     c->operand[0] = DESCRIPTOR_SUBUNIT_IDENTIFIER;
0722     c->operand[1] = 0xff;
0723     c->operand[2] = 0x00;
0724     c->operand[3] = 0x00; /* length highbyte */
0725     c->operand[4] = 0x08; /* length lowbyte  */
0726     c->operand[5] = 0x00; /* offset highbyte */
0727     c->operand[6] = 0x0d; /* offset lowbyte  */
0728     clear_operands(c, 7, 8); /* padding */
0729 
0730     fdtv->avc_data_length = 12;
0731     ret = avc_write(fdtv);
0732     if (ret < 0)
0733         goto out;
0734 
0735     if ((r->response != AVC_RESPONSE_STABLE &&
0736          r->response != AVC_RESPONSE_ACCEPTED) ||
0737         (r->operand[3] << 8) + r->operand[4] != 8) {
0738         dev_err(fdtv->device, "cannot read subunit identifier\n");
0739         ret = -EINVAL;
0740     }
0741 out:
0742     mutex_unlock(&fdtv->avc_mutex);
0743 
0744     return ret;
0745 }
0746 
0747 #define SIZEOF_ANTENNA_INPUT_INFO 22
0748 
0749 int avc_tuner_status(struct firedtv *fdtv, struct firedtv_tuner_status *stat)
0750 {
0751     struct avc_command_frame *c = (void *)fdtv->avc_data;
0752     struct avc_response_frame *r = (void *)fdtv->avc_data;
0753     int length, ret;
0754 
0755     mutex_lock(&fdtv->avc_mutex);
0756 
0757     c->ctype   = AVC_CTYPE_CONTROL;
0758     c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit;
0759     c->opcode  = AVC_OPCODE_READ_DESCRIPTOR;
0760 
0761     c->operand[0] = DESCRIPTOR_TUNER_STATUS;
0762     c->operand[1] = 0xff;   /* read_result_status */
0763     /*
0764      * operand[2]: reserved
0765      * operand[3]: SIZEOF_ANTENNA_INPUT_INFO >> 8
0766      * operand[4]: SIZEOF_ANTENNA_INPUT_INFO & 0xff
0767      */
0768     clear_operands(c, 2, 31);
0769 
0770     fdtv->avc_data_length = 12;
0771     ret = avc_write(fdtv);
0772     if (ret < 0)
0773         goto out;
0774 
0775     if (r->response != AVC_RESPONSE_STABLE &&
0776         r->response != AVC_RESPONSE_ACCEPTED) {
0777         dev_err(fdtv->device, "cannot read tuner status\n");
0778         ret = -EINVAL;
0779         goto out;
0780     }
0781 
0782     length = r->operand[9];
0783     if (r->operand[1] != 0x10 || length != SIZEOF_ANTENNA_INPUT_INFO) {
0784         dev_err(fdtv->device, "got invalid tuner status\n");
0785         ret = -EINVAL;
0786         goto out;
0787     }
0788 
0789     stat->active_system     = r->operand[10];
0790     stat->searching         = r->operand[11] >> 7 & 1;
0791     stat->moving            = r->operand[11] >> 6 & 1;
0792     stat->no_rf         = r->operand[11] >> 5 & 1;
0793     stat->input         = r->operand[12] >> 7 & 1;
0794     stat->selected_antenna      = r->operand[12] & 0x7f;
0795     stat->ber           = r->operand[13] << 24 |
0796                       r->operand[14] << 16 |
0797                       r->operand[15] << 8 |
0798                       r->operand[16];
0799     stat->signal_strength       = r->operand[17];
0800     stat->raster_frequency      = r->operand[18] >> 6 & 2;
0801     stat->rf_frequency      = (r->operand[18] & 0x3f) << 16 |
0802                       r->operand[19] << 8 |
0803                       r->operand[20];
0804     stat->man_dep_info_length   = r->operand[21];
0805     stat->front_end_error       = r->operand[22] >> 4 & 1;
0806     stat->antenna_error     = r->operand[22] >> 3 & 1;
0807     stat->front_end_power_status    = r->operand[22] >> 1 & 1;
0808     stat->power_supply      = r->operand[22] & 1;
0809     stat->carrier_noise_ratio   = r->operand[23] << 8 |
0810                       r->operand[24];
0811     stat->power_supply_voltage  = r->operand[27];
0812     stat->antenna_voltage       = r->operand[28];
0813     stat->firewire_bus_voltage  = r->operand[29];
0814     stat->ca_mmi            = r->operand[30] & 1;
0815     stat->ca_pmt_reply      = r->operand[31] >> 7 & 1;
0816     stat->ca_date_time_request  = r->operand[31] >> 6 & 1;
0817     stat->ca_application_info   = r->operand[31] >> 5 & 1;
0818     stat->ca_module_present_status  = r->operand[31] >> 4 & 1;
0819     stat->ca_dvb_flag       = r->operand[31] >> 3 & 1;
0820     stat->ca_error_flag     = r->operand[31] >> 2 & 1;
0821     stat->ca_initialization_status  = r->operand[31] >> 1 & 1;
0822 out:
0823     mutex_unlock(&fdtv->avc_mutex);
0824 
0825     return ret;
0826 }
0827 
0828 int avc_lnb_control(struct firedtv *fdtv, char voltage, char burst,
0829             char conttone, char nrdiseq,
0830             struct dvb_diseqc_master_cmd *diseqcmd)
0831 {
0832     struct avc_command_frame *c = (void *)fdtv->avc_data;
0833     struct avc_response_frame *r = (void *)fdtv->avc_data;
0834     int pos, j, k, ret;
0835 
0836     mutex_lock(&fdtv->avc_mutex);
0837 
0838     c->ctype   = AVC_CTYPE_CONTROL;
0839     c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit;
0840     c->opcode  = AVC_OPCODE_VENDOR;
0841 
0842     c->operand[0] = SFE_VENDOR_DE_COMPANYID_0;
0843     c->operand[1] = SFE_VENDOR_DE_COMPANYID_1;
0844     c->operand[2] = SFE_VENDOR_DE_COMPANYID_2;
0845     c->operand[3] = SFE_VENDOR_OPCODE_LNB_CONTROL;
0846     c->operand[4] = voltage;
0847     c->operand[5] = nrdiseq;
0848 
0849     pos = 6;
0850     for (j = 0; j < nrdiseq; j++) {
0851         c->operand[pos++] = diseqcmd[j].msg_len;
0852 
0853         for (k = 0; k < diseqcmd[j].msg_len; k++)
0854             c->operand[pos++] = diseqcmd[j].msg[k];
0855     }
0856     c->operand[pos++] = burst;
0857     c->operand[pos++] = conttone;
0858     pad_operands(c, pos);
0859 
0860     fdtv->avc_data_length = ALIGN(3 + pos, 4);
0861     ret = avc_write(fdtv);
0862     if (ret < 0)
0863         goto out;
0864 
0865     if (r->response != AVC_RESPONSE_ACCEPTED) {
0866         dev_err(fdtv->device, "LNB control failed\n");
0867         ret = -EINVAL;
0868     }
0869 out:
0870     mutex_unlock(&fdtv->avc_mutex);
0871 
0872     return ret;
0873 }
0874 
0875 int avc_register_remote_control(struct firedtv *fdtv)
0876 {
0877     struct avc_command_frame *c = (void *)fdtv->avc_data;
0878     int ret;
0879 
0880     mutex_lock(&fdtv->avc_mutex);
0881 
0882     c->ctype   = AVC_CTYPE_NOTIFY;
0883     c->subunit = AVC_SUBUNIT_TYPE_UNIT | 7;
0884     c->opcode  = AVC_OPCODE_VENDOR;
0885 
0886     c->operand[0] = SFE_VENDOR_DE_COMPANYID_0;
0887     c->operand[1] = SFE_VENDOR_DE_COMPANYID_1;
0888     c->operand[2] = SFE_VENDOR_DE_COMPANYID_2;
0889     c->operand[3] = SFE_VENDOR_OPCODE_REGISTER_REMOTE_CONTROL;
0890     c->operand[4] = 0; /* padding */
0891 
0892     fdtv->avc_data_length = 8;
0893     ret = avc_write(fdtv);
0894 
0895     /* FIXME: check response code? */
0896 
0897     mutex_unlock(&fdtv->avc_mutex);
0898 
0899     return ret;
0900 }
0901 
0902 void avc_remote_ctrl_work(struct work_struct *work)
0903 {
0904     struct firedtv *fdtv =
0905             container_of(work, struct firedtv, remote_ctrl_work);
0906 
0907     /* Should it be rescheduled in failure cases? */
0908     avc_register_remote_control(fdtv);
0909 }
0910 
0911 #if 0 /* FIXME: unused */
0912 int avc_tuner_host2ca(struct firedtv *fdtv)
0913 {
0914     struct avc_command_frame *c = (void *)fdtv->avc_data;
0915     int ret;
0916 
0917     mutex_lock(&fdtv->avc_mutex);
0918 
0919     c->ctype   = AVC_CTYPE_CONTROL;
0920     c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit;
0921     c->opcode  = AVC_OPCODE_VENDOR;
0922 
0923     c->operand[0] = SFE_VENDOR_DE_COMPANYID_0;
0924     c->operand[1] = SFE_VENDOR_DE_COMPANYID_1;
0925     c->operand[2] = SFE_VENDOR_DE_COMPANYID_2;
0926     c->operand[3] = SFE_VENDOR_OPCODE_HOST2CA;
0927     c->operand[4] = 0; /* slot */
0928     c->operand[5] = SFE_VENDOR_TAG_CA_APPLICATION_INFO; /* ca tag */
0929     clear_operands(c, 6, 8);
0930 
0931     fdtv->avc_data_length = 12;
0932     ret = avc_write(fdtv);
0933 
0934     /* FIXME: check response code? */
0935 
0936     mutex_unlock(&fdtv->avc_mutex);
0937 
0938     return ret;
0939 }
0940 #endif
0941 
0942 static int get_ca_object_pos(struct avc_response_frame *r)
0943 {
0944     int length = 1;
0945 
0946     /* Check length of length field */
0947     if (r->operand[7] & 0x80)
0948         length = (r->operand[7] & 0x7f) + 1;
0949     return length + 7;
0950 }
0951 
0952 static int get_ca_object_length(struct avc_response_frame *r)
0953 {
0954 #if 0 /* FIXME: unused */
0955     int size = 0;
0956     int i;
0957 
0958     if (r->operand[7] & 0x80)
0959         for (i = 0; i < (r->operand[7] & 0x7f); i++) {
0960             size <<= 8;
0961             size += r->operand[8 + i];
0962         }
0963 #endif
0964     return r->operand[7];
0965 }
0966 
0967 int avc_ca_app_info(struct firedtv *fdtv, unsigned char *app_info,
0968             unsigned int *len)
0969 {
0970     struct avc_command_frame *c = (void *)fdtv->avc_data;
0971     struct avc_response_frame *r = (void *)fdtv->avc_data;
0972     int pos, ret;
0973 
0974     mutex_lock(&fdtv->avc_mutex);
0975 
0976     c->ctype   = AVC_CTYPE_STATUS;
0977     c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit;
0978     c->opcode  = AVC_OPCODE_VENDOR;
0979 
0980     c->operand[0] = SFE_VENDOR_DE_COMPANYID_0;
0981     c->operand[1] = SFE_VENDOR_DE_COMPANYID_1;
0982     c->operand[2] = SFE_VENDOR_DE_COMPANYID_2;
0983     c->operand[3] = SFE_VENDOR_OPCODE_CA2HOST;
0984     c->operand[4] = 0; /* slot */
0985     c->operand[5] = SFE_VENDOR_TAG_CA_APPLICATION_INFO; /* ca tag */
0986     clear_operands(c, 6, LAST_OPERAND);
0987 
0988     fdtv->avc_data_length = 12;
0989     ret = avc_write(fdtv);
0990     if (ret < 0)
0991         goto out;
0992 
0993     /* FIXME: check response code and validate response data */
0994 
0995     pos = get_ca_object_pos(r);
0996     app_info[0] = (EN50221_TAG_APP_INFO >> 16) & 0xff;
0997     app_info[1] = (EN50221_TAG_APP_INFO >>  8) & 0xff;
0998     app_info[2] = (EN50221_TAG_APP_INFO >>  0) & 0xff;
0999     app_info[3] = 6 + r->operand[pos + 4];
1000     app_info[4] = 0x01;
1001     memcpy(&app_info[5], &r->operand[pos], 5 + r->operand[pos + 4]);
1002     *len = app_info[3] + 4;
1003 out:
1004     mutex_unlock(&fdtv->avc_mutex);
1005 
1006     return ret;
1007 }
1008 
1009 int avc_ca_info(struct firedtv *fdtv, unsigned char *app_info,
1010         unsigned int *len)
1011 {
1012     struct avc_command_frame *c = (void *)fdtv->avc_data;
1013     struct avc_response_frame *r = (void *)fdtv->avc_data;
1014     int i, pos, ret;
1015 
1016     mutex_lock(&fdtv->avc_mutex);
1017 
1018     c->ctype   = AVC_CTYPE_STATUS;
1019     c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit;
1020     c->opcode  = AVC_OPCODE_VENDOR;
1021 
1022     c->operand[0] = SFE_VENDOR_DE_COMPANYID_0;
1023     c->operand[1] = SFE_VENDOR_DE_COMPANYID_1;
1024     c->operand[2] = SFE_VENDOR_DE_COMPANYID_2;
1025     c->operand[3] = SFE_VENDOR_OPCODE_CA2HOST;
1026     c->operand[4] = 0; /* slot */
1027     c->operand[5] = SFE_VENDOR_TAG_CA_APPLICATION_INFO; /* ca tag */
1028     clear_operands(c, 6, LAST_OPERAND);
1029 
1030     fdtv->avc_data_length = 12;
1031     ret = avc_write(fdtv);
1032     if (ret < 0)
1033         goto out;
1034 
1035     /* FIXME: check response code and validate response data */
1036 
1037     pos = get_ca_object_pos(r);
1038     app_info[0] = (EN50221_TAG_CA_INFO >> 16) & 0xff;
1039     app_info[1] = (EN50221_TAG_CA_INFO >>  8) & 0xff;
1040     app_info[2] = (EN50221_TAG_CA_INFO >>  0) & 0xff;
1041     if (num_fake_ca_system_ids == 0) {
1042         app_info[3] = 2;
1043         app_info[4] = r->operand[pos + 0];
1044         app_info[5] = r->operand[pos + 1];
1045     } else {
1046         app_info[3] = num_fake_ca_system_ids * 2;
1047         for (i = 0; i < num_fake_ca_system_ids; i++) {
1048             app_info[4 + i * 2] =
1049                 (fake_ca_system_ids[i] >> 8) & 0xff;
1050             app_info[5 + i * 2] = fake_ca_system_ids[i] & 0xff;
1051         }
1052     }
1053     *len = app_info[3] + 4;
1054 out:
1055     mutex_unlock(&fdtv->avc_mutex);
1056 
1057     return ret;
1058 }
1059 
1060 int avc_ca_reset(struct firedtv *fdtv)
1061 {
1062     struct avc_command_frame *c = (void *)fdtv->avc_data;
1063     int ret;
1064 
1065     mutex_lock(&fdtv->avc_mutex);
1066 
1067     c->ctype   = AVC_CTYPE_CONTROL;
1068     c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit;
1069     c->opcode  = AVC_OPCODE_VENDOR;
1070 
1071     c->operand[0] = SFE_VENDOR_DE_COMPANYID_0;
1072     c->operand[1] = SFE_VENDOR_DE_COMPANYID_1;
1073     c->operand[2] = SFE_VENDOR_DE_COMPANYID_2;
1074     c->operand[3] = SFE_VENDOR_OPCODE_HOST2CA;
1075     c->operand[4] = 0; /* slot */
1076     c->operand[5] = SFE_VENDOR_TAG_CA_RESET; /* ca tag */
1077     c->operand[6] = 0; /* more/last */
1078     c->operand[7] = 1; /* length */
1079     c->operand[8] = 0; /* force hardware reset */
1080 
1081     fdtv->avc_data_length = 12;
1082     ret = avc_write(fdtv);
1083 
1084     /* FIXME: check response code? */
1085 
1086     mutex_unlock(&fdtv->avc_mutex);
1087 
1088     return ret;
1089 }
1090 
1091 int avc_ca_pmt(struct firedtv *fdtv, char *msg, int length)
1092 {
1093     struct avc_command_frame *c = (void *)fdtv->avc_data;
1094     struct avc_response_frame *r = (void *)fdtv->avc_data;
1095     int list_management;
1096     int program_info_length;
1097     int pmt_cmd_id;
1098     int read_pos;
1099     int write_pos;
1100     int es_info_length;
1101     int crc32_csum;
1102     int ret;
1103 
1104     if (unlikely(avc_debug & AVC_DEBUG_APPLICATION_PMT))
1105         debug_pmt(msg, length);
1106 
1107     mutex_lock(&fdtv->avc_mutex);
1108 
1109     c->ctype   = AVC_CTYPE_CONTROL;
1110     c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit;
1111     c->opcode  = AVC_OPCODE_VENDOR;
1112 
1113     if (msg[0] != EN50221_LIST_MANAGEMENT_ONLY) {
1114         dev_info(fdtv->device, "forcing list_management to ONLY\n");
1115         msg[0] = EN50221_LIST_MANAGEMENT_ONLY;
1116     }
1117     /* We take the cmd_id from the programme level only! */
1118     list_management = msg[0];
1119     program_info_length = ((msg[4] & 0x0f) << 8) + msg[5];
1120     if (program_info_length > 0)
1121         program_info_length--; /* Remove pmt_cmd_id */
1122     pmt_cmd_id = msg[6];
1123 
1124     c->operand[0] = SFE_VENDOR_DE_COMPANYID_0;
1125     c->operand[1] = SFE_VENDOR_DE_COMPANYID_1;
1126     c->operand[2] = SFE_VENDOR_DE_COMPANYID_2;
1127     c->operand[3] = SFE_VENDOR_OPCODE_HOST2CA;
1128     c->operand[4] = 0; /* slot */
1129     c->operand[5] = SFE_VENDOR_TAG_CA_PMT; /* ca tag */
1130     c->operand[6] = 0; /* more/last */
1131     /* Use three bytes for length field in case length > 127 */
1132     c->operand[10] = list_management;
1133     c->operand[11] = 0x01; /* pmt_cmd=OK_descramble */
1134 
1135     /* TS program map table */
1136 
1137     c->operand[12] = 0x02; /* Table id=2 */
1138     c->operand[13] = 0x80; /* Section syntax + length */
1139 
1140     c->operand[15] = msg[1]; /* Program number */
1141     c->operand[16] = msg[2];
1142     c->operand[17] = msg[3]; /* Version number and current/next */
1143     c->operand[18] = 0x00; /* Section number=0 */
1144     c->operand[19] = 0x00; /* Last section number=0 */
1145     c->operand[20] = 0x1f; /* PCR_PID=1FFF */
1146     c->operand[21] = 0xff;
1147     c->operand[22] = (program_info_length >> 8); /* Program info length */
1148     c->operand[23] = (program_info_length & 0xff);
1149 
1150     /* CA descriptors at programme level */
1151     read_pos = 6;
1152     write_pos = 24;
1153     if (program_info_length > 0) {
1154         pmt_cmd_id = msg[read_pos++];
1155         if (pmt_cmd_id != 1 && pmt_cmd_id != 4)
1156             dev_err(fdtv->device,
1157                 "invalid pmt_cmd_id %d\n", pmt_cmd_id);
1158         if (program_info_length > sizeof(c->operand) - 4 - write_pos) {
1159             ret = -EINVAL;
1160             goto out;
1161         }
1162 
1163         memcpy(&c->operand[write_pos], &msg[read_pos],
1164                program_info_length);
1165         read_pos += program_info_length;
1166         write_pos += program_info_length;
1167     }
1168     while (read_pos + 4 < length) {
1169         if (write_pos + 4 >= sizeof(c->operand) - 4) {
1170             ret = -EINVAL;
1171             goto out;
1172         }
1173         c->operand[write_pos++] = msg[read_pos++];
1174         c->operand[write_pos++] = msg[read_pos++];
1175         c->operand[write_pos++] = msg[read_pos++];
1176         es_info_length =
1177             ((msg[read_pos] & 0x0f) << 8) + msg[read_pos + 1];
1178         read_pos += 2;
1179         if (es_info_length > 0)
1180             es_info_length--; /* Remove pmt_cmd_id */
1181         c->operand[write_pos++] = es_info_length >> 8;
1182         c->operand[write_pos++] = es_info_length & 0xff;
1183         if (es_info_length > 0) {
1184             if (read_pos >= length) {
1185                 ret = -EINVAL;
1186                 goto out;
1187             }
1188             pmt_cmd_id = msg[read_pos++];
1189             if (pmt_cmd_id != 1 && pmt_cmd_id != 4)
1190                 dev_err(fdtv->device, "invalid pmt_cmd_id %d at stream level\n",
1191                     pmt_cmd_id);
1192 
1193             if (es_info_length > sizeof(c->operand) - 4 - write_pos ||
1194                 es_info_length > length - read_pos) {
1195                 ret = -EINVAL;
1196                 goto out;
1197             }
1198 
1199             memcpy(&c->operand[write_pos], &msg[read_pos],
1200                    es_info_length);
1201             read_pos += es_info_length;
1202             write_pos += es_info_length;
1203         }
1204     }
1205     write_pos += 4; /* CRC */
1206 
1207     c->operand[7] = 0x82;
1208     c->operand[8] = (write_pos - 10) >> 8;
1209     c->operand[9] = (write_pos - 10) & 0xff;
1210     c->operand[14] = write_pos - 15;
1211 
1212     crc32_csum = crc32_be(0, &c->operand[10], c->operand[12] - 1);
1213     c->operand[write_pos - 4] = (crc32_csum >> 24) & 0xff;
1214     c->operand[write_pos - 3] = (crc32_csum >> 16) & 0xff;
1215     c->operand[write_pos - 2] = (crc32_csum >>  8) & 0xff;
1216     c->operand[write_pos - 1] = (crc32_csum >>  0) & 0xff;
1217     pad_operands(c, write_pos);
1218 
1219     fdtv->avc_data_length = ALIGN(3 + write_pos, 4);
1220     ret = avc_write(fdtv);
1221     if (ret < 0)
1222         goto out;
1223 
1224     if (r->response != AVC_RESPONSE_ACCEPTED) {
1225         dev_err(fdtv->device,
1226             "CA PMT failed with response 0x%x\n", r->response);
1227         ret = -EACCES;
1228     }
1229 out:
1230     mutex_unlock(&fdtv->avc_mutex);
1231 
1232     return ret;
1233 }
1234 
1235 int avc_ca_get_time_date(struct firedtv *fdtv, int *interval)
1236 {
1237     struct avc_command_frame *c = (void *)fdtv->avc_data;
1238     struct avc_response_frame *r = (void *)fdtv->avc_data;
1239     int ret;
1240 
1241     mutex_lock(&fdtv->avc_mutex);
1242 
1243     c->ctype   = AVC_CTYPE_STATUS;
1244     c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit;
1245     c->opcode  = AVC_OPCODE_VENDOR;
1246 
1247     c->operand[0] = SFE_VENDOR_DE_COMPANYID_0;
1248     c->operand[1] = SFE_VENDOR_DE_COMPANYID_1;
1249     c->operand[2] = SFE_VENDOR_DE_COMPANYID_2;
1250     c->operand[3] = SFE_VENDOR_OPCODE_CA2HOST;
1251     c->operand[4] = 0; /* slot */
1252     c->operand[5] = SFE_VENDOR_TAG_CA_DATE_TIME; /* ca tag */
1253     clear_operands(c, 6, LAST_OPERAND);
1254 
1255     fdtv->avc_data_length = 12;
1256     ret = avc_write(fdtv);
1257     if (ret < 0)
1258         goto out;
1259 
1260     /* FIXME: check response code and validate response data */
1261 
1262     *interval = r->operand[get_ca_object_pos(r)];
1263 out:
1264     mutex_unlock(&fdtv->avc_mutex);
1265 
1266     return ret;
1267 }
1268 
1269 int avc_ca_enter_menu(struct firedtv *fdtv)
1270 {
1271     struct avc_command_frame *c = (void *)fdtv->avc_data;
1272     int ret;
1273 
1274     mutex_lock(&fdtv->avc_mutex);
1275 
1276     c->ctype   = AVC_CTYPE_STATUS;
1277     c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit;
1278     c->opcode  = AVC_OPCODE_VENDOR;
1279 
1280     c->operand[0] = SFE_VENDOR_DE_COMPANYID_0;
1281     c->operand[1] = SFE_VENDOR_DE_COMPANYID_1;
1282     c->operand[2] = SFE_VENDOR_DE_COMPANYID_2;
1283     c->operand[3] = SFE_VENDOR_OPCODE_HOST2CA;
1284     c->operand[4] = 0; /* slot */
1285     c->operand[5] = SFE_VENDOR_TAG_CA_ENTER_MENU;
1286     clear_operands(c, 6, 8);
1287 
1288     fdtv->avc_data_length = 12;
1289     ret = avc_write(fdtv);
1290 
1291     /* FIXME: check response code? */
1292 
1293     mutex_unlock(&fdtv->avc_mutex);
1294 
1295     return ret;
1296 }
1297 
1298 int avc_ca_get_mmi(struct firedtv *fdtv, char *mmi_object, unsigned int *len)
1299 {
1300     struct avc_command_frame *c = (void *)fdtv->avc_data;
1301     struct avc_response_frame *r = (void *)fdtv->avc_data;
1302     int ret;
1303 
1304     mutex_lock(&fdtv->avc_mutex);
1305 
1306     c->ctype   = AVC_CTYPE_STATUS;
1307     c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit;
1308     c->opcode  = AVC_OPCODE_VENDOR;
1309 
1310     c->operand[0] = SFE_VENDOR_DE_COMPANYID_0;
1311     c->operand[1] = SFE_VENDOR_DE_COMPANYID_1;
1312     c->operand[2] = SFE_VENDOR_DE_COMPANYID_2;
1313     c->operand[3] = SFE_VENDOR_OPCODE_CA2HOST;
1314     c->operand[4] = 0; /* slot */
1315     c->operand[5] = SFE_VENDOR_TAG_CA_MMI;
1316     clear_operands(c, 6, LAST_OPERAND);
1317 
1318     fdtv->avc_data_length = 12;
1319     ret = avc_write(fdtv);
1320     if (ret < 0)
1321         goto out;
1322 
1323     /* FIXME: check response code and validate response data */
1324 
1325     *len = get_ca_object_length(r);
1326     memcpy(mmi_object, &r->operand[get_ca_object_pos(r)], *len);
1327 out:
1328     mutex_unlock(&fdtv->avc_mutex);
1329 
1330     return ret;
1331 }
1332 
1333 #define CMP_OUTPUT_PLUG_CONTROL_REG_0   0xfffff0000904ULL
1334 
1335 static int cmp_read(struct firedtv *fdtv, u64 addr, __be32 *data)
1336 {
1337     int ret;
1338 
1339     ret = fdtv_read(fdtv, addr, data);
1340     if (ret < 0)
1341         dev_err(fdtv->device, "CMP: read I/O error\n");
1342 
1343     return ret;
1344 }
1345 
1346 static int cmp_lock(struct firedtv *fdtv, u64 addr, __be32 data[])
1347 {
1348     int ret;
1349 
1350     ret = fdtv_lock(fdtv, addr, data);
1351     if (ret < 0)
1352         dev_err(fdtv->device, "CMP: lock I/O error\n");
1353 
1354     return ret;
1355 }
1356 
1357 static inline u32 get_opcr(__be32 opcr, u32 mask, u32 shift)
1358 {
1359     return (be32_to_cpu(opcr) >> shift) & mask;
1360 }
1361 
1362 static inline void set_opcr(__be32 *opcr, u32 value, u32 mask, u32 shift)
1363 {
1364     *opcr &= ~cpu_to_be32(mask << shift);
1365     *opcr |= cpu_to_be32((value & mask) << shift);
1366 }
1367 
1368 #define get_opcr_online(v)      get_opcr((v), 0x1, 31)
1369 #define get_opcr_p2p_connections(v) get_opcr((v), 0x3f, 24)
1370 #define get_opcr_channel(v)     get_opcr((v), 0x3f, 16)
1371 
1372 #define set_opcr_p2p_connections(p, v)  set_opcr((p), (v), 0x3f, 24)
1373 #define set_opcr_channel(p, v)      set_opcr((p), (v), 0x3f, 16)
1374 #define set_opcr_data_rate(p, v)    set_opcr((p), (v), 0x3, 14)
1375 #define set_opcr_overhead_id(p, v)  set_opcr((p), (v), 0xf, 10)
1376 
1377 int cmp_establish_pp_connection(struct firedtv *fdtv, int plug, int channel)
1378 {
1379     __be32 old_opcr, opcr[2];
1380     u64 opcr_address = CMP_OUTPUT_PLUG_CONTROL_REG_0 + (plug << 2);
1381     int attempts = 0;
1382     int ret;
1383 
1384     ret = cmp_read(fdtv, opcr_address, opcr);
1385     if (ret < 0)
1386         return ret;
1387 
1388 repeat:
1389     if (!get_opcr_online(*opcr)) {
1390         dev_err(fdtv->device, "CMP: output offline\n");
1391         return -EBUSY;
1392     }
1393 
1394     old_opcr = *opcr;
1395 
1396     if (get_opcr_p2p_connections(*opcr)) {
1397         if (get_opcr_channel(*opcr) != channel) {
1398             dev_err(fdtv->device, "CMP: cannot change channel\n");
1399             return -EBUSY;
1400         }
1401         dev_info(fdtv->device, "CMP: overlaying connection\n");
1402 
1403         /* We don't allocate isochronous resources. */
1404     } else {
1405         set_opcr_channel(opcr, channel);
1406         set_opcr_data_rate(opcr, 2); /* S400 */
1407 
1408         /* FIXME: this is for the worst case - optimize */
1409         set_opcr_overhead_id(opcr, 0);
1410 
1411         /* FIXME: allocate isochronous channel and bandwidth at IRM */
1412     }
1413 
1414     set_opcr_p2p_connections(opcr, get_opcr_p2p_connections(*opcr) + 1);
1415 
1416     opcr[1] = *opcr;
1417     opcr[0] = old_opcr;
1418 
1419     ret = cmp_lock(fdtv, opcr_address, opcr);
1420     if (ret < 0)
1421         return ret;
1422 
1423     if (old_opcr != *opcr) {
1424         /*
1425          * FIXME: if old_opcr.P2P_Connections > 0,
1426          * deallocate isochronous channel and bandwidth at IRM
1427          */
1428 
1429         if (++attempts < 6) /* arbitrary limit */
1430             goto repeat;
1431         return -EBUSY;
1432     }
1433 
1434     return 0;
1435 }
1436 
1437 void cmp_break_pp_connection(struct firedtv *fdtv, int plug, int channel)
1438 {
1439     __be32 old_opcr, opcr[2];
1440     u64 opcr_address = CMP_OUTPUT_PLUG_CONTROL_REG_0 + (plug << 2);
1441     int attempts = 0;
1442 
1443     if (cmp_read(fdtv, opcr_address, opcr) < 0)
1444         return;
1445 
1446 repeat:
1447     if (!get_opcr_online(*opcr) || !get_opcr_p2p_connections(*opcr) ||
1448         get_opcr_channel(*opcr) != channel) {
1449         dev_err(fdtv->device, "CMP: no connection to break\n");
1450         return;
1451     }
1452 
1453     old_opcr = *opcr;
1454     set_opcr_p2p_connections(opcr, get_opcr_p2p_connections(*opcr) - 1);
1455 
1456     opcr[1] = *opcr;
1457     opcr[0] = old_opcr;
1458 
1459     if (cmp_lock(fdtv, opcr_address, opcr) < 0)
1460         return;
1461 
1462     if (old_opcr != *opcr) {
1463         /*
1464          * FIXME: if old_opcr.P2P_Connections == 1, i.e. we were last
1465          * owner, deallocate isochronous channel and bandwidth at IRM
1466          * if (...)
1467          *  fdtv->backend->dealloc_resources(fdtv, channel, bw);
1468          */
1469 
1470         if (++attempts < 6) /* arbitrary limit */
1471             goto repeat;
1472     }
1473 }