| 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. |