blob: 11e74a2ef54e68995428cf08fc11b14743e23412 [file] [log] [blame]
Introduction
============
TSC Driver
The TSC (Transport Stream Controller) is a hardware block used in products such
as smart TVs, Set-top boxes and digital media adapters, and is responsible for
two main functionalities:
1. Mux function: enabling the routing of MPEG-2 transport streams (TS) received
from terrestrial/cable/satelite in order to support the different topologies of
the end product, as it may be deployed in many different topologies.
In addition, the active topology may change according to various factors such as
broadcast technology and/or conditional access system.
2. CI function: acting as a common interface, complying with both PC Card and
CI/+ specifications.
The TSC driver has two different interfaces, one for each function.
Hardware description
====================
The TSC HW contains the TSC core, and uses the VBIF unit (IOMMU) which is part
of the broadcast subsystem HW.
Mux function:
-------------
The TSC can receive transport streams from:
a. Two Transport Stream Interfaces (TSIFs) 0 or 1, connected to two external
demods or to external bridge.
b. One TSIF from an integrated demod.
The TSC can route TS from any of the above TSIFs to an external CICAM, using a
software configurable mux.
The TSC can route TS from any of the above TSIFs, and TS received from the CI
Conditional Access Mudule (CICAM) to two TSIF outputs (0 or 1), using two
software configurable muexes.
The CICAM input and outputs are also managed via two additional TSIFs: TSIF-out
to the CAM, and TSIF-in from the CAM.
CI function:
------------
The common interface is composed of:
1. Card detection logic: the TSC notifies the SW of any change in the card
detection status (via HW interrupt).
2. Control interface used to send/receive the CI messages (APDUs), supporting
data transmission in two formats:
a. Single byte transactions: to/from the attribute memory space of the CAM and
the command area of the CAM.
b. Buffer transactions: to/from the command area of the CAM, using a
configurable buffer size of 1k bytes-64k bytes. This enables transferring
large chunks of data between the CAM and applications.
The data buffer resides in the external memory and the interface to the
memory is done through BCSS VBIF.
The TSC uses PCMCIA interface to interact with the CAM.
The following diagram provides an overview of the TSC HW:
+-------------------------------------------------------------------------+
| |
| +------------------------------+ |
| +-----------+ | TSC Core --. | |
| |Ext. TSIF 0+------------+------------>| \ | +-----------+ |
| +-----------+ | +-----|------------>|Mux)----->TSPP TSIF 0| |
| +-----------+ | | +--|------------>| / | +-----------+ |
| |Ext. TSIF 1+------| | | +->--' | |
| +-----------+ | | | | | --. | |
| | | | +----------|->| \ | +-----------+ |
| +-----------+ | +--|--|-+--------|->|Mux)----->TSPP TSIF 1| |
| |Int. TSIF +---------+--|-|-+------|->| / | +-----------+ |
| +-----------+ | | | | +->--' | |
| | | | | | | |
| | | | | | | |
| |+------+(v-v-v--) | +-----+| |
| ||Card | \ Mux / | |CI/+ +---Data-Interface--+ |
| ||detect| `---' | +----++| | |
| |+-^-^--+ | | | | | |
| +--|-|-------|-------|-------|-+ +------+----+ |
| | | | | | | VBIF | |
| | | +-----v--+ +--+----+ | | | |
| | | |TSIF-Out| |TSIF-In| | +-----------+ |
| | | +-----+--+ +--^----+ | |
| | | | | | |
| ++-+-------v-------+-------++ |
| | CICAM | |
| | | |
| +---------------------------+ |
+-------------------------------------------------------------------------+
Software description
====================
The TSC Linux kernel driver manages the TSC core. It is a standard Linux
platform device driver. It can be configured as a loadable or built-in kernel
module. The driver is supported only in platforms that contain the TSC HW.
The TSC driver uses ION driver to control the IOMMU and map user-allocated
buffers to the TSC IOMMU domain.
The driver provides an abstraction of the TSC HW functionality for user-space
clients via two separate interfaces: tsc_mux and tsc_ci. These interfaces may
be used by upper layers to utilize the TSC HW for routing the TS and supporting
the Common Interface specification.
Driver initialization
---------------------
The driver's probe function is invoked if there is a matching device tree node.
The probe function gets the required memory resources (i.e., register address
spaces) and maps them to kernel space for the driver's use.
The probe function also requests the required IRQs, GPIOs and clocks, and gets
the TSC IOMMU domain. The probe function also disables the TSIFs input.
Finally, the function creates two character device drivers: "tsc_mux","tsc_ci".
See API description in interface section.
Data paths
-----------
The TSC does not process the TS data received from the TSIFs. It just manages
the routing of that data.
Control paths - Mux function
----------------------------
Example for routing the TS from external demod TSIF 0 to the CAM, and from the
CAM to TSIF 1 of the TSPP:
struct tsc_route tsif_cam = {TSC_SOURCE_EXTERNAL0, TSC_DEST_CICAM};
struct tsc_route cam_tspp = {TSC_SOURCE_CICAM, TSC_DEST_TSPP1};
int mux_fd, ret;
enum tsc_source tsif0 = TSC_SOURCE_EXTERNAL0;
enum tsc_source cam = TSC_SOURCE_CICAM;
/* opening Mux char device */
mux_fd = open("/dev/tsc_mux0");
/* Configure the CAM mux to route TS from external demod TSIF 0: */
ret = ioctl(mux_fd, TSC_CONFIG_ROUTE, &tsif_cam);
/* Configure the TSPP TSIF 1 mux to route TS from CAM: */
ret = ioctl(mux_fd, TSC_CONFIG_ROUTE, &cam_tspp);
/* Enabling the external demod TSIF 0, and the CAM TSIF-in and TSIF-out */
ret = ioctl(mux_fd, TSC_ENABLE_INPUT, &tsif0);
ret = ioctl(mux_fd, TSC_ENABLE_INPUT, &cam);
close(mux_fd);
Control paths - CI function
---------------------------
Example for writing a buffer to the CAM command area:
Assumptions:
1. The user allocated a buffer using ION driver and wrote to that buffer.
Also, retrieved the ion fd of that buffer and saved it to:
int buffer_fd;
2. The user already performed buffer size negotiation with the CAM according to
CI/+ specification, and had set the CAM size register with the buffer size. This
size is saved to: int size;
3. The user decided about the time the user wants to wait for the data
transmission.
struct tsc_buffer_mode buff_params = {buffer_fd, size, timeout};
int ret;
/* Perform a blocking write buffer transaction for at most timeout */
ret = ioctl(fd, TSC_WRITE_CAM_BUFFER, &buff_params);
/* ret indicate whether the transaction succeeded */
Example for SW reset to the CAM (according to CI/+ specification):
struct single_byte_mode cmd_params = {1, RS bit set, timeout};
struct single_byte_mode stat_params = {1, not initialize, timeout};
int ci_fd, ret;
u8 data;
/* opening CI char device */
ci_fd = open("/dev/tsc_ci0");
/* Setting the RS bit of the CAM command register */
ret = ioctl(ci_fd, TSC_WRITE_CAM_IO, &cmd_params);
/* Polling the FR bit of the CAM status register */
ret = ioctl(ci_fd, TSC_READ_CAM_IO, &stat_params);
data = stat_params.data;
while (data & FR_BIT_MASK) {
ret = ioctl(ci_fd, TSC_READ_CAM_IO, &stat_params);
data = stat_params.data;
}
close(ci_fd);
Design
======
The TSC driver is a regular Linux platform driver designed to support the
TSC HW available on specific SoCs.
The driver provides two user-space APIs: tsc_mux that allows the client full
control over the configuration of the TS routing, and tsc_ci that enables the
client to implement the Common Interface in front of the CAM. It does so while
encapsulating HW implementation details that are not relevant to the clients.
The driver enforces HW restrictions and checks for input parameters
validity, providing a success or failure return value for each API function:
0 upon success or negative value on failure. Errno parameter is set to indicate
the failure reason.
However, the driver does not enforce any high-level policy with regard to the
correct use of the TSC HW for various use-cases.
Power Management
================
The TSC driver prevents the CPU from sleeping while the HW is active by using
wakeup_source API. When there are no open devices the driver releases the wakeup
source. In a similar manner, the driver enables the HW clocks only when needed.
SMP/multi-core
==============
The driver uses a spinlock to protect accesses to its internal databases,
for synchronization between user control API and kernel interrupt handlers.
The driver uses a mutex for all the Mux operations to synchronize access to the
routing internal databases. The driver uses another mutex for all the CI
operations to synchronize data sent and received to and from the CAM.
Security
========
Although the TSC is the bridge the external conditional access module, it has no
security aspects. Any protection which is needed is performed by the upper
layers. For example, the messages which are written to the CAM are encrypted.
Thus the TSC accesses only non-protected, HLOS accessible memory regions.
Performance
===========
Control operations are not considered as performance critical.
Most of the control operations are assumed to be fairly uncommon.
Interface
=========
Kernel-space API
----------------
The TSC driver does not provide any kernel-space API, only a user-space API.
User-space API
----------------
Open: upper layer can open tsc_mux device and/or tsc_ci device.
Release: close the device and release all the allocated resources.
Poll: two different functions- one for Mux, one for CI. The Mux poll wait for
rate mismatch interrupt. The CI poll waits for card detection HW interrupt.
The rate mismatch interrupt is not cleared in the interrupt handler because it
will signal again all the time. Therefore it is cleared via a specific ioctl
that upper layer can use after the problem is solved. Additionally, the
interrupt is cleared when the card is removed.
ioctl: two functions, one for mux and one for ci. The ioctl are specified below.
TSC Mux - routing the TS:
-------------------------
enum tsc_source {
TSC_SOURCE_EXTERNAL0,
TSC_SOURCE_EXTERNAL1,
TSC_SOURCE_INTERNAL,
TSC_SOURCE_CICAM
};
enum tsc_dest {
TSC_DEST_TSPP0,
TSC_DEST_TSPP1,
TSC_DSET_CICAM
};
struct tsc_route {
enum tsc_source source;
enum tsc_dest dest;
};
#define TSC_CONFIG_ROUTE _IOW(TSC_IOCTL_BASE, 0, struct tsc_tspp_route)
#define TSC_ENABLE_INPUT _IOW(TSC_IOCTL_BASE, 1, enum tsc_source)
#define TSC_DISABLE_INPUT _IOW(TSC_IOCTL_BASE, 2, enum tsc_source)
These 3 IOCTLs control the 3 muxes that route the TS, and enable/disable the
TSIFs input.
TSC Mux - configuring the TSIFs:
--------------------------------
enum tsc_data_type {
TSC_DATA_TYPE_SERIAL,
TSC_DATA_TYPE_PARALLEL
};
enum tsc_receive_mode {
TSC_RECEIVE_MODE_START_VALID,
TSC_RECEIVE_MODE_START_ONLY,
TSC_RECEIVE_MODE_VALID_ONLY
};
struct tsc_tsif_params {
enum tsc_source source;
enum tsc_receive_mode receive_mode;
enum tsc_data_type data_type;
int clock_polarity;
int data_polarity;
int start_polarity;
int valid_polarity;
int error_polarity;
int data_swap;
int set_error;
};
#define TSC_SET_TSIF_CONFIG _IOW(TSC_IOCTL_BASE, 3, struct tsc_tsif_params)
This IOCTL enables configuring a specific TSIF with all possible configurations.
TSC Mux - clearing rate mismatch interrupt
------------------------------------------
#define TSC_CLEAR_RATE_MISMATCH_IRQ _IO(TSC_IOCTL_BASE, 4)
This IOCTL is used for clearing the interrupt, which is not done automatically
by the driver.
TSC CI - CAM configuration:
---------------------------
enum tsc_cam_personality {
TSC_CICAM_PERSONALITY_CI,
TSC_CICAM_PERSONALITY_CIPLUS,
TSC_CICAM_PERSONALITY_PCCARD,
TSC_CICAM_PERSONALITY_DISABLE
};
enum tsc_card_status {
TSC_CARD_STATUS_NOT_DETECTED,
TSC_CARD_STATUS_DETECTED,
TSC_CARD_STATUS_FAILURE
};
#define TSC_CICAM_SET_CLOCK _IOW(TSC_IOCTL_BASE, 5, int)
This IOCTL sets the clock rate of the TS from the TSC to the CAM
#define TSC_CAM_RESET _IO(TSC_IOCTL_BASE, 6)
This IOCTL performs HW reset to the CAM
#define TSC_CICAM_PERSONALITY_CHANGE \
_IOW(TSC_IOCTL_BASE, 7, enum tsc_cam_personality)
This IOCTL configures the PCMCIA pins according to the specified card type.
#define TSC_GET_CARD_STATUS _IOR(TSC_IOCTL_BASE, 8, enum tsc_card_status)
This IOCTL queries the card detection pins and returns their status.
TSC CI - Data transactions:
---------------------------
struct tsc_single_byte_mode {
u16 address;
u8 data;
int timeout; /* in msec */
};
struct tsc_buffer_mode {
int buffer_fd;
u16 buffer_size;
int timeout; /* in msec */
};
#define TSC_READ_CAM_MEMORY \
_IOWR(TSC_IOCTL_BASE, 9, struct tsc_single_byte_mode)
#define TSC_WRITE_CAM_MEMORY \
_IOW(TSC_IOCTL_BASE, 10, struct tsc_single_byte_mode)
#define TSC_READ_CAM_IO \
_IOWR(TSC_IOCTL_BASE, 11, struct tsc_single_byte_mode)
#define TSC_WRITE_CAM_IO \
_IOW(TSC_IOCTL_BASE, 12, struct tsc_single_byte_mode)
#define TSC_READ_CAM_BUFFER \
_IOWR(TSC_IOCTL_BASE, 13, struct tsc_buffer_mode)
#define TSC_WRITE_CAM_BUFFER \
_IOW(TSC_IOCTL_BASE, 14, struct tsc_buffer_mode)
These IOCTLs performs a read/write data transaction of the requested type.
Driver parameters
=================
The TSC module receives one parameter:
tsc_iommu_bypass - 0 for using the VBIF, 1 for not using it. Not using the VBIF
is a debug configuration.
Config options
==============
To enable the driver, set CONFIG_TSC to y (built-in) or m (kernel module)
in the kernel configuration menu.
Dependencies
============
The TSC driver uses the ION driver for IOMMU registration and buffer
mapping to BCSS VBIF.
User space utilities
====================
None.
Other
=====
None.
Known issues
============
None.
To do
=====
None.