]> pilppa.com Git - linux-2.6-omap-h63xx.git/commitdiff
firedtv: massive refactoring
authorStefan Richter <stefanr@s5r6.in-berlin.de>
Mon, 23 Feb 2009 13:21:10 +0000 (14:21 +0100)
committerStefan Richter <stefanr@s5r6.in-berlin.de>
Tue, 24 Feb 2009 13:51:29 +0000 (14:51 +0100)
Combination of the following changes:

Mon, 23 Feb 2009 14:21:10 +0100 (CET)
firedtv: reinstate debug logging option

    Henrik Kurelid tells me that FCP debug logging (which I removed during
    cleanups) is still useful when working on driver issues together with
    end users.  So bring it back in an updated form with only 60% of the
    original code footprint.

    Logging can be enabled with
    # echo -1 > /sys/module/firedtv/parameters/debug

    1 instead of -1 enables only FCP header logging,
    2 instead of -1 enables only hexdumps of the entire FCP frames.
    0 switches logging off again.

Fri, 20 Feb 2009 20:54:27 +0100 (CET)
firedtv: build fix for INPUT=m and DVB_FIREDTV=y

Thu, 19 Feb 2009 20:40:39 +0100
firedtv: use msecs_to_jiffies

    Pointed out by Mauro Carvalho Chehab.

Sun Feb 15 20:50:46 CET 2009
firedtv: some more housekeeping

    Fix an old checkpatch warning and a new compiler warning.

Sun Feb 15 15:33:17 CET 2009
firedtv: rename a file once more

    At the moment, about a third of avc.c is specific to FireDTVs rather
    than generic AV/C code.  Rename it to firedtv-avc.c.

Sun Feb 15 15:33:17 CET 2009
firedtv: dvb demux: more compact channels backing store

    Replace struct firedtv_channel { bool active; int pid; } channel[16];
    by unsigned long channel_active; u16 channel_pid[16];.

Sun Feb 15 15:33:17 CET 2009
firedtv: dvb demux: some simplifications

    c->active was unnecessarily cleared twice.

    Also, by marking the channel inactive before the for loop,
    the loop becomes identical with fdtv_channel_collect().

Sun Feb 15 15:33:17 CET 2009
firedtv: dvb demux: remove a bogus loop

    This loop is unnecessary because
      - only active channel[].pid's will be sent to the device,
      - when a channel is activated, its pid is set to dvbdmxfeed->pid.

    Perhaps the original code was there because it was initially not fully
    covered by the fdtv->demux_mutex.

Sun Feb 15 15:33:17 CET 2009
firedtv: dvb demux: fix mutex protection

    fdtv_start_feed() accessed the channel list unsafely.
    Fully serialize it with itself and fdtv_stop_feed().

Sun Feb 15 15:33:17 CET 2009
firedtv: dvb demux: fix missing braces

    Original code was:
            ...
            case DMX_TS_PES_OTHER:
                    //Dirty fix to keep firesat->channel pid-list up to date
                    for(k=0;k<16;k++){
                            if(firesat->channel[k].active == 0)
                                    firesat->channel[k].pid =
                                            dvbdmxfeed->pid;
                                    break;
                    }
                    channel = firesat_channel_allocate(firesat);
                    break;
            default:
            ...

    Looks bogus in several respects. For now let's just add braces to the if
    because that seems to be what the author meant.

Sun Feb 15 15:33:17 CET 2009
firedtv: allow build without input subsystem

    !CONFIG_INPUT is very unlikely on systems on which firedtv is of
    interest.  But we can easily support it.

Sun Feb 15 15:33:17 CET 2009
firedtv: replace EXTRA_CFLAGS by ccflags

    The former are deprecated.
    The latter can depend on Kconfig variables.

Sun Feb 15 15:33:17 CET 2009
firedtv: concentrate ieee1394 dependencies

    Move the entire interface with drivers/ieee1394 to firedtv-1394.c.
    Move 1394-independent module initialization code to firedtv-dvb.c.

    This prepares interfacing with drivers/firewire.

Sun Feb 15 15:33:17 CET 2009
firedtv: amend Kconfig menu prompt

Sun Feb 15 15:33:17 CET 2009
firedtv: remove kernel version compatibility macro

Sun Feb 15 15:33:17 CET 2009
firedtv: combine header files

    avc.h and firedtv-*.h are small and currently not shared with other
    drivers, hence concatenate them all into firedtv.h.

Sun Feb 15 15:33:17 CET 2009
firedtv: misc style touch-ups

    Standardize on lower-case hexadecimal constants.  Adjust whitespace.
    Omit unnecessary pointer type casts and an unnecessary list head
    initialization.  Use dev_printk.

Wed Feb 11 21:21:04 CET 2009
firedtv: avc, ci: remove unused constants

Wed Feb 11 21:21:04 CET 2009
firedtv: avc: remove bitfields from read descriptor response operands

    Don't use bitfields in struct types of on-the-wire data.

Wed Feb 11 21:21:04 CET 2009
firedtv: avc: remove bitfields from DSD command operands

    Don't use bitfields in struct types of on-the-wire data.

Wed Feb 11 21:21:04 CET 2009
firedtv: avc: header file cleanup

    Remove unused constants and declarations.
    Move privately used constants into .c files.

Wed Feb 11 21:21:04 CET 2009
firedtv: avc: remove bitfields from FCP frame types

    Don't use bitfields in struct types of on-the-wire data.

    Also move many privately used constants from avc.h to avc.c
    and remove some unused constants.

Sun, 18 Jan 2009 16:30:00 +0100 (CET)
firedtv: avc: fix offset in avc_tuner_get_ts

    The parentheses were wrong.  It didn't matter though because this code
    only writes a 0 into an area which is already initialized to 0.

Sun, 18 Jan 2009 16:30:00 +0100 (CET)
firedtv: avc: reduce stack usage, remove two typedefs

    It is safe to share a memory buffer for command frame and response frame
    because the response data come in after the command frame was last used.

    Even less stack would be required if only the actual required frame size
    instead of the entire FCP register size was allocated.

    Also, rename the defined types AVCCmdFrm and AVCRspFrm to
    struct avc_command_frame and struct avc_response_frame.
    TODO:  Remove the bitfields in these types.

Sun, 18 Jan 2009 16:30:00 +0100 (CET)
firedtv: cmp: move code to avc

Sun, 18 Jan 2009 16:30:00 +0100 (CET)
firedtv: iso: move code to firedtv-1394

Sun, 18 Jan 2009 16:30:00 +0100 (CET)
firedtv: iso: remove unnecessary struct type definitions

Sun, 18 Jan 2009 16:30:00 +0100 (CET)
firedtv: iso: style changes and fixlets

    Add cleanup after failure in setup_iso_channel.
    Replace printk() by dv_err().
    Decrease indentation level in rawiso_activity_cb().

Signed-off-by: Stefan Richter <stefanr@s5r6.in-berlin.de>
17 files changed:
drivers/media/dvb/Kconfig
drivers/media/dvb/firewire/Kconfig
drivers/media/dvb/firewire/Makefile
drivers/media/dvb/firewire/avc.c [deleted file]
drivers/media/dvb/firewire/avc.h [deleted file]
drivers/media/dvb/firewire/cmp.c [deleted file]
drivers/media/dvb/firewire/cmp.h [deleted file]
drivers/media/dvb/firewire/firedtv-1394.c
drivers/media/dvb/firewire/firedtv-avc.c [new file with mode: 0644]
drivers/media/dvb/firewire/firedtv-ci.c
drivers/media/dvb/firewire/firedtv-ci.h [deleted file]
drivers/media/dvb/firewire/firedtv-dvb.c
drivers/media/dvb/firewire/firedtv-fe.c
drivers/media/dvb/firewire/firedtv-iso.c [deleted file]
drivers/media/dvb/firewire/firedtv-rc.c
drivers/media/dvb/firewire/firedtv-rc.h [deleted file]
drivers/media/dvb/firewire/firedtv.h

index 5a74c5c62f15310f40851fc67243a7ff9b7a3f7e..b0198691892a4a4ecab85d7febccf554c5dfe381 100644 (file)
@@ -51,6 +51,8 @@ comment "Supported SDMC DM1105 Adapters"
        depends on DVB_CORE && PCI && I2C
 source "drivers/media/dvb/dm1105/Kconfig"
 
+comment "Supported FireWire (IEEE 1394) Adapters"
+       depends on DVB_CORE && IEEE1394
 source "drivers/media/dvb/firewire/Kconfig"
 
 comment "Supported DVB Frontends"
index 03d25ad1035091e4a58e90336625da95d82f12bf..69028253e984f5a8225d0c6cb0d2df5786a25802 100644 (file)
@@ -1,12 +1,22 @@
 config DVB_FIREDTV
-       tristate "FireDTV (FireWire attached DVB receivers)"
-       depends on DVB_CORE && IEEE1394 && INPUT
+       tristate "FireDTV and FloppyDTV"
+       depends on DVB_CORE && IEEE1394
        help
-         Support for DVB receivers from Digital Everywhere, known as FireDTV
-         and FloppyDTV, which are connected via IEEE 1394 (FireWire).
+         Support for DVB receivers from Digital Everywhere
+         which are connected via IEEE 1394 (FireWire).
 
-         These devices don't have an MPEG decoder built in, so you need
-         an external software decoder to watch TV.
+         These devices don't have an MPEG decoder built in,
+         so you need an external software decoder to watch TV.
 
-         To compile this driver as a module, say M here: the module will be
-         called firedtv.
+         To compile this driver as a module, say M here:
+         the module will be called firedtv.
+
+if DVB_FIREDTV
+
+config DVB_FIREDTV_IEEE1394
+       def_bool IEEE1394
+
+config DVB_FIREDTV_INPUT
+       def_bool INPUT = y || (INPUT = m && DVB_FIREDTV = m)
+
+endif # DVB_FIREDTV
index 628dacd10daf1ec83292e31141c8893c58bd6e6f..2034695ba1942abb9a0fc5a354191964dde352fd 100644 (file)
@@ -1,13 +1,8 @@
-firedtv-objs := firedtv-1394.o \
-               firedtv-dvb.o   \
-               firedtv-fe.o    \
-               firedtv-iso.o   \
-               avc.o           \
-               cmp.o           \
-               firedtv-rc.o    \
-               firedtv-ci.o
-
 obj-$(CONFIG_DVB_FIREDTV) += firedtv.o
 
-EXTRA_CFLAGS := -Idrivers/ieee1394
-EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core
+firedtv-y := firedtv-avc.o firedtv-ci.o firedtv-dvb.o firedtv-fe.o
+firedtv-$(CONFIG_DVB_FIREDTV_IEEE1394) += firedtv-1394.o
+firedtv-$(CONFIG_DVB_FIREDTV_INPUT)    += firedtv-rc.o
+
+ccflags-y += -Idrivers/media/dvb/dvb-core
+ccflags-$(CONFIG_DVB_FIREDTV_IEEE1394) += -Idrivers/ieee1394
diff --git a/drivers/media/dvb/firewire/avc.c b/drivers/media/dvb/firewire/avc.c
deleted file mode 100644 (file)
index 847a537..0000000
+++ /dev/null
@@ -1,1051 +0,0 @@
-/*
- * FireDTV driver (formerly known as FireSAT)
- *
- * Copyright (C) 2004 Andreas Monitzer <andy@monitzer.com>
- * Copyright (C) 2008 Ben Backx <ben@bbackx.com>
- * Copyright (C) 2008 Henrik Kurelid <henrik@kurelid.se>
- *
- *     This program is free software; you can redistribute it and/or
- *     modify it under the terms of the GNU General Public License as
- *     published by the Free Software Foundation; either version 2 of
- *     the License, or (at your option) any later version.
- */
-
-#include <linux/bug.h>
-#include <linux/crc32.h>
-#include <linux/delay.h>
-#include <linux/device.h>
-#include <linux/kernel.h>
-#include <linux/moduleparam.h>
-#include <linux/mutex.h>
-#include <linux/string.h>
-#include <linux/wait.h>
-#include <linux/workqueue.h>
-
-#include <ieee1394_transactions.h>
-#include <nodemgr.h>
-
-#include "avc.h"
-#include "firedtv.h"
-#include "firedtv-rc.h"
-
-#define FCP_COMMAND_REGISTER   0xfffff0000b00ULL
-
-static int __avc_write(struct firedtv *fdtv,
-                      const AVCCmdFrm *CmdFrm, AVCRspFrm *RspFrm)
-{
-       int err, retry;
-
-       if (RspFrm)
-               fdtv->avc_reply_received = false;
-
-       for (retry = 0; retry < 6; retry++) {
-               err = hpsb_node_write(fdtv->ud->ne, FCP_COMMAND_REGISTER,
-                                     (quadlet_t *)CmdFrm, CmdFrm->length);
-               if (err) {
-                       fdtv->avc_reply_received = true;
-                       dev_err(&fdtv->ud->device,
-                               "FCP command write failed\n");
-                       return err;
-               }
-
-               if (!RspFrm)
-                       return 0;
-
-               /*
-                * AV/C specs say that answers should be sent within 150 ms.
-                * Time out after 200 ms.
-                */
-               if (wait_event_timeout(fdtv->avc_wait,
-                                      fdtv->avc_reply_received,
-                                      HZ / 5) != 0) {
-                       memcpy(RspFrm, fdtv->respfrm, fdtv->resp_length);
-                       RspFrm->length = fdtv->resp_length;
-
-                       return 0;
-               }
-       }
-       dev_err(&fdtv->ud->device, "FCP response timed out\n");
-       return -ETIMEDOUT;
-}
-
-static int avc_write(struct firedtv *fdtv,
-                    const AVCCmdFrm *CmdFrm, AVCRspFrm *RspFrm)
-{
-       int ret;
-
-       if (mutex_lock_interruptible(&fdtv->avc_mutex))
-               return -EINTR;
-
-       ret = __avc_write(fdtv, CmdFrm, RspFrm);
-
-       mutex_unlock(&fdtv->avc_mutex);
-       return ret;
-}
-
-int avc_recv(struct firedtv *fdtv, u8 *data, size_t length)
-{
-       AVCRspFrm *RspFrm = (AVCRspFrm *)data;
-
-       if (length >= 8 &&
-           RspFrm->operand[0] == SFE_VENDOR_DE_COMPANYID_0 &&
-           RspFrm->operand[1] == SFE_VENDOR_DE_COMPANYID_1 &&
-           RspFrm->operand[2] == SFE_VENDOR_DE_COMPANYID_2 &&
-           RspFrm->operand[3] == SFE_VENDOR_OPCODE_REGISTER_REMOTE_CONTROL) {
-               if (RspFrm->resp == CHANGED) {
-                       fdtv_handle_rc(fdtv,
-                           RspFrm->operand[4] << 8 | RspFrm->operand[5]);
-                       schedule_work(&fdtv->remote_ctrl_work);
-               } else if (RspFrm->resp != INTERIM) {
-                       dev_info(&fdtv->ud->device,
-                                "remote control result = %d\n", RspFrm->resp);
-               }
-               return 0;
-       }
-
-       if (fdtv->avc_reply_received) {
-               dev_err(&fdtv->ud->device,
-                       "received out-of-order AVC response, ignored\n");
-               return -EIO;
-       }
-
-       memcpy(fdtv->respfrm, data, length);
-       fdtv->resp_length = length;
-
-       fdtv->avc_reply_received = true;
-       wake_up(&fdtv->avc_wait);
-
-       return 0;
-}
-
-/*
- * tuning command for setting the relative LNB frequency
- * (not supported by the AVC standard)
- */
-static void avc_tuner_tuneqpsk(struct firedtv *fdtv,
-               struct dvb_frontend_parameters *params, AVCCmdFrm *CmdFrm)
-{
-       CmdFrm->opcode = VENDOR;
-
-       CmdFrm->operand[0] = SFE_VENDOR_DE_COMPANYID_0;
-       CmdFrm->operand[1] = SFE_VENDOR_DE_COMPANYID_1;
-       CmdFrm->operand[2] = SFE_VENDOR_DE_COMPANYID_2;
-       CmdFrm->operand[3] = SFE_VENDOR_OPCODE_TUNE_QPSK;
-
-       CmdFrm->operand[4] = (params->frequency >> 24) & 0xff;
-       CmdFrm->operand[5] = (params->frequency >> 16) & 0xff;
-       CmdFrm->operand[6] = (params->frequency >> 8) & 0xff;
-       CmdFrm->operand[7] = params->frequency & 0xff;
-
-       CmdFrm->operand[8] = ((params->u.qpsk.symbol_rate / 1000) >> 8) & 0xff;
-       CmdFrm->operand[9] = (params->u.qpsk.symbol_rate / 1000) & 0xff;
-
-       switch(params->u.qpsk.fec_inner) {
-       case FEC_1_2:
-               CmdFrm->operand[10] = 0x1; break;
-       case FEC_2_3:
-               CmdFrm->operand[10] = 0x2; break;
-       case FEC_3_4:
-               CmdFrm->operand[10] = 0x3; break;
-       case FEC_5_6:
-               CmdFrm->operand[10] = 0x4; break;
-       case FEC_7_8:
-               CmdFrm->operand[10] = 0x5; break;
-       case FEC_4_5:
-       case FEC_8_9:
-       case FEC_AUTO:
-       default:
-               CmdFrm->operand[10] = 0x0;
-       }
-
-       if (fdtv->voltage == 0xff)
-               CmdFrm->operand[11] = 0xff;
-       else if (fdtv->voltage == SEC_VOLTAGE_18) /* polarisation */
-               CmdFrm->operand[11] = 0;
-       else
-               CmdFrm->operand[11] = 1;
-
-       if (fdtv->tone == 0xff)
-               CmdFrm->operand[12] = 0xff;
-       else if (fdtv->tone == SEC_TONE_ON) /* band */
-               CmdFrm->operand[12] = 1;
-       else
-               CmdFrm->operand[12] = 0;
-
-       if (fdtv->type == FIREDTV_DVB_S2) {
-               CmdFrm->operand[13] = 0x1;
-               CmdFrm->operand[14] = 0xff;
-               CmdFrm->operand[15] = 0xff;
-               CmdFrm->length = 20;
-       } else {
-               CmdFrm->length = 16;
-       }
-}
-
-static void avc_tuner_dsd_dvb_c(struct dvb_frontend_parameters *params,
-               AVCCmdFrm *CmdFrm)
-{
-       M_VALID_FLAGS flags;
-
-       flags.Bits.Modulation = params->u.qam.modulation != QAM_AUTO;
-       flags.Bits.FEC_inner = params->u.qam.fec_inner != FEC_AUTO;
-       flags.Bits.FEC_outer = 0;
-       flags.Bits.Symbol_Rate = 1;
-       flags.Bits.Frequency = 1;
-       flags.Bits.Orbital_Pos = 0;
-       flags.Bits.Polarisation = 0;
-       flags.Bits.reserved_fields = 0;
-       flags.Bits.reserved1 = 0;
-       flags.Bits.Network_ID = 0;
-
-       CmdFrm->opcode  = DSD;
-
-       CmdFrm->operand[0]  = 0;    /* source plug */
-       CmdFrm->operand[1]  = 0xd2; /* subfunction replace */
-       CmdFrm->operand[2]  = 0x20; /* system id = DVB */
-       CmdFrm->operand[3]  = 0x00; /* antenna number */
-       /* system_specific_multiplex selection_length */
-       CmdFrm->operand[4]  = 0x11;
-       CmdFrm->operand[5]  = flags.Valid_Word.ByteHi; /* valid_flags [0] */
-       CmdFrm->operand[6]  = flags.Valid_Word.ByteLo; /* valid_flags [1] */
-       CmdFrm->operand[7]  = 0x00;
-       CmdFrm->operand[8]  = 0x00;
-       CmdFrm->operand[9]  = 0x00;
-       CmdFrm->operand[10] = 0x00;
-
-       CmdFrm->operand[11] =
-               (((params->frequency / 4000) >> 16) & 0xff) | (2 << 6);
-       CmdFrm->operand[12] =
-               ((params->frequency / 4000) >> 8) & 0xff;
-       CmdFrm->operand[13] = (params->frequency / 4000) & 0xff;
-       CmdFrm->operand[14] =
-               ((params->u.qpsk.symbol_rate / 1000) >> 12) & 0xff;
-       CmdFrm->operand[15] =
-               ((params->u.qpsk.symbol_rate / 1000) >> 4) & 0xff;
-       CmdFrm->operand[16] =
-               ((params->u.qpsk.symbol_rate / 1000) << 4) & 0xf0;
-       CmdFrm->operand[17] = 0x00;
-
-       switch (params->u.qpsk.fec_inner) {
-       case FEC_1_2:
-               CmdFrm->operand[18] = 0x1; break;
-       case FEC_2_3:
-               CmdFrm->operand[18] = 0x2; break;
-       case FEC_3_4:
-               CmdFrm->operand[18] = 0x3; break;
-       case FEC_5_6:
-               CmdFrm->operand[18] = 0x4; break;
-       case FEC_7_8:
-               CmdFrm->operand[18] = 0x5; break;
-       case FEC_8_9:
-               CmdFrm->operand[18] = 0x6; break;
-       case FEC_4_5:
-               CmdFrm->operand[18] = 0x8; break;
-       case FEC_AUTO:
-       default:
-               CmdFrm->operand[18] = 0x0;
-       }
-       switch (params->u.qam.modulation) {
-       case QAM_16:
-               CmdFrm->operand[19] = 0x08; break;
-       case QAM_32:
-               CmdFrm->operand[19] = 0x10; break;
-       case QAM_64:
-               CmdFrm->operand[19] = 0x18; break;
-       case QAM_128:
-               CmdFrm->operand[19] = 0x20; break;
-       case QAM_256:
-               CmdFrm->operand[19] = 0x28; break;
-       case QAM_AUTO:
-       default:
-               CmdFrm->operand[19] = 0x00;
-       }
-       CmdFrm->operand[20] = 0x00;
-       CmdFrm->operand[21] = 0x00;
-       /* Nr_of_dsd_sel_specs = 0 -> no PIDs are transmitted */
-       CmdFrm->operand[22] = 0x00;
-
-       CmdFrm->length = 28;
-}
-
-static void avc_tuner_dsd_dvb_t(struct dvb_frontend_parameters *params,
-               AVCCmdFrm *CmdFrm)
-{
-       M_VALID_FLAGS flags;
-
-       flags.Bits_T.GuardInterval =
-               params->u.ofdm.guard_interval != GUARD_INTERVAL_AUTO;
-       flags.Bits_T.CodeRateLPStream =
-               params->u.ofdm.code_rate_LP != FEC_AUTO;
-       flags.Bits_T.CodeRateHPStream =
-               params->u.ofdm.code_rate_HP != FEC_AUTO;
-       flags.Bits_T.HierarchyInfo =
-               params->u.ofdm.hierarchy_information != HIERARCHY_AUTO;
-       flags.Bits_T.Constellation =
-               params->u.ofdm.constellation != QAM_AUTO;
-       flags.Bits_T.Bandwidth =
-               params->u.ofdm.bandwidth != BANDWIDTH_AUTO;
-       flags.Bits_T.CenterFrequency = 1;
-       flags.Bits_T.reserved1 = 0;
-       flags.Bits_T.reserved2 = 0;
-       flags.Bits_T.OtherFrequencyFlag = 0;
-       flags.Bits_T.TransmissionMode =
-               params->u.ofdm.transmission_mode != TRANSMISSION_MODE_AUTO;
-       flags.Bits_T.NetworkId = 0;
-
-       CmdFrm->opcode  = DSD;
-
-       CmdFrm->operand[0]  = 0;    /* source plug */
-       CmdFrm->operand[1]  = 0xd2; /* subfunction replace */
-       CmdFrm->operand[2]  = 0x20; /* system id = DVB */
-       CmdFrm->operand[3]  = 0x00; /* antenna number */
-       /* system_specific_multiplex selection_length */
-       CmdFrm->operand[4]  = 0x0c;
-       CmdFrm->operand[5]  = flags.Valid_Word.ByteHi; /* valid_flags [0] */
-       CmdFrm->operand[6]  = flags.Valid_Word.ByteLo; /* valid_flags [1] */
-       CmdFrm->operand[7]  = 0x0;
-       CmdFrm->operand[8]  = (params->frequency / 10) >> 24;
-       CmdFrm->operand[9]  = ((params->frequency / 10) >> 16) & 0xff;
-       CmdFrm->operand[10] = ((params->frequency / 10) >>  8) & 0xff;
-       CmdFrm->operand[11] = (params->frequency / 10) & 0xff;
-
-       switch (params->u.ofdm.bandwidth) {
-       case BANDWIDTH_7_MHZ:
-               CmdFrm->operand[12] = 0x20; break;
-       case BANDWIDTH_8_MHZ:
-       case BANDWIDTH_6_MHZ: /* not defined by AVC spec */
-       case BANDWIDTH_AUTO:
-       default:
-               CmdFrm->operand[12] = 0x00;
-       }
-       switch (params->u.ofdm.constellation) {
-       case QAM_16:
-               CmdFrm->operand[13] = 1 << 6; break;
-       case QAM_64:
-               CmdFrm->operand[13] = 2 << 6; break;
-       case QPSK:
-       default:
-               CmdFrm->operand[13] = 0x00;
-       }
-       switch (params->u.ofdm.hierarchy_information) {
-       case HIERARCHY_1:
-               CmdFrm->operand[13] |= 1 << 3; break;
-       case HIERARCHY_2:
-               CmdFrm->operand[13] |= 2 << 3; break;
-       case HIERARCHY_4:
-               CmdFrm->operand[13] |= 3 << 3; break;
-       case HIERARCHY_AUTO:
-       case HIERARCHY_NONE:
-       default:
-               break;
-       }
-       switch (params->u.ofdm.code_rate_HP) {
-       case FEC_2_3:
-               CmdFrm->operand[13] |= 1; break;
-       case FEC_3_4:
-               CmdFrm->operand[13] |= 2; break;
-       case FEC_5_6:
-               CmdFrm->operand[13] |= 3; break;
-       case FEC_7_8:
-               CmdFrm->operand[13] |= 4; break;
-       case FEC_1_2:
-       default:
-               break;
-       }
-       switch (params->u.ofdm.code_rate_LP) {
-       case FEC_2_3:
-               CmdFrm->operand[14] = 1 << 5; break;
-       case FEC_3_4:
-               CmdFrm->operand[14] = 2 << 5; break;
-       case FEC_5_6:
-               CmdFrm->operand[14] = 3 << 5; break;
-       case FEC_7_8:
-               CmdFrm->operand[14] = 4 << 5; break;
-       case FEC_1_2:
-       default:
-               CmdFrm->operand[14] = 0x00; break;
-       }
-       switch (params->u.ofdm.guard_interval) {
-       case GUARD_INTERVAL_1_16:
-               CmdFrm->operand[14] |= 1 << 3; break;
-       case GUARD_INTERVAL_1_8:
-               CmdFrm->operand[14] |= 2 << 3; break;
-       case GUARD_INTERVAL_1_4:
-               CmdFrm->operand[14] |= 3 << 3; break;
-       case GUARD_INTERVAL_1_32:
-       case GUARD_INTERVAL_AUTO:
-       default:
-               break;
-       }
-       switch (params->u.ofdm.transmission_mode) {
-       case TRANSMISSION_MODE_8K:
-               CmdFrm->operand[14] |= 1 << 1; break;
-       case TRANSMISSION_MODE_2K:
-       case TRANSMISSION_MODE_AUTO:
-       default:
-               break;
-       }
-
-       CmdFrm->operand[15] = 0x00; /* network_ID[0] */
-       CmdFrm->operand[16] = 0x00; /* network_ID[1] */
-       /* Nr_of_dsd_sel_specs = 0 -> no PIDs are transmitted */
-       CmdFrm->operand[17] = 0x00;
-
-       CmdFrm->length = 24;
-}
-
-int avc_tuner_dsd(struct firedtv *fdtv,
-                 struct dvb_frontend_parameters *params)
-{
-       AVCCmdFrm CmdFrm;
-       AVCRspFrm RspFrm;
-
-       memset(&CmdFrm, 0, sizeof(AVCCmdFrm));
-
-       CmdFrm.cts      = AVC;
-       CmdFrm.ctype    = CONTROL;
-       CmdFrm.sutyp    = 0x5;
-       CmdFrm.suid     = fdtv->subunit;
-
-       switch (fdtv->type) {
-       case FIREDTV_DVB_S:
-       case FIREDTV_DVB_S2:
-               avc_tuner_tuneqpsk(fdtv, params, &CmdFrm); break;
-       case FIREDTV_DVB_C:
-               avc_tuner_dsd_dvb_c(params, &CmdFrm); break;
-       case FIREDTV_DVB_T:
-               avc_tuner_dsd_dvb_t(params, &CmdFrm); break;
-       default:
-               BUG();
-       }
-
-       if (avc_write(fdtv, &CmdFrm, &RspFrm) < 0)
-               return -EIO;
-
-       msleep(500);
-#if 0
-       /* FIXME: */
-       /* u8 *status was an out-parameter of avc_tuner_dsd, unused by caller */
-       if(status)
-               *status=RspFrm.operand[2];
-#endif
-       return 0;
-}
-
-int avc_tuner_set_pids(struct firedtv *fdtv, unsigned char pidc, u16 pid[])
-{
-       AVCCmdFrm CmdFrm;
-       AVCRspFrm RspFrm;
-       int pos, k;
-
-       if (pidc > 16 && pidc != 0xff)
-               return -EINVAL;
-
-       memset(&CmdFrm, 0, sizeof(AVCCmdFrm));
-
-       CmdFrm.cts      = AVC;
-       CmdFrm.ctype    = CONTROL;
-       CmdFrm.sutyp    = 0x5;
-       CmdFrm.suid     = fdtv->subunit;
-       CmdFrm.opcode   = DSD;
-
-       CmdFrm.operand[0]  = 0; // source plug
-       CmdFrm.operand[1]  = 0xD2; // subfunction replace
-       CmdFrm.operand[2]  = 0x20; // system id = DVB
-       CmdFrm.operand[3]  = 0x00; // antenna number
-       CmdFrm.operand[4]  = 0x00; // system_specific_multiplex selection_length
-       CmdFrm.operand[5]  = pidc; // Nr_of_dsd_sel_specs
-
-       pos = 6;
-       if (pidc != 0xff)
-               for (k = 0; k < pidc; k++) {
-                       CmdFrm.operand[pos++] = 0x13; // flowfunction relay
-                       CmdFrm.operand[pos++] = 0x80; // dsd_sel_spec_valid_flags -> PID
-                       CmdFrm.operand[pos++] = (pid[k] >> 8) & 0x1F;
-                       CmdFrm.operand[pos++] = pid[k] & 0xFF;
-                       CmdFrm.operand[pos++] = 0x00; // tableID
-                       CmdFrm.operand[pos++] = 0x00; // filter_length
-               }
-
-       CmdFrm.length = ALIGN(3 + pos, 4);
-
-       if (avc_write(fdtv, &CmdFrm, &RspFrm) < 0)
-               return -EIO;
-
-       msleep(50);
-       return 0;
-}
-
-int avc_tuner_get_ts(struct firedtv *fdtv)
-{
-       AVCCmdFrm CmdFrm;
-       AVCRspFrm RspFrm;
-
-       memset(&CmdFrm, 0, sizeof(AVCCmdFrm));
-
-       CmdFrm.cts              = AVC;
-       CmdFrm.ctype    = CONTROL;
-       CmdFrm.sutyp    = 0x5;
-       CmdFrm.suid             = fdtv->subunit;
-       CmdFrm.opcode   = DSIT;
-
-       CmdFrm.operand[0]  = 0; // source plug
-       CmdFrm.operand[1]  = 0xD2; // subfunction replace
-       CmdFrm.operand[2]  = 0xFF; //status
-       CmdFrm.operand[3]  = 0x20; // system id = DVB
-       CmdFrm.operand[4]  = 0x00; // antenna number
-       CmdFrm.operand[5]  = 0x0;  // system_specific_search_flags
-       CmdFrm.operand[6]  = (fdtv->type == FIREDTV_DVB_T)?0x0c:0x11; // system_specific_multiplex selection_length
-       CmdFrm.operand[7]  = 0x00; // valid_flags [0]
-       CmdFrm.operand[8]  = 0x00; // valid_flags [1]
-       CmdFrm.operand[7 + (fdtv->type == FIREDTV_DVB_T)?0x0c:0x11] = 0x00; // nr_of_dsit_sel_specs (always 0)
-
-       CmdFrm.length = (fdtv->type == FIREDTV_DVB_T)?24:28;
-
-       if (avc_write(fdtv, &CmdFrm, &RspFrm) < 0)
-               return -EIO;
-
-       msleep(250);
-       return 0;
-}
-
-int avc_identify_subunit(struct firedtv *fdtv)
-{
-       AVCCmdFrm CmdFrm;
-       AVCRspFrm RspFrm;
-
-       memset(&CmdFrm,0,sizeof(AVCCmdFrm));
-
-       CmdFrm.cts = AVC;
-       CmdFrm.ctype = CONTROL;
-       CmdFrm.sutyp = 0x5; // tuner
-       CmdFrm.suid = fdtv->subunit;
-       CmdFrm.opcode = READ_DESCRIPTOR;
-
-       CmdFrm.operand[0]=DESCRIPTOR_SUBUNIT_IDENTIFIER;
-       CmdFrm.operand[1]=0xff;
-       CmdFrm.operand[2]=0x00;
-       CmdFrm.operand[3]=0x00; // length highbyte
-       CmdFrm.operand[4]=0x08; // length lowbyte
-       CmdFrm.operand[5]=0x00; // offset highbyte
-       CmdFrm.operand[6]=0x0d; // offset lowbyte
-
-       CmdFrm.length=12;
-
-       if (avc_write(fdtv, &CmdFrm, &RspFrm) < 0)
-               return -EIO;
-
-       if ((RspFrm.resp != STABLE && RspFrm.resp != ACCEPTED) ||
-           (RspFrm.operand[3] << 8) + RspFrm.operand[4] != 8) {
-               dev_err(&fdtv->ud->device,
-                       "cannot read subunit identifier\n");
-               return -EINVAL;
-       }
-       return 0;
-}
-
-int avc_tuner_status(struct firedtv *fdtv,
-                    ANTENNA_INPUT_INFO *antenna_input_info)
-{
-       AVCCmdFrm CmdFrm;
-       AVCRspFrm RspFrm;
-       int length;
-
-       memset(&CmdFrm, 0, sizeof(AVCCmdFrm));
-
-       CmdFrm.cts=AVC;
-       CmdFrm.ctype=CONTROL;
-       CmdFrm.sutyp=0x05; // tuner
-       CmdFrm.suid=fdtv->subunit;
-       CmdFrm.opcode=READ_DESCRIPTOR;
-
-       CmdFrm.operand[0]=DESCRIPTOR_TUNER_STATUS;
-       CmdFrm.operand[1]=0xff; //read_result_status
-       CmdFrm.operand[2]=0x00; // reserver
-       CmdFrm.operand[3]=0;//sizeof(ANTENNA_INPUT_INFO) >> 8;
-       CmdFrm.operand[4]=0;//sizeof(ANTENNA_INPUT_INFO) & 0xFF;
-       CmdFrm.operand[5]=0x00;
-       CmdFrm.operand[6]=0x00;
-       CmdFrm.length=12;
-
-       if (avc_write(fdtv, &CmdFrm, &RspFrm) < 0)
-               return -EIO;
-
-       if (RspFrm.resp != STABLE && RspFrm.resp != ACCEPTED) {
-               dev_err(&fdtv->ud->device, "cannot read tuner status\n");
-               return -EINVAL;
-       }
-
-       length = RspFrm.operand[9];
-       if (RspFrm.operand[1] != 0x10 || length != sizeof(ANTENNA_INPUT_INFO)) {
-               dev_err(&fdtv->ud->device, "got invalid tuner status\n");
-               return -EINVAL;
-       }
-
-       memcpy(antenna_input_info, &RspFrm.operand[10], length);
-       return 0;
-}
-
-int avc_lnb_control(struct firedtv *fdtv, char voltage, char burst,
-                   char conttone, char nrdiseq,
-                   struct dvb_diseqc_master_cmd *diseqcmd)
-{
-       AVCCmdFrm CmdFrm;
-       AVCRspFrm RspFrm;
-       int i, j, k;
-
-       memset(&CmdFrm, 0, sizeof(AVCCmdFrm));
-
-       CmdFrm.cts=AVC;
-       CmdFrm.ctype=CONTROL;
-       CmdFrm.sutyp=0x05;
-       CmdFrm.suid=fdtv->subunit;
-       CmdFrm.opcode=VENDOR;
-
-       CmdFrm.operand[0]=SFE_VENDOR_DE_COMPANYID_0;
-       CmdFrm.operand[1]=SFE_VENDOR_DE_COMPANYID_1;
-       CmdFrm.operand[2]=SFE_VENDOR_DE_COMPANYID_2;
-       CmdFrm.operand[3]=SFE_VENDOR_OPCODE_LNB_CONTROL;
-
-       CmdFrm.operand[4]=voltage;
-       CmdFrm.operand[5]=nrdiseq;
-
-       i=6;
-
-       for (j = 0; j < nrdiseq; j++) {
-               CmdFrm.operand[i++] = diseqcmd[j].msg_len;
-
-               for (k = 0; k < diseqcmd[j].msg_len; k++)
-                       CmdFrm.operand[i++] = diseqcmd[j].msg[k];
-       }
-
-       CmdFrm.operand[i++]=burst;
-       CmdFrm.operand[i++]=conttone;
-
-       CmdFrm.length = ALIGN(3 + i, 4);
-
-       if (avc_write(fdtv, &CmdFrm, &RspFrm) < 0)
-               return -EIO;
-
-       if (RspFrm.resp != ACCEPTED) {
-               dev_err(&fdtv->ud->device, "LNB control failed\n");
-               return -EINVAL;
-       }
-
-       return 0;
-}
-
-int avc_register_remote_control(struct firedtv *fdtv)
-{
-       AVCCmdFrm CmdFrm;
-
-       memset(&CmdFrm, 0, sizeof(AVCCmdFrm));
-
-       CmdFrm.cts = AVC;
-       CmdFrm.ctype = NOTIFY;
-       CmdFrm.sutyp = 0x1f;
-       CmdFrm.suid = 0x7;
-       CmdFrm.opcode = VENDOR;
-
-       CmdFrm.operand[0] = SFE_VENDOR_DE_COMPANYID_0;
-       CmdFrm.operand[1] = SFE_VENDOR_DE_COMPANYID_1;
-       CmdFrm.operand[2] = SFE_VENDOR_DE_COMPANYID_2;
-       CmdFrm.operand[3] = SFE_VENDOR_OPCODE_REGISTER_REMOTE_CONTROL;
-
-       CmdFrm.length = 8;
-
-       return avc_write(fdtv, &CmdFrm, NULL);
-}
-
-void avc_remote_ctrl_work(struct work_struct *work)
-{
-       struct firedtv *fdtv =
-                       container_of(work, struct firedtv, remote_ctrl_work);
-
-       /* Should it be rescheduled in failure cases? */
-       avc_register_remote_control(fdtv);
-}
-
-#if 0 /* FIXME: unused */
-int avc_tuner_host2ca(struct firedtv *fdtv)
-{
-       AVCCmdFrm CmdFrm;
-       AVCRspFrm RspFrm;
-
-       memset(&CmdFrm, 0, sizeof(AVCCmdFrm));
-       CmdFrm.cts = AVC;
-       CmdFrm.ctype = CONTROL;
-       CmdFrm.sutyp = 0x5;
-       CmdFrm.suid = fdtv->subunit;
-       CmdFrm.opcode = VENDOR;
-
-       CmdFrm.operand[0]=SFE_VENDOR_DE_COMPANYID_0;
-       CmdFrm.operand[1]=SFE_VENDOR_DE_COMPANYID_1;
-       CmdFrm.operand[2]=SFE_VENDOR_DE_COMPANYID_2;
-       CmdFrm.operand[3]=SFE_VENDOR_OPCODE_HOST2CA;
-       CmdFrm.operand[4] = 0; // slot
-       CmdFrm.operand[5] = SFE_VENDOR_TAG_CA_APPLICATION_INFO; // ca tag
-       CmdFrm.operand[6] = 0; // more/last
-       CmdFrm.operand[7] = 0; // length
-       CmdFrm.length = 12;
-
-       if (avc_write(fdtv, &CmdFrm, &RspFrm) < 0)
-               return -EIO;
-
-       return 0;
-}
-#endif
-
-static int get_ca_object_pos(AVCRspFrm *RspFrm)
-{
-       int length = 1;
-
-       /* Check length of length field */
-       if (RspFrm->operand[7] & 0x80)
-               length = (RspFrm->operand[7] & 0x7f) + 1;
-       return length + 7;
-}
-
-static int get_ca_object_length(AVCRspFrm *RspFrm)
-{
-#if 0 /* FIXME: unused */
-       int size = 0;
-       int i;
-
-       if (RspFrm->operand[7] & 0x80)
-               for (i = 0; i < (RspFrm->operand[7] & 0x7f); i++) {
-                       size <<= 8;
-                       size += RspFrm->operand[8 + i];
-               }
-#endif
-       return RspFrm->operand[7];
-}
-
-int avc_ca_app_info(struct firedtv *fdtv, char *app_info, unsigned int *len)
-{
-       AVCCmdFrm CmdFrm;
-       AVCRspFrm RspFrm;
-       int pos;
-
-       memset(&CmdFrm, 0, sizeof(AVCCmdFrm));
-       CmdFrm.cts = AVC;
-       CmdFrm.ctype = STATUS;
-       CmdFrm.sutyp = 0x5;
-       CmdFrm.suid = fdtv->subunit;
-       CmdFrm.opcode = VENDOR;
-
-       CmdFrm.operand[0]=SFE_VENDOR_DE_COMPANYID_0;
-       CmdFrm.operand[1]=SFE_VENDOR_DE_COMPANYID_1;
-       CmdFrm.operand[2]=SFE_VENDOR_DE_COMPANYID_2;
-       CmdFrm.operand[3]=SFE_VENDOR_OPCODE_CA2HOST;
-       CmdFrm.operand[4] = 0; // slot
-       CmdFrm.operand[5] = SFE_VENDOR_TAG_CA_APPLICATION_INFO; // ca tag
-       CmdFrm.length = 12;
-
-       if (avc_write(fdtv, &CmdFrm, &RspFrm) < 0)
-               return -EIO;
-
-       /* FIXME: check response code and validate response data */
-
-       pos = get_ca_object_pos(&RspFrm);
-       app_info[0] = (TAG_APP_INFO >> 16) & 0xFF;
-       app_info[1] = (TAG_APP_INFO >> 8) & 0xFF;
-       app_info[2] = (TAG_APP_INFO >> 0) & 0xFF;
-       app_info[3] = 6 + RspFrm.operand[pos + 4];
-       app_info[4] = 0x01;
-       memcpy(&app_info[5], &RspFrm.operand[pos], 5 + RspFrm.operand[pos + 4]);
-       *len = app_info[3] + 4;
-
-       return 0;
-}
-
-int avc_ca_info(struct firedtv *fdtv, char *app_info, unsigned int *len)
-{
-       AVCCmdFrm CmdFrm;
-       AVCRspFrm RspFrm;
-       int pos;
-
-       memset(&CmdFrm, 0, sizeof(AVCCmdFrm));
-       CmdFrm.cts = AVC;
-       CmdFrm.ctype = STATUS;
-       CmdFrm.sutyp = 0x5;
-       CmdFrm.suid = fdtv->subunit;
-       CmdFrm.opcode = VENDOR;
-
-       CmdFrm.operand[0]=SFE_VENDOR_DE_COMPANYID_0;
-       CmdFrm.operand[1]=SFE_VENDOR_DE_COMPANYID_1;
-       CmdFrm.operand[2]=SFE_VENDOR_DE_COMPANYID_2;
-       CmdFrm.operand[3]=SFE_VENDOR_OPCODE_CA2HOST;
-       CmdFrm.operand[4] = 0; // slot
-       CmdFrm.operand[5] = SFE_VENDOR_TAG_CA_APPLICATION_INFO; // ca tag
-       CmdFrm.length = 12;
-
-       if (avc_write(fdtv, &CmdFrm, &RspFrm) < 0)
-               return -EIO;
-
-       pos = get_ca_object_pos(&RspFrm);
-       app_info[0] = (TAG_CA_INFO >> 16) & 0xFF;
-       app_info[1] = (TAG_CA_INFO >> 8) & 0xFF;
-       app_info[2] = (TAG_CA_INFO >> 0) & 0xFF;
-       app_info[3] = 2;
-       app_info[4] = RspFrm.operand[pos + 0];
-       app_info[5] = RspFrm.operand[pos + 1];
-       *len = app_info[3] + 4;
-
-       return 0;
-}
-
-int avc_ca_reset(struct firedtv *fdtv)
-{
-       AVCCmdFrm CmdFrm;
-       AVCRspFrm RspFrm;
-
-       memset(&CmdFrm, 0, sizeof(AVCCmdFrm));
-       CmdFrm.cts = AVC;
-       CmdFrm.ctype = CONTROL;
-       CmdFrm.sutyp = 0x5;
-       CmdFrm.suid = fdtv->subunit;
-       CmdFrm.opcode = VENDOR;
-
-       CmdFrm.operand[0]=SFE_VENDOR_DE_COMPANYID_0;
-       CmdFrm.operand[1]=SFE_VENDOR_DE_COMPANYID_1;
-       CmdFrm.operand[2]=SFE_VENDOR_DE_COMPANYID_2;
-       CmdFrm.operand[3]=SFE_VENDOR_OPCODE_HOST2CA;
-       CmdFrm.operand[4] = 0; // slot
-       CmdFrm.operand[5] = SFE_VENDOR_TAG_CA_RESET; // ca tag
-       CmdFrm.operand[6] = 0; // more/last
-       CmdFrm.operand[7] = 1; // length
-       CmdFrm.operand[8] = 0; // force hardware reset
-       CmdFrm.length = 12;
-
-       if (avc_write(fdtv, &CmdFrm, &RspFrm) < 0)
-               return -EIO;
-
-       return 0;
-}
-
-int avc_ca_pmt(struct firedtv *fdtv, char *msg, int length)
-{
-       AVCCmdFrm CmdFrm;
-       AVCRspFrm RspFrm;
-       int list_management;
-       int program_info_length;
-       int pmt_cmd_id;
-       int read_pos;
-       int write_pos;
-       int es_info_length;
-       int crc32_csum;
-
-       memset(&CmdFrm, 0, sizeof(AVCCmdFrm));
-       CmdFrm.cts = AVC;
-       CmdFrm.ctype = CONTROL;
-       CmdFrm.sutyp = 0x5;
-       CmdFrm.suid = fdtv->subunit;
-       CmdFrm.opcode = VENDOR;
-
-       if (msg[0] != LIST_MANAGEMENT_ONLY) {
-               dev_info(&fdtv->ud->device,
-                        "forcing list_management to ONLY\n");
-               msg[0] = LIST_MANAGEMENT_ONLY;
-       }
-       // We take the cmd_id from the programme level only!
-       list_management = msg[0];
-       program_info_length = ((msg[4] & 0x0F) << 8) + msg[5];
-       if (program_info_length > 0)
-               program_info_length--; // Remove pmt_cmd_id
-       pmt_cmd_id = msg[6];
-
-       CmdFrm.operand[0]=SFE_VENDOR_DE_COMPANYID_0;
-       CmdFrm.operand[1]=SFE_VENDOR_DE_COMPANYID_1;
-       CmdFrm.operand[2]=SFE_VENDOR_DE_COMPANYID_2;
-       CmdFrm.operand[3]=SFE_VENDOR_OPCODE_HOST2CA;
-       CmdFrm.operand[4] = 0; // slot
-       CmdFrm.operand[5] = SFE_VENDOR_TAG_CA_PMT; // ca tag
-       CmdFrm.operand[6] = 0; // more/last
-       //CmdFrm.operand[7] = XXXprogram_info_length + 17; // length
-       CmdFrm.operand[8] = list_management;
-       CmdFrm.operand[9] = 0x01; // pmt_cmd=OK_descramble
-
-       // TS program map table
-
-       // Table id=2
-       CmdFrm.operand[10] = 0x02;
-       // Section syntax + length
-       CmdFrm.operand[11] = 0x80;
-       //CmdFrm.operand[12] = XXXprogram_info_length + 12;
-       // Program number
-       CmdFrm.operand[13] = msg[1];
-       CmdFrm.operand[14] = msg[2];
-       // Version number=0 + current/next=1
-       CmdFrm.operand[15] = 0x01;
-       // Section number=0
-       CmdFrm.operand[16] = 0x00;
-       // Last section number=0
-       CmdFrm.operand[17] = 0x00;
-       // PCR_PID=1FFF
-       CmdFrm.operand[18] = 0x1F;
-       CmdFrm.operand[19] = 0xFF;
-       // Program info length
-       CmdFrm.operand[20] = (program_info_length >> 8);
-       CmdFrm.operand[21] = (program_info_length & 0xFF);
-       // CA descriptors at programme level
-       read_pos = 6;
-       write_pos = 22;
-       if (program_info_length > 0) {
-               pmt_cmd_id = msg[read_pos++];
-               if (pmt_cmd_id != 1 && pmt_cmd_id != 4)
-                       dev_err(&fdtv->ud->device,
-                               "invalid pmt_cmd_id %d\n", pmt_cmd_id);
-
-               memcpy(&CmdFrm.operand[write_pos], &msg[read_pos],
-                      program_info_length);
-               read_pos += program_info_length;
-               write_pos += program_info_length;
-       }
-       while (read_pos < length) {
-               CmdFrm.operand[write_pos++] = msg[read_pos++];
-               CmdFrm.operand[write_pos++] = msg[read_pos++];
-               CmdFrm.operand[write_pos++] = msg[read_pos++];
-               es_info_length =
-                       ((msg[read_pos] & 0x0F) << 8) + msg[read_pos + 1];
-               read_pos += 2;
-               if (es_info_length > 0)
-                       es_info_length--; // Remove pmt_cmd_id
-               CmdFrm.operand[write_pos++] = es_info_length >> 8;
-               CmdFrm.operand[write_pos++] = es_info_length & 0xFF;
-               if (es_info_length > 0) {
-                       pmt_cmd_id = msg[read_pos++];
-                       if (pmt_cmd_id != 1 && pmt_cmd_id != 4)
-                               dev_err(&fdtv->ud->device,
-                                       "invalid pmt_cmd_id %d "
-                                       "at stream level\n", pmt_cmd_id);
-
-                       memcpy(&CmdFrm.operand[write_pos], &msg[read_pos],
-                              es_info_length);
-                       read_pos += es_info_length;
-                       write_pos += es_info_length;
-               }
-       }
-
-       // CRC
-       CmdFrm.operand[write_pos++] = 0x00;
-       CmdFrm.operand[write_pos++] = 0x00;
-       CmdFrm.operand[write_pos++] = 0x00;
-       CmdFrm.operand[write_pos++] = 0x00;
-
-       CmdFrm.operand[7] = write_pos - 8;
-       CmdFrm.operand[12] = write_pos - 13;
-
-       crc32_csum = crc32_be(0, &CmdFrm.operand[10],
-                          CmdFrm.operand[12] - 1);
-       CmdFrm.operand[write_pos - 4] = (crc32_csum >> 24) & 0xFF;
-       CmdFrm.operand[write_pos - 3] = (crc32_csum >> 16) & 0xFF;
-       CmdFrm.operand[write_pos - 2] = (crc32_csum >>  8) & 0xFF;
-       CmdFrm.operand[write_pos - 1] = (crc32_csum >>  0) & 0xFF;
-
-       CmdFrm.length = ALIGN(3 + write_pos, 4);
-
-       if (avc_write(fdtv, &CmdFrm, &RspFrm) < 0)
-               return -EIO;
-
-       if (RspFrm.resp != ACCEPTED) {
-               dev_err(&fdtv->ud->device,
-                       "CA PMT failed with response 0x%x\n", RspFrm.resp);
-               return -EFAULT;
-       }
-
-       return 0;
-}
-
-int avc_ca_get_time_date(struct firedtv *fdtv, int *interval)
-{
-       AVCCmdFrm CmdFrm;
-       AVCRspFrm RspFrm;
-
-       memset(&CmdFrm, 0, sizeof(AVCCmdFrm));
-       CmdFrm.cts = AVC;
-       CmdFrm.ctype = STATUS;
-       CmdFrm.sutyp = 0x5;
-       CmdFrm.suid = fdtv->subunit;
-       CmdFrm.opcode = VENDOR;
-
-       CmdFrm.operand[0]=SFE_VENDOR_DE_COMPANYID_0;
-       CmdFrm.operand[1]=SFE_VENDOR_DE_COMPANYID_1;
-       CmdFrm.operand[2]=SFE_VENDOR_DE_COMPANYID_2;
-       CmdFrm.operand[3]=SFE_VENDOR_OPCODE_CA2HOST;
-       CmdFrm.operand[4] = 0; // slot
-       CmdFrm.operand[5] = SFE_VENDOR_TAG_CA_DATE_TIME; // ca tag
-       CmdFrm.operand[6] = 0; // more/last
-       CmdFrm.operand[7] = 0; // length
-       CmdFrm.length = 12;
-
-       if (avc_write(fdtv, &CmdFrm, &RspFrm) < 0)
-               return -EIO;
-
-       /* FIXME: check response code and validate response data */
-
-       *interval = RspFrm.operand[get_ca_object_pos(&RspFrm)];
-
-       return 0;
-}
-
-int avc_ca_enter_menu(struct firedtv *fdtv)
-{
-       AVCCmdFrm CmdFrm;
-       AVCRspFrm RspFrm;
-
-       memset(&CmdFrm, 0, sizeof(AVCCmdFrm));
-       CmdFrm.cts = AVC;
-       CmdFrm.ctype = STATUS;
-       CmdFrm.sutyp = 0x5;
-       CmdFrm.suid = fdtv->subunit;
-       CmdFrm.opcode = VENDOR;
-
-       CmdFrm.operand[0]=SFE_VENDOR_DE_COMPANYID_0;
-       CmdFrm.operand[1]=SFE_VENDOR_DE_COMPANYID_1;
-       CmdFrm.operand[2]=SFE_VENDOR_DE_COMPANYID_2;
-       CmdFrm.operand[3]=SFE_VENDOR_OPCODE_HOST2CA;
-       CmdFrm.operand[4] = 0; // slot
-       CmdFrm.operand[5] = SFE_VENDOR_TAG_CA_ENTER_MENU;
-       CmdFrm.operand[6] = 0; // more/last
-       CmdFrm.operand[7] = 0; // length
-       CmdFrm.length = 12;
-
-       if (avc_write(fdtv, &CmdFrm, &RspFrm) < 0)
-               return -EIO;
-
-       return 0;
-}
-
-int avc_ca_get_mmi(struct firedtv *fdtv, char *mmi_object, unsigned int *len)
-{
-       AVCCmdFrm CmdFrm;
-       AVCRspFrm RspFrm;
-
-       memset(&CmdFrm, 0, sizeof(AVCCmdFrm));
-       CmdFrm.cts = AVC;
-       CmdFrm.ctype = STATUS;
-       CmdFrm.sutyp = 0x5;
-       CmdFrm.suid = fdtv->subunit;
-       CmdFrm.opcode = VENDOR;
-
-       CmdFrm.operand[0]=SFE_VENDOR_DE_COMPANYID_0;
-       CmdFrm.operand[1]=SFE_VENDOR_DE_COMPANYID_1;
-       CmdFrm.operand[2]=SFE_VENDOR_DE_COMPANYID_2;
-       CmdFrm.operand[3]=SFE_VENDOR_OPCODE_CA2HOST;
-       CmdFrm.operand[4] = 0; // slot
-       CmdFrm.operand[5] = SFE_VENDOR_TAG_CA_MMI;
-       CmdFrm.operand[6] = 0; // more/last
-       CmdFrm.operand[7] = 0; // length
-       CmdFrm.length = 12;
-
-       if (avc_write(fdtv, &CmdFrm, &RspFrm) < 0)
-               return -EIO;
-
-       /* FIXME: check response code and validate response data */
-
-       *len = get_ca_object_length(&RspFrm);
-       memcpy(mmi_object, &RspFrm.operand[get_ca_object_pos(&RspFrm)], *len);
-
-       return 0;
-}
diff --git a/drivers/media/dvb/firewire/avc.h b/drivers/media/dvb/firewire/avc.h
deleted file mode 100644 (file)
index 168f371..0000000
+++ /dev/null
@@ -1,432 +0,0 @@
-/*
- * AV/C API
- *
- * Copyright (C) 2000 Manfred Weihs
- * Copyright (C) 2003 Philipp Gutgsell <0014guph@edu.fh-kaernten.ac.at>
- * Copyright (C) 2004 Andreas Monitzer <andy@monitzer.com>
- * Copyright (C) 2008 Ben Backx <ben@bbackx.com>
- * Copyright (C) 2008 Henrik Kurelid <henrik@kurelid.se>
- *
- * This is based on code written by Peter Halwachs, Thomas Groiss and
- * Andreas Monitzer.
- *
- *     This program is free software; you can redistribute it and/or
- *     modify it under the terms of the GNU General Public License as
- *     published by the Free Software Foundation; either version 2 of
- *     the License, or (at your option) any later version.
- */
-
-#ifndef _AVC_API_H
-#define _AVC_API_H
-
-#include <linux/types.h>
-
-/*************************************************************
-       Constants from EN510221
-**************************************************************/
-#define LIST_MANAGEMENT_ONLY 0x03
-
-/************************************************************
-       definition of structures
-*************************************************************/
-typedef struct {
-          int           Nr_SourcePlugs;
-          int           Nr_DestinationPlugs;
-} TunerInfo;
-
-
-/***********************************************
-
-         supported cts
-
-************************************************/
-
-#define AVC  0x0
-
-// FCP command frame with ctype = 0x0 is AVC command frame
-
-#ifdef __LITTLE_ENDIAN
-
-// Definition FCP Command Frame
-typedef struct _AVCCmdFrm
-{
-               // AV/C command frame
-       __u8 ctype  : 4 ;   // command type
-       __u8 cts    : 4 ;   // always 0x0 for AVC
-       __u8 suid   : 3 ;   // subunit ID
-       __u8 sutyp  : 5 ;   // subunit_typ
-       __u8 opcode : 8 ;   // opcode
-       __u8 operand[509] ; // array of operands [1-507]
-       int length;         //length of the command frame
-} AVCCmdFrm ;
-
-// Definition FCP Response Frame
-typedef struct _AVCRspFrm
-{
-        // AV/C response frame
-       __u8 resp               : 4 ;   // response type
-       __u8 cts                : 4 ;   // always 0x0 for AVC
-       __u8 suid               : 3 ;   // subunit ID
-       __u8 sutyp      : 5 ;   // subunit_typ
-       __u8 opcode     : 8 ;   // opcode
-       __u8 operand[509] ; // array of operands [1-507]
-       int length;         //length of the response frame
-} AVCRspFrm ;
-
-#else
-
-typedef struct _AVCCmdFrm
-{
-       __u8 cts:4;
-       __u8 ctype:4;
-       __u8 sutyp:5;
-       __u8 suid:3;
-       __u8 opcode;
-       __u8 operand[509];
-       int length;
-} AVCCmdFrm;
-
-typedef struct _AVCRspFrm
-{
-       __u8 cts:4;
-       __u8 resp:4;
-       __u8 sutyp:5;
-       __u8 suid:3;
-       __u8 opcode;
-       __u8 operand[509];
-       int length;
-} AVCRspFrm;
-
-#endif
-
-/*************************************************************
-       AVC command types (ctype)
-**************************************************************///
-#define CONTROL    0x00
-#define STATUS     0x01
-#define INQUIRY    0x02
-#define NOTIFY     0x03
-
-/*************************************************************
-       AVC respond types
-**************************************************************///
-#define NOT_IMPLEMENTED 0x8
-#define ACCEPTED        0x9
-#define REJECTED        0xA
-#define STABLE          0xC
-#define CHANGED         0xD
-#define INTERIM         0xF
-
-/*************************************************************
-       AVC opcodes
-**************************************************************///
-#define CONNECT                        0x24
-#define DISCONNECT             0x25
-#define UNIT_INFO              0x30
-#define SUBUNIT_Info           0x31
-#define VENDOR                 0x00
-
-#define PLUG_INFO              0x02
-#define OPEN_DESCRIPTOR                0x08
-#define READ_DESCRIPTOR                0x09
-#define OBJECT_NUMBER_SELECT   0x0D
-
-/*************************************************************
-       AVCTuner opcodes
-**************************************************************/
-
-#define DSIT                           0xC8
-#define DSD                            0xCB
-#define DESCRIPTOR_TUNER_STATUS        0x80
-#define DESCRIPTOR_SUBUNIT_IDENTIFIER  0x00
-
-/*************************************************************
-       AVCTuner list types
-**************************************************************/
-#define Multiplex_List   0x80
-#define Service_List     0x82
-
-/*************************************************************
-       AVCTuner object entries
-**************************************************************/
-#define Multiplex                              0x80
-#define Service                                0x82
-#define Service_with_specified_components      0x83
-#define Preferred_components                   0x90
-#define Component                              0x84
-
-/*************************************************************
-       Vendor-specific commands
-**************************************************************/
-
-// digital everywhere vendor ID
-#define SFE_VENDOR_DE_COMPANYID_0                      0x00
-#define SFE_VENDOR_DE_COMPANYID_1                      0x12
-#define SFE_VENDOR_DE_COMPANYID_2                      0x87
-
-#define SFE_VENDOR_MAX_NR_COMPONENTS           0x4
-#define SFE_VENDOR_MAX_NR_SERVICES                     0x3
-#define SFE_VENDOR_MAX_NR_DSD_ELEMENTS         0x10
-
-// vendor commands
-#define SFE_VENDOR_OPCODE_REGISTER_REMOTE_CONTROL      0x0A
-#define SFE_VENDOR_OPCODE_LNB_CONTROL          0x52
-#define SFE_VENDOR_OPCODE_TUNE_QPSK                    0x58    // QPSK command for DVB-S
-
-// TODO: following vendor specific commands needs to be implemented
-#define SFE_VENDOR_OPCODE_GET_FIRMWARE_VERSION 0x00
-#define SFE_VENDOR_OPCODE_HOST2CA                              0x56
-#define SFE_VENDOR_OPCODE_CA2HOST                              0x57
-#define SFE_VENDOR_OPCODE_CISTATUS                             0x59
-#define SFE_VENDOR_OPCODE_TUNE_QPSK2                   0x60 // QPSK command for DVB-S2 devices
-
-// CA Tags
-#define SFE_VENDOR_TAG_CA_RESET                        0x00
-#define SFE_VENDOR_TAG_CA_APPLICATION_INFO     0x01
-#define SFE_VENDOR_TAG_CA_PMT                  0x02
-#define SFE_VENDOR_TAG_CA_DATE_TIME            0x04
-#define SFE_VENDOR_TAG_CA_MMI                  0x05
-#define SFE_VENDOR_TAG_CA_ENTER_MENU           0x07
-
-
-//AVCTuner DVB identifier service_ID
-#define DVB 0x20
-
-/*************************************************************
-                                               AVC descriptor types
-**************************************************************/
-
-#define Subunit_Identifier_Descriptor           0x00
-#define Tuner_Status_Descriptor                                 0x80
-
-typedef struct {
-       __u8          Subunit_Type;
-       __u8          Max_Subunit_ID;
-} SUBUNIT_INFO;
-
-/*************************************************************
-
-               AVCTuner DVB object IDs are 6 byte long
-
-**************************************************************/
-
-typedef struct {
-       __u8  Byte0;
-       __u8  Byte1;
-       __u8  Byte2;
-       __u8  Byte3;
-       __u8  Byte4;
-       __u8  Byte5;
-}OBJECT_ID;
-
-/*************************************************************
-                                               MULIPLEX Structs
-**************************************************************/
-typedef struct
-{
-#ifdef __LITTLE_ENDIAN
-       __u8       RF_frequency_hByte:6;
-       __u8       raster_Frequency:2;//Bit7,6 raster frequency
-#else
-       __u8 raster_Frequency:2;
-       __u8 RF_frequency_hByte:6;
-#endif
-       __u8       RF_frequency_mByte;
-       __u8       RF_frequency_lByte;
-
-}FREQUENCY;
-
-#ifdef __LITTLE_ENDIAN
-
-typedef struct
-{
-                __u8        Modulation     :1;
-                __u8        FEC_inner      :1;
-                __u8        FEC_outer      :1;
-                __u8        Symbol_Rate    :1;
-                __u8        Frequency      :1;
-                __u8        Orbital_Pos        :1;
-                __u8        Polarisation       :1;
-                __u8        reserved_fields :1;
-                __u8        reserved1          :7;
-                __u8        Network_ID :1;
-
-}MULTIPLEX_VALID_FLAGS;
-
-typedef struct
-{
-       __u8    GuardInterval:1;
-       __u8    CodeRateLPStream:1;
-       __u8    CodeRateHPStream:1;
-       __u8    HierarchyInfo:1;
-       __u8    Constellation:1;
-       __u8    Bandwidth:1;
-       __u8    CenterFrequency:1;
-       __u8    reserved1:1;
-       __u8    reserved2:5;
-       __u8    OtherFrequencyFlag:1;
-       __u8    TransmissionMode:1;
-       __u8    NetworkId:1;
-}MULTIPLEX_VALID_FLAGS_DVBT;
-
-#else
-
-typedef struct {
-       __u8 reserved_fields:1;
-       __u8 Polarisation:1;
-       __u8 Orbital_Pos:1;
-       __u8 Frequency:1;
-       __u8 Symbol_Rate:1;
-       __u8 FEC_outer:1;
-       __u8 FEC_inner:1;
-       __u8 Modulation:1;
-       __u8 Network_ID:1;
-       __u8 reserved1:7;
-}MULTIPLEX_VALID_FLAGS;
-
-typedef struct {
-       __u8 reserved1:1;
-       __u8 CenterFrequency:1;
-       __u8 Bandwidth:1;
-       __u8 Constellation:1;
-       __u8 HierarchyInfo:1;
-       __u8 CodeRateHPStream:1;
-       __u8 CodeRateLPStream:1;
-       __u8 GuardInterval:1;
-       __u8 NetworkId:1;
-       __u8 TransmissionMode:1;
-       __u8 OtherFrequencyFlag:1;
-       __u8 reserved2:5;
-}MULTIPLEX_VALID_FLAGS_DVBT;
-
-#endif
-
-typedef union {
-       MULTIPLEX_VALID_FLAGS Bits;
-       MULTIPLEX_VALID_FLAGS_DVBT Bits_T;
-       struct {
-               __u8    ByteHi;
-               __u8    ByteLo;
-       } Valid_Word;
-} M_VALID_FLAGS;
-
-typedef struct
-{
-#ifdef __LITTLE_ENDIAN
-  __u8      ActiveSystem;
-  __u8      reserved:5;
-  __u8      NoRF:1;
-  __u8      Moving:1;
-  __u8      Searching:1;
-
-  __u8      SelectedAntenna:7;
-  __u8      Input:1;
-
-  __u8      BER[4];
-
-  __u8      SignalStrength;
-  FREQUENCY Frequency;
-
-  __u8      ManDepInfoLength;
-
-  __u8 PowerSupply:1;
-  __u8 FrontEndPowerStatus:1;
-  __u8 reserved3:1;
-  __u8 AntennaError:1;
-  __u8 FrontEndError:1;
-  __u8 reserved2:3;
-
-  __u8 CarrierNoiseRatio[2];
-  __u8 reserved4[2];
-  __u8 PowerSupplyVoltage;
-  __u8 AntennaVoltage;
-  __u8 FirewireBusVoltage;
-
-  __u8 CaMmi:1;
-  __u8 reserved5:7;
-
-  __u8 reserved6:1;
-  __u8 CaInitializationStatus:1;
-  __u8 CaErrorFlag:1;
-  __u8 CaDvbFlag:1;
-  __u8 CaModulePresentStatus:1;
-  __u8 CaApplicationInfo:1;
-  __u8 CaDateTimeRequest:1;
-  __u8 CaPmtReply:1;
-
-#else
-  __u8 ActiveSystem;
-  __u8 Searching:1;
-  __u8 Moving:1;
-  __u8 NoRF:1;
-  __u8 reserved:5;
-
-  __u8 Input:1;
-  __u8 SelectedAntenna:7;
-
-  __u8 BER[4];
-
-  __u8 SignalStrength;
-  FREQUENCY Frequency;
-
-  __u8 ManDepInfoLength;
-
-  __u8 reserved2:3;
-  __u8 FrontEndError:1;
-  __u8 AntennaError:1;
-  __u8 reserved3:1;
-  __u8 FrontEndPowerStatus:1;
-  __u8 PowerSupply:1;
-
-  __u8 CarrierNoiseRatio[2];
-  __u8 reserved4[2];
-  __u8 PowerSupplyVoltage;
-  __u8 AntennaVoltage;
-  __u8 FirewireBusVoltage;
-
-  __u8 reserved5:7;
-  __u8 CaMmi:1;
-  __u8 CaPmtReply:1;
-  __u8 CaDateTimeRequest:1;
-  __u8 CaApplicationInfo:1;
-  __u8 CaModulePresentStatus:1;
-  __u8 CaDvbFlag:1;
-  __u8 CaErrorFlag:1;
-  __u8 CaInitializationStatus:1;
-  __u8 reserved6:1;
-
-#endif
-} ANTENNA_INPUT_INFO; // 22 Byte
-
-#define LNBCONTROL_DONTCARE 0xff
-
-struct dvb_diseqc_master_cmd;
-struct dvb_frontend_parameters;
-struct firedtv;
-
-int avc_recv(struct firedtv *fdtv, u8 *data, size_t length);
-
-int AVCTuner_DSIT(struct firedtv *fdtv, int Source_Plug,
-               struct dvb_frontend_parameters *params, __u8 *status);
-
-int avc_tuner_status(struct firedtv *fdtv,
-               ANTENNA_INPUT_INFO *antenna_input_info);
-int avc_tuner_dsd(struct firedtv *fdtv,
-               struct dvb_frontend_parameters *params);
-int avc_tuner_set_pids(struct firedtv *fdtv, unsigned char pidc, u16 pid[]);
-int avc_tuner_get_ts(struct firedtv *fdtv);
-int avc_identify_subunit(struct firedtv *fdtv);
-int avc_lnb_control(struct firedtv *fdtv, char voltage, char burst,
-               char conttone, char nrdiseq,
-               struct dvb_diseqc_master_cmd *diseqcmd);
-void avc_remote_ctrl_work(struct work_struct *work);
-int avc_register_remote_control(struct firedtv *fdtv);
-int avc_ca_app_info(struct firedtv *fdtv, char *app_info, unsigned int *len);
-int avc_ca_info(struct firedtv *fdtv, char *app_info, unsigned int *len);
-int avc_ca_reset(struct firedtv *fdtv);
-int avc_ca_pmt(struct firedtv *fdtv, char *app_info, int length);
-int avc_ca_get_time_date(struct firedtv *fdtv, int *interval);
-int avc_ca_enter_menu(struct firedtv *fdtv);
-int avc_ca_get_mmi(struct firedtv *fdtv, char *mmi_object, unsigned int *len);
-
-#endif /* _AVC_API_H */
diff --git a/drivers/media/dvb/firewire/cmp.c b/drivers/media/dvb/firewire/cmp.c
deleted file mode 100644 (file)
index 821e033..0000000
+++ /dev/null
@@ -1,171 +0,0 @@
-/*
- * FireDTV driver (formerly known as FireSAT)
- *
- * Copyright (C) 2004 Andreas Monitzer <andy@monitzer.com>
- * Copyright (C) 2008 Henrik Kurelid <henrik@kurelid.se>
- *
- *     This program is free software; you can redistribute it and/or
- *     modify it under the terms of the GNU General Public License as
- *     published by the Free Software Foundation; either version 2 of
- *     the License, or (at your option) any later version.
- */
-
-#include <linux/device.h>
-#include <linux/kernel.h>
-#include <linux/mutex.h>
-#include <linux/types.h>
-
-#include <asm/byteorder.h>
-
-#include <ieee1394.h>
-#include <nodemgr.h>
-
-#include "avc.h"
-#include "cmp.h"
-#include "firedtv.h"
-
-#define CMP_OUTPUT_PLUG_CONTROL_REG_0  0xfffff0000904ULL
-
-static int cmp_read(struct firedtv *fdtv, void *buf, u64 addr, size_t len)
-{
-       int ret;
-
-       if (mutex_lock_interruptible(&fdtv->avc_mutex))
-               return -EINTR;
-
-       ret = hpsb_node_read(fdtv->ud->ne, addr, buf, len);
-       if (ret < 0)
-               dev_err(&fdtv->ud->device, "CMP: read I/O error\n");
-
-       mutex_unlock(&fdtv->avc_mutex);
-       return ret;
-}
-
-static int cmp_lock(struct firedtv *fdtv, void *data, u64 addr, __be32 arg,
-                   int ext_tcode)
-{
-       int ret;
-
-       if (mutex_lock_interruptible(&fdtv->avc_mutex))
-               return -EINTR;
-
-       ret = hpsb_node_lock(fdtv->ud->ne, addr, ext_tcode, data,
-                            (__force quadlet_t)arg);
-       if (ret < 0)
-               dev_err(&fdtv->ud->device, "CMP: lock I/O error\n");
-
-       mutex_unlock(&fdtv->avc_mutex);
-       return ret;
-}
-
-static inline u32 get_opcr(__be32 opcr, u32 mask, u32 shift)
-{
-       return (be32_to_cpu(opcr) >> shift) & mask;
-}
-
-static inline void set_opcr(__be32 *opcr, u32 value, u32 mask, u32 shift)
-{
-       *opcr &= ~cpu_to_be32(mask << shift);
-       *opcr |= cpu_to_be32((value & mask) << shift);
-}
-
-#define get_opcr_online(v)             get_opcr((v), 0x1, 31)
-#define get_opcr_p2p_connections(v)    get_opcr((v), 0x3f, 24)
-#define get_opcr_channel(v)            get_opcr((v), 0x3f, 16)
-
-#define set_opcr_p2p_connections(p, v) set_opcr((p), (v), 0x3f, 24)
-#define set_opcr_channel(p, v)         set_opcr((p), (v), 0x3f, 16)
-#define set_opcr_data_rate(p, v)       set_opcr((p), (v), 0x3, 14)
-#define set_opcr_overhead_id(p, v)     set_opcr((p), (v), 0xf, 10)
-
-int cmp_establish_pp_connection(struct firedtv *fdtv, int plug, int channel)
-{
-       __be32 old_opcr, opcr;
-       u64 opcr_address = CMP_OUTPUT_PLUG_CONTROL_REG_0 + (plug << 2);
-       int attempts = 0;
-       int ret;
-
-       ret = cmp_read(fdtv, &opcr, opcr_address, 4);
-       if (ret < 0)
-               return ret;
-
-repeat:
-       if (!get_opcr_online(opcr)) {
-               dev_err(&fdtv->ud->device, "CMP: output offline\n");
-               return -EBUSY;
-       }
-
-       old_opcr = opcr;
-
-       if (get_opcr_p2p_connections(opcr)) {
-               if (get_opcr_channel(opcr) != channel) {
-                       dev_err(&fdtv->ud->device,
-                               "CMP: cannot change channel\n");
-                       return -EBUSY;
-               }
-               dev_info(&fdtv->ud->device,
-                        "CMP: overlaying existing connection\n");
-
-               /* We don't allocate isochronous resources. */
-       } else {
-               set_opcr_channel(&opcr, channel);
-               set_opcr_data_rate(&opcr, IEEE1394_SPEED_400);
-
-               /* FIXME: this is for the worst case - optimize */
-               set_opcr_overhead_id(&opcr, 0);
-
-               /* FIXME: allocate isochronous channel and bandwidth at IRM */
-       }
-
-       set_opcr_p2p_connections(&opcr, get_opcr_p2p_connections(opcr) + 1);
-
-       ret = cmp_lock(fdtv, &opcr, opcr_address, old_opcr, 2);
-       if (ret < 0)
-               return ret;
-
-       if (old_opcr != opcr) {
-               /*
-                * FIXME: if old_opcr.P2P_Connections > 0,
-                * deallocate isochronous channel and bandwidth at IRM
-                */
-
-               if (++attempts < 6) /* arbitrary limit */
-                       goto repeat;
-               return -EBUSY;
-       }
-
-       return 0;
-}
-
-void cmp_break_pp_connection(struct firedtv *fdtv, int plug, int channel)
-{
-       __be32 old_opcr, opcr;
-       u64 opcr_address = CMP_OUTPUT_PLUG_CONTROL_REG_0 + (plug << 2);
-       int attempts = 0;
-
-       if (cmp_read(fdtv, &opcr, opcr_address, 4) < 0)
-               return;
-
-repeat:
-       if (!get_opcr_online(opcr) || !get_opcr_p2p_connections(opcr) ||
-           get_opcr_channel(opcr) != channel) {
-               dev_err(&fdtv->ud->device, "CMP: no connection to break\n");
-               return;
-       }
-
-       old_opcr = opcr;
-       set_opcr_p2p_connections(&opcr, get_opcr_p2p_connections(opcr) - 1);
-
-       if (cmp_lock(fdtv, &opcr, opcr_address, old_opcr, 2) < 0)
-               return;
-
-       if (old_opcr != opcr) {
-               /*
-                * FIXME: if old_opcr.P2P_Connections == 1, i.e. we were last
-                * owner, deallocate isochronous channel and bandwidth at IRM
-                */
-
-               if (++attempts < 6) /* arbitrary limit */
-                       goto repeat;
-       }
-}
diff --git a/drivers/media/dvb/firewire/cmp.h b/drivers/media/dvb/firewire/cmp.h
deleted file mode 100644 (file)
index 17e182c..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-#ifndef _CMP_H
-#define _CMP_H
-
-struct firedtv;
-
-int cmp_establish_pp_connection(struct firedtv *fdtv, int plug, int channel);
-void cmp_break_pp_connection(struct firedtv *fdtv, int plug, int channel);
-
-#endif /* _CMP_H */
index 953618246e8e3ef6c683987e564d32055ca41903..4e207658c5d95a0c58dca4d62e6b664ad7e41f3f 100644 (file)
 #include <linux/errno.h>
 #include <linux/kernel.h>
 #include <linux/list.h>
-#include <linux/module.h>
-#include <linux/mutex.h>
-#include <linux/slab.h>
 #include <linux/spinlock.h>
-#include <linux/string.h>
 #include <linux/types.h>
 
-#include <dmxdev.h>
-#include <dvb_demux.h>
-#include <dvb_frontend.h>
-#include <dvbdev.h>
-
+#include <dma.h>
 #include <csr1212.h>
 #include <highlevel.h>
 #include <hosts.h>
-#include <ieee1394_hotplug.h>
+#include <ieee1394.h>
+#include <iso.h>
 #include <nodemgr.h>
 
-#include "avc.h"
-#include "cmp.h"
 #include "firedtv.h"
-#include "firedtv-ci.h"
-#include "firedtv-rc.h"
-
-#define MATCH_FLAGS    IEEE1394_MATCH_VENDOR_ID | IEEE1394_MATCH_MODEL_ID | \
-                       IEEE1394_MATCH_SPECIFIER_ID | IEEE1394_MATCH_VERSION
-#define DIGITAL_EVERYWHERE_OUI   0x001287
-
-static struct ieee1394_device_id fdtv_id_table[] = {
-
-       {
-               /* FloppyDTV S/CI and FloppyDTV S2 */
-               .match_flags    = MATCH_FLAGS,
-               .vendor_id      = DIGITAL_EVERYWHERE_OUI,
-               .model_id       = 0x000024,
-               .specifier_id   = AVC_UNIT_SPEC_ID_ENTRY,
-               .version        = AVC_SW_VERSION_ENTRY,
-       },{
-               /* FloppyDTV T/CI */
-               .match_flags    = MATCH_FLAGS,
-               .vendor_id      = DIGITAL_EVERYWHERE_OUI,
-               .model_id       = 0x000025,
-               .specifier_id   = AVC_UNIT_SPEC_ID_ENTRY,
-               .version        = AVC_SW_VERSION_ENTRY,
-       },{
-               /* FloppyDTV C/CI */
-               .match_flags    = MATCH_FLAGS,
-               .vendor_id      = DIGITAL_EVERYWHERE_OUI,
-               .model_id       = 0x000026,
-               .specifier_id   = AVC_UNIT_SPEC_ID_ENTRY,
-               .version        = AVC_SW_VERSION_ENTRY,
-       },{
-               /* FireDTV S/CI and FloppyDTV S2 */
-               .match_flags    = MATCH_FLAGS,
-               .vendor_id      = DIGITAL_EVERYWHERE_OUI,
-               .model_id       = 0x000034,
-               .specifier_id   = AVC_UNIT_SPEC_ID_ENTRY,
-               .version        = AVC_SW_VERSION_ENTRY,
-       },{
-               /* FireDTV T/CI */
-               .match_flags    = MATCH_FLAGS,
-               .vendor_id      = DIGITAL_EVERYWHERE_OUI,
-               .model_id       = 0x000035,
-               .specifier_id   = AVC_UNIT_SPEC_ID_ENTRY,
-               .version        = AVC_SW_VERSION_ENTRY,
-       },{
-               /* FireDTV C/CI */
-               .match_flags    = MATCH_FLAGS,
-               .vendor_id      = DIGITAL_EVERYWHERE_OUI,
-               .model_id       = 0x000036,
-               .specifier_id   = AVC_UNIT_SPEC_ID_ENTRY,
-               .version        = AVC_SW_VERSION_ENTRY,
-       }, { }
-};
 
-MODULE_DEVICE_TABLE(ieee1394, fdtv_id_table);
+static LIST_HEAD(node_list);
+static DEFINE_SPINLOCK(node_list_lock);
 
-/* list of all firedtv devices */
-LIST_HEAD(fdtv_list);
-DEFINE_SPINLOCK(fdtv_list_lock);
+#define FIREWIRE_HEADER_SIZE   4
+#define CIP_HEADER_SIZE                8
 
-static void fcp_request(struct hpsb_host *host,
-                       int nodeid,
-                       int direction,
-                       int cts,
-                       u8 *data,
-                       size_t length)
+static void rawiso_activity_cb(struct hpsb_iso *iso)
 {
-       struct firedtv *fdtv = NULL;
-       struct firedtv *fdtv_entry;
+       struct firedtv *f, *fdtv = NULL;
+       unsigned int i, num, packet;
+       unsigned char *buf;
        unsigned long flags;
+       int count;
+
+       spin_lock_irqsave(&node_list_lock, flags);
+       list_for_each_entry(f, &node_list, list)
+               if (f->backend_data == iso) {
+                       fdtv = f;
+                       break;
+               }
+       spin_unlock_irqrestore(&node_list_lock, flags);
+
+       packet = iso->first_packet;
+       num = hpsb_iso_n_ready(iso);
+
+       if (!fdtv) {
+               dev_err(fdtv->device, "received at unknown iso channel\n");
+               goto out;
+       }
 
-       if (length > 0 && ((data[0] & 0xf0) >> 4) == 0) {
-
-               spin_lock_irqsave(&fdtv_list_lock, flags);
-               list_for_each_entry(fdtv_entry,&fdtv_list,list) {
-                       if (fdtv_entry->ud->ne->host == host &&
-                           fdtv_entry->ud->ne->nodeid == nodeid &&
-                           (fdtv_entry->subunit == (data[1]&0x7) ||
-                            (fdtv_entry->subunit == 0 &&
-                             (data[1]&0x7) == 0x7))) {
-                               fdtv=fdtv_entry;
-                               break;
-                       }
+       for (i = 0; i < num; i++, packet = (packet + 1) % iso->buf_packets) {
+               buf = dma_region_i(&iso->data_buf, unsigned char,
+                       iso->infos[packet].offset + CIP_HEADER_SIZE);
+               count = (iso->infos[packet].len - CIP_HEADER_SIZE) /
+                       (188 + FIREWIRE_HEADER_SIZE);
+
+               /* ignore empty packet */
+               if (iso->infos[packet].len <= CIP_HEADER_SIZE)
+                       continue;
+
+               while (count--) {
+                       if (buf[FIREWIRE_HEADER_SIZE] == 0x47)
+                               dvb_dmx_swfilter_packets(&fdtv->demux,
+                                               &buf[FIREWIRE_HEADER_SIZE], 1);
+                       else
+                               dev_err(fdtv->device,
+                                       "skipping invalid packet\n");
+                       buf += 188 + FIREWIRE_HEADER_SIZE;
                }
-               spin_unlock_irqrestore(&fdtv_list_lock, flags);
+       }
+out:
+       hpsb_iso_recv_release_packets(iso, num);
+}
+
+static inline struct node_entry *node_of(struct firedtv *fdtv)
+{
+       return container_of(fdtv->device, struct unit_directory, device)->ne;
+}
+
+static int node_lock(struct firedtv *fdtv, u64 addr, void *data, __be32 arg)
+{
+       return hpsb_node_lock(node_of(fdtv), addr, EXTCODE_COMPARE_SWAP, data,
+                             (__force quadlet_t)arg);
+}
+
+static int node_read(struct firedtv *fdtv, u64 addr, void *data, size_t len)
+{
+       return hpsb_node_read(node_of(fdtv), addr, data, len);
+}
+
+static int node_write(struct firedtv *fdtv, u64 addr, void *data, size_t len)
+{
+       return hpsb_node_write(node_of(fdtv), addr, data, len);
+}
+
+#define FDTV_ISO_BUFFER_PACKETS 256
+#define FDTV_ISO_BUFFER_SIZE (FDTV_ISO_BUFFER_PACKETS * 200)
+
+static int start_iso(struct firedtv *fdtv)
+{
+       struct hpsb_iso *iso_handle;
+       int ret;
+
+       iso_handle = hpsb_iso_recv_init(node_of(fdtv)->host,
+                               FDTV_ISO_BUFFER_SIZE, FDTV_ISO_BUFFER_PACKETS,
+                               fdtv->isochannel, HPSB_ISO_DMA_DEFAULT,
+                               -1, /* stat.config.irq_interval */
+                               rawiso_activity_cb);
+       if (iso_handle == NULL) {
+               dev_err(fdtv->device, "cannot initialize iso receive\n");
+               return -ENOMEM;
+       }
+       fdtv->backend_data = iso_handle;
+
+       ret = hpsb_iso_recv_start(iso_handle, -1, -1, 0);
+       if (ret != 0) {
+               dev_err(fdtv->device, "cannot start iso receive\n");
+               hpsb_iso_shutdown(iso_handle);
+               fdtv->backend_data = NULL;
+       }
+       return ret;
+}
+
+static void stop_iso(struct firedtv *fdtv)
+{
+       struct hpsb_iso *iso_handle = fdtv->backend_data;
 
-               if (fdtv)
-                       avc_recv(fdtv, data, length);
+       if (iso_handle != NULL) {
+               hpsb_iso_stop(iso_handle);
+               hpsb_iso_shutdown(iso_handle);
        }
+       fdtv->backend_data = NULL;
 }
 
-const char *fdtv_model_names[] = {
-       [FIREDTV_UNKNOWN] = "unknown type",
-       [FIREDTV_DVB_S]   = "FireDTV S/CI",
-       [FIREDTV_DVB_C]   = "FireDTV C/CI",
-       [FIREDTV_DVB_T]   = "FireDTV T/CI",
-       [FIREDTV_DVB_S2]  = "FireDTV S2  ",
+static const struct firedtv_backend fdtv_1394_backend = {
+       .lock           = node_lock,
+       .read           = node_read,
+       .write          = node_write,
+       .start_iso      = start_iso,
+       .stop_iso       = stop_iso,
 };
 
-static int fdtv_probe(struct device *dev)
+static void fcp_request(struct hpsb_host *host, int nodeid, int direction,
+                       int cts, u8 *data, size_t length)
 {
-       struct unit_directory *ud =
-                       container_of(dev, struct unit_directory, device);
-       struct firedtv *fdtv;
+       struct firedtv *f, *fdtv = NULL;
        unsigned long flags;
-       int kv_len;
-       void *kv_str;
-       int i;
-       int err = -ENOMEM;
+       int su;
 
-       fdtv = kzalloc(sizeof(*fdtv), GFP_KERNEL);
-       if (!fdtv)
-               return -ENOMEM;
+       if (length == 0 || (data[0] & 0xf0) != 0)
+               return;
 
-       dev->driver_data        = fdtv;
-       fdtv->ud                = ud;
-       fdtv->subunit           = 0;
-       fdtv->isochannel        = -1;
-       fdtv->tone              = 0xff;
-       fdtv->voltage           = 0xff;
+       su = data[1] & 0x7;
+
+       spin_lock_irqsave(&node_list_lock, flags);
+       list_for_each_entry(f, &node_list, list)
+               if (node_of(f)->host == host &&
+                   node_of(f)->nodeid == nodeid &&
+                   (f->subunit == su || (f->subunit == 0 && su == 0x7))) {
+                       fdtv = f;
+                       break;
+               }
+       spin_unlock_irqrestore(&node_list_lock, flags);
 
-       mutex_init(&fdtv->avc_mutex);
-       init_waitqueue_head(&fdtv->avc_wait);
-       fdtv->avc_reply_received = true;
-       mutex_init(&fdtv->demux_mutex);
-       INIT_WORK(&fdtv->remote_ctrl_work, avc_remote_ctrl_work);
+       if (fdtv)
+               avc_recv(fdtv, data, length);
+}
+
+static int node_probe(struct device *dev)
+{
+       struct unit_directory *ud =
+                       container_of(dev, struct unit_directory, device);
+       struct firedtv *fdtv;
+       int kv_len, err;
+       void *kv_str;
 
-       /* Reading device model from ROM */
        kv_len = (ud->model_name_kv->value.leaf.len - 2) * sizeof(quadlet_t);
        kv_str = CSR1212_TEXTUAL_DESCRIPTOR_LEAF_DATA(ud->model_name_kv);
-       for (i = ARRAY_SIZE(fdtv_model_names); --i;)
-               if (strlen(fdtv_model_names[i]) <= kv_len &&
-                   strncmp(kv_str, fdtv_model_names[i], kv_len) == 0)
-                       break;
-       fdtv->type = i;
+
+       fdtv = fdtv_alloc(dev, &fdtv_1394_backend, kv_str, kv_len);
+       if (!fdtv)
+               return -ENOMEM;
 
        /*
         * Work around a bug in udev's path_id script:  Use the fw-host's dev
@@ -180,50 +199,39 @@ static int fdtv_probe(struct device *dev)
        if (err)
                goto fail_free;
 
-       INIT_LIST_HEAD(&fdtv->list);
-       spin_lock_irqsave(&fdtv_list_lock, flags);
-       list_add_tail(&fdtv->list, &fdtv_list);
-       spin_unlock_irqrestore(&fdtv_list_lock, flags);
+       spin_lock_irq(&node_list_lock);
+       list_add_tail(&fdtv->list, &node_list);
+       spin_unlock_irq(&node_list_lock);
 
        err = avc_identify_subunit(fdtv);
        if (err)
                goto fail;
 
-       err = fdtv_dvbdev_init(fdtv, dev);
+       err = fdtv_dvb_register(fdtv);
        if (err)
                goto fail;
 
        avc_register_remote_control(fdtv);
        return 0;
-
 fail:
-       spin_lock_irqsave(&fdtv_list_lock, flags);
+       spin_lock_irq(&node_list_lock);
        list_del(&fdtv->list);
-       spin_unlock_irqrestore(&fdtv_list_lock, flags);
+       spin_unlock_irq(&node_list_lock);
        fdtv_unregister_rc(fdtv);
 fail_free:
        kfree(fdtv);
        return err;
 }
 
-static int fdtv_remove(struct device *dev)
+static int node_remove(struct device *dev)
 {
        struct firedtv *fdtv = dev->driver_data;
-       unsigned long flags;
 
-       fdtv_ca_release(fdtv);
-       dvb_unregister_frontend(&fdtv->fe);
-       dvb_net_release(&fdtv->dvbnet);
-       fdtv->demux.dmx.close(&fdtv->demux.dmx);
-       fdtv->demux.dmx.remove_frontend(&fdtv->demux.dmx,
-                                          &fdtv->frontend);
-       dvb_dmxdev_release(&fdtv->dmxdev);
-       dvb_dmx_release(&fdtv->demux);
-       dvb_unregister_adapter(&fdtv->adapter);
-
-       spin_lock_irqsave(&fdtv_list_lock, flags);
+       fdtv_dvb_unregister(fdtv);
+
+       spin_lock_irq(&node_list_lock);
        list_del(&fdtv->list);
-       spin_unlock_irqrestore(&fdtv_list_lock, flags);
+       spin_unlock_irq(&node_list_lock);
 
        cancel_work_sync(&fdtv->remote_ctrl_work);
        fdtv_unregister_rc(fdtv);
@@ -232,7 +240,7 @@ static int fdtv_remove(struct device *dev)
        return 0;
 }
 
-static int fdtv_update(struct unit_directory *ud)
+static int node_update(struct unit_directory *ud)
 {
        struct firedtv *fdtv = ud->device.driver_data;
 
@@ -243,17 +251,11 @@ static int fdtv_update(struct unit_directory *ud)
 }
 
 static struct hpsb_protocol_driver fdtv_driver = {
-
        .name           = "firedtv",
-       .id_table       = fdtv_id_table,
-       .update         = fdtv_update,
-
+       .update         = node_update,
        .driver         = {
-               //.name and .bus are filled in for us in more recent linux versions
-               //.name = "FireDTV",
-               //.bus  = &ieee1394_bus_type,
-               .probe  = fdtv_probe,
-               .remove = fdtv_remove,
+               .probe  = node_probe,
+               .remove = node_remove,
        },
 };
 
@@ -262,11 +264,12 @@ static struct hpsb_highlevel fdtv_highlevel = {
        .fcp_request    = fcp_request,
 };
 
-static int __init fdtv_init(void)
+int __init fdtv_1394_init(struct ieee1394_device_id id_table[])
 {
        int ret;
 
        hpsb_register_highlevel(&fdtv_highlevel);
+       fdtv_driver.id_table = id_table;
        ret = hpsb_register_protocol(&fdtv_driver);
        if (ret) {
                printk(KERN_ERR "firedtv: failed to register protocol\n");
@@ -275,17 +278,8 @@ static int __init fdtv_init(void)
        return ret;
 }
 
-static void __exit fdtv_exit(void)
+void __exit fdtv_1394_exit(void)
 {
        hpsb_unregister_protocol(&fdtv_driver);
        hpsb_unregister_highlevel(&fdtv_highlevel);
 }
-
-module_init(fdtv_init);
-module_exit(fdtv_exit);
-
-MODULE_AUTHOR("Andreas Monitzer <andy@monitzer.com>");
-MODULE_AUTHOR("Ben Backx <ben@bbackx.com>");
-MODULE_DESCRIPTION("FireDTV DVB Driver");
-MODULE_LICENSE("GPL");
-MODULE_SUPPORTED_DEVICE("FireDTV DVB");
diff --git a/drivers/media/dvb/firewire/firedtv-avc.c b/drivers/media/dvb/firewire/firedtv-avc.c
new file mode 100644 (file)
index 0000000..b55d9cc
--- /dev/null
@@ -0,0 +1,1315 @@
+/*
+ * FireDTV driver (formerly known as FireSAT)
+ *
+ * Copyright (C) 2004 Andreas Monitzer <andy@monitzer.com>
+ * Copyright (C) 2008 Ben Backx <ben@bbackx.com>
+ * Copyright (C) 2008 Henrik Kurelid <henrik@kurelid.se>
+ *
+ *     This program is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License as
+ *     published by the Free Software Foundation; either version 2 of
+ *     the License, or (at your option) any later version.
+ */
+
+#include <linux/bug.h>
+#include <linux/crc32.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/jiffies.h>
+#include <linux/kernel.h>
+#include <linux/moduleparam.h>
+#include <linux/mutex.h>
+#include <linux/string.h>
+#include <linux/stringify.h>
+#include <linux/wait.h>
+#include <linux/workqueue.h>
+
+#include "firedtv.h"
+
+#define FCP_COMMAND_REGISTER           0xfffff0000b00ULL
+
+#define AVC_CTYPE_CONTROL              0x0
+#define AVC_CTYPE_STATUS               0x1
+#define AVC_CTYPE_NOTIFY               0x3
+
+#define AVC_RESPONSE_ACCEPTED          0x9
+#define AVC_RESPONSE_STABLE            0xc
+#define AVC_RESPONSE_CHANGED           0xd
+#define AVC_RESPONSE_INTERIM           0xf
+
+#define AVC_SUBUNIT_TYPE_TUNER         (0x05 << 3)
+#define AVC_SUBUNIT_TYPE_UNIT          (0x1f << 3)
+
+#define AVC_OPCODE_VENDOR              0x00
+#define AVC_OPCODE_READ_DESCRIPTOR     0x09
+#define AVC_OPCODE_DSIT                        0xc8
+#define AVC_OPCODE_DSD                 0xcb
+
+#define DESCRIPTOR_TUNER_STATUS        0x80
+#define DESCRIPTOR_SUBUNIT_IDENTIFIER  0x00
+
+#define SFE_VENDOR_DE_COMPANYID_0      0x00 /* OUI of Digital Everywhere */
+#define SFE_VENDOR_DE_COMPANYID_1      0x12
+#define SFE_VENDOR_DE_COMPANYID_2      0x87
+
+#define SFE_VENDOR_OPCODE_REGISTER_REMOTE_CONTROL 0x0a
+#define SFE_VENDOR_OPCODE_LNB_CONTROL          0x52
+#define SFE_VENDOR_OPCODE_TUNE_QPSK            0x58 /* for DVB-S */
+
+#define SFE_VENDOR_OPCODE_GET_FIRMWARE_VERSION 0x00
+#define SFE_VENDOR_OPCODE_HOST2CA              0x56
+#define SFE_VENDOR_OPCODE_CA2HOST              0x57
+#define SFE_VENDOR_OPCODE_CISTATUS             0x59
+#define SFE_VENDOR_OPCODE_TUNE_QPSK2           0x60 /* for DVB-S2 */
+
+#define SFE_VENDOR_TAG_CA_RESET                        0x00
+#define SFE_VENDOR_TAG_CA_APPLICATION_INFO     0x01
+#define SFE_VENDOR_TAG_CA_PMT                  0x02
+#define SFE_VENDOR_TAG_CA_DATE_TIME            0x04
+#define SFE_VENDOR_TAG_CA_MMI                  0x05
+#define SFE_VENDOR_TAG_CA_ENTER_MENU           0x07
+
+#define EN50221_LIST_MANAGEMENT_ONLY   0x03
+#define EN50221_TAG_APP_INFO           0x9f8021
+#define EN50221_TAG_CA_INFO            0x9f8031
+
+struct avc_command_frame {
+       int length;
+       u8 ctype;
+       u8 subunit;
+       u8 opcode;
+       u8 operand[509];
+};
+
+struct avc_response_frame {
+       int length;
+       u8 response;
+       u8 subunit;
+       u8 opcode;
+       u8 operand[509];
+};
+
+#define AVC_DEBUG_FCP_SUBACTIONS       1
+#define AVC_DEBUG_FCP_PAYLOADS         2
+
+static int avc_debug;
+module_param_named(debug, avc_debug, int, 0644);
+MODULE_PARM_DESC(debug, "Verbose logging (default = 0"
+       ", FCP subactions = "   __stringify(AVC_DEBUG_FCP_SUBACTIONS)
+       ", FCP payloads = "     __stringify(AVC_DEBUG_FCP_PAYLOADS)
+       ", or all = -1)");
+
+static const char *debug_fcp_ctype(unsigned int ctype)
+{
+       static const char *ctypes[] = {
+               [0x0] = "CONTROL",              [0x1] = "STATUS",
+               [0x2] = "SPECIFIC INQUIRY",     [0x3] = "NOTIFY",
+               [0x4] = "GENERAL INQUIRY",      [0x8] = "NOT IMPLEMENTED",
+               [0x9] = "ACCEPTED",             [0xa] = "REJECTED",
+               [0xb] = "IN TRANSITION",        [0xc] = "IMPLEMENTED/STABLE",
+               [0xd] = "CHANGED",              [0xf] = "INTERIM",
+       };
+       const char *ret = ctype < ARRAY_SIZE(ctypes) ? ctypes[ctype] : NULL;
+
+       return ret ? ret : "?";
+}
+
+static const char *debug_fcp_opcode(unsigned int opcode,
+                                   const u8 *data, size_t length)
+{
+       switch (opcode) {
+       case AVC_OPCODE_VENDOR:                 break;
+       case AVC_OPCODE_READ_DESCRIPTOR:        return "ReadDescriptor";
+       case AVC_OPCODE_DSIT:                   return "DirectSelectInfo.Type";
+       case AVC_OPCODE_DSD:                    return "DirectSelectData";
+       default:                                return "?";
+       }
+
+       if (length < 7 ||
+           data[3] != SFE_VENDOR_DE_COMPANYID_0 ||
+           data[4] != SFE_VENDOR_DE_COMPANYID_1 ||
+           data[5] != SFE_VENDOR_DE_COMPANYID_2)
+               return "Vendor";
+
+       switch (data[6]) {
+       case SFE_VENDOR_OPCODE_REGISTER_REMOTE_CONTROL: return "RegisterRC";
+       case SFE_VENDOR_OPCODE_LNB_CONTROL:             return "LNBControl";
+       case SFE_VENDOR_OPCODE_TUNE_QPSK:               return "TuneQPSK";
+       case SFE_VENDOR_OPCODE_HOST2CA:                 return "Host2CA";
+       case SFE_VENDOR_OPCODE_CA2HOST:                 return "CA2Host";
+       }
+       return "Vendor";
+}
+
+static void debug_fcp(const u8 *data, size_t length)
+{
+       unsigned int subunit_type, subunit_id, op;
+       const char *prefix = data[0] > 7 ? "FCP <- " : "FCP -> ";
+
+       if (avc_debug & AVC_DEBUG_FCP_SUBACTIONS) {
+               subunit_type = data[1] >> 3;
+               subunit_id = data[1] & 7;
+               op = subunit_type == 0x1e || subunit_id == 5 ? ~0 : data[2];
+               printk(KERN_INFO "%ssu=%x.%x l=%d: %-8s - %s\n",
+                      prefix, subunit_type, subunit_id, length,
+                      debug_fcp_ctype(data[0]),
+                      debug_fcp_opcode(op, data, length));
+       }
+
+       if (avc_debug & AVC_DEBUG_FCP_PAYLOADS)
+               print_hex_dump(KERN_INFO, prefix, DUMP_PREFIX_NONE, 16, 1,
+                              data, length, false);
+}
+
+static int __avc_write(struct firedtv *fdtv,
+               const struct avc_command_frame *c, struct avc_response_frame *r)
+{
+       int err, retry;
+
+       if (r)
+               fdtv->avc_reply_received = false;
+
+       for (retry = 0; retry < 6; retry++) {
+               if (unlikely(avc_debug))
+                       debug_fcp(&c->ctype, c->length);
+
+               err = fdtv->backend->write(fdtv, FCP_COMMAND_REGISTER,
+                                          (void *)&c->ctype, c->length);
+               if (err) {
+                       fdtv->avc_reply_received = true;
+                       dev_err(fdtv->device, "FCP command write failed\n");
+                       return err;
+               }
+
+               if (!r)
+                       return 0;
+
+               /*
+                * AV/C specs say that answers should be sent within 150 ms.
+                * Time out after 200 ms.
+                */
+               if (wait_event_timeout(fdtv->avc_wait,
+                                      fdtv->avc_reply_received,
+                                      msecs_to_jiffies(200)) != 0) {
+                       r->length = fdtv->response_length;
+                       memcpy(&r->response, fdtv->response, r->length);
+
+                       return 0;
+               }
+       }
+       dev_err(fdtv->device, "FCP response timed out\n");
+       return -ETIMEDOUT;
+}
+
+static int avc_write(struct firedtv *fdtv,
+               const struct avc_command_frame *c, struct avc_response_frame *r)
+{
+       int ret;
+
+       if (mutex_lock_interruptible(&fdtv->avc_mutex))
+               return -EINTR;
+
+       ret = __avc_write(fdtv, c, r);
+
+       mutex_unlock(&fdtv->avc_mutex);
+       return ret;
+}
+
+int avc_recv(struct firedtv *fdtv, void *data, size_t length)
+{
+       struct avc_response_frame *r =
+                       data - offsetof(struct avc_response_frame, response);
+
+       if (unlikely(avc_debug))
+               debug_fcp(data, length);
+
+       if (length >= 8 &&
+           r->operand[0] == SFE_VENDOR_DE_COMPANYID_0 &&
+           r->operand[1] == SFE_VENDOR_DE_COMPANYID_1 &&
+           r->operand[2] == SFE_VENDOR_DE_COMPANYID_2 &&
+           r->operand[3] == SFE_VENDOR_OPCODE_REGISTER_REMOTE_CONTROL) {
+               if (r->response == AVC_RESPONSE_CHANGED) {
+                       fdtv_handle_rc(fdtv,
+                           r->operand[4] << 8 | r->operand[5]);
+                       schedule_work(&fdtv->remote_ctrl_work);
+               } else if (r->response != AVC_RESPONSE_INTERIM) {
+                       dev_info(fdtv->device,
+                                "remote control result = %d\n", r->response);
+               }
+               return 0;
+       }
+
+       if (fdtv->avc_reply_received) {
+               dev_err(fdtv->device, "out-of-order AVC response, ignored\n");
+               return -EIO;
+       }
+
+       memcpy(fdtv->response, data, length);
+       fdtv->response_length = length;
+
+       fdtv->avc_reply_received = true;
+       wake_up(&fdtv->avc_wait);
+
+       return 0;
+}
+
+/*
+ * tuning command for setting the relative LNB frequency
+ * (not supported by the AVC standard)
+ */
+static void avc_tuner_tuneqpsk(struct firedtv *fdtv,
+                              struct dvb_frontend_parameters *params,
+                              struct avc_command_frame *c)
+{
+       c->opcode = AVC_OPCODE_VENDOR;
+
+       c->operand[0] = SFE_VENDOR_DE_COMPANYID_0;
+       c->operand[1] = SFE_VENDOR_DE_COMPANYID_1;
+       c->operand[2] = SFE_VENDOR_DE_COMPANYID_2;
+       c->operand[3] = SFE_VENDOR_OPCODE_TUNE_QPSK;
+
+       c->operand[4] = (params->frequency >> 24) & 0xff;
+       c->operand[5] = (params->frequency >> 16) & 0xff;
+       c->operand[6] = (params->frequency >> 8) & 0xff;
+       c->operand[7] = params->frequency & 0xff;
+
+       c->operand[8] = ((params->u.qpsk.symbol_rate / 1000) >> 8) & 0xff;
+       c->operand[9] = (params->u.qpsk.symbol_rate / 1000) & 0xff;
+
+       switch (params->u.qpsk.fec_inner) {
+       case FEC_1_2:   c->operand[10] = 0x1; break;
+       case FEC_2_3:   c->operand[10] = 0x2; break;
+       case FEC_3_4:   c->operand[10] = 0x3; break;
+       case FEC_5_6:   c->operand[10] = 0x4; break;
+       case FEC_7_8:   c->operand[10] = 0x5; break;
+       case FEC_4_5:
+       case FEC_8_9:
+       case FEC_AUTO:
+       default:        c->operand[10] = 0x0;
+       }
+
+       if (fdtv->voltage == 0xff)
+               c->operand[11] = 0xff;
+       else if (fdtv->voltage == SEC_VOLTAGE_18) /* polarisation */
+               c->operand[11] = 0;
+       else
+               c->operand[11] = 1;
+
+       if (fdtv->tone == 0xff)
+               c->operand[12] = 0xff;
+       else if (fdtv->tone == SEC_TONE_ON) /* band */
+               c->operand[12] = 1;
+       else
+               c->operand[12] = 0;
+
+       if (fdtv->type == FIREDTV_DVB_S2) {
+               c->operand[13] = 0x1;
+               c->operand[14] = 0xff;
+               c->operand[15] = 0xff;
+               c->length = 20;
+       } else {
+               c->length = 16;
+       }
+}
+
+static void avc_tuner_dsd_dvb_c(struct dvb_frontend_parameters *params,
+                               struct avc_command_frame *c)
+{
+       c->opcode = AVC_OPCODE_DSD;
+
+       c->operand[0] = 0;    /* source plug */
+       c->operand[1] = 0xd2; /* subfunction replace */
+       c->operand[2] = 0x20; /* system id = DVB */
+       c->operand[3] = 0x00; /* antenna number */
+       c->operand[4] = 0x11; /* system_specific_multiplex selection_length */
+
+       /* multiplex_valid_flags, high byte */
+       c->operand[5] =   0 << 7 /* reserved */
+                       | 0 << 6 /* Polarisation */
+                       | 0 << 5 /* Orbital_Pos */
+                       | 1 << 4 /* Frequency */
+                       | 1 << 3 /* Symbol_Rate */
+                       | 0 << 2 /* FEC_outer */
+                       | (params->u.qam.fec_inner  != FEC_AUTO ? 1 << 1 : 0)
+                       | (params->u.qam.modulation != QAM_AUTO ? 1 << 0 : 0);
+
+       /* multiplex_valid_flags, low byte */
+       c->operand[6] =   0 << 7 /* NetworkID */
+                       | 0 << 0 /* reserved */ ;
+
+       c->operand[7]  = 0x00;
+       c->operand[8]  = 0x00;
+       c->operand[9]  = 0x00;
+       c->operand[10] = 0x00;
+
+       c->operand[11] = (((params->frequency / 4000) >> 16) & 0xff) | (2 << 6);
+       c->operand[12] = ((params->frequency / 4000) >> 8) & 0xff;
+       c->operand[13] = (params->frequency / 4000) & 0xff;
+       c->operand[14] = ((params->u.qpsk.symbol_rate / 1000) >> 12) & 0xff;
+       c->operand[15] = ((params->u.qpsk.symbol_rate / 1000) >> 4) & 0xff;
+       c->operand[16] = ((params->u.qpsk.symbol_rate / 1000) << 4) & 0xf0;
+       c->operand[17] = 0x00;
+
+       switch (params->u.qpsk.fec_inner) {
+       case FEC_1_2:   c->operand[18] = 0x1; break;
+       case FEC_2_3:   c->operand[18] = 0x2; break;
+       case FEC_3_4:   c->operand[18] = 0x3; break;
+       case FEC_5_6:   c->operand[18] = 0x4; break;
+       case FEC_7_8:   c->operand[18] = 0x5; break;
+       case FEC_8_9:   c->operand[18] = 0x6; break;
+       case FEC_4_5:   c->operand[18] = 0x8; break;
+       case FEC_AUTO:
+       default:        c->operand[18] = 0x0;
+       }
+
+       switch (params->u.qam.modulation) {
+       case QAM_16:    c->operand[19] = 0x08; break;
+       case QAM_32:    c->operand[19] = 0x10; break;
+       case QAM_64:    c->operand[19] = 0x18; break;
+       case QAM_128:   c->operand[19] = 0x20; break;
+       case QAM_256:   c->operand[19] = 0x28; break;
+       case QAM_AUTO:
+       default:        c->operand[19] = 0x00;
+       }
+
+       c->operand[20] = 0x00;
+       c->operand[21] = 0x00;
+       /* Nr_of_dsd_sel_specs = 0 -> no PIDs are transmitted */
+       c->operand[22] = 0x00;
+
+       c->length = 28;
+}
+
+static void avc_tuner_dsd_dvb_t(struct dvb_frontend_parameters *params,
+                               struct avc_command_frame *c)
+{
+       struct dvb_ofdm_parameters *ofdm = &params->u.ofdm;
+
+       c->opcode = AVC_OPCODE_DSD;
+
+       c->operand[0] = 0;    /* source plug */
+       c->operand[1] = 0xd2; /* subfunction replace */
+       c->operand[2] = 0x20; /* system id = DVB */
+       c->operand[3] = 0x00; /* antenna number */
+       c->operand[4] = 0x0c; /* system_specific_multiplex selection_length */
+
+       /* multiplex_valid_flags, high byte */
+       c->operand[5] =
+             0 << 7 /* reserved */
+           | 1 << 6 /* CenterFrequency */
+           | (ofdm->bandwidth      != BANDWIDTH_AUTO        ? 1 << 5 : 0)
+           | (ofdm->constellation  != QAM_AUTO              ? 1 << 4 : 0)
+           | (ofdm->hierarchy_information != HIERARCHY_AUTO ? 1 << 3 : 0)
+           | (ofdm->code_rate_HP   != FEC_AUTO              ? 1 << 2 : 0)
+           | (ofdm->code_rate_LP   != FEC_AUTO              ? 1 << 1 : 0)
+           | (ofdm->guard_interval != GUARD_INTERVAL_AUTO   ? 1 << 0 : 0);
+
+       /* multiplex_valid_flags, low byte */
+       c->operand[6] =
+             0 << 7 /* NetworkID */
+           | (ofdm->transmission_mode != TRANSMISSION_MODE_AUTO ? 1 << 6 : 0)
+           | 0 << 5 /* OtherFrequencyFlag */
+           | 0 << 0 /* reserved */ ;
+
+       c->operand[7]  = 0x0;
+       c->operand[8]  = (params->frequency / 10) >> 24;
+       c->operand[9]  = ((params->frequency / 10) >> 16) & 0xff;
+       c->operand[10] = ((params->frequency / 10) >>  8) & 0xff;
+       c->operand[11] = (params->frequency / 10) & 0xff;
+
+       switch (ofdm->bandwidth) {
+       case BANDWIDTH_7_MHZ:   c->operand[12] = 0x20; break;
+       case BANDWIDTH_8_MHZ:
+       case BANDWIDTH_6_MHZ:   /* not defined by AVC spec */
+       case BANDWIDTH_AUTO:
+       default:                c->operand[12] = 0x00;
+       }
+
+       switch (ofdm->constellation) {
+       case QAM_16:    c->operand[13] = 1 << 6; break;
+       case QAM_64:    c->operand[13] = 2 << 6; break;
+       case QPSK:
+       default:        c->operand[13] = 0x00;
+       }
+
+       switch (ofdm->hierarchy_information) {
+       case HIERARCHY_1:       c->operand[13] |= 1 << 3; break;
+       case HIERARCHY_2:       c->operand[13] |= 2 << 3; break;
+       case HIERARCHY_4:       c->operand[13] |= 3 << 3; break;
+       case HIERARCHY_AUTO:
+       case HIERARCHY_NONE:
+       default:                break;
+       }
+
+       switch (ofdm->code_rate_HP) {
+       case FEC_2_3:   c->operand[13] |= 1; break;
+       case FEC_3_4:   c->operand[13] |= 2; break;
+       case FEC_5_6:   c->operand[13] |= 3; break;
+       case FEC_7_8:   c->operand[13] |= 4; break;
+       case FEC_1_2:
+       default:        break;
+       }
+
+       switch (ofdm->code_rate_LP) {
+       case FEC_2_3:   c->operand[14] = 1 << 5; break;
+       case FEC_3_4:   c->operand[14] = 2 << 5; break;
+       case FEC_5_6:   c->operand[14] = 3 << 5; break;
+       case FEC_7_8:   c->operand[14] = 4 << 5; break;
+       case FEC_1_2:
+       default:        c->operand[14] = 0x00; break;
+       }
+
+       switch (ofdm->guard_interval) {
+       case GUARD_INTERVAL_1_16:       c->operand[14] |= 1 << 3; break;
+       case GUARD_INTERVAL_1_8:        c->operand[14] |= 2 << 3; break;
+       case GUARD_INTERVAL_1_4:        c->operand[14] |= 3 << 3; break;
+       case GUARD_INTERVAL_1_32:
+       case GUARD_INTERVAL_AUTO:
+       default:                        break;
+       }
+
+       switch (ofdm->transmission_mode) {
+       case TRANSMISSION_MODE_8K:      c->operand[14] |= 1 << 1; break;
+       case TRANSMISSION_MODE_2K:
+       case TRANSMISSION_MODE_AUTO:
+       default:                        break;
+       }
+
+       c->operand[15] = 0x00; /* network_ID[0] */
+       c->operand[16] = 0x00; /* network_ID[1] */
+       /* Nr_of_dsd_sel_specs = 0 -> no PIDs are transmitted */
+       c->operand[17] = 0x00;
+
+       c->length = 24;
+}
+
+int avc_tuner_dsd(struct firedtv *fdtv,
+                 struct dvb_frontend_parameters *params)
+{
+       char buffer[sizeof(struct avc_command_frame)];
+       struct avc_command_frame *c = (void *)buffer;
+       struct avc_response_frame *r = (void *)buffer; /* FIXME: unused */
+
+       memset(c, 0, sizeof(*c));
+
+       c->ctype   = AVC_CTYPE_CONTROL;
+       c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit;
+
+       switch (fdtv->type) {
+       case FIREDTV_DVB_S:
+       case FIREDTV_DVB_S2: avc_tuner_tuneqpsk(fdtv, params, c); break;
+       case FIREDTV_DVB_C: avc_tuner_dsd_dvb_c(params, c); break;
+       case FIREDTV_DVB_T: avc_tuner_dsd_dvb_t(params, c); break;
+       default:
+               BUG();
+       }
+
+       if (avc_write(fdtv, c, r) < 0)
+               return -EIO;
+
+       msleep(500);
+#if 0
+       /* FIXME: */
+       /* u8 *status was an out-parameter of avc_tuner_dsd, unused by caller */
+       if (status)
+               *status = r->operand[2];
+#endif
+       return 0;
+}
+
+int avc_tuner_set_pids(struct firedtv *fdtv, unsigned char pidc, u16 pid[])
+{
+       char buffer[sizeof(struct avc_command_frame)];
+       struct avc_command_frame *c = (void *)buffer;
+       struct avc_response_frame *r = (void *)buffer; /* FIXME: unused */
+       int pos, k;
+
+       if (pidc > 16 && pidc != 0xff)
+               return -EINVAL;
+
+       memset(c, 0, sizeof(*c));
+
+       c->ctype   = AVC_CTYPE_CONTROL;
+       c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit;
+       c->opcode  = AVC_OPCODE_DSD;
+
+       c->operand[0] = 0;      /* source plug */
+       c->operand[1] = 0xd2;   /* subfunction replace */
+       c->operand[2] = 0x20;   /* system id = DVB */
+       c->operand[3] = 0x00;   /* antenna number */
+       c->operand[4] = 0x00;   /* system_specific_multiplex selection_length */
+       c->operand[5] = pidc;   /* Nr_of_dsd_sel_specs */
+
+       pos = 6;
+       if (pidc != 0xff)
+               for (k = 0; k < pidc; k++) {
+                       c->operand[pos++] = 0x13; /* flowfunction relay */
+                       c->operand[pos++] = 0x80; /* dsd_sel_spec_valid_flags -> PID */
+                       c->operand[pos++] = (pid[k] >> 8) & 0x1f;
+                       c->operand[pos++] = pid[k] & 0xff;
+                       c->operand[pos++] = 0x00; /* tableID */
+                       c->operand[pos++] = 0x00; /* filter_length */
+               }
+
+       c->length = ALIGN(3 + pos, 4);
+
+       if (avc_write(fdtv, c, r) < 0)
+               return -EIO;
+
+       msleep(50);
+       return 0;
+}
+
+int avc_tuner_get_ts(struct firedtv *fdtv)
+{
+       char buffer[sizeof(struct avc_command_frame)];
+       struct avc_command_frame *c = (void *)buffer;
+       struct avc_response_frame *r = (void *)buffer; /* FIXME: unused */
+       int sl;
+
+       memset(c, 0, sizeof(*c));
+
+       c->ctype   = AVC_CTYPE_CONTROL;
+       c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit;
+       c->opcode  = AVC_OPCODE_DSIT;
+
+       sl = fdtv->type == FIREDTV_DVB_T ? 0x0c : 0x11;
+
+       c->operand[0] = 0;      /* source plug */
+       c->operand[1] = 0xd2;   /* subfunction replace */
+       c->operand[2] = 0xff;   /* status */
+       c->operand[3] = 0x20;   /* system id = DVB */
+       c->operand[4] = 0x00;   /* antenna number */
+       c->operand[5] = 0x0;    /* system_specific_search_flags */
+       c->operand[6] = sl;     /* system_specific_multiplex selection_length */
+       c->operand[7] = 0x00;   /* valid_flags [0] */
+       c->operand[8] = 0x00;   /* valid_flags [1] */
+       c->operand[7 + sl] = 0x00; /* nr_of_dsit_sel_specs (always 0) */
+
+       c->length = fdtv->type == FIREDTV_DVB_T ? 24 : 28;
+
+       if (avc_write(fdtv, c, r) < 0)
+               return -EIO;
+
+       msleep(250);
+       return 0;
+}
+
+int avc_identify_subunit(struct firedtv *fdtv)
+{
+       char buffer[sizeof(struct avc_command_frame)];
+       struct avc_command_frame *c = (void *)buffer;
+       struct avc_response_frame *r = (void *)buffer;
+
+       memset(c, 0, sizeof(*c));
+
+       c->ctype   = AVC_CTYPE_CONTROL;
+       c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit;
+       c->opcode  = AVC_OPCODE_READ_DESCRIPTOR;
+
+       c->operand[0] = DESCRIPTOR_SUBUNIT_IDENTIFIER;
+       c->operand[1] = 0xff;
+       c->operand[2] = 0x00;
+       c->operand[3] = 0x00; /* length highbyte */
+       c->operand[4] = 0x08; /* length lowbyte  */
+       c->operand[5] = 0x00; /* offset highbyte */
+       c->operand[6] = 0x0d; /* offset lowbyte  */
+
+       c->length = 12;
+
+       if (avc_write(fdtv, c, r) < 0)
+               return -EIO;
+
+       if ((r->response != AVC_RESPONSE_STABLE &&
+            r->response != AVC_RESPONSE_ACCEPTED) ||
+           (r->operand[3] << 8) + r->operand[4] != 8) {
+               dev_err(fdtv->device, "cannot read subunit identifier\n");
+               return -EINVAL;
+       }
+       return 0;
+}
+
+#define SIZEOF_ANTENNA_INPUT_INFO 22
+
+int avc_tuner_status(struct firedtv *fdtv, struct firedtv_tuner_status *stat)
+{
+       char buffer[sizeof(struct avc_command_frame)];
+       struct avc_command_frame *c = (void *)buffer;
+       struct avc_response_frame *r = (void *)buffer;
+       int length;
+
+       memset(c, 0, sizeof(*c));
+
+       c->ctype   = AVC_CTYPE_CONTROL;
+       c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit;
+       c->opcode  = AVC_OPCODE_READ_DESCRIPTOR;
+
+       c->operand[0] = DESCRIPTOR_TUNER_STATUS;
+       c->operand[1] = 0xff;   /* read_result_status */
+       c->operand[2] = 0x00;   /* reserved */
+       c->operand[3] = 0;      /* SIZEOF_ANTENNA_INPUT_INFO >> 8; */
+       c->operand[4] = 0;      /* SIZEOF_ANTENNA_INPUT_INFO & 0xff; */
+       c->operand[5] = 0x00;
+       c->operand[6] = 0x00;
+
+       c->length = 12;
+
+       if (avc_write(fdtv, c, r) < 0)
+               return -EIO;
+
+       if (r->response != AVC_RESPONSE_STABLE &&
+           r->response != AVC_RESPONSE_ACCEPTED) {
+               dev_err(fdtv->device, "cannot read tuner status\n");
+               return -EINVAL;
+       }
+
+       length = r->operand[9];
+       if (r->operand[1] != 0x10 || length != SIZEOF_ANTENNA_INPUT_INFO) {
+               dev_err(fdtv->device, "got invalid tuner status\n");
+               return -EINVAL;
+       }
+
+       stat->active_system             = r->operand[10];
+       stat->searching                 = r->operand[11] >> 7 & 1;
+       stat->moving                    = r->operand[11] >> 6 & 1;
+       stat->no_rf                     = r->operand[11] >> 5 & 1;
+       stat->input                     = r->operand[12] >> 7 & 1;
+       stat->selected_antenna          = r->operand[12] & 0x7f;
+       stat->ber                       = r->operand[13] << 24 |
+                                         r->operand[14] << 16 |
+                                         r->operand[15] << 8 |
+                                         r->operand[16];
+       stat->signal_strength           = r->operand[17];
+       stat->raster_frequency          = r->operand[18] >> 6 & 2;
+       stat->rf_frequency              = (r->operand[18] & 0x3f) << 16 |
+                                         r->operand[19] << 8 |
+                                         r->operand[20];
+       stat->man_dep_info_length       = r->operand[21];
+       stat->front_end_error           = r->operand[22] >> 4 & 1;
+       stat->antenna_error             = r->operand[22] >> 3 & 1;
+       stat->front_end_power_status    = r->operand[22] >> 1 & 1;
+       stat->power_supply              = r->operand[22] & 1;
+       stat->carrier_noise_ratio       = r->operand[23] << 8 |
+                                         r->operand[24];
+       stat->power_supply_voltage      = r->operand[27];
+       stat->antenna_voltage           = r->operand[28];
+       stat->firewire_bus_voltage      = r->operand[29];
+       stat->ca_mmi                    = r->operand[30] & 1;
+       stat->ca_pmt_reply              = r->operand[31] >> 7 & 1;
+       stat->ca_date_time_request      = r->operand[31] >> 6 & 1;
+       stat->ca_application_info       = r->operand[31] >> 5 & 1;
+       stat->ca_module_present_status  = r->operand[31] >> 4 & 1;
+       stat->ca_dvb_flag               = r->operand[31] >> 3 & 1;
+       stat->ca_error_flag             = r->operand[31] >> 2 & 1;
+       stat->ca_initialization_status  = r->operand[31] >> 1 & 1;
+
+       return 0;
+}
+
+int avc_lnb_control(struct firedtv *fdtv, char voltage, char burst,
+                   char conttone, char nrdiseq,
+                   struct dvb_diseqc_master_cmd *diseqcmd)
+{
+       char buffer[sizeof(struct avc_command_frame)];
+       struct avc_command_frame *c = (void *)buffer;
+       struct avc_response_frame *r = (void *)buffer;
+       int i, j, k;
+
+       memset(c, 0, sizeof(*c));
+
+       c->ctype   = AVC_CTYPE_CONTROL;
+       c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit;
+       c->opcode  = AVC_OPCODE_VENDOR;
+
+       c->operand[0] = SFE_VENDOR_DE_COMPANYID_0;
+       c->operand[1] = SFE_VENDOR_DE_COMPANYID_1;
+       c->operand[2] = SFE_VENDOR_DE_COMPANYID_2;
+       c->operand[3] = SFE_VENDOR_OPCODE_LNB_CONTROL;
+
+       c->operand[4] = voltage;
+       c->operand[5] = nrdiseq;
+
+       i = 6;
+
+       for (j = 0; j < nrdiseq; j++) {
+               c->operand[i++] = diseqcmd[j].msg_len;
+
+               for (k = 0; k < diseqcmd[j].msg_len; k++)
+                       c->operand[i++] = diseqcmd[j].msg[k];
+       }
+
+       c->operand[i++] = burst;
+       c->operand[i++] = conttone;
+
+       c->length = ALIGN(3 + i, 4);
+
+       if (avc_write(fdtv, c, r) < 0)
+               return -EIO;
+
+       if (r->response != AVC_RESPONSE_ACCEPTED) {
+               dev_err(fdtv->device, "LNB control failed\n");
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+int avc_register_remote_control(struct firedtv *fdtv)
+{
+       char buffer[sizeof(struct avc_command_frame)];
+       struct avc_command_frame *c = (void *)buffer;
+
+       memset(c, 0, sizeof(*c));
+
+       c->ctype   = AVC_CTYPE_NOTIFY;
+       c->subunit = AVC_SUBUNIT_TYPE_UNIT | 7;
+       c->opcode  = AVC_OPCODE_VENDOR;
+
+       c->operand[0] = SFE_VENDOR_DE_COMPANYID_0;
+       c->operand[1] = SFE_VENDOR_DE_COMPANYID_1;
+       c->operand[2] = SFE_VENDOR_DE_COMPANYID_2;
+       c->operand[3] = SFE_VENDOR_OPCODE_REGISTER_REMOTE_CONTROL;
+
+       c->length = 8;
+
+       return avc_write(fdtv, c, NULL);
+}
+
+void avc_remote_ctrl_work(struct work_struct *work)
+{
+       struct firedtv *fdtv =
+                       container_of(work, struct firedtv, remote_ctrl_work);
+
+       /* Should it be rescheduled in failure cases? */
+       avc_register_remote_control(fdtv);
+}
+
+#if 0 /* FIXME: unused */
+int avc_tuner_host2ca(struct firedtv *fdtv)
+{
+       char buffer[sizeof(struct avc_command_frame)];
+       struct avc_command_frame *c = (void *)buffer;
+       struct avc_response_frame *r = (void *)buffer; /* FIXME: unused */
+
+       memset(c, 0, sizeof(*c));
+
+       c->ctype   = AVC_CTYPE_CONTROL;
+       c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit;
+       c->opcode  = AVC_OPCODE_VENDOR;
+
+       c->operand[0] = SFE_VENDOR_DE_COMPANYID_0;
+       c->operand[1] = SFE_VENDOR_DE_COMPANYID_1;
+       c->operand[2] = SFE_VENDOR_DE_COMPANYID_2;
+       c->operand[3] = SFE_VENDOR_OPCODE_HOST2CA;
+       c->operand[4] = 0; /* slot */
+       c->operand[5] = SFE_VENDOR_TAG_CA_APPLICATION_INFO; /* ca tag */
+       c->operand[6] = 0; /* more/last */
+       c->operand[7] = 0; /* length */
+
+       c->length = 12;
+
+       if (avc_write(fdtv, c, r) < 0)
+               return -EIO;
+
+       return 0;
+}
+#endif
+
+static int get_ca_object_pos(struct avc_response_frame *r)
+{
+       int length = 1;
+
+       /* Check length of length field */
+       if (r->operand[7] & 0x80)
+               length = (r->operand[7] & 0x7f) + 1;
+       return length + 7;
+}
+
+static int get_ca_object_length(struct avc_response_frame *r)
+{
+#if 0 /* FIXME: unused */
+       int size = 0;
+       int i;
+
+       if (r->operand[7] & 0x80)
+               for (i = 0; i < (r->operand[7] & 0x7f); i++) {
+                       size <<= 8;
+                       size += r->operand[8 + i];
+               }
+#endif
+       return r->operand[7];
+}
+
+int avc_ca_app_info(struct firedtv *fdtv, char *app_info, unsigned int *len)
+{
+       char buffer[sizeof(struct avc_command_frame)];
+       struct avc_command_frame *c = (void *)buffer;
+       struct avc_response_frame *r = (void *)buffer;
+       int pos;
+
+       memset(c, 0, sizeof(*c));
+
+       c->ctype   = AVC_CTYPE_STATUS;
+       c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit;
+       c->opcode  = AVC_OPCODE_VENDOR;
+
+       c->operand[0] = SFE_VENDOR_DE_COMPANYID_0;
+       c->operand[1] = SFE_VENDOR_DE_COMPANYID_1;
+       c->operand[2] = SFE_VENDOR_DE_COMPANYID_2;
+       c->operand[3] = SFE_VENDOR_OPCODE_CA2HOST;
+       c->operand[4] = 0; /* slot */
+       c->operand[5] = SFE_VENDOR_TAG_CA_APPLICATION_INFO; /* ca tag */
+
+       c->length = 12;
+
+       if (avc_write(fdtv, c, r) < 0)
+               return -EIO;
+
+       /* FIXME: check response code and validate response data */
+
+       pos = get_ca_object_pos(r);
+       app_info[0] = (EN50221_TAG_APP_INFO >> 16) & 0xff;
+       app_info[1] = (EN50221_TAG_APP_INFO >>  8) & 0xff;
+       app_info[2] = (EN50221_TAG_APP_INFO >>  0) & 0xff;
+       app_info[3] = 6 + r->operand[pos + 4];
+       app_info[4] = 0x01;
+       memcpy(&app_info[5], &r->operand[pos], 5 + r->operand[pos + 4]);
+       *len = app_info[3] + 4;
+
+       return 0;
+}
+
+int avc_ca_info(struct firedtv *fdtv, char *app_info, unsigned int *len)
+{
+       char buffer[sizeof(struct avc_command_frame)];
+       struct avc_command_frame *c = (void *)buffer;
+       struct avc_response_frame *r = (void *)buffer;
+       int pos;
+
+       memset(c, 0, sizeof(*c));
+
+       c->ctype   = AVC_CTYPE_STATUS;
+       c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit;
+       c->opcode  = AVC_OPCODE_VENDOR;
+
+       c->operand[0] = SFE_VENDOR_DE_COMPANYID_0;
+       c->operand[1] = SFE_VENDOR_DE_COMPANYID_1;
+       c->operand[2] = SFE_VENDOR_DE_COMPANYID_2;
+       c->operand[3] = SFE_VENDOR_OPCODE_CA2HOST;
+       c->operand[4] = 0; /* slot */
+       c->operand[5] = SFE_VENDOR_TAG_CA_APPLICATION_INFO; /* ca tag */
+
+       c->length = 12;
+
+       if (avc_write(fdtv, c, r) < 0)
+               return -EIO;
+
+       pos = get_ca_object_pos(r);
+       app_info[0] = (EN50221_TAG_CA_INFO >> 16) & 0xff;
+       app_info[1] = (EN50221_TAG_CA_INFO >>  8) & 0xff;
+       app_info[2] = (EN50221_TAG_CA_INFO >>  0) & 0xff;
+       app_info[3] = 2;
+       app_info[4] = r->operand[pos + 0];
+       app_info[5] = r->operand[pos + 1];
+       *len = app_info[3] + 4;
+
+       return 0;
+}
+
+int avc_ca_reset(struct firedtv *fdtv)
+{
+       char buffer[sizeof(struct avc_command_frame)];
+       struct avc_command_frame *c = (void *)buffer;
+       struct avc_response_frame *r = (void *)buffer; /* FIXME: unused */
+
+       memset(c, 0, sizeof(*c));
+
+       c->ctype   = AVC_CTYPE_CONTROL;
+       c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit;
+       c->opcode  = AVC_OPCODE_VENDOR;
+
+       c->operand[0] = SFE_VENDOR_DE_COMPANYID_0;
+       c->operand[1] = SFE_VENDOR_DE_COMPANYID_1;
+       c->operand[2] = SFE_VENDOR_DE_COMPANYID_2;
+       c->operand[3] = SFE_VENDOR_OPCODE_HOST2CA;
+       c->operand[4] = 0; /* slot */
+       c->operand[5] = SFE_VENDOR_TAG_CA_RESET; /* ca tag */
+       c->operand[6] = 0; /* more/last */
+       c->operand[7] = 1; /* length */
+       c->operand[8] = 0; /* force hardware reset */
+
+       c->length = 12;
+
+       if (avc_write(fdtv, c, r) < 0)
+               return -EIO;
+
+       return 0;
+}
+
+int avc_ca_pmt(struct firedtv *fdtv, char *msg, int length)
+{
+       char buffer[sizeof(struct avc_command_frame)];
+       struct avc_command_frame *c = (void *)buffer;
+       struct avc_response_frame *r = (void *)buffer;
+       int list_management;
+       int program_info_length;
+       int pmt_cmd_id;
+       int read_pos;
+       int write_pos;
+       int es_info_length;
+       int crc32_csum;
+
+       memset(c, 0, sizeof(*c));
+
+       c->ctype   = AVC_CTYPE_CONTROL;
+       c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit;
+       c->opcode  = AVC_OPCODE_VENDOR;
+
+       if (msg[0] != EN50221_LIST_MANAGEMENT_ONLY) {
+               dev_info(fdtv->device, "forcing list_management to ONLY\n");
+               msg[0] = EN50221_LIST_MANAGEMENT_ONLY;
+       }
+       /* We take the cmd_id from the programme level only! */
+       list_management = msg[0];
+       program_info_length = ((msg[4] & 0x0f) << 8) + msg[5];
+       if (program_info_length > 0)
+               program_info_length--; /* Remove pmt_cmd_id */
+       pmt_cmd_id = msg[6];
+
+       c->operand[0] = SFE_VENDOR_DE_COMPANYID_0;
+       c->operand[1] = SFE_VENDOR_DE_COMPANYID_1;
+       c->operand[2] = SFE_VENDOR_DE_COMPANYID_2;
+       c->operand[3] = SFE_VENDOR_OPCODE_HOST2CA;
+       c->operand[4] = 0; /* slot */
+       c->operand[5] = SFE_VENDOR_TAG_CA_PMT; /* ca tag */
+       c->operand[6] = 0; /* more/last */
+       /* c->operand[7] = XXXprogram_info_length + 17; */ /* length */
+       c->operand[8] = list_management;
+       c->operand[9] = 0x01; /* pmt_cmd=OK_descramble */
+
+       /* TS program map table */
+
+       c->operand[10] = 0x02; /* Table id=2 */
+       c->operand[11] = 0x80; /* Section syntax + length */
+       /* c->operand[12] = XXXprogram_info_length + 12; */
+       c->operand[13] = msg[1]; /* Program number */
+       c->operand[14] = msg[2];
+       c->operand[15] = 0x01; /* Version number=0 + current/next=1 */
+       c->operand[16] = 0x00; /* Section number=0 */
+       c->operand[17] = 0x00; /* Last section number=0 */
+       c->operand[18] = 0x1f; /* PCR_PID=1FFF */
+       c->operand[19] = 0xff;
+       c->operand[20] = (program_info_length >> 8); /* Program info length */
+       c->operand[21] = (program_info_length & 0xff);
+
+       /* CA descriptors at programme level */
+       read_pos = 6;
+       write_pos = 22;
+       if (program_info_length > 0) {
+               pmt_cmd_id = msg[read_pos++];
+               if (pmt_cmd_id != 1 && pmt_cmd_id != 4)
+                       dev_err(fdtv->device,
+                               "invalid pmt_cmd_id %d\n", pmt_cmd_id);
+
+               memcpy(&c->operand[write_pos], &msg[read_pos],
+                      program_info_length);
+               read_pos += program_info_length;
+               write_pos += program_info_length;
+       }
+       while (read_pos < length) {
+               c->operand[write_pos++] = msg[read_pos++];
+               c->operand[write_pos++] = msg[read_pos++];
+               c->operand[write_pos++] = msg[read_pos++];
+               es_info_length =
+                       ((msg[read_pos] & 0x0f) << 8) + msg[read_pos + 1];
+               read_pos += 2;
+               if (es_info_length > 0)
+                       es_info_length--; /* Remove pmt_cmd_id */
+               c->operand[write_pos++] = es_info_length >> 8;
+               c->operand[write_pos++] = es_info_length & 0xff;
+               if (es_info_length > 0) {
+                       pmt_cmd_id = msg[read_pos++];
+                       if (pmt_cmd_id != 1 && pmt_cmd_id != 4)
+                               dev_err(fdtv->device, "invalid pmt_cmd_id %d "
+                                       "at stream level\n", pmt_cmd_id);
+
+                       memcpy(&c->operand[write_pos], &msg[read_pos],
+                              es_info_length);
+                       read_pos += es_info_length;
+                       write_pos += es_info_length;
+               }
+       }
+
+       /* CRC */
+       c->operand[write_pos++] = 0x00;
+       c->operand[write_pos++] = 0x00;
+       c->operand[write_pos++] = 0x00;
+       c->operand[write_pos++] = 0x00;
+
+       c->operand[7] = write_pos - 8;
+       c->operand[12] = write_pos - 13;
+
+       crc32_csum = crc32_be(0, &c->operand[10], c->operand[12] - 1);
+       c->operand[write_pos - 4] = (crc32_csum >> 24) & 0xff;
+       c->operand[write_pos - 3] = (crc32_csum >> 16) & 0xff;
+       c->operand[write_pos - 2] = (crc32_csum >>  8) & 0xff;
+       c->operand[write_pos - 1] = (crc32_csum >>  0) & 0xff;
+
+       c->length = ALIGN(3 + write_pos, 4);
+
+       if (avc_write(fdtv, c, r) < 0)
+               return -EIO;
+
+       if (r->response != AVC_RESPONSE_ACCEPTED) {
+               dev_err(fdtv->device,
+                       "CA PMT failed with response 0x%x\n", r->response);
+               return -EFAULT;
+       }
+
+       return 0;
+}
+
+int avc_ca_get_time_date(struct firedtv *fdtv, int *interval)
+{
+       char buffer[sizeof(struct avc_command_frame)];
+       struct avc_command_frame *c = (void *)buffer;
+       struct avc_response_frame *r = (void *)buffer;
+
+       memset(c, 0, sizeof(*c));
+
+       c->ctype   = AVC_CTYPE_STATUS;
+       c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit;
+       c->opcode  = AVC_OPCODE_VENDOR;
+
+       c->operand[0] = SFE_VENDOR_DE_COMPANYID_0;
+       c->operand[1] = SFE_VENDOR_DE_COMPANYID_1;
+       c->operand[2] = SFE_VENDOR_DE_COMPANYID_2;
+       c->operand[3] = SFE_VENDOR_OPCODE_CA2HOST;
+       c->operand[4] = 0; /* slot */
+       c->operand[5] = SFE_VENDOR_TAG_CA_DATE_TIME; /* ca tag */
+       c->operand[6] = 0; /* more/last */
+       c->operand[7] = 0; /* length */
+
+       c->length = 12;
+
+       if (avc_write(fdtv, c, r) < 0)
+               return -EIO;
+
+       /* FIXME: check response code and validate response data */
+
+       *interval = r->operand[get_ca_object_pos(r)];
+
+       return 0;
+}
+
+int avc_ca_enter_menu(struct firedtv *fdtv)
+{
+       char buffer[sizeof(struct avc_command_frame)];
+       struct avc_command_frame *c = (void *)buffer;
+       struct avc_response_frame *r = (void *)buffer; /* FIXME: unused */
+
+       memset(c, 0, sizeof(*c));
+
+       c->ctype   = AVC_CTYPE_STATUS;
+       c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit;
+       c->opcode  = AVC_OPCODE_VENDOR;
+
+       c->operand[0] = SFE_VENDOR_DE_COMPANYID_0;
+       c->operand[1] = SFE_VENDOR_DE_COMPANYID_1;
+       c->operand[2] = SFE_VENDOR_DE_COMPANYID_2;
+       c->operand[3] = SFE_VENDOR_OPCODE_HOST2CA;
+       c->operand[4] = 0; /* slot */
+       c->operand[5] = SFE_VENDOR_TAG_CA_ENTER_MENU;
+       c->operand[6] = 0; /* more/last */
+       c->operand[7] = 0; /* length */
+
+       c->length = 12;
+
+       if (avc_write(fdtv, c, r) < 0)
+               return -EIO;
+
+       return 0;
+}
+
+int avc_ca_get_mmi(struct firedtv *fdtv, char *mmi_object, unsigned int *len)
+{
+       char buffer[sizeof(struct avc_command_frame)];
+       struct avc_command_frame *c = (void *)buffer;
+       struct avc_response_frame *r = (void *)buffer;
+
+       memset(c, 0, sizeof(*c));
+
+       c->ctype   = AVC_CTYPE_STATUS;
+       c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit;
+       c->opcode  = AVC_OPCODE_VENDOR;
+
+       c->operand[0] = SFE_VENDOR_DE_COMPANYID_0;
+       c->operand[1] = SFE_VENDOR_DE_COMPANYID_1;
+       c->operand[2] = SFE_VENDOR_DE_COMPANYID_2;
+       c->operand[3] = SFE_VENDOR_OPCODE_CA2HOST;
+       c->operand[4] = 0; /* slot */
+       c->operand[5] = SFE_VENDOR_TAG_CA_MMI;
+       c->operand[6] = 0; /* more/last */
+       c->operand[7] = 0; /* length */
+
+       c->length = 12;
+
+       if (avc_write(fdtv, c, r) < 0)
+               return -EIO;
+
+       /* FIXME: check response code and validate response data */
+
+       *len = get_ca_object_length(r);
+       memcpy(mmi_object, &r->operand[get_ca_object_pos(r)], *len);
+
+       return 0;
+}
+
+#define CMP_OUTPUT_PLUG_CONTROL_REG_0  0xfffff0000904ULL
+
+static int cmp_read(struct firedtv *fdtv, void *buf, u64 addr, size_t len)
+{
+       int ret;
+
+       if (mutex_lock_interruptible(&fdtv->avc_mutex))
+               return -EINTR;
+
+       ret = fdtv->backend->read(fdtv, addr, buf, len);
+       if (ret < 0)
+               dev_err(fdtv->device, "CMP: read I/O error\n");
+
+       mutex_unlock(&fdtv->avc_mutex);
+       return ret;
+}
+
+static int cmp_lock(struct firedtv *fdtv, void *data, u64 addr, __be32 arg)
+{
+       int ret;
+
+       if (mutex_lock_interruptible(&fdtv->avc_mutex))
+               return -EINTR;
+
+       ret = fdtv->backend->lock(fdtv, addr, data, arg);
+       if (ret < 0)
+               dev_err(fdtv->device, "CMP: lock I/O error\n");
+
+       mutex_unlock(&fdtv->avc_mutex);
+       return ret;
+}
+
+static inline u32 get_opcr(__be32 opcr, u32 mask, u32 shift)
+{
+       return (be32_to_cpu(opcr) >> shift) & mask;
+}
+
+static inline void set_opcr(__be32 *opcr, u32 value, u32 mask, u32 shift)
+{
+       *opcr &= ~cpu_to_be32(mask << shift);
+       *opcr |= cpu_to_be32((value & mask) << shift);
+}
+
+#define get_opcr_online(v)             get_opcr((v), 0x1, 31)
+#define get_opcr_p2p_connections(v)    get_opcr((v), 0x3f, 24)
+#define get_opcr_channel(v)            get_opcr((v), 0x3f, 16)
+
+#define set_opcr_p2p_connections(p, v) set_opcr((p), (v), 0x3f, 24)
+#define set_opcr_channel(p, v)         set_opcr((p), (v), 0x3f, 16)
+#define set_opcr_data_rate(p, v)       set_opcr((p), (v), 0x3, 14)
+#define set_opcr_overhead_id(p, v)     set_opcr((p), (v), 0xf, 10)
+
+int cmp_establish_pp_connection(struct firedtv *fdtv, int plug, int channel)
+{
+       __be32 old_opcr, opcr;
+       u64 opcr_address = CMP_OUTPUT_PLUG_CONTROL_REG_0 + (plug << 2);
+       int attempts = 0;
+       int ret;
+
+       ret = cmp_read(fdtv, &opcr, opcr_address, 4);
+       if (ret < 0)
+               return ret;
+
+repeat:
+       if (!get_opcr_online(opcr)) {
+               dev_err(fdtv->device, "CMP: output offline\n");
+               return -EBUSY;
+       }
+
+       old_opcr = opcr;
+
+       if (get_opcr_p2p_connections(opcr)) {
+               if (get_opcr_channel(opcr) != channel) {
+                       dev_err(fdtv->device, "CMP: cannot change channel\n");
+                       return -EBUSY;
+               }
+               dev_info(fdtv->device, "CMP: overlaying connection\n");
+
+               /* We don't allocate isochronous resources. */
+       } else {
+               set_opcr_channel(&opcr, channel);
+               set_opcr_data_rate(&opcr, 2); /* S400 */
+
+               /* FIXME: this is for the worst case - optimize */
+               set_opcr_overhead_id(&opcr, 0);
+
+               /*
+                * FIXME: allocate isochronous channel and bandwidth at IRM
+                * fdtv->backend->alloc_resources(fdtv, channels_mask, bw);
+                */
+       }
+
+       set_opcr_p2p_connections(&opcr, get_opcr_p2p_connections(opcr) + 1);
+
+       ret = cmp_lock(fdtv, &opcr, opcr_address, old_opcr);
+       if (ret < 0)
+               return ret;
+
+       if (old_opcr != opcr) {
+               /*
+                * FIXME: if old_opcr.P2P_Connections > 0,
+                * deallocate isochronous channel and bandwidth at IRM
+                * if (...)
+                *      fdtv->backend->dealloc_resources(fdtv, channel, bw);
+                */
+
+               if (++attempts < 6) /* arbitrary limit */
+                       goto repeat;
+               return -EBUSY;
+       }
+
+       return 0;
+}
+
+void cmp_break_pp_connection(struct firedtv *fdtv, int plug, int channel)
+{
+       __be32 old_opcr, opcr;
+       u64 opcr_address = CMP_OUTPUT_PLUG_CONTROL_REG_0 + (plug << 2);
+       int attempts = 0;
+
+       if (cmp_read(fdtv, &opcr, opcr_address, 4) < 0)
+               return;
+
+repeat:
+       if (!get_opcr_online(opcr) || !get_opcr_p2p_connections(opcr) ||
+           get_opcr_channel(opcr) != channel) {
+               dev_err(fdtv->device, "CMP: no connection to break\n");
+               return;
+       }
+
+       old_opcr = opcr;
+       set_opcr_p2p_connections(&opcr, get_opcr_p2p_connections(opcr) - 1);
+
+       if (cmp_lock(fdtv, &opcr, opcr_address, old_opcr) < 0)
+               return;
+
+       if (old_opcr != opcr) {
+               /*
+                * FIXME: if old_opcr.P2P_Connections == 1, i.e. we were last
+                * owner, deallocate isochronous channel and bandwidth at IRM
+                * if (...)
+                *      fdtv->backend->dealloc_resources(fdtv, channel, bw);
+                */
+
+               if (++attempts < 6) /* arbitrary limit */
+                       goto repeat;
+       }
+}
index 6d87926b8bfe1fdcd3a47c386897145fc97676cf..eeb80d0ea3ff24585295aad880e0a77ecc9078fb 100644 (file)
  *     the License, or (at your option) any later version.
  */
 
+#include <linux/device.h>
 #include <linux/dvb/ca.h>
 #include <linux/fs.h>
 #include <linux/module.h>
 
 #include <dvbdev.h>
 
-#include "avc.h"
 #include "firedtv.h"
-#include "firedtv-ci.h"
 
-static int fdtv_ca_ready(ANTENNA_INPUT_INFO *info)
+#define EN50221_TAG_APP_INFO_ENQUIRY   0x9f8020
+#define EN50221_TAG_CA_INFO_ENQUIRY    0x9f8030
+#define EN50221_TAG_CA_PMT             0x9f8032
+#define EN50221_TAG_ENTER_MENU         0x9f8022
+
+static int fdtv_ca_ready(struct firedtv_tuner_status *stat)
 {
-       return info->CaInitializationStatus == 1 &&
-              info->CaErrorFlag == 0 &&
-              info->CaDvbFlag == 1 &&
-              info->CaModulePresentStatus == 1;
+       return stat->ca_initialization_status   == 1 &&
+              stat->ca_error_flag              == 0 &&
+              stat->ca_dvb_flag                == 1 &&
+              stat->ca_module_present_status   == 1;
 }
 
-static int fdtv_get_ca_flags(ANTENNA_INPUT_INFO *info)
+static int fdtv_get_ca_flags(struct firedtv_tuner_status *stat)
 {
        int flags = 0;
 
-       if (info->CaModulePresentStatus == 1)
+       if (stat->ca_module_present_status == 1)
                flags |= CA_CI_MODULE_PRESENT;
-       if (info->CaInitializationStatus == 1 &&
-           info->CaErrorFlag == 0 &&
-           info->CaDvbFlag == 1)
+       if (stat->ca_initialization_status == 1 &&
+           stat->ca_error_flag            == 0 &&
+           stat->ca_dvb_flag              == 1)
                flags |= CA_CI_MODULE_READY;
        return flags;
 }
@@ -59,17 +63,17 @@ static int fdtv_ca_get_caps(void *arg)
 
 static int fdtv_ca_get_slot_info(struct firedtv *fdtv, void *arg)
 {
-       ANTENNA_INPUT_INFO info;
+       struct firedtv_tuner_status stat;
        struct ca_slot_info *slot = arg;
 
-       if (avc_tuner_status(fdtv, &info))
+       if (avc_tuner_status(fdtv, &stat))
                return -EFAULT;
 
        if (slot->num != 0)
                return -EFAULT;
 
        slot->type = CA_CI;
-       slot->flags = fdtv_get_ca_flags(&info);
+       slot->flags = fdtv_get_ca_flags(&stat);
        return 0;
 }
 
@@ -77,8 +81,7 @@ static int fdtv_ca_app_info(struct firedtv *fdtv, void *arg)
 {
        struct ca_msg *reply = arg;
 
-       return
-           avc_ca_app_info(fdtv, reply->msg, &reply->length) ? -EFAULT : 0;
+       return avc_ca_app_info(fdtv, reply->msg, &reply->length) ? -EFAULT : 0;
 }
 
 static int fdtv_ca_info(struct firedtv *fdtv, void *arg)
@@ -92,30 +95,29 @@ static int fdtv_ca_get_mmi(struct firedtv *fdtv, void *arg)
 {
        struct ca_msg *reply = arg;
 
-       return
-           avc_ca_get_mmi(fdtv, reply->msg, &reply->length) ? -EFAULT : 0;
+       return avc_ca_get_mmi(fdtv, reply->msg, &reply->length) ? -EFAULT : 0;
 }
 
 static int fdtv_ca_get_msg(struct firedtv *fdtv, void *arg)
 {
-       ANTENNA_INPUT_INFO info;
+       struct firedtv_tuner_status stat;
        int err;
 
        switch (fdtv->ca_last_command) {
-       case TAG_APP_INFO_ENQUIRY:
+       case EN50221_TAG_APP_INFO_ENQUIRY:
                err = fdtv_ca_app_info(fdtv, arg);
                break;
-       case TAG_CA_INFO_ENQUIRY:
+       case EN50221_TAG_CA_INFO_ENQUIRY:
                err = fdtv_ca_info(fdtv, arg);
                break;
        default:
-               if (avc_tuner_status(fdtv, &info))
+               if (avc_tuner_status(fdtv, &stat))
                        err = -EFAULT;
-               else if (info.CaMmi == 1)
+               else if (stat.ca_mmi == 1)
                        err = fdtv_ca_get_mmi(fdtv, arg);
                else {
-                       printk(KERN_INFO "%s: Unhandled message 0x%08X\n",
-                              __func__, fdtv->ca_last_command);
+                       dev_info(fdtv->device, "unhandled CA message 0x%08x\n",
+                                fdtv->ca_last_command);
                        err = -EFAULT;
                }
        }
@@ -133,14 +135,13 @@ static int fdtv_ca_pmt(struct firedtv *fdtv, void *arg)
        data_pos = 4;
        if (msg->msg[3] & 0x80) {
                data_length = 0;
-               for (i = 0; i < (msg->msg[3] & 0x7F); i++)
+               for (i = 0; i < (msg->msg[3] & 0x7f); i++)
                        data_length = (data_length << 8) + msg->msg[data_pos++];
        } else {
                data_length = msg->msg[3];
        }
 
-       return avc_ca_pmt(fdtv, &msg->msg[data_pos], data_length) ?
-              -EFAULT : 0;
+       return avc_ca_pmt(fdtv, &msg->msg[data_pos], data_length) ? -EFAULT : 0;
 }
 
 static int fdtv_ca_send_msg(struct firedtv *fdtv, void *arg)
@@ -152,23 +153,23 @@ static int fdtv_ca_send_msg(struct firedtv *fdtv, void *arg)
        fdtv->ca_last_command =
                (msg->msg[0] << 16) + (msg->msg[1] << 8) + msg->msg[2];
        switch (fdtv->ca_last_command) {
-       case TAG_CA_PMT:
+       case EN50221_TAG_CA_PMT:
                err = fdtv_ca_pmt(fdtv, arg);
                break;
-       case TAG_APP_INFO_ENQUIRY:
+       case EN50221_TAG_APP_INFO_ENQUIRY:
                /* handled in ca_get_msg */
                err = 0;
                break;
-       case TAG_CA_INFO_ENQUIRY:
+       case EN50221_TAG_CA_INFO_ENQUIRY:
                /* handled in ca_get_msg */
                err = 0;
                break;
-       case TAG_ENTER_MENU:
+       case EN50221_TAG_ENTER_MENU:
                err = avc_ca_enter_menu(fdtv);
                break;
        default:
-               printk(KERN_ERR "%s: Unhandled unknown message 0x%08X\n",
-                      __func__, fdtv->ca_last_command);
+               dev_err(fdtv->device, "unhandled CA message 0x%08x\n",
+                       fdtv->ca_last_command);
                err = -EFAULT;
        }
        return err;
@@ -179,10 +180,10 @@ static int fdtv_ca_ioctl(struct inode *inode, struct file *file,
 {
        struct dvb_device *dvbdev = file->private_data;
        struct firedtv *fdtv = dvbdev->priv;
-       ANTENNA_INPUT_INFO info;
+       struct firedtv_tuner_status stat;
        int err;
 
-       switch(cmd) {
+       switch (cmd) {
        case CA_RESET:
                err = fdtv_ca_reset(fdtv);
                break;
@@ -199,13 +200,12 @@ static int fdtv_ca_ioctl(struct inode *inode, struct file *file,
                err = fdtv_ca_send_msg(fdtv, arg);
                break;
        default:
-               printk(KERN_INFO "%s: Unhandled ioctl, command: %u\n",__func__,
-                      cmd);
+               dev_info(fdtv->device, "unhandled CA ioctl %u\n", cmd);
                err = -EOPNOTSUPP;
        }
 
        /* FIXME Is this necessary? */
-       avc_tuner_status(fdtv, &info);
+       avc_tuner_status(fdtv, &stat);
 
        return err;
 }
@@ -233,22 +233,21 @@ static struct dvb_device fdtv_ca = {
 
 int fdtv_ca_register(struct firedtv *fdtv)
 {
-       ANTENNA_INPUT_INFO info;
+       struct firedtv_tuner_status stat;
        int err;
 
-       if (avc_tuner_status(fdtv, &info))
+       if (avc_tuner_status(fdtv, &stat))
                return -EINVAL;
 
-       if (!fdtv_ca_ready(&info))
+       if (!fdtv_ca_ready(&stat))
                return -EFAULT;
 
        err = dvb_register_device(&fdtv->adapter, &fdtv->cadev,
                                  &fdtv_ca, fdtv, DVB_DEVICE_CA);
 
-       if (info.CaApplicationInfo == 0)
-               printk(KERN_ERR "%s: CaApplicationInfo is not set.\n",
-                      __func__);
-       if (info.CaDateTimeRequest == 1)
+       if (stat.ca_application_info == 0)
+               dev_err(fdtv->device, "CaApplicationInfo is not set\n");
+       if (stat.ca_date_time_request == 1)
                avc_ca_get_time_date(fdtv, &fdtv->ca_time_interval);
 
        return err;
diff --git a/drivers/media/dvb/firewire/firedtv-ci.h b/drivers/media/dvb/firewire/firedtv-ci.h
deleted file mode 100644 (file)
index d6840f5..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-#ifndef _FIREDTV_CI_H
-#define _FIREDTV_CI_H
-
-struct firedtv;
-
-int fdtv_ca_register(struct firedtv *fdtv);
-void fdtv_ca_release(struct firedtv *fdtv);
-
-#endif /* _FIREDTV_CI_H */
index 1823058696f21eea41a7906359ab19d46f4f2e6f..9d308dd32a5ce4337efe97f594b2663aebe5570f 100644 (file)
  *     the License, or (at your option) any later version.
  */
 
+#include <linux/bitops.h>
+#include <linux/device.h>
 #include <linux/errno.h>
 #include <linux/kernel.h>
+#include <linux/mod_devicetable.h>
+#include <linux/module.h>
 #include <linux/mutex.h>
+#include <linux/slab.h>
+#include <linux/string.h>
 #include <linux/types.h>
+#include <linux/wait.h>
+#include <linux/workqueue.h>
 
+#include <dmxdev.h>
 #include <dvb_demux.h>
-#include <dvb_frontend.h>
 #include <dvbdev.h>
+#include <dvb_frontend.h>
 
-#include "avc.h"
 #include "firedtv.h"
-#include "firedtv-ci.h"
-
-DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
 
-static struct firedtv_channel *fdtv_channel_allocate(struct firedtv *fdtv)
+static int alloc_channel(struct firedtv *fdtv)
 {
-       struct firedtv_channel *c = NULL;
-       int k;
+       int i;
 
-       if (mutex_lock_interruptible(&fdtv->demux_mutex))
-               return NULL;
-
-       for (k = 0; k < 16; k++)
-               if (!fdtv->channel[k].active) {
-                       fdtv->channel[k].active = true;
-                       c = &fdtv->channel[k];
+       for (i = 0; i < 16; i++)
+               if (!__test_and_set_bit(i, &fdtv->channel_active))
                        break;
-               }
-
-       mutex_unlock(&fdtv->demux_mutex);
-       return c;
+       return i;
 }
 
-static int fdtv_channel_collect(struct firedtv *fdtv, int *pidc, u16 pid[])
+static void collect_channels(struct firedtv *fdtv, int *pidc, u16 pid[])
 {
-       int k, l = 0;
-
-       if (mutex_lock_interruptible(&fdtv->demux_mutex))
-               return -EINTR;
-
-       for (k = 0; k < 16; k++)
-               if (fdtv->channel[k].active)
-                       pid[l++] = fdtv->channel[k].pid;
-
-       mutex_unlock(&fdtv->demux_mutex);
+       int i, n;
 
-       *pidc = l;
-
-       return 0;
+       for (i = 0, n = 0; i < 16; i++)
+               if (test_bit(i, &fdtv->channel_active))
+                       pid[n++] = fdtv->channel_pid[i];
+       *pidc = n;
 }
 
-static int fdtv_channel_release(struct firedtv *fdtv,
-                                  struct firedtv_channel *channel)
+static inline void dealloc_channel(struct firedtv *fdtv, int i)
 {
-       if (mutex_lock_interruptible(&fdtv->demux_mutex))
-               return -EINTR;
-
-       channel->active = false;
-
-       mutex_unlock(&fdtv->demux_mutex);
-       return 0;
+       __clear_bit(i, &fdtv->channel_active);
 }
 
 int fdtv_start_feed(struct dvb_demux_feed *dvbdmxfeed)
 {
-       struct firedtv *fdtv = (struct firedtv*)dvbdmxfeed->demux->priv;
-       struct firedtv_channel *channel;
-       int pidc,k;
+       struct firedtv *fdtv = dvbdmxfeed->demux->priv;
+       int pidc, c, ret;
        u16 pids[16];
 
        switch (dvbdmxfeed->type) {
@@ -86,11 +66,14 @@ int fdtv_start_feed(struct dvb_demux_feed *dvbdmxfeed)
        case DMX_TYPE_SEC:
                break;
        default:
-               printk(KERN_ERR "%s: invalid type %u\n",
-                      __func__, dvbdmxfeed->type);
+               dev_err(fdtv->device, "can't start dmx feed: invalid type %u\n",
+                       dvbdmxfeed->type);
                return -EINVAL;
        }
 
+       if (mutex_lock_interruptible(&fdtv->demux_mutex))
+               return -EINTR;
+
        if (dvbdmxfeed->type == DMX_TYPE_TS) {
                switch (dvbdmxfeed->pes_type) {
                case DMX_TS_PES_VIDEO:
@@ -98,75 +81,64 @@ int fdtv_start_feed(struct dvb_demux_feed *dvbdmxfeed)
                case DMX_TS_PES_TELETEXT:
                case DMX_TS_PES_PCR:
                case DMX_TS_PES_OTHER:
-                       //Dirty fix to keep fdtv->channel pid-list up to date
-                       for(k=0;k<16;k++){
-                               if (!fdtv->channel[k].active)
-                                       fdtv->channel[k].pid =
-                                               dvbdmxfeed->pid;
-                                       break;
-                       }
-                       channel = fdtv_channel_allocate(fdtv);
+                       c = alloc_channel(fdtv);
                        break;
                default:
-                       printk(KERN_ERR "%s: invalid pes type %u\n",
-                              __func__, dvbdmxfeed->pes_type);
-                       return -EINVAL;
+                       dev_err(fdtv->device,
+                               "can't start dmx feed: invalid pes type %u\n",
+                               dvbdmxfeed->pes_type);
+                       ret = -EINVAL;
+                       goto out;
                }
        } else {
-               channel = fdtv_channel_allocate(fdtv);
+               c = alloc_channel(fdtv);
        }
 
-       if (!channel) {
-               printk(KERN_ERR "%s: busy!\n", __func__);
-               return -EBUSY;
+       if (c > 15) {
+               dev_err(fdtv->device, "can't start dmx feed: busy\n");
+               ret = -EBUSY;
+               goto out;
        }
 
-       dvbdmxfeed->priv = channel;
-       channel->pid = dvbdmxfeed->pid;
-
-       if (fdtv_channel_collect(fdtv, &pidc, pids)) {
-               fdtv_channel_release(fdtv, channel);
-               printk(KERN_ERR "%s: could not collect pids!\n", __func__);
-               return -EINTR;
-       }
+       dvbdmxfeed->priv = (typeof(dvbdmxfeed->priv))(unsigned long)c;
+       fdtv->channel_pid[c] = dvbdmxfeed->pid;
+       collect_channels(fdtv, &pidc, pids);
 
        if (dvbdmxfeed->pid == 8192) {
-               k = avc_tuner_get_ts(fdtv);
-               if (k) {
-                       fdtv_channel_release(fdtv, channel);
-                       printk("%s: AVCTuner_GetTS failed with error %d\n",
-                              __func__, k);
-                       return k;
+               ret = avc_tuner_get_ts(fdtv);
+               if (ret) {
+                       dealloc_channel(fdtv, c);
+                       dev_err(fdtv->device, "can't get TS\n");
+                       goto out;
                }
        } else {
-               k = avc_tuner_set_pids(fdtv, pidc, pids);
-               if (k) {
-                       fdtv_channel_release(fdtv, channel);
-                       printk("%s: AVCTuner_SetPIDs failed with error %d\n",
-                              __func__, k);
-                       return k;
+               ret = avc_tuner_set_pids(fdtv, pidc, pids);
+               if (ret) {
+                       dealloc_channel(fdtv, c);
+                       dev_err(fdtv->device, "can't set PIDs\n");
+                       goto out;
                }
        }
+out:
+       mutex_unlock(&fdtv->demux_mutex);
 
-       return 0;
+       return ret;
 }
 
 int fdtv_stop_feed(struct dvb_demux_feed *dvbdmxfeed)
 {
        struct dvb_demux *demux = dvbdmxfeed->demux;
-       struct firedtv *fdtv = (struct firedtv*)demux->priv;
-       struct firedtv_channel *c = dvbdmxfeed->priv;
-       int k, l;
+       struct firedtv *fdtv = demux->priv;
+       int pidc, c, ret;
        u16 pids[16];
 
-       if (dvbdmxfeed->type == DMX_TYPE_TS && !((dvbdmxfeed->ts_type & TS_PACKET) &&
-                               (demux->dmx.frontend->source != DMX_MEMORY_FE))) {
+       if (dvbdmxfeed->type == DMX_TYPE_TS &&
+           !((dvbdmxfeed->ts_type & TS_PACKET) &&
+             (demux->dmx.frontend->source != DMX_MEMORY_FE))) {
 
                if (dvbdmxfeed->ts_type & TS_DECODER) {
-
                        if (dvbdmxfeed->pes_type >= DMX_TS_PES_OTHER ||
-                               !demux->pesfilter[dvbdmxfeed->pes_type])
-
+                           !demux->pesfilter[dvbdmxfeed->pes_type])
                                return -EINVAL;
 
                        demux->pids[dvbdmxfeed->pes_type] |= 0x8000;
@@ -174,38 +146,32 @@ int fdtv_stop_feed(struct dvb_demux_feed *dvbdmxfeed)
                }
 
                if (!(dvbdmxfeed->ts_type & TS_DECODER &&
-                       dvbdmxfeed->pes_type < DMX_TS_PES_OTHER))
-
+                     dvbdmxfeed->pes_type < DMX_TS_PES_OTHER))
                        return 0;
        }
 
        if (mutex_lock_interruptible(&fdtv->demux_mutex))
                return -EINTR;
 
-       /* list except channel to be removed */
-       for (k = 0, l = 0; k < 16; k++)
-               if (fdtv->channel[k].active) {
-                       if (&fdtv->channel[k] != c)
-                               pids[l++] = fdtv->channel[k].pid;
-                       else
-                               fdtv->channel[k].active = false;
-               }
+       c = (unsigned long)dvbdmxfeed->priv;
+       dealloc_channel(fdtv, c);
+       collect_channels(fdtv, &pidc, pids);
 
-       k = avc_tuner_set_pids(fdtv, l, pids);
-       if (!k)
-               c->active = false;
+       ret = avc_tuner_set_pids(fdtv, pidc, pids);
 
        mutex_unlock(&fdtv->demux_mutex);
-       return k;
+
+       return ret;
 }
 
-int fdtv_dvbdev_init(struct firedtv *fdtv, struct device *dev)
+DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
+
+int fdtv_dvb_register(struct firedtv *fdtv)
 {
        int err;
 
-       err = DVB_REGISTER_ADAPTER(&fdtv->adapter,
-                                  fdtv_model_names[fdtv->type],
-                                  THIS_MODULE, dev, adapter_nr);
+       err = dvb_register_adapter(&fdtv->adapter, fdtv_model_names[fdtv->type],
+                                  THIS_MODULE, fdtv->device, adapter_nr);
        if (err < 0)
                goto fail_log;
 
@@ -223,9 +189,9 @@ int fdtv_dvbdev_init(struct firedtv *fdtv, struct device *dev)
        if (err)
                goto fail_unreg_adapter;
 
-       fdtv->dmxdev.filternum  = 16;
-       fdtv->dmxdev.demux              = &fdtv->demux.dmx;
-       fdtv->dmxdev.capabilities       = 0;
+       fdtv->dmxdev.filternum    = 16;
+       fdtv->dmxdev.demux        = &fdtv->demux.dmx;
+       fdtv->dmxdev.capabilities = 0;
 
        err = dvb_dmxdev_init(&fdtv->dmxdev, &fdtv->adapter);
        if (err)
@@ -233,13 +199,12 @@ int fdtv_dvbdev_init(struct firedtv *fdtv, struct device *dev)
 
        fdtv->frontend.source = DMX_FRONTEND_0;
 
-       err = fdtv->demux.dmx.add_frontend(&fdtv->demux.dmx,
-                                             &fdtv->frontend);
+       err = fdtv->demux.dmx.add_frontend(&fdtv->demux.dmx, &fdtv->frontend);
        if (err)
                goto fail_dmxdev_release;
 
        err = fdtv->demux.dmx.connect_frontend(&fdtv->demux.dmx,
-                                                 &fdtv->frontend);
+                                              &fdtv->frontend);
        if (err)
                goto fail_rem_frontend;
 
@@ -252,16 +217,15 @@ int fdtv_dvbdev_init(struct firedtv *fdtv, struct device *dev)
 
        err = fdtv_ca_register(fdtv);
        if (err)
-               dev_info(dev, "Conditional Access Module not enabled\n");
-
+               dev_info(fdtv->device,
+                        "Conditional Access Module not enabled\n");
        return 0;
 
 fail_net_release:
        dvb_net_release(&fdtv->dvbnet);
        fdtv->demux.dmx.close(&fdtv->demux.dmx);
 fail_rem_frontend:
-       fdtv->demux.dmx.remove_frontend(&fdtv->demux.dmx,
-                                          &fdtv->frontend);
+       fdtv->demux.dmx.remove_frontend(&fdtv->demux.dmx, &fdtv->frontend);
 fail_dmxdev_release:
        dvb_dmxdev_release(&fdtv->dmxdev);
 fail_dmx_release:
@@ -269,8 +233,132 @@ fail_dmx_release:
 fail_unreg_adapter:
        dvb_unregister_adapter(&fdtv->adapter);
 fail_log:
-       dev_err(dev, "DVB initialization failed\n");
+       dev_err(fdtv->device, "DVB initialization failed\n");
        return err;
 }
 
+void fdtv_dvb_unregister(struct firedtv *fdtv)
+{
+       fdtv_ca_release(fdtv);
+       dvb_unregister_frontend(&fdtv->fe);
+       dvb_net_release(&fdtv->dvbnet);
+       fdtv->demux.dmx.close(&fdtv->demux.dmx);
+       fdtv->demux.dmx.remove_frontend(&fdtv->demux.dmx, &fdtv->frontend);
+       dvb_dmxdev_release(&fdtv->dmxdev);
+       dvb_dmx_release(&fdtv->demux);
+       dvb_unregister_adapter(&fdtv->adapter);
+}
+
+const char *fdtv_model_names[] = {
+       [FIREDTV_UNKNOWN] = "unknown type",
+       [FIREDTV_DVB_S]   = "FireDTV S/CI",
+       [FIREDTV_DVB_C]   = "FireDTV C/CI",
+       [FIREDTV_DVB_T]   = "FireDTV T/CI",
+       [FIREDTV_DVB_S2]  = "FireDTV S2  ",
+};
+
+struct firedtv *fdtv_alloc(struct device *dev,
+                          const struct firedtv_backend *backend,
+                          const char *name, size_t name_len)
+{
+       struct firedtv *fdtv;
+       int i;
+
+       fdtv = kzalloc(sizeof(*fdtv), GFP_KERNEL);
+       if (!fdtv)
+               return NULL;
+
+       dev->driver_data        = fdtv;
+       fdtv->device            = dev;
+       fdtv->isochannel        = -1;
+       fdtv->voltage           = 0xff;
+       fdtv->tone              = 0xff;
+       fdtv->backend           = backend;
+
+       mutex_init(&fdtv->avc_mutex);
+       init_waitqueue_head(&fdtv->avc_wait);
+       fdtv->avc_reply_received = true;
+       mutex_init(&fdtv->demux_mutex);
+       INIT_WORK(&fdtv->remote_ctrl_work, avc_remote_ctrl_work);
+
+       for (i = ARRAY_SIZE(fdtv_model_names); --i; )
+               if (strlen(fdtv_model_names[i]) <= name_len &&
+                   strncmp(name, fdtv_model_names[i], name_len) == 0)
+                       break;
+       fdtv->type = i;
+
+       return fdtv;
+}
+
+#define MATCH_FLAGS (IEEE1394_MATCH_VENDOR_ID | IEEE1394_MATCH_MODEL_ID | \
+                    IEEE1394_MATCH_SPECIFIER_ID | IEEE1394_MATCH_VERSION)
+
+#define DIGITAL_EVERYWHERE_OUI 0x001287
+#define AVC_UNIT_SPEC_ID_ENTRY 0x00a02d
+#define AVC_SW_VERSION_ENTRY   0x010001
+
+static struct ieee1394_device_id fdtv_id_table[] = {
+       {
+               /* FloppyDTV S/CI and FloppyDTV S2 */
+               .match_flags    = MATCH_FLAGS,
+               .vendor_id      = DIGITAL_EVERYWHERE_OUI,
+               .model_id       = 0x000024,
+               .specifier_id   = AVC_UNIT_SPEC_ID_ENTRY,
+               .version        = AVC_SW_VERSION_ENTRY,
+       }, {
+               /* FloppyDTV T/CI */
+               .match_flags    = MATCH_FLAGS,
+               .vendor_id      = DIGITAL_EVERYWHERE_OUI,
+               .model_id       = 0x000025,
+               .specifier_id   = AVC_UNIT_SPEC_ID_ENTRY,
+               .version        = AVC_SW_VERSION_ENTRY,
+       }, {
+               /* FloppyDTV C/CI */
+               .match_flags    = MATCH_FLAGS,
+               .vendor_id      = DIGITAL_EVERYWHERE_OUI,
+               .model_id       = 0x000026,
+               .specifier_id   = AVC_UNIT_SPEC_ID_ENTRY,
+               .version        = AVC_SW_VERSION_ENTRY,
+       }, {
+               /* FireDTV S/CI and FloppyDTV S2 */
+               .match_flags    = MATCH_FLAGS,
+               .vendor_id      = DIGITAL_EVERYWHERE_OUI,
+               .model_id       = 0x000034,
+               .specifier_id   = AVC_UNIT_SPEC_ID_ENTRY,
+               .version        = AVC_SW_VERSION_ENTRY,
+       }, {
+               /* FireDTV T/CI */
+               .match_flags    = MATCH_FLAGS,
+               .vendor_id      = DIGITAL_EVERYWHERE_OUI,
+               .model_id       = 0x000035,
+               .specifier_id   = AVC_UNIT_SPEC_ID_ENTRY,
+               .version        = AVC_SW_VERSION_ENTRY,
+       }, {
+               /* FireDTV C/CI */
+               .match_flags    = MATCH_FLAGS,
+               .vendor_id      = DIGITAL_EVERYWHERE_OUI,
+               .model_id       = 0x000036,
+               .specifier_id   = AVC_UNIT_SPEC_ID_ENTRY,
+               .version        = AVC_SW_VERSION_ENTRY,
+       }, {}
+};
+MODULE_DEVICE_TABLE(ieee1394, fdtv_id_table);
+
+static int __init fdtv_init(void)
+{
+       return fdtv_1394_init(fdtv_id_table);
+}
+
+static void __exit fdtv_exit(void)
+{
+       fdtv_1394_exit();
+}
+
+module_init(fdtv_init);
+module_exit(fdtv_exit);
 
+MODULE_AUTHOR("Andreas Monitzer <andy@monitzer.com>");
+MODULE_AUTHOR("Ben Backx <ben@bbackx.com>");
+MODULE_DESCRIPTION("FireDTV DVB Driver");
+MODULE_LICENSE("GPL");
+MODULE_SUPPORTED_DEVICE("FireDTV DVB");
index f8150f402bb618cacc398d39640eb4aef308f678..9b9539c800f851f6c45d6cfe2e03a19f6e2fc564 100644 (file)
@@ -10,6 +10,7 @@
  *     the License, or (at your option) any later version.
  */
 
+#include <linux/device.h>
 #include <linux/errno.h>
 #include <linux/kernel.h>
 #include <linux/string.h>
@@ -17,8 +18,6 @@
 
 #include <dvb_frontend.h>
 
-#include "avc.h"
-#include "cmp.h"
 #include "firedtv.h"
 
 static int fdtv_dvb_init(struct dvb_frontend *fe)
@@ -32,35 +31,37 @@ static int fdtv_dvb_init(struct dvb_frontend *fe)
        err = cmp_establish_pp_connection(fdtv, fdtv->subunit,
                                          fdtv->isochannel);
        if (err) {
-               printk(KERN_ERR "Could not establish point to point "
-                      "connection.\n");
+               dev_err(fdtv->device,
+                       "could not establish point to point connection\n");
                return err;
        }
 
-       return setup_iso_channel(fdtv);
+       return fdtv->backend->start_iso(fdtv);
 }
 
 static int fdtv_sleep(struct dvb_frontend *fe)
 {
        struct firedtv *fdtv = fe->sec_priv;
 
-       tear_down_iso_channel(fdtv);
+       fdtv->backend->stop_iso(fdtv);
        cmp_break_pp_connection(fdtv, fdtv->subunit, fdtv->isochannel);
        fdtv->isochannel = -1;
        return 0;
 }
 
+#define LNBCONTROL_DONTCARE 0xff
+
 static int fdtv_diseqc_send_master_cmd(struct dvb_frontend *fe,
-                                         struct dvb_diseqc_master_cmd *cmd)
+                                      struct dvb_diseqc_master_cmd *cmd)
 {
        struct firedtv *fdtv = fe->sec_priv;
 
-       return avc_lnb_control(fdtv, LNBCONTROL_DONTCARE,
-                       LNBCONTROL_DONTCARE, LNBCONTROL_DONTCARE, 1, cmd);
+       return avc_lnb_control(fdtv, LNBCONTROL_DONTCARE, LNBCONTROL_DONTCARE,
+                              LNBCONTROL_DONTCARE, 1, cmd);
 }
 
 static int fdtv_diseqc_send_burst(struct dvb_frontend *fe,
-                                    fe_sec_mini_cmd_t minicmd)
+                                 fe_sec_mini_cmd_t minicmd)
 {
        return 0;
 }
@@ -74,7 +75,7 @@ static int fdtv_set_tone(struct dvb_frontend *fe, fe_sec_tone_mode_t tone)
 }
 
 static int fdtv_set_voltage(struct dvb_frontend *fe,
-                              fe_sec_voltage_t voltage)
+                           fe_sec_voltage_t voltage)
 {
        struct firedtv *fdtv = fe->sec_priv;
 
@@ -85,12 +86,12 @@ static int fdtv_set_voltage(struct dvb_frontend *fe,
 static int fdtv_read_status(struct dvb_frontend *fe, fe_status_t *status)
 {
        struct firedtv *fdtv = fe->sec_priv;
-       ANTENNA_INPUT_INFO info;
+       struct firedtv_tuner_status stat;
 
-       if (avc_tuner_status(fdtv, &info))
+       if (avc_tuner_status(fdtv, &stat))
                return -EINVAL;
 
-       if (info.NoRF)
+       if (stat.no_rf)
                *status = 0;
        else
                *status = FE_HAS_SIGNAL | FE_HAS_VITERBI | FE_HAS_SYNC |
@@ -101,39 +102,37 @@ static int fdtv_read_status(struct dvb_frontend *fe, fe_status_t *status)
 static int fdtv_read_ber(struct dvb_frontend *fe, u32 *ber)
 {
        struct firedtv *fdtv = fe->sec_priv;
-       ANTENNA_INPUT_INFO info;
+       struct firedtv_tuner_status stat;
 
-       if (avc_tuner_status(fdtv, &info))
+       if (avc_tuner_status(fdtv, &stat))
                return -EINVAL;
 
-       *ber = info.BER[0] << 24 | info.BER[1] << 16 |
-              info.BER[2] << 8 | info.BER[3];
+       *ber = stat.ber;
        return 0;
 }
 
-static int fdtv_read_signal_strength (struct dvb_frontend *fe, u16 *strength)
+static int fdtv_read_signal_strength(struct dvb_frontend *fe, u16 *strength)
 {
        struct firedtv *fdtv = fe->sec_priv;
-       ANTENNA_INPUT_INFO info;
+       struct firedtv_tuner_status stat;
 
-       if (avc_tuner_status(fdtv, &info))
+       if (avc_tuner_status(fdtv, &stat))
                return -EINVAL;
 
-       *strength = info.SignalStrength << 8;
+       *strength = stat.signal_strength << 8;
        return 0;
 }
 
 static int fdtv_read_snr(struct dvb_frontend *fe, u16 *snr)
 {
        struct firedtv *fdtv = fe->sec_priv;
-       ANTENNA_INPUT_INFO info;
+       struct firedtv_tuner_status stat;
 
-       if (avc_tuner_status(fdtv, &info))
+       if (avc_tuner_status(fdtv, &stat))
                return -EINVAL;
 
        /* C/N[dB] = -10 * log10(snr / 65535) */
-       *snr = (info.CarrierNoiseRatio[0] << 8) + info.CarrierNoiseRatio[1];
-       *snr *= 257;
+       *snr = stat.carrier_noise_ratio * 257;
        return 0;
 }
 
@@ -142,8 +141,10 @@ static int fdtv_read_uncorrected_blocks(struct dvb_frontend *fe, u32 *ucblocks)
        return -EOPNOTSUPP;
 }
 
+#define ACCEPTED 0x9
+
 static int fdtv_set_frontend(struct dvb_frontend *fe,
-                               struct dvb_frontend_parameters *params)
+                            struct dvb_frontend_parameters *params)
 {
        struct firedtv *fdtv = fe->sec_priv;
 
@@ -155,7 +156,7 @@ static int fdtv_set_frontend(struct dvb_frontend *fe,
 }
 
 static int fdtv_get_frontend(struct dvb_frontend *fe,
-                               struct dvb_frontend_parameters *params)
+                            struct dvb_frontend_parameters *params)
 {
        return -EOPNOTSUPP;
 }
@@ -235,8 +236,8 @@ void fdtv_frontend_init(struct firedtv *fdtv)
                break;
 
        default:
-               printk(KERN_ERR "FireDTV: no frontend for model type %d\n",
-                      fdtv->type);
+               dev_err(fdtv->device, "no frontend for model type %d\n",
+                       fdtv->type);
        }
        strcpy(fi->name, fdtv_model_names[fdtv->type]);
 
diff --git a/drivers/media/dvb/firewire/firedtv-iso.c b/drivers/media/dvb/firewire/firedtv-iso.c
deleted file mode 100644 (file)
index a72df22..0000000
+++ /dev/null
@@ -1,111 +0,0 @@
-/*
- * FireSAT DVB driver
- *
- * Copyright (C) 2008 Henrik Kurelid <henrik@kurelid.se>
- *
- *     This program is free software; you can redistribute it and/or
- *     modify it under the terms of the GNU General Public License as
- *     published by the Free Software Foundation; either version 2 of
- *     the License, or (at your option) any later version.
- */
-
-#include <linux/errno.h>
-#include <linux/kernel.h>
-#include <linux/list.h>
-#include <linux/spinlock.h>
-
-#include <dvb_demux.h>
-
-#include <dma.h>
-#include <iso.h>
-#include <nodemgr.h>
-
-#include "firedtv.h"
-
-static void rawiso_activity_cb(struct hpsb_iso *iso);
-
-void tear_down_iso_channel(struct firedtv *fdtv)
-{
-       if (fdtv->iso_handle != NULL) {
-               hpsb_iso_stop(fdtv->iso_handle);
-               hpsb_iso_shutdown(fdtv->iso_handle);
-       }
-       fdtv->iso_handle = NULL;
-}
-
-int setup_iso_channel(struct firedtv *fdtv)
-{
-       int result;
-       fdtv->iso_handle =
-               hpsb_iso_recv_init(fdtv->ud->ne->host,
-                                  256 * 200, //data_buf_size,
-                                  256, //buf_packets,
-                                  fdtv->isochannel,
-                                  HPSB_ISO_DMA_DEFAULT, //dma_mode,
-                                  -1, //stat.config.irq_interval,
-                                  rawiso_activity_cb);
-       if (fdtv->iso_handle == NULL) {
-               printk(KERN_ERR "Cannot initialize iso receive.\n");
-               return -EINVAL;
-       }
-       result = hpsb_iso_recv_start(fdtv->iso_handle, -1, -1, 0);
-       if (result != 0) {
-               printk(KERN_ERR "Cannot start iso receive.\n");
-               return -EINVAL;
-       }
-       return 0;
-}
-
-static void rawiso_activity_cb(struct hpsb_iso *iso)
-{
-       unsigned int num;
-       unsigned int i;
-       unsigned int packet;
-       unsigned long flags;
-       struct firedtv *fdtv = NULL;
-       struct firedtv *fdtv_iterator;
-
-       spin_lock_irqsave(&fdtv_list_lock, flags);
-       list_for_each_entry(fdtv_iterator, &fdtv_list, list) {
-               if(fdtv_iterator->iso_handle == iso) {
-                       fdtv = fdtv_iterator;
-                       break;
-               }
-       }
-       spin_unlock_irqrestore(&fdtv_list_lock, flags);
-
-       if (fdtv) {
-               packet = iso->first_packet;
-               num = hpsb_iso_n_ready(iso);
-               for (i = 0; i < num; i++,
-                            packet = (packet + 1) % iso->buf_packets) {
-                       unsigned char *buf =
-                               dma_region_i(&iso->data_buf, unsigned char,
-                                            iso->infos[packet].offset +
-                                            sizeof(struct CIPHeader));
-                       int count = (iso->infos[packet].len -
-                                    sizeof(struct CIPHeader)) /
-                               (188 + sizeof(struct firewireheader));
-                       if (iso->infos[packet].len <= sizeof(struct CIPHeader))
-                               continue; // ignore empty packet
-
-                       while (count --) {
-                               if (buf[sizeof(struct firewireheader)] == 0x47)
-                                       dvb_dmx_swfilter_packets(&fdtv->demux,
-                                                                &buf[sizeof(struct firewireheader)], 1);
-                               else
-                                       printk("%s: invalid packet, skipping\n", __func__);
-                               buf += 188 + sizeof(struct firewireheader);
-
-                       }
-
-               }
-               hpsb_iso_recv_release_packets(iso, num);
-       }
-       else {
-               printk("%s: packets for unknown iso channel, skipping\n",
-                      __func__);
-               hpsb_iso_recv_release_packets(iso, hpsb_iso_n_ready(iso));
-       }
-}
-
index 436c0c69a13de6ed7f12b7aa84aef86f95366e8d..46a6324d7b730fe0e0b1ab2212ad32ab582aa213 100644 (file)
@@ -15,7 +15,6 @@
 #include <linux/string.h>
 #include <linux/types.h>
 
-#include "firedtv-rc.h"
 #include "firedtv.h"
 
 /* fixed table with older keycodes, geared towards MythTV */
diff --git a/drivers/media/dvb/firewire/firedtv-rc.h b/drivers/media/dvb/firewire/firedtv-rc.h
deleted file mode 100644 (file)
index d3e1472..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-#ifndef _FIREDTV_RC_H
-#define _FIREDTV_RC_H
-
-struct firedtv;
-struct device;
-
-int fdtv_register_rc(struct firedtv *fdtv, struct device *dev);
-void fdtv_unregister_rc(struct firedtv *fdtv);
-void fdtv_handle_rc(struct firedtv *fdtv, unsigned int code);
-
-#endif /* _FIREDTV_RC_H */
index 2a34028ccbcdcacafc2524e45bb5eb1f2f05b3a0..d48530b81e6184254927246353d3bea5c5e13159 100644 (file)
 #include <dvb_net.h>
 #include <dvbdev.h>
 
-#include <linux/version.h>
-#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 25)
-#define DVB_REGISTER_ADAPTER(x, y, z, w, v) dvb_register_adapter(x, y, z, w, v)
-#else
-#define DVB_REGISTER_ADAPTER(x, y, z, w, v) dvb_register_adapter(x, y, z, w)
-#define DVB_DEFINE_MOD_OPT_ADAPTER_NR(x)
-#endif
-
-/*****************************************************************
- * CA message command constants from en50221_app_tags.h of libdvb
- *****************************************************************/
-/*     Resource Manager                */
-#define TAG_PROFILE_ENQUIRY            0x9f8010
-#define TAG_PROFILE                    0x9f8011
-#define TAG_PROFILE_CHANGE             0x9f8012
-
-/*     Application Info                */
-#define TAG_APP_INFO_ENQUIRY           0x9f8020
-#define TAG_APP_INFO                   0x9f8021
-#define TAG_ENTER_MENU                 0x9f8022
-
-/*     CA Support                      */
-#define TAG_CA_INFO_ENQUIRY            0x9f8030
-#define TAG_CA_INFO                    0x9f8031
-#define TAG_CA_PMT                     0x9f8032
-#define TAG_CA_PMT_REPLY               0x9f8033
-
-/*     Host Control                    */
-#define TAG_TUNE                       0x9f8400
-#define TAG_REPLACE                    0x9f8401
-#define TAG_CLEAR_REPLACE              0x9f8402
-#define TAG_ASK_RELEASE                        0x9f8403
-
-/*     Date and Time                   */
-#define TAG_DATE_TIME_ENQUIRY          0x9f8440
-#define TAG_DATE_TIME                  0x9f8441
-
-/*     Man Machine Interface (MMI)     */
-#define TAG_CLOSE_MMI                  0x9f8800
-#define TAG_DISPLAY_CONTROL            0x9f8801
-#define TAG_DISPLAY_REPLY              0x9f8802
-#define TAG_TEXT_LAST                  0x9f8803
-#define TAG_TEXT_MORE                  0x9f8804
-#define TAG_KEYPAD_CONTROL             0x9f8805
-#define TAG_KEYPRESS                   0x9f8806
-#define TAG_ENQUIRY                    0x9f8807
-#define TAG_ANSWER                     0x9f8808
-#define TAG_MENU_LAST                  0x9f8809
-#define TAG_MENU_MORE                  0x9f880a
-#define TAG_MENU_ANSWER                        0x9f880b
-#define TAG_LIST_LAST                  0x9f880c
-#define TAG_LIST_MORE                  0x9f880d
-#define TAG_SUBTITLE_SEGMENT_LAST      0x9f880e
-#define TAG_SUBTITLE_SEGMENT_MORE      0x9f880f
-#define TAG_DISPLAY_MESSAGE            0x9f8810
-#define TAG_SCENE_END_MARK             0x9f8811
-#define TAG_SCENE_DONE                 0x9f8812
-#define TAG_SCENE_CONTROL              0x9f8813
-#define TAG_SUBTITLE_DOWNLOAD_LAST     0x9f8814
-#define TAG_SUBTITLE_DOWNLOAD_MORE     0x9f8815
-#define TAG_FLUSH_DOWNLOAD             0x9f8816
-#define TAG_DOWNLOAD_REPLY             0x9f8817
-
-/*     Low Speed Communications        */
-#define TAG_COMMS_COMMAND              0x9f8c00
-#define TAG_CONNECTION_DESCRIPTOR      0x9f8c01
-#define TAG_COMMS_REPLY                        0x9f8c02
-#define TAG_COMMS_SEND_LAST            0x9f8c03
-#define TAG_COMMS_SEND_MORE            0x9f8c04
-#define TAG_COMMS_RECV_LAST            0x9f8c05
-#define TAG_COMMS_RECV_MORE            0x9f8c06
-
-/* Authentication */
-#define TAG_AUTH_REQ                   0x9f8200
-#define TAG_AUTH_RESP                  0x9f8201
-
-/* Teletext */
-#define TAG_TELETEXT_EBU               0x9f9000
-
-/* Smartcard */
-#define TAG_SMARTCARD_COMMAND          0x9f8e00
-#define TAG_SMARTCARD_REPLY            0x9f8e01
-#define TAG_SMARTCARD_SEND             0x9f8e02
-#define TAG_SMARTCARD_RCV              0x9f8e03
-
-/* EPG */
-#define TAG_EPG_ENQUIRY                0x9f8f00
-#define TAG_EPG_REPLY                  0x9f8f01
-
+struct firedtv_tuner_status {
+       unsigned active_system:8;
+       unsigned searching:1;
+       unsigned moving:1;
+       unsigned no_rf:1;
+       unsigned input:1;
+       unsigned selected_antenna:7;
+       unsigned ber:32;
+       unsigned signal_strength:8;
+       unsigned raster_frequency:2;
+       unsigned rf_frequency:22;
+       unsigned man_dep_info_length:8;
+       unsigned front_end_error:1;
+       unsigned antenna_error:1;
+       unsigned front_end_power_status:1;
+       unsigned power_supply:1;
+       unsigned carrier_noise_ratio:16;
+       unsigned power_supply_voltage:8;
+       unsigned antenna_voltage:8;
+       unsigned firewire_bus_voltage:8;
+       unsigned ca_mmi:1;
+       unsigned ca_pmt_reply:1;
+       unsigned ca_date_time_request:1;
+       unsigned ca_application_info:1;
+       unsigned ca_module_present_status:1;
+       unsigned ca_dvb_flag:1;
+       unsigned ca_error_flag:1;
+       unsigned ca_initialization_status:1;
+};
 
 enum model_type {
        FIREDTV_UNKNOWN = 0,
@@ -127,11 +67,22 @@ enum model_type {
        FIREDTV_DVB_S2  = 4,
 };
 
+struct device;
 struct input_dev;
-struct hpsb_iso;
-struct unit_directory;
+struct firedtv;
+
+struct firedtv_backend {
+       int (*lock)(struct firedtv *fdtv, u64 addr, void *data, __be32 arg);
+       int (*read)(struct firedtv *fdtv, u64 addr, void *data, size_t len);
+       int (*write)(struct firedtv *fdtv, u64 addr, void *data, size_t len);
+       int (*start_iso)(struct firedtv *fdtv);
+       void (*stop_iso)(struct firedtv *fdtv);
+};
 
 struct firedtv {
+       struct device *device;
+       struct list_head list;
+
        struct dvb_adapter      adapter;
        struct dmxdev           dmxdev;
        struct dvb_demux        demux;
@@ -149,79 +100,83 @@ struct firedtv {
        struct work_struct      remote_ctrl_work;
        struct input_dev        *remote_ctrl_dev;
 
-       struct firedtv_channel {
-               bool active;
-               int pid;
-       } channel[16];
-       struct mutex demux_mutex;
+       enum model_type         type;
+       char                    subunit;
+       char                    isochannel;
+       fe_sec_voltage_t        voltage;
+       fe_sec_tone_mode_t      tone;
 
-       struct unit_directory *ud;
+       const struct firedtv_backend *backend;
+       void                    *backend_data;
 
-       enum model_type type;
-       char subunit;
-       fe_sec_voltage_t voltage;
-       fe_sec_tone_mode_t tone;
-
-       int isochannel;
-       struct hpsb_iso *iso_handle;
-
-       struct list_head list;
+       struct mutex            demux_mutex;
+       unsigned long           channel_active;
+       u16                     channel_pid[16];
 
-       /* needed by avc_api */
-       int resp_length;
-       u8 respfrm[512];
+       size_t                  response_length;
+       u8                      response[512];
 };
 
-struct firewireheader {
-       union {
-               struct {
-                       __u8 tcode:4;
-                       __u8 sy:4;
-                       __u8 tag:2;
-                       __u8 channel:6;
-
-                       __u8 length_l;
-                       __u8 length_h;
-               } hdr;
-               __u32 val;
-       };
-};
-
-struct CIPHeader {
-       union {
-               struct {
-                       __u8 syncbits:2;
-                       __u8 sid:6;
-                       __u8 dbs;
-                       __u8 fn:2;
-                       __u8 qpc:3;
-                       __u8 sph:1;
-                       __u8 rsv:2;
-                       __u8 dbc;
-                       __u8 syncbits2:2;
-                       __u8 fmt:6;
-                       __u32 fdf:24;
-               } cip;
-               __u64 val;
-       };
-};
-
-extern const char *fdtv_model_names[];
-extern struct list_head fdtv_list;
-extern spinlock_t fdtv_list_lock;
+/* firedtv-1394.c */
+#ifdef CONFIG_DVB_FIREDTV_IEEE1394
+int fdtv_1394_init(struct ieee1394_device_id id_table[]);
+void fdtv_1394_exit(void);
+#else
+static inline int fdtv_1394_init(struct ieee1394_device_id it[]) { return 0; }
+static inline void fdtv_1394_exit(void) {}
+#endif
 
-struct device;
+/* firedtv-avc.c */
+int avc_recv(struct firedtv *fdtv, void *data, size_t length);
+int avc_tuner_status(struct firedtv *fdtv, struct firedtv_tuner_status *stat);
+struct dvb_frontend_parameters;
+int avc_tuner_dsd(struct firedtv *fdtv, struct dvb_frontend_parameters *params);
+int avc_tuner_set_pids(struct firedtv *fdtv, unsigned char pidc, u16 pid[]);
+int avc_tuner_get_ts(struct firedtv *fdtv);
+int avc_identify_subunit(struct firedtv *fdtv);
+struct dvb_diseqc_master_cmd;
+int avc_lnb_control(struct firedtv *fdtv, char voltage, char burst,
+                   char conttone, char nrdiseq,
+                   struct dvb_diseqc_master_cmd *diseqcmd);
+void avc_remote_ctrl_work(struct work_struct *work);
+int avc_register_remote_control(struct firedtv *fdtv);
+int avc_ca_app_info(struct firedtv *fdtv, char *app_info, unsigned int *len);
+int avc_ca_info(struct firedtv *fdtv, char *app_info, unsigned int *len);
+int avc_ca_reset(struct firedtv *fdtv);
+int avc_ca_pmt(struct firedtv *fdtv, char *app_info, int length);
+int avc_ca_get_time_date(struct firedtv *fdtv, int *interval);
+int avc_ca_enter_menu(struct firedtv *fdtv);
+int avc_ca_get_mmi(struct firedtv *fdtv, char *mmi_object, unsigned int *len);
+int cmp_establish_pp_connection(struct firedtv *fdtv, int plug, int channel);
+void cmp_break_pp_connection(struct firedtv *fdtv, int plug, int channel);
+
+/* firedtv-ci.c */
+int fdtv_ca_register(struct firedtv *fdtv);
+void fdtv_ca_release(struct firedtv *fdtv);
 
 /* firedtv-dvb.c */
 int fdtv_start_feed(struct dvb_demux_feed *dvbdmxfeed);
 int fdtv_stop_feed(struct dvb_demux_feed *dvbdmxfeed);
-int fdtv_dvbdev_init(struct firedtv *fdtv, struct device *dev);
+int fdtv_dvb_register(struct firedtv *fdtv);
+void fdtv_dvb_unregister(struct firedtv *fdtv);
+struct firedtv *fdtv_alloc(struct device *dev,
+                          const struct firedtv_backend *backend,
+                          const char *name, size_t name_len);
+extern const char *fdtv_model_names[];
 
 /* firedtv-fe.c */
 void fdtv_frontend_init(struct firedtv *fdtv);
 
-/* firedtv-iso.c */
-int setup_iso_channel(struct firedtv *fdtv);
-void tear_down_iso_channel(struct firedtv *fdtv);
+/* firedtv-rc.c */
+#ifdef CONFIG_DVB_FIREDTV_INPUT
+int fdtv_register_rc(struct firedtv *fdtv, struct device *dev);
+void fdtv_unregister_rc(struct firedtv *fdtv);
+void fdtv_handle_rc(struct firedtv *fdtv, unsigned int code);
+#else
+static inline int fdtv_register_rc(struct firedtv *fdtv,
+                                  struct device *dev) { return 0; }
+static inline void fdtv_unregister_rc(struct firedtv *fdtv) {}
+static inline void fdtv_handle_rc(struct firedtv *fdtv, unsigned int code) {}
+#endif
 
 #endif /* _FIREDTV_H */