Introduction
============
MPQ DVB Adapter implements Digital Video Broadcasting devices according
to LinuxTV (linuxtv.org) defined API and infrastructure.

The implemented devices are dvb/demux devices, dvb/dvr devices and
dvb/video devices.

These devices are used in Qualcomm's MPQ chipsets that support
broadcast applications.

dvb/demux is responsible to receive a digital stream broadcasted over
the air from a hardware unit (TSPP - Transport stream packet processor,
or TSIF - Transport Stream Interface) and separates the stream into its
various sub-streams such as video, audio and auxiliary data.
The separation operation is named demuxing.

dvb/dvr is used in conjunction with dvb/demux to re-play a digital
stream from memory or to record stream to memory.

dvb/video is used to handle the video decoding, it receives compressed
video from dvb/demux through a stream-buffer interface and interacts
with the existing HW video driver to perform the decoding.

For more information on the TSIF interface, please refer to TSIF
documentation under "Documentation/arm/msm/tsif.txt".
For more information on the TSPP interface, please refer to TSPP
documentation under "Documentation/arm/msm/tspp.txt".
For more information on DVB-API definition, please refer dvb
documentation under "Documentation/dvb/readme.txt".

Hardware description
====================
dvb/demux, dvb/dvr and dvb/video do not interact with a hardware directly;
The implementation of these drivers is done using the kernel API of TSPP,
TSIF and video drivers.

Software description
====================

Terminology
-----------
Stream: A stream is a TS packet source
  - For example, MPEG2 Transport Stream from TSIF0
Filter: Enables TS packet filtering and routing according to PID (packet ID)
  - The decision regarding which PIDs in the stream will be routed
    is done via filters, each demux open request corresponds to a filter.
  - Filters can pass TS packets as-is (for recording), assemble them into
    "other" PES packets (for PES packets read by client), assemble and send
    them to decoder (for decoder PES), or assemble them into sections.
Service: A service is a set of PIDs as defined in the service PMT.
  Each service may be carried in a different transport stream or part of the
  same transport stream. Processing a service means either preparing the
  data for display and/or for recording.

Requirments
-----------
1. Demuxing from different sources:
   - Live transport stream inputs (TSIF)
   - Memory inputs
2. Support different packet formats:
   - 188-bytes transport packets
   - 192-bytes transport packets
3. PID filtering
4. Output of the following data:
   - Decoder PES: PES (video and/or audio) that can be directed to HW decoders
     in tunneling mode (without interaction of user-space).
   - Other PES: a non-decoder PES, such as subtitle, teletext. The consumer
     of this data is user-space that reads the data through standard read
     calls.
   - Sections: Sections are used by user-space to acquire different kinds of
     information such as channels list, program user guide, etc.
   - Transport Stream Packets: Transport stream packets of specific PIDs as
     they were received in the input stream. User-space can use those to
     record specific services and/or to perform time-shift buffer.
   - PCR/STC: Pairs of PCR/STC can be used by user-space to perform
     clock-recovery.
   - Frame-indexing: For recorded stream, demux provides indexing of the
     I-frames within the stream that can be used for trick-modes operations
     while playing a recorded file.
5. Support decryption of scrambled transport packets.
6. Support recording of scrambled streams.
8. Section filtering.

Control path
------------
1. Client opens a demux device. Open request is done on the same demux
   device for each filter.
2. Client may configure the demux's internal ring-buffer size used to
   hold the data for user-space (or default is used).
3. Client configures the opened filter either to capture sections,
   TS packets (for recording) or PES (decoder or non-decoder PES).
   - The demux configures the underlying HW accordingly through
     TSPP or TSIF kernel APIs
   - demux receives notification of new data from the underlying HW and
     performs demuxing operation based on the configuration.
4. Client can then read data received from the selected filter.

Data path
---------
For each filter that is opened, demux manages a circular buffer that
holds the captured filter data; Client read commands extract data from
the relevant ring buffer. Data loss can occur if a client cannot keep up
with stream bandwidth.

For PES data tunneled to decoder, demux manages a stream-buffer used to
transfer the PES data to the decoder. The stream-buffer is built from
two ring-buffers: One holding the PES payload (elementary stream) and
the other holding PES parameters extracted from the PES header. The
ring-buffer with PES parameters points to the location of respective PES
payload in the PES payload ring-buffer.

To allow concurrency of multiple stream processing, multiple demux/dvr
devices exist. Each demux devices handles a single stream input. The
number of demux devices is configurable depending on the required number
of concurrent stream processing.

The client configures each demux device with the stream to process,
by default, all devices are configured to process stream from memory.
The default setting can be changed by issuing ioctl that configures
the demux source to either TSIF0 or TSIF1. For specific TSIF input,
only one demux device may process it at a time.

Background Processing
---------------------
Demux allocates a kernel thread for each live-input to process
the TS packets notified from the HW for specific input. There
are two such inputs (TSIF0 and TSIF1), both can be processed in
parallel by two seperate threads.

The processing is the action of demuxing of the new data; it may sleep
as it locks against the demux data-structure that may be accessed by
user-space in the meanwhile.

Dependencies
------------
The demux driver depends on the following kernel drivers and subsystems:
1. TSIF driver: Used to receive TS packets from TSIF interface for
   targets supporting TSIF only.
2. TSPP driver: Used to receive TS packets and/or PES from TSPP
   interface for targets supporting TSPP.
3. TZ-COM: Used to communicate with TrustZone to handle scrambled
   streams.
4. ION: Used to allocate memory for buffers holding decoder-data in
   case the data is tunneled between demux and decoders.
   Also used to allocate memory for TSPP/TSIF output pipes.
5. dvb-core: Existing Linux infrastructure used for implementation of
   dvb devices.

Design
======

Goals
-----
The demux driver is designed to:
1. Fulfil the requirements listed above.
2. Be able to work on different chipsets having different HW
   capabilities. For example, some chipsets are equipped with TSIF only,
   others are equipped with TSPP of different versions.

Design Blocks
-------------
Demux implementation hooks to the existing Linux dvb-core
infrastructure as follows:

     +----------+  +------------------------------------------+
     |          |  |             MPQ Demux Driver             |
     |          |  | +----------+  +----------+  +----------+ |
     |          |  | | MPQ DMX  |  | MPQ DMX  |  | MPQ DMX  | |
     | QCOM MPQ |  | | TSIF     |  | TSPPv1   |  | TSPPv2   | |
     |  Adapter |  | | Plugin   |  | Plugin   |  | Plugin   | |
     |          |  | +----------+  +----------+  +----------+ |
     |          |  | +--------------------------------------+ |
     |          |  | |       MPQ Demux Common Services      | |
     |          |  | +--------------------------------------+ |
     +----------+  +------------------------------------------+
     +--------------------------------------------------------+
     |                    Linux DVB Core                      |
     |     +----------+      +----------+       +----------+  |
     |     |   DVB    |      | DVB DMX  |       |  DVB     |  |
     |     |  Demux   |      |  Device  |       |  Device  |  |
     |     +----------+      +----------+       +----------+  |
     +--------------------------------------------------------+

The new developed code is QCOM MPQ Adapter and the MPQ Demux driver
with the various MPQ-DMX Plugins.

QCOM MPQ Adapter registers a new DVB adapter to Linux dvb-core.
The MPQ DVB adapter is built as a separate kernel module. Using it
demux and video devices can register themselves to the adapter.

MPQ-DMX plugins exist to hook to dvb-core demux implementation
depending on the HW capabilities. Only one of these plugins might be
compiled and run at a time on the target.
As the name of each plugin implies, one plugin implements demux
functionality for targets supporting TSIF only, and the others
implement pluging for targets supporting TSPP in different versions.

The plugin implementation is not hooked to specific chipset as
different chipsets might have the same HW capability.

The MPQ-DMX Plugin Common Services provides common services that are
used by all plugins, such as registrations of demux devices to
the dvb-core.

The demux plugin is built as a separate kernel module. Each plugin
hooks to the DVB-Demux by providing set of pointers to functions
required for DVB-Demux and dvb-core operation. The actual
implementation of these function differs between the plugins depending
on the HW capabilities. The plugins may be viewed as "classes"
inheriting from DVB-Demux "class".

Interface to TSPP/TSIF Drivers
------------------------------
Each demux plugin interacts with the kernel API of the relevant driver
(either TSIF or TSPP) to receive TS packets or other kinds of data
depending on the HW capabilities.

The demux uses the kernel API of TSIF and TSPP drivers and registers
callback triggered when new data is received. The callback schedules
work to a single-threaded workqueue to process the data. The actual
processing of the data depends on the HW capabilities.

Interface to TZ-COM Driver
--------------------------
For cases HW does not support descrambling, the descrambling is
performed by communicating with TZ using TZ-COM kernel API.

ION driver is used to allocate input and output buffers provided to TZ.

Interface to Decoders
---------------------
The interface to the decoders is done through a stream-buffer interface.
The design aims not to have direct calls between dvb/demux and
dvb/video for de-coupling and generality. dvb/demux and dvb/video
interact only with stream-buffer API.

Stream buffer is built of two ring-buffers, one holding the PES payload
(the video elementary stream) and the other holding parameters from PES
headers required by decoders.

The separation to two ring-buffers allows locking the payload buffer
as secured buffer that only the decoder's HW may access while allowing
the software to access the PES headers which are not required to be
secured. Locking of the payload buffer is done when the data should be
secured (scrambled video stream for example).

The stream-buffer API make use of dvb-ring buffer implementation that
is part of dvb-core.

SMP/multi-core
==============
Driver is fully SMP aware.

Interface
=========

User-space API
--------------
dvb/demux and dvb/dvr each expose a char device interface to user-space
as defined by linuxtv.org. Extension to this interface is done to add
new features required by MPQ use-cases. The extensions preserve backward
compatibility of the API defined by linuxtv.org

The devices appear in file-system under:
/dev/dvb/adapter0/demuxN
/dev/dvb/adapter0/dvrN

Where "N" ranges between 0 to total number of demux devices defined.
The default configuration is 4 devices.

Extensions to this API (through new ioctl) exist to provide the
following functionality:

1. DMX_SET_TS_PACKET_FORMAT: Set the transport stream TS packet format.
   Configures whether the stream fed to demux from memory is with TS packet
   of 188 bytes long, 192 bytes long, etc.
   Default is 188 bytes long to preserve backward compatibility.

   Returns the following values:
   0 in case of success.
   -EINVAL if the parameter is invalid.
   -EBUSY if demux is already running.

2. DMX_SET_DECODER_BUFFER_SIZE: Set the decoder's buffer size.
   For data tunneled to decoder, client can configure the size of the buffer
   holding the PES payload.
   Default is set to the fixed size value that exists in current dvb-core to
   preserve backward compatibility.

   Returns the following values:
   0 in case of success.
   -EINVAL if the parameter is invalid.
   -EBUSY if demux is already running.

3. DMX_SET_TS_OUT_FORMAT: Set the TS packet recording format.
   Indicates whether the TS packet used for recording should be in 188 or 192
   bytes long format. In case of 192-packets output, 4 bytes zero timestamp
   is attached to the original 188 packet.
   Default is set for 188 to preserve backward compatibility.

   Returns the following values:
   0 in case of success.
   -EINVAL if the parameter is invalid.
   -EBUSY if demux is already running.

4. Added support for mmap for direct access to input/output buffers.
   User can either use the original read/write syscalls or use mmap
   on the specific file-handle. Several ioctls were exposed so that
   user can find-out the status of the buffers (DMX_GET_BUFFER_STATUS),
   to notify demux when data is consumed (DMX_RELEASE_DATA) or notify
   dvr when data is fed (DMX_FEED_DATA).

5. DMX_SET_PLAYBACK_MODE: Set playback mode in memory input.
   In memory input, contrary to live input, playback can be in pull mode,
   where if one of output buffers is full, demux stalls waiting for free space,
   this would cause DVR input buffer fullness to accumulate.

   Returns the following values:
   0 in case of success.
   -EINVAL if the parameter is invalid.
   -EBUSY if demux is already running.

debugfs
-------
debugfs is used for debug purposes.

Directory in debugfs is created for each demux device.

Each directory includes several performance counters of the specific demux:
Total demuxing time, total CRC time, HW notification rate, HW notification
buffer size.


Exported Kernel API
-------------------
MPQ adapter exports the following kernel API:
1. Getter API for the registered MPQ adapter handle.
   This is used by demux plugin as well as dvb/video implementation to
   register their devices to that adapter.
2. Stream buffer API: Used to tunnel the data between dvb/demux and
   decoders. The API is used by dvb/demux and by decoders to write/read
   tunneled data.
3. Stream buffer interface registration: Used to register stream-buffer
   interfaces. When demux driver is asked to tunnel data to a decoder,
   the demux allocates a stream-buffer to be shared between demux and
   the decoder. For the decoder to retrieve the info of the
   stream-buffer it should connect to, stream-buffer registration API
   exist.
   The demux registers the new allocated stream buffer handle to MPQ
   Adapter, and the decoder may query the registered interface through
   MPQ Adapter.

Driver parameters
=================
There are three kernel modules required for DVB API operation:
1. dvb-core.ko: This is an existing Linux module for dvb functionality.
   The parameters for this module are the one defined by linuxtv.org.
   An additional parameter was added to specify whether to collect
   performance debug information exposed through debugfs.
   Parameter name: dvb_demux_performancecheck

2. mpq-adapter.ko: MPQ DVB adapter module. Has a parameter to
   specify the adapter number, the number (X) is the same as the one
   that appears in /dev/dvb/adapterX. Default is 0.
   Parameter name: adapter_nr

3. mpq-dmx-hw-plugin.ko: Module for demux HW plugin. Receives as a
   parameter the number of required demux devices. Default is set to the
   number specified in kernel configuration.
   Parameter name: mpq_demux_device_num

Config options
==============
New kernel configurations is available (through make menuconfig) to
enable MPQ based adapter functionality. The following configurations
exist:
1. Control whether to enable QCOM MPQ DVB adapter (tri-state).
   It depends on having dvb-core enabled.
2. If MPQ adapter is enabled:
   2.1. Control whether to enable MPQ dvb/demux (tri-state)
   2.2. Control whether to enable MPQ dvb/video (tri-state)
   2.3. If dvb/demux is enabled:
        2.3.1. Configure the number of demux devices. Default is 4.
        2.3.2. Select the desired demux plugin. Each plugin would appear
               in the list of options depending whether the respective
               driver (TSIF/TSPP) is enabled or not.

Dependencies
============
1. The implementation depends on having dvb-core enabled.
2. Each demux plugin depends on whether the relevant driver it uses
   is enabled. TSIF plugin depends on TSIF driver and TSPP plugins
   depend on TSPP driver.
3. There's no communication to other processors.

User space utilities
====================
N/A

Other
=====
N/A

Known issues
============
N/A
