diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-11 08:27:49 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-11 08:27:49 +0000 |
commit | ace9429bb58fd418f0c81d4c2835699bddf6bde6 (patch) | |
tree | b2d64bc10158fdd5497876388cd68142ca374ed3 /Documentation/driver-api/media | |
parent | Initial commit. (diff) | |
download | linux-ace9429bb58fd418f0c81d4c2835699bddf6bde6.tar.xz linux-ace9429bb58fd418f0c81d4c2835699bddf6bde6.zip |
Adding upstream version 6.6.15.upstream/6.6.15
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'Documentation/driver-api/media')
56 files changed, 13169 insertions, 0 deletions
diff --git a/Documentation/driver-api/media/camera-sensor.rst b/Documentation/driver-api/media/camera-sensor.rst new file mode 100644 index 0000000000..93f4f2536c --- /dev/null +++ b/Documentation/driver-api/media/camera-sensor.rst @@ -0,0 +1,175 @@ +.. SPDX-License-Identifier: GPL-2.0 + +Writing camera sensor drivers +============================= + +CSI-2 and parallel (BT.601 and BT.656) busses +--------------------------------------------- + +Please see :ref:`transmitter-receiver`. + +Handling clocks +--------------- + +Camera sensors have an internal clock tree including a PLL and a number of +divisors. The clock tree is generally configured by the driver based on a few +input parameters that are specific to the hardware:: the external clock frequency +and the link frequency. The two parameters generally are obtained from system +firmware. **No other frequencies should be used in any circumstances.** + +The reason why the clock frequencies are so important is that the clock signals +come out of the SoC, and in many cases a specific frequency is designed to be +used in the system. Using another frequency may cause harmful effects +elsewhere. Therefore only the pre-determined frequencies are configurable by the +user. + +ACPI +~~~~ + +Read the ``clock-frequency`` _DSD property to denote the frequency. The driver +can rely on this frequency being used. + +Devicetree +~~~~~~~~~~ + +The currently preferred way to achieve this is using ``assigned-clocks``, +``assigned-clock-parents`` and ``assigned-clock-rates`` properties. See +``Documentation/devicetree/bindings/clock/clock-bindings.txt`` for more +information. The driver then gets the frequency using ``clk_get_rate()``. + +This approach has the drawback that there's no guarantee that the frequency +hasn't been modified directly or indirectly by another driver, or supported by +the board's clock tree to begin with. Changes to the Common Clock Framework API +are required to ensure reliability. + +Frame size +---------- + +There are two distinct ways to configure the frame size produced by camera +sensors. + +Freely configurable camera sensor drivers +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Freely configurable camera sensor drivers expose the device's internal +processing pipeline as one or more sub-devices with different cropping and +scaling configurations. The output size of the device is the result of a series +of cropping and scaling operations from the device's pixel array's size. + +An example of such a driver is the CCS driver (see ``drivers/media/i2c/ccs``). + +Register list based drivers +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Register list based drivers generally, instead of able to configure the device +they control based on user requests, are limited to a number of preset +configurations that combine a number of different parameters that on hardware +level are independent. How a driver picks such configuration is based on the +format set on a source pad at the end of the device's internal pipeline. + +Most sensor drivers are implemented this way, see e.g. +``drivers/media/i2c/imx319.c`` for an example. + +Frame interval configuration +---------------------------- + +There are two different methods for obtaining possibilities for different frame +intervals as well as configuring the frame interval. Which one to implement +depends on the type of the device. + +Raw camera sensors +~~~~~~~~~~~~~~~~~~ + +Instead of a high level parameter such as frame interval, the frame interval is +a result of the configuration of a number of camera sensor implementation +specific parameters. Luckily, these parameters tend to be the same for more or +less all modern raw camera sensors. + +The frame interval is calculated using the following equation:: + + frame interval = (analogue crop width + horizontal blanking) * + (analogue crop height + vertical blanking) / pixel rate + +The formula is bus independent and is applicable for raw timing parameters on +large variety of devices beyond camera sensors. Devices that have no analogue +crop, use the full source image size, i.e. pixel array size. + +Horizontal and vertical blanking are specified by ``V4L2_CID_HBLANK`` and +``V4L2_CID_VBLANK``, respectively. The unit of the ``V4L2_CID_HBLANK`` control +is pixels and the unit of the ``V4L2_CID_VBLANK`` is lines. The pixel rate in +the sensor's **pixel array** is specified by ``V4L2_CID_PIXEL_RATE`` in the same +sub-device. The unit of that control is pixels per second. + +Register list based drivers need to implement read-only sub-device nodes for the +purpose. Devices that are not register list based need these to configure the +device's internal processing pipeline. + +The first entity in the linear pipeline is the pixel array. The pixel array may +be followed by other entities that are there to allow configuring binning, +skipping, scaling or digital crop :ref:`v4l2-subdev-selections`. + +USB cameras etc. devices +~~~~~~~~~~~~~~~~~~~~~~~~ + +USB video class hardware, as well as many cameras offering a similar higher +level interface natively, generally use the concept of frame interval (or frame +rate) on device level in firmware or hardware. This means lower level controls +implemented by raw cameras may not be used on uAPI (or even kAPI) to control the +frame interval on these devices. + +Power management +---------------- + +Always use runtime PM to manage the power states of your device. Camera sensor +drivers are in no way special in this respect: they are responsible for +controlling the power state of the device they otherwise control as well. In +general, the device must be powered on at least when its registers are being +accessed and when it is streaming. + +Existing camera sensor drivers may rely on the old +struct v4l2_subdev_core_ops->s_power() callback for bridge or ISP drivers to +manage their power state. This is however **deprecated**. If you feel you need +to begin calling an s_power from an ISP or a bridge driver, instead please add +runtime PM support to the sensor driver you are using. Likewise, new drivers +should not use s_power. + +Please see examples in e.g. ``drivers/media/i2c/ov8856.c`` and +``drivers/media/i2c/ccs/ccs-core.c``. The two drivers work in both ACPI +and DT based systems. + +Control framework +~~~~~~~~~~~~~~~~~ + +``v4l2_ctrl_handler_setup()`` function may not be used in the device's runtime +PM ``runtime_resume`` callback, as it has no way to figure out the power state +of the device. This is because the power state of the device is only changed +after the power state transition has taken place. The ``s_ctrl`` callback can be +used to obtain device's power state after the power state transition: + +.. c:function:: int pm_runtime_get_if_in_use(struct device *dev); + +The function returns a non-zero value if it succeeded getting the power count or +runtime PM was disabled, in either of which cases the driver may proceed to +access the device. + +Rotation, orientation and flipping +---------------------------------- + +Some systems have the camera sensor mounted upside down compared to its natural +mounting rotation. In such cases, drivers shall expose the information to +userspace with the :ref:`V4L2_CID_CAMERA_SENSOR_ROTATION +<v4l2-camera-sensor-rotation>` control. + +Sensor drivers shall also report the sensor's mounting orientation with the +:ref:`V4L2_CID_CAMERA_SENSOR_ORIENTATION <v4l2-camera-sensor-orientation>`. + +Use ``v4l2_fwnode_device_parse()`` to obtain rotation and orientation +information from system firmware and ``v4l2_ctrl_new_fwnode_properties()`` to +register the appropriate controls. + +Sensor drivers that have any vertical or horizontal flips embedded in the +register programming sequences shall initialize the V4L2_CID_HFLIP and +V4L2_CID_VFLIP controls with the values programmed by the register sequences. +The default values of these controls shall be 0 (disabled). Especially these +controls shall not be inverted, independently of the sensor's mounting +rotation. diff --git a/Documentation/driver-api/media/cec-core.rst b/Documentation/driver-api/media/cec-core.rst new file mode 100644 index 0000000000..f1ffdec388 --- /dev/null +++ b/Documentation/driver-api/media/cec-core.rst @@ -0,0 +1,502 @@ +.. SPDX-License-Identifier: GPL-2.0 + +CEC Kernel Support +================== + +The CEC framework provides a unified kernel interface for use with HDMI CEC +hardware. It is designed to handle a multiple types of hardware (receivers, +transmitters, USB dongles). The framework also gives the option to decide +what to do in the kernel driver and what should be handled by userspace +applications. In addition it integrates the remote control passthrough +feature into the kernel's remote control framework. + + +The CEC Protocol +---------------- + +The CEC protocol enables consumer electronic devices to communicate with each +other through the HDMI connection. The protocol uses logical addresses in the +communication. The logical address is strictly connected with the functionality +provided by the device. The TV acting as the communication hub is always +assigned address 0. The physical address is determined by the physical +connection between devices. + +The CEC framework described here is up to date with the CEC 2.0 specification. +It is documented in the HDMI 1.4 specification with the new 2.0 bits documented +in the HDMI 2.0 specification. But for most of the features the freely available +HDMI 1.3a specification is sufficient: + +https://www.hdmi.org/spec/index + + +CEC Adapter Interface +--------------------- + +The struct cec_adapter represents the CEC adapter hardware. It is created by +calling cec_allocate_adapter() and deleted by calling cec_delete_adapter(): + +.. c:function:: + struct cec_adapter *cec_allocate_adapter(const struct cec_adap_ops *ops, \ + void *priv, const char *name, \ + u32 caps, u8 available_las); + +.. c:function:: + void cec_delete_adapter(struct cec_adapter *adap); + +To create an adapter you need to pass the following information: + +ops: + adapter operations which are called by the CEC framework and that you + have to implement. + +priv: + will be stored in adap->priv and can be used by the adapter ops. + Use cec_get_drvdata(adap) to get the priv pointer. + +name: + the name of the CEC adapter. Note: this name will be copied. + +caps: + capabilities of the CEC adapter. These capabilities determine the + capabilities of the hardware and which parts are to be handled + by userspace and which parts are handled by kernelspace. The + capabilities are returned by CEC_ADAP_G_CAPS. + +available_las: + the number of simultaneous logical addresses that this + adapter can handle. Must be 1 <= available_las <= CEC_MAX_LOG_ADDRS. + +To obtain the priv pointer use this helper function: + +.. c:function:: + void *cec_get_drvdata(const struct cec_adapter *adap); + +To register the /dev/cecX device node and the remote control device (if +CEC_CAP_RC is set) you call: + +.. c:function:: + int cec_register_adapter(struct cec_adapter *adap, \ + struct device *parent); + +where parent is the parent device. + +To unregister the devices call: + +.. c:function:: + void cec_unregister_adapter(struct cec_adapter *adap); + +Note: if cec_register_adapter() fails, then call cec_delete_adapter() to +clean up. But if cec_register_adapter() succeeded, then only call +cec_unregister_adapter() to clean up, never cec_delete_adapter(). The +unregister function will delete the adapter automatically once the last user +of that /dev/cecX device has closed its file handle. + + +Implementing the Low-Level CEC Adapter +-------------------------------------- + +The following low-level adapter operations have to be implemented in +your driver: + +.. c:struct:: cec_adap_ops + +.. code-block:: none + + struct cec_adap_ops + { + /* Low-level callbacks */ + int (*adap_enable)(struct cec_adapter *adap, bool enable); + int (*adap_monitor_all_enable)(struct cec_adapter *adap, bool enable); + int (*adap_monitor_pin_enable)(struct cec_adapter *adap, bool enable); + int (*adap_log_addr)(struct cec_adapter *adap, u8 logical_addr); + void (*adap_unconfigured)(struct cec_adapter *adap); + int (*adap_transmit)(struct cec_adapter *adap, u8 attempts, + u32 signal_free_time, struct cec_msg *msg); + void (*adap_nb_transmit_canceled)(struct cec_adapter *adap, + const struct cec_msg *msg); + void (*adap_status)(struct cec_adapter *adap, struct seq_file *file); + void (*adap_free)(struct cec_adapter *adap); + + /* Error injection callbacks */ + ... + + /* High-level callback */ + ... + }; + +These low-level ops deal with various aspects of controlling the CEC adapter +hardware. They are all called with the mutex adap->lock held. + + +To enable/disable the hardware:: + + int (*adap_enable)(struct cec_adapter *adap, bool enable); + +This callback enables or disables the CEC hardware. Enabling the CEC hardware +means powering it up in a state where no logical addresses are claimed. The +physical address will always be valid if CEC_CAP_NEEDS_HPD is set. If that +capability is not set, then the physical address can change while the CEC +hardware is enabled. CEC drivers should not set CEC_CAP_NEEDS_HPD unless +the hardware design requires that as this will make it impossible to wake +up displays that pull the HPD low when in standby mode. The initial +state of the CEC adapter after calling cec_allocate_adapter() is disabled. + +Note that adap_enable must return 0 if enable is false. + + +To enable/disable the 'monitor all' mode:: + + int (*adap_monitor_all_enable)(struct cec_adapter *adap, bool enable); + +If enabled, then the adapter should be put in a mode to also monitor messages +that are not for us. Not all hardware supports this and this function is only +called if the CEC_CAP_MONITOR_ALL capability is set. This callback is optional +(some hardware may always be in 'monitor all' mode). + +Note that adap_monitor_all_enable must return 0 if enable is false. + + +To enable/disable the 'monitor pin' mode:: + + int (*adap_monitor_pin_enable)(struct cec_adapter *adap, bool enable); + +If enabled, then the adapter should be put in a mode to also monitor CEC pin +changes. Not all hardware supports this and this function is only called if +the CEC_CAP_MONITOR_PIN capability is set. This callback is optional +(some hardware may always be in 'monitor pin' mode). + +Note that adap_monitor_pin_enable must return 0 if enable is false. + + +To program a new logical address:: + + int (*adap_log_addr)(struct cec_adapter *adap, u8 logical_addr); + +If logical_addr == CEC_LOG_ADDR_INVALID then all programmed logical addresses +are to be erased. Otherwise the given logical address should be programmed. +If the maximum number of available logical addresses is exceeded, then it +should return -ENXIO. Once a logical address is programmed the CEC hardware +can receive directed messages to that address. + +Note that adap_log_addr must return 0 if logical_addr is CEC_LOG_ADDR_INVALID. + + +Called when the adapter is unconfigured:: + + void (*adap_unconfigured)(struct cec_adapter *adap); + +The adapter is unconfigured. If the driver has to take specific actions after +unconfiguration, then that can be done through this optional callback. + + +To transmit a new message:: + + int (*adap_transmit)(struct cec_adapter *adap, u8 attempts, + u32 signal_free_time, struct cec_msg *msg); + +This transmits a new message. The attempts argument is the suggested number of +attempts for the transmit. + +The signal_free_time is the number of data bit periods that the adapter should +wait when the line is free before attempting to send a message. This value +depends on whether this transmit is a retry, a message from a new initiator or +a new message for the same initiator. Most hardware will handle this +automatically, but in some cases this information is needed. + +The CEC_FREE_TIME_TO_USEC macro can be used to convert signal_free_time to +microseconds (one data bit period is 2.4 ms). + + +To pass on the result of a canceled non-blocking transmit:: + + void (*adap_nb_transmit_canceled)(struct cec_adapter *adap, + const struct cec_msg *msg); + +This optional callback can be used to obtain the result of a canceled +non-blocking transmit with sequence number msg->sequence. This is +called if the transmit was aborted, the transmit timed out (i.e. the +hardware never signaled that the transmit finished), or the transmit +was successful, but the wait for the expected reply was either aborted +or it timed out. + + +To log the current CEC hardware status:: + + void (*adap_status)(struct cec_adapter *adap, struct seq_file *file); + +This optional callback can be used to show the status of the CEC hardware. +The status is available through debugfs: cat /sys/kernel/debug/cec/cecX/status + +To free any resources when the adapter is deleted:: + + void (*adap_free)(struct cec_adapter *adap); + +This optional callback can be used to free any resources that might have been +allocated by the driver. It's called from cec_delete_adapter. + + +Your adapter driver will also have to react to events (typically interrupt +driven) by calling into the framework in the following situations: + +When a transmit finished (successfully or otherwise):: + + void cec_transmit_done(struct cec_adapter *adap, u8 status, + u8 arb_lost_cnt, u8 nack_cnt, u8 low_drive_cnt, + u8 error_cnt); + +or:: + + void cec_transmit_attempt_done(struct cec_adapter *adap, u8 status); + +The status can be one of: + +CEC_TX_STATUS_OK: + the transmit was successful. + +CEC_TX_STATUS_ARB_LOST: + arbitration was lost: another CEC initiator + took control of the CEC line and you lost the arbitration. + +CEC_TX_STATUS_NACK: + the message was nacked (for a directed message) or + acked (for a broadcast message). A retransmission is needed. + +CEC_TX_STATUS_LOW_DRIVE: + low drive was detected on the CEC bus. This indicates that + a follower detected an error on the bus and requested a + retransmission. + +CEC_TX_STATUS_ERROR: + some unspecified error occurred: this can be one of ARB_LOST + or LOW_DRIVE if the hardware cannot differentiate or something + else entirely. Some hardware only supports OK and FAIL as the + result of a transmit, i.e. there is no way to differentiate + between the different possible errors. In that case map FAIL + to CEC_TX_STATUS_NACK and not to CEC_TX_STATUS_ERROR. + +CEC_TX_STATUS_MAX_RETRIES: + could not transmit the message after trying multiple times. + Should only be set by the driver if it has hardware support for + retrying messages. If set, then the framework assumes that it + doesn't have to make another attempt to transmit the message + since the hardware did that already. + +The hardware must be able to differentiate between OK, NACK and 'something +else'. + +The \*_cnt arguments are the number of error conditions that were seen. +This may be 0 if no information is available. Drivers that do not support +hardware retry can just set the counter corresponding to the transmit error +to 1, if the hardware does support retry then either set these counters to +0 if the hardware provides no feedback of which errors occurred and how many +times, or fill in the correct values as reported by the hardware. + +Be aware that calling these functions can immediately start a new transmit +if there is one pending in the queue. So make sure that the hardware is in +a state where new transmits can be started *before* calling these functions. + +The cec_transmit_attempt_done() function is a helper for cases where the +hardware never retries, so the transmit is always for just a single +attempt. It will call cec_transmit_done() in turn, filling in 1 for the +count argument corresponding to the status. Or all 0 if the status was OK. + +When a CEC message was received: + +.. c:function:: + void cec_received_msg(struct cec_adapter *adap, struct cec_msg *msg); + +Speaks for itself. + +Implementing the interrupt handler +---------------------------------- + +Typically the CEC hardware provides interrupts that signal when a transmit +finished and whether it was successful or not, and it provides and interrupt +when a CEC message was received. + +The CEC driver should always process the transmit interrupts first before +handling the receive interrupt. The framework expects to see the cec_transmit_done +call before the cec_received_msg call, otherwise it can get confused if the +received message was in reply to the transmitted message. + +Optional: Implementing Error Injection Support +---------------------------------------------- + +If the CEC adapter supports Error Injection functionality, then that can +be exposed through the Error Injection callbacks: + +.. code-block:: none + + struct cec_adap_ops { + /* Low-level callbacks */ + ... + + /* Error injection callbacks */ + int (*error_inj_show)(struct cec_adapter *adap, struct seq_file *sf); + bool (*error_inj_parse_line)(struct cec_adapter *adap, char *line); + + /* High-level CEC message callback */ + ... + }; + +If both callbacks are set, then an ``error-inj`` file will appear in debugfs. +The basic syntax is as follows: + +Leading spaces/tabs are ignored. If the next character is a ``#`` or the end of the +line was reached, then the whole line is ignored. Otherwise a command is expected. + +This basic parsing is done in the CEC Framework. It is up to the driver to decide +what commands to implement. The only requirement is that the command ``clear`` without +any arguments must be implemented and that it will remove all current error injection +commands. + +This ensures that you can always do ``echo clear >error-inj`` to clear any error +injections without having to know the details of the driver-specific commands. + +Note that the output of ``error-inj`` shall be valid as input to ``error-inj``. +So this must work: + +.. code-block:: none + + $ cat error-inj >einj.txt + $ cat einj.txt >error-inj + +The first callback is called when this file is read and it should show the +current error injection state:: + + int (*error_inj_show)(struct cec_adapter *adap, struct seq_file *sf); + +It is recommended that it starts with a comment block with basic usage +information. It returns 0 for success and an error otherwise. + +The second callback will parse commands written to the ``error-inj`` file:: + + bool (*error_inj_parse_line)(struct cec_adapter *adap, char *line); + +The ``line`` argument points to the start of the command. Any leading +spaces or tabs have already been skipped. It is a single line only (so there +are no embedded newlines) and it is 0-terminated. The callback is free to +modify the contents of the buffer. It is only called for lines containing a +command, so this callback is never called for empty lines or comment lines. + +Return true if the command was valid or false if there were syntax errors. + +Implementing the High-Level CEC Adapter +--------------------------------------- + +The low-level operations drive the hardware, the high-level operations are +CEC protocol driven. The high-level callbacks are called without the adap->lock +mutex being held. The following high-level callbacks are available: + +.. code-block:: none + + struct cec_adap_ops { + /* Low-level callbacks */ + ... + + /* Error injection callbacks */ + ... + + /* High-level CEC message callback */ + void (*configured)(struct cec_adapter *adap); + int (*received)(struct cec_adapter *adap, struct cec_msg *msg); + }; + +Called when the adapter is configured:: + + void (*configured)(struct cec_adapter *adap); + +The adapter is fully configured, i.e. all logical addresses have been +successfully claimed. If the driver has to take specific actions after +configuration, then that can be done through this optional callback. + + +The received() callback allows the driver to optionally handle a newly +received CEC message:: + + int (*received)(struct cec_adapter *adap, struct cec_msg *msg); + +If the driver wants to process a CEC message, then it can implement this +callback. If it doesn't want to handle this message, then it should return +-ENOMSG, otherwise the CEC framework assumes it processed this message and +it will not do anything with it. + + +CEC framework functions +----------------------- + +CEC Adapter drivers can call the following CEC framework functions: + +.. c:function:: + int cec_transmit_msg(struct cec_adapter *adap, struct cec_msg *msg, \ + bool block); + +Transmit a CEC message. If block is true, then wait until the message has been +transmitted, otherwise just queue it and return. + +.. c:function:: + void cec_s_phys_addr(struct cec_adapter *adap, u16 phys_addr, bool block); + +Change the physical address. This function will set adap->phys_addr and +send an event if it has changed. If cec_s_log_addrs() has been called and +the physical address has become valid, then the CEC framework will start +claiming the logical addresses. If block is true, then this function won't +return until this process has finished. + +When the physical address is set to a valid value the CEC adapter will +be enabled (see the adap_enable op). When it is set to CEC_PHYS_ADDR_INVALID, +then the CEC adapter will be disabled. If you change a valid physical address +to another valid physical address, then this function will first set the +address to CEC_PHYS_ADDR_INVALID before enabling the new physical address. + +.. c:function:: + void cec_s_phys_addr_from_edid(struct cec_adapter *adap, \ + const struct edid *edid); + +A helper function that extracts the physical address from the edid struct +and calls cec_s_phys_addr() with that address, or CEC_PHYS_ADDR_INVALID +if the EDID did not contain a physical address or edid was a NULL pointer. + +.. c:function:: + int cec_s_log_addrs(struct cec_adapter *adap, \ + struct cec_log_addrs *log_addrs, bool block); + +Claim the CEC logical addresses. Should never be called if CEC_CAP_LOG_ADDRS +is set. If block is true, then wait until the logical addresses have been +claimed, otherwise just queue it and return. To unconfigure all logical +addresses call this function with log_addrs set to NULL or with +log_addrs->num_log_addrs set to 0. The block argument is ignored when +unconfiguring. This function will just return if the physical address is +invalid. Once the physical address becomes valid, then the framework will +attempt to claim these logical addresses. + +CEC Pin framework +----------------- + +Most CEC hardware operates on full CEC messages where the software provides +the message and the hardware handles the low-level CEC protocol. But some +hardware only drives the CEC pin and software has to handle the low-level +CEC protocol. The CEC pin framework was created to handle such devices. + +Note that due to the close-to-realtime requirements it can never be guaranteed +to work 100%. This framework uses highres timers internally, but if a +timer goes off too late by more than 300 microseconds wrong results can +occur. In reality it appears to be fairly reliable. + +One advantage of this low-level implementation is that it can be used as +a cheap CEC analyser, especially if interrupts can be used to detect +CEC pin transitions from low to high or vice versa. + +.. kernel-doc:: include/media/cec-pin.h + +CEC Notifier framework +---------------------- + +Most drm HDMI implementations have an integrated CEC implementation and no +notifier support is needed. But some have independent CEC implementations +that have their own driver. This could be an IP block for an SoC or a +completely separate chip that deals with the CEC pin. For those cases a +drm driver can install a notifier and use the notifier to inform the +CEC driver about changes in the physical address. + +.. kernel-doc:: include/media/cec-notifier.h diff --git a/Documentation/driver-api/media/drivers/bttv-devel.rst b/Documentation/driver-api/media/drivers/bttv-devel.rst new file mode 100644 index 0000000000..0885a04563 --- /dev/null +++ b/Documentation/driver-api/media/drivers/bttv-devel.rst @@ -0,0 +1,116 @@ +.. SPDX-License-Identifier: GPL-2.0 + +The bttv driver +=============== + +bttv and sound mini howto +------------------------- + +There are a lot of different bt848/849/878/879 based boards available. +Making video work often is not a big deal, because this is handled +completely by the bt8xx chip, which is common on all boards. But +sound is handled in slightly different ways on each board. + +To handle the grabber boards correctly, there is a array tvcards[] in +bttv-cards.c, which holds the information required for each board. +Sound will work only, if the correct entry is used (for video it often +makes no difference). The bttv driver prints a line to the kernel +log, telling which card type is used. Like this one:: + + bttv0: model: BT848(Hauppauge old) [autodetected] + +You should verify this is correct. If it isn't, you have to pass the +correct board type as insmod argument, ``insmod bttv card=2`` for +example. The file Documentation/admin-guide/media/bttv-cardlist.rst has a list +of valid arguments for card. + +If your card isn't listed there, you might check the source code for +new entries which are not listed yet. If there isn't one for your +card, you can check if one of the existing entries does work for you +(just trial and error...). + +Some boards have an extra processor for sound to do stereo decoding +and other nice features. The msp34xx chips are used by Hauppauge for +example. If your board has one, you might have to load a helper +module like ``msp3400`` to make sound work. If there isn't one for the +chip used on your board: Bad luck. Start writing a new one. Well, +you might want to check the video4linux mailing list archive first... + +Of course you need a correctly installed soundcard unless you have the +speakers connected directly to the grabber board. Hint: check the +mixer settings too. ALSA for example has everything muted by default. + + +How sound works in detail +~~~~~~~~~~~~~~~~~~~~~~~~~ + +Still doesn't work? Looks like some driver hacking is required. +Below is a do-it-yourself description for you. + +The bt8xx chips have 32 general purpose pins, and registers to control +these pins. One register is the output enable register +(``BT848_GPIO_OUT_EN``), it says which pins are actively driven by the +bt848 chip. Another one is the data register (``BT848_GPIO_DATA``), where +you can get/set the status if these pins. They can be used for input +and output. + +Most grabber board vendors use these pins to control an external chip +which does the sound routing. But every board is a little different. +These pins are also used by some companies to drive remote control +receiver chips. Some boards use the i2c bus instead of the gpio pins +to connect the mux chip. + +As mentioned above, there is a array which holds the required +information for each known board. You basically have to create a new +line for your board. The important fields are these two:: + + struct tvcard + { + [ ... ] + u32 gpiomask; + u32 audiomux[6]; /* Tuner, Radio, external, internal, mute, stereo */ + }; + +gpiomask specifies which pins are used to control the audio mux chip. +The corresponding bits in the output enable register +(``BT848_GPIO_OUT_EN``) will be set as these pins must be driven by the +bt848 chip. + +The ``audiomux[]`` array holds the data values for the different inputs +(i.e. which pins must be high/low for tuner/mute/...). This will be +written to the data register (``BT848_GPIO_DATA``) to switch the audio +mux. + + +What you have to do is figure out the correct values for gpiomask and +the audiomux array. If you have Windows and the drivers four your +card installed, you might to check out if you can read these registers +values used by the windows driver. A tool to do this is available +from http://btwincap.sourceforge.net/download.html. + +You might also dig around in the ``*.ini`` files of the Windows applications. +You can have a look at the board to see which of the gpio pins are +connected at all and then start trial-and-error ... + + +Starting with release 0.7.41 bttv has a number of insmod options to +make the gpio debugging easier: + + ================= ============================================== + bttv_gpio=0/1 enable/disable gpio debug messages + gpiomask=n set the gpiomask value + audiomux=i,j,... set the values of the audiomux array + audioall=a set the values of the audiomux array (one + value for all array elements, useful to check + out which effect the particular value has). + ================= ============================================== + +The messages printed with ``bttv_gpio=1`` look like this:: + + bttv0: gpio: en=00000027, out=00000024 in=00ffffd8 [audio: off] + + en = output _en_able register (BT848_GPIO_OUT_EN) + out = _out_put bits of the data register (BT848_GPIO_DATA), + i.e. BT848_GPIO_DATA & BT848_GPIO_OUT_EN + in = _in_put bits of the data register, + i.e. BT848_GPIO_DATA & ~BT848_GPIO_OUT_EN diff --git a/Documentation/driver-api/media/drivers/ccs/ccs-regs.asc b/Documentation/driver-api/media/drivers/ccs/ccs-regs.asc new file mode 100644 index 0000000000..bbf9213c33 --- /dev/null +++ b/Documentation/driver-api/media/drivers/ccs/ccs-regs.asc @@ -0,0 +1,1041 @@ +# SPDX-License-Identifier: GPL-2.0-only OR BSD-3-Clause +# Copyright (C) 2019--2020 Intel Corporation + +# register rflags +# - f field LSB MSB rflags +# - e enum value # after a field +# - e enum value [LSB MSB] +# - b bool bit +# - l arg name min max elsize [discontig...] +# +# rflags +# 8, 16, 32 register bits (default is 8) +# v1.1 defined in version 1.1 +# f formula +# float_ireal iReal or IEEE 754; 32 bits +# ireal unsigned iReal + +# general status registers +module_model_id 0x0000 16 +module_revision_number_major 0x0002 8 +frame_count 0x0005 8 +pixel_order 0x0006 8 +- e GRBG 0 +- e RGGB 1 +- e BGGR 2 +- e GBRG 3 +MIPI_CCS_version 0x0007 8 +- e v1_0 0x10 +- e v1_1 0x11 +- f major 4 7 +- f minor 0 3 +data_pedestal 0x0008 16 +module_manufacturer_id 0x000e 16 +module_revision_number_minor 0x0010 8 +module_date_year 0x0012 8 +module_date_month 0x0013 8 +module_date_day 0x0014 8 +module_date_phase 0x0015 8 +- f 0 2 +- e ts 0 +- e es 1 +- e cs 2 +- e mp 3 +sensor_model_id 0x0016 16 +sensor_revision_number 0x0018 8 +sensor_firmware_version 0x001a 8 +serial_number 0x001c 32 +sensor_manufacturer_id 0x0020 16 +sensor_revision_number_16 0x0022 16 + +# frame format description registers +frame_format_model_type 0x0040 8 +- e 2-byte 1 +- e 4-byte 2 +frame_format_model_subtype 0x0041 8 +- f rows 0 3 +- f columns 4 7 +frame_format_descriptor(n) 0x0042 16 f +- l n 0 14 2 +- f pixels 0 11 +- f pcode 12 15 +- e embedded 1 +- e dummy_pixel 2 +- e black_pixel 3 +- e dark_pixel 4 +- e visible_pixel 5 +- e manuf_specific_0 8 +- e manuf_specific_1 9 +- e manuf_specific_2 10 +- e manuf_specific_3 11 +- e manuf_specific_4 12 +- e manuf_specific_5 13 +- e manuf_specific_6 14 +frame_format_descriptor_4(n) 0x0060 32 f +- l n 0 7 4 +- f pixels 0 15 +- f pcode 28 31 +- e embedded 1 +- e dummy_pixel 2 +- e black_pixel 3 +- e dark_pixel 4 +- e visible_pixel 5 +- e manuf_specific_0 8 +- e manuf_specific_1 9 +- e manuf_specific_2 10 +- e manuf_specific_3 11 +- e manuf_specific_4 12 +- e manuf_specific_5 13 +- e manuf_specific_6 14 + +# analog gain description registers +analog_gain_capability 0x0080 16 +- e global 0 +- e alternate_global 2 +analog_gain_code_min 0x0084 16 +analog_gain_code_max 0x0086 16 +analog_gain_code_step 0x0088 16 +analog_gain_type 0x008a 16 +analog_gain_m0 0x008c 16 +analog_gain_c0 0x008e 16 +analog_gain_m1 0x0090 16 +analog_gain_c1 0x0092 16 +analog_linear_gain_min 0x0094 16 v1.1 +analog_linear_gain_max 0x0096 16 v1.1 +analog_linear_gain_step_size 0x0098 16 v1.1 +analog_exponential_gain_min 0x009a 16 v1.1 +analog_exponential_gain_max 0x009c 16 v1.1 +analog_exponential_gain_step_size 0x009e 16 v1.1 + +# data format description registers +data_format_model_type 0x00c0 8 +- e normal 1 +- e extended 2 +data_format_model_subtype 0x00c1 8 +- f rows 0 3 +- f columns 4 7 +data_format_descriptor(n) 0x00c2 16 f +- l n 0 15 2 +- f compressed 0 7 +- f uncompressed 8 15 + +# general set-up registers +mode_select 0x0100 8 +- e software_standby 0 +- e streaming 1 +image_orientation 0x0101 8 +- b horizontal_mirror 0 +- b vertical_flip 1 +software_reset 0x0103 8 +- e off 0 +- e on 1 +grouped_parameter_hold 0x0104 8 +mask_corrupted_frames 0x0105 8 +- e allow 0 +- e mask 1 +fast_standby_ctrl 0x0106 8 +- e complete_frames 0 +- e frame_truncation 1 +CCI_address_ctrl 0x0107 8 +2nd_CCI_if_ctrl 0x0108 8 +- b enable 0 +- b ack 1 +2nd_CCI_address_ctrl 0x0109 8 +CSI_channel_identifier 0x0110 8 +CSI_signaling_mode 0x0111 8 +- e csi_2_dphy 2 +- e csi_2_cphy 3 +CSI_data_format 0x0112 16 +CSI_lane_mode 0x0114 8 +DPCM_Frame_DT 0x011d 8 +Bottom_embedded_data_DT 0x011e 8 +Bottom_embedded_data_VC 0x011f 8 + +gain_mode 0x0120 8 +- e global 0 +- e alternate 1 +ADC_bit_depth 0x0121 8 +emb_data_ctrl 0x0122 v1.1 +- b raw8_packing_for_raw16 0 +- b raw10_packing_for_raw20 1 +- b raw12_packing_for_raw24 2 + +GPIO_TRIG_mode 0x0130 8 +extclk_frequency_mhz 0x0136 16 ireal +temp_sensor_ctrl 0x0138 8 +- b enable 0 +temp_sensor_mode 0x0139 8 +temp_sensor_output 0x013a 8 + +# integration time registers +fine_integration_time 0x0200 16 +coarse_integration_time 0x0202 16 + +# analog gain registers +analog_gain_code_global 0x0204 16 +analog_linear_gain_global 0x0206 16 v1.1 +analog_exponential_gain_global 0x0208 16 v1.1 + +# digital gain registers +digital_gain_global 0x020e 16 + +# hdr control registers +Short_analog_gain_global 0x0216 16 +Short_digital_gain_global 0x0218 16 + +HDR_mode 0x0220 8 +- b enabled 0 +- b separate_analog_gain 1 +- b upscaling 2 +- b reset_sync 3 +- b timing_mode 4 +- b exposure_ctrl_direct 5 +- b separate_digital_gain 6 +HDR_resolution_reduction 0x0221 8 +- f row 0 3 +- f column 4 7 +Exposure_ratio 0x0222 8 +HDR_internal_bit_depth 0x0223 8 +Direct_short_integration_time 0x0224 16 +Short_analog_linear_gain_global 0x0226 16 v1.1 +Short_analog_exponential_gain_global 0x0228 16 v1.1 + +# clock set-up registers +vt_pix_clk_div 0x0300 16 +vt_sys_clk_div 0x0302 16 +pre_pll_clk_div 0x0304 16 +#vt_pre_pll_clk_div 0x0304 16 +pll_multiplier 0x0306 16 +#vt_pll_multiplier 0x0306 16 +op_pix_clk_div 0x0308 16 +op_sys_clk_div 0x030a 16 +op_pre_pll_clk_div 0x030c 16 +op_pll_multiplier 0x030e 16 +pll_mode 0x0310 8 +- f 0 0 +- e single 0 +- e dual 1 +op_pix_clk_div_rev 0x0312 16 v1.1 +op_sys_clk_div_rev 0x0314 16 v1.1 + +# frame timing registers +frame_length_lines 0x0340 16 +line_length_pck 0x0342 16 + +# image size registers +x_addr_start 0x0344 16 +y_addr_start 0x0346 16 +x_addr_end 0x0348 16 +y_addr_end 0x034a 16 +x_output_size 0x034c 16 +y_output_size 0x034e 16 + +# timing mode registers +Frame_length_ctrl 0x0350 8 +- b automatic 0 +Timing_mode_ctrl 0x0352 8 +- b manual_readout 0 +- b delayed_exposure 1 +Start_readout_rs 0x0353 8 +- b manual_readout_start 0 +Frame_margin 0x0354 16 + +# sub-sampling registers +x_even_inc 0x0380 16 +x_odd_inc 0x0382 16 +y_even_inc 0x0384 16 +y_odd_inc 0x0386 16 + +# monochrome readout registers +monochrome_en 0x0390 v1.1 +- e enabled 0 + +# image scaling registers +Scaling_mode 0x0400 16 +- e no_scaling 0 +- e horizontal 1 +scale_m 0x0404 16 +scale_n 0x0406 16 +digital_crop_x_offset 0x0408 16 +digital_crop_y_offset 0x040a 16 +digital_crop_image_width 0x040c 16 +digital_crop_image_height 0x040e 16 + +# image compression registers +compression_mode 0x0500 16 +- e none 0 +- e dpcm_pcm_simple 1 + +# test pattern registers +test_pattern_mode 0x0600 16 +- e none 0 +- e solid_color 1 +- e color_bars 2 +- e fade_to_grey 3 +- e pn9 4 +- e color_tile 5 +test_data_red 0x0602 16 +test_data_greenR 0x0604 16 +test_data_blue 0x0606 16 +test_data_greenB 0x0608 16 +value_step_size_smooth 0x060a 8 +value_step_size_quantised 0x060b 8 + +# phy configuration registers +tclk_post 0x0800 8 +ths_prepare 0x0801 8 +ths_zero_min 0x0802 8 +ths_trail 0x0803 8 +tclk_trail_min 0x0804 8 +tclk_prepare 0x0805 8 +tclk_zero 0x0806 8 +tlpx 0x0807 8 +phy_ctrl 0x0808 8 +- e auto 0 +- e UI 1 +- e manual 2 +tclk_post_ex 0x080a 16 +ths_prepare_ex 0x080c 16 +ths_zero_min_ex 0x080e 16 +ths_trail_ex 0x0810 16 +tclk_trail_min_ex 0x0812 16 +tclk_prepare_ex 0x0814 16 +tclk_zero_ex 0x0816 16 +tlpx_ex 0x0818 16 + +# link rate register +requested_link_rate 0x0820 32 u16.16 + +# equalization control registers +DPHY_equalization_mode 0x0824 8 v1.1 +- b eq2 0 +PHY_equalization_ctrl 0x0825 8 v1.1 +- b enable 0 + +# d-phy preamble control registers +DPHY_preamble_ctrl 0x0826 8 v1.1 +- b enable 0 +DPHY_preamble_length 0x0826 8 v1.1 + +# d-phy spread spectrum control registers +PHY_SSC_ctrl 0x0828 8 v1.1 +- b enable 0 + +# manual lp control register +manual_LP_ctrl 0x0829 8 v1.1 +- b enable 0 + +# additional phy configuration registers +twakeup 0x082a v1.1 +tinit 0x082b v1.1 +ths_exit 0x082c v1.1 +ths_exit_ex 0x082e 16 v1.1 + +# phy calibration configuration registers +PHY_periodic_calibration_ctrl 0x0830 8 +- b frame_blanking 0 +PHY_periodic_calibration_interval 0x0831 8 +PHY_init_calibration_ctrl 0x0832 8 +- b stream_start 0 +DPHY_calibration_mode 0x0833 8 v1.1 +- b also_alternate 0 +CPHY_calibration_mode 0x0834 8 v1.1 +- e format_1 0 +- e format_2 1 +- e format_3 2 +t3_calpreamble_length 0x0835 8 v1.1 +t3_calpreamble_length_per 0x0836 8 v1.1 +t3_calaltseq_length 0x0837 8 v1.1 +t3_calaltseq_length_per 0x0838 8 v1.1 +FM2_init_seed 0x083a 16 v1.1 +t3_caludefseq_length 0x083c 16 v1.1 +t3_caludefseq_length_per 0x083e 16 v1.1 + +# c-phy manual control registers +TGR_Preamble_Length 0x0841 8 +- b preamable_prog_seq 7 +- f begin_preamble_length 0 5 +TGR_Post_Length 0x0842 8 +- f post_length 0 4 +TGR_Preamble_Prog_Sequence(n2) 0x0843 +- l n2 0 6 1 +- f symbol_n_1 3 5 +- f symbol_n 0 2 +t3_prepare 0x084e 16 +t3_lpx 0x0850 16 + +# alps control register +ALPS_ctrl 0x085a 8 +- b lvlp_dphy 0 +- b lvlp_cphy 1 +- b alp_cphy 2 + +# lrte control registers +TX_REG_CSI_EPD_EN_SSP_cphy 0x0860 16 +TX_REG_CSI_EPD_OP_SLP_cphy 0x0862 16 +TX_REG_CSI_EPD_EN_SSP_dphy 0x0864 16 +TX_REG_CSI_EPD_OP_SLP_dphy 0x0866 16 +TX_REG_CSI_EPD_MISC_OPTION_cphy 0x0868 v1.1 +TX_REG_CSI_EPD_MISC_OPTION_dphy 0x0869 v1.1 + +# scrambling control registers +Scrambling_ctrl 0x0870 +- b enabled 0 +- f 2 3 +- e 1_seed_cphy 0 +- e 4_seed_cphy 3 +lane_seed_value(seed, lane) 0x0872 16 +- l seed 0 3 0x10 +- l lane 0 7 0x2 + +# usl control registers +TX_USL_REV_ENTRY 0x08c0 16 v1.1 +TX_USL_REV_Clock_Counter 0x08c2 16 v1.1 +TX_USL_REV_LP_Counter 0x08c4 16 v1.1 +TX_USL_REV_Frame_Counter 0x08c6 16 v1.1 +TX_USL_REV_Chronological_Timer 0x08c8 16 v1.1 +TX_USL_FWD_ENTRY 0x08ca 16 v1.1 +TX_USL_GPIO 0x08cc 16 v1.1 +TX_USL_Operation 0x08ce 16 v1.1 +- b reset 0 +TX_USL_ALP_ctrl 0x08d0 16 v1.1 +- b clock_pause 0 +TX_USL_APP_BTA_ACK_TIMEOUT 0x08d2 16 v1.1 +TX_USL_SNS_BTA_ACK_TIMEOUT 0x08d2 16 v1.1 +USL_Clock_Mode_d_ctrl 0x08d2 v1.1 +- b cont_clock_standby 0 +- b cont_clock_vblank 1 +- b cont_clock_hblank 2 + +# binning configuration registers +binning_mode 0x0900 8 +binning_type 0x0901 8 +binning_weighting 0x0902 8 + +# data transfer interface registers +data_transfer_if_1_ctrl 0x0a00 8 +- b enable 0 +- b write 1 +- b clear_error 2 +data_transfer_if_1_status 0x0a01 8 +- b read_if_ready 0 +- b write_if_ready 1 +- b data_corrupted 2 +- b improper_if_usage 3 +data_transfer_if_1_page_select 0x0a02 8 +data_transfer_if_1_data(p) 0x0a04 8 f +- l p 0 63 1 + +# image processing and sensor correction configuration registers +shading_correction_en 0x0b00 8 +- b enable 0 +luminance_correction_level 0x0b01 8 +green_imbalance_filter_en 0x0b02 8 +- b enable 0 +mapped_defect_correct_en 0x0b05 8 +- b enable 0 +single_defect_correct_en 0x0b06 8 +- b enable 0 +dynamic_couplet_correct_en 0x0b08 8 +- b enable 0 +combined_defect_correct_en 0x0b0a 8 +- b enable 0 +module_specific_correction_en 0x0b0c 8 +- b enable 0 +dynamic_triplet_defect_correct_en 0x0b13 8 +- b enable 0 +NF_ctrl 0x0b15 8 +- b luma 0 +- b chroma 1 +- b combined 2 + +# optical black pixel readout registers +OB_readout_control 0x0b30 8 +- b enable 0 +- b interleaving 1 +OB_virtual_channel 0x0b31 8 +OB_DT 0x0b32 8 +OB_data_format 0x0b33 8 + +# color temperature feedback registers +color_temperature 0x0b8c 16 +absolute_gain_greenr 0x0b8e 16 +absolute_gain_red 0x0b90 16 +absolute_gain_blue 0x0b92 16 +absolute_gain_greenb 0x0b94 16 + +# cfa conversion registers +CFA_conversion_ctrl 0x0ba0 v1.1 +- b bayer_conversion_enable 0 + +# flash strobe and sa strobe control registers +flash_strobe_adjustment 0x0c12 8 +flash_strobe_start_point 0x0c14 16 +tflash_strobe_delay_rs_ctrl 0x0c16 16 +tflash_strobe_width_high_rs_ctrl 0x0c18 16 +flash_mode_rs 0x0c1a 8 +- b continuous 0 +- b truncate 1 +- b async 3 +flash_trigger_rs 0x0c1b 8 +flash_status 0x0c1c 8 +- b retimed 0 +sa_strobe_mode 0x0c1d 8 +- b continuous 0 +- b truncate 1 +- b async 3 +- b adjust_edge 4 +sa_strobe_start_point 0x0c1e 16 +tsa_strobe_delay_ctrl 0x0c20 16 +tsa_strobe_width_ctrl 0x0c22 16 +sa_strobe_trigger 0x0c24 8 +sa_strobe_status 0x0c25 8 +- b retimed 0 +tSA_strobe_re_delay_ctrl 0x0c30 16 +tSA_strobe_fe_delay_ctrl 0x0c32 16 + +# pdaf control registers +PDAF_ctrl 0x0d00 16 +- b enable 0 +- b processed 1 +- b interleaved 2 +- b visible_pdaf_correction 3 +PDAF_VC 0x0d02 8 +PDAF_DT 0x0d03 8 +pd_x_addr_start 0x0d04 16 +pd_y_addr_start 0x0d06 16 +pd_x_addr_end 0x0d08 16 +pd_y_addr_end 0x0d0a 16 + +# bracketing interface configuration registers +bracketing_LUT_ctrl 0x0e00 8 +bracketing_LUT_mode 0x0e01 8 +- b continue_streaming 0 +- b loop_mode 1 +bracketing_LUT_entry_ctrl 0x0e02 8 +bracketing_LUT_frame(n) 0x0e10 v1.1 f +- l n 0 0xef 1 + +# integration time and gain parameter limit registers +integration_time_capability 0x1000 16 +- b fine 0 +coarse_integration_time_min 0x1004 16 +coarse_integration_time_max_margin 0x1006 16 +fine_integration_time_min 0x1008 16 +fine_integration_time_max_margin 0x100a 16 + +# digital gain parameter limit registers +digital_gain_capability 0x1081 +- e none 0 +- e global 2 +digital_gain_min 0x1084 16 +digital_gain_max 0x1086 16 +digital_gain_step_size 0x1088 16 + +# data pedestal capability registers +Pedestal_capability 0x10e0 8 v1.1 + +# adc capability registers +ADC_capability 0x10f0 8 +- b bit_depth_ctrl 0 +ADC_bit_depth_capability 0x10f4 32 v1.1 + +# video timing parameter limit registers +min_ext_clk_freq_mhz 0x1100 32 float_ireal +max_ext_clk_freq_mhz 0x1104 32 float_ireal +min_pre_pll_clk_div 0x1108 16 +# min_vt_pre_pll_clk_div 0x1108 16 +max_pre_pll_clk_div 0x110a 16 +# max_vt_pre_pll_clk_div 0x110a 16 +min_pll_ip_clk_freq_mhz 0x110c 32 float_ireal +# min_vt_pll_ip_clk_freq_mhz 0x110c 32 float_ireal +max_pll_ip_clk_freq_mhz 0x1110 32 float_ireal +# max_vt_pll_ip_clk_freq_mhz 0x1110 32 float_ireal +min_pll_multiplier 0x1114 16 +# min_vt_pll_multiplier 0x1114 16 +max_pll_multiplier 0x1116 16 +# max_vt_pll_multiplier 0x1116 16 +min_pll_op_clk_freq_mhz 0x1118 32 float_ireal +max_pll_op_clk_freq_mhz 0x111c 32 float_ireal + +# video timing set-up capability registers +min_vt_sys_clk_div 0x1120 16 +max_vt_sys_clk_div 0x1122 16 +min_vt_sys_clk_freq_mhz 0x1124 32 float_ireal +max_vt_sys_clk_freq_mhz 0x1128 32 float_ireal +min_vt_pix_clk_freq_mhz 0x112c 32 float_ireal +max_vt_pix_clk_freq_mhz 0x1130 32 float_ireal +min_vt_pix_clk_div 0x1134 16 +max_vt_pix_clk_div 0x1136 16 +clock_calculation 0x1138 +- b lane_speed 0 +- b link_decoupled 1 +- b dual_pll_op_sys_ddr 2 +- b dual_pll_op_pix_ddr 3 +num_of_vt_lanes 0x1139 +num_of_op_lanes 0x113a +op_bits_per_lane 0x113b 8 v1.1 + +# frame timing parameter limits +min_frame_length_lines 0x1140 16 +max_frame_length_lines 0x1142 16 +min_line_length_pck 0x1144 16 +max_line_length_pck 0x1146 16 +min_line_blanking_pck 0x1148 16 +min_frame_blanking_lines 0x114a 16 +min_line_length_pck_step_size 0x114c +timing_mode_capability 0x114d +- b auto_frame_length 0 +- b rolling_shutter_manual_readout 2 +- b delayed_exposure_start 3 +- b manual_exposure_embedded_data 4 +frame_margin_max_value 0x114e 16 +frame_margin_min_value 0x1150 +gain_delay_type 0x1151 +- e fixed 0 +- e variable 1 + +# output clock set-up capability registers +min_op_sys_clk_div 0x1160 16 +max_op_sys_clk_div 0x1162 16 +min_op_sys_clk_freq_mhz 0x1164 32 float_ireal +max_op_sys_clk_freq_mhz 0x1168 32 float_ireal +min_op_pix_clk_div 0x116c 16 +max_op_pix_clk_div 0x116e 16 +min_op_pix_clk_freq_mhz 0x1170 32 float_ireal +max_op_pix_clk_freq_mhz 0x1174 32 float_ireal + +# image size parameter limit registers +x_addr_min 0x1180 16 +y_addr_min 0x1182 16 +x_addr_max 0x1184 16 +y_addr_max 0x1186 16 +min_x_output_size 0x1188 16 +min_y_output_size 0x118a 16 +max_x_output_size 0x118c 16 +max_y_output_size 0x118e 16 + +x_addr_start_div_constant 0x1190 v1.1 +y_addr_start_div_constant 0x1191 v1.1 +x_addr_end_div_constant 0x1192 v1.1 +y_addr_end_div_constant 0x1193 v1.1 +x_size_div 0x1194 v1.1 +y_size_div 0x1195 v1.1 +x_output_div 0x1196 v1.1 +y_output_div 0x1197 v1.1 +non_flexible_resolution_support 0x1198 v1.1 +- b new_pix_addr 0 +- b new_output_res 1 +- b output_crop_no_pad 2 +- b output_size_lane_dep 3 + +min_op_pre_pll_clk_div 0x11a0 16 +max_op_pre_pll_clk_div 0x11a2 16 +min_op_pll_ip_clk_freq_mhz 0x11a4 32 float_ireal +max_op_pll_ip_clk_freq_mhz 0x11a8 32 float_ireal +min_op_pll_multiplier 0x11ac 16 +max_op_pll_multiplier 0x11ae 16 +min_op_pll_op_clk_freq_mhz 0x11b0 32 float_ireal +max_op_pll_op_clk_freq_mhz 0x11b4 32 float_ireal +clock_tree_pll_capability 0x11b8 8 +- b dual_pll 0 +- b single_pll 1 +- b ext_divider 2 +- b flexible_op_pix_clk_div 3 +clock_capa_type_capability 0x11b9 v1.1 +- b ireal 0 + +# sub-sampling parameters limit registers +min_even_inc 0x11c0 16 +min_odd_inc 0x11c2 16 +max_even_inc 0x11c4 16 +max_odd_inc 0x11c6 16 +aux_subsamp_capability 0x11c8 v1.1 +- b factor_power_of_2 1 +aux_subsamp_mono_capability 0x11c9 v1.1 +- b factor_power_of_2 1 +monochrome_capability 0x11ca v1.1 +- e inc_odd 0 +- e inc_even 1 +pixel_readout_capability 0x11cb v1.1 +- e bayer 0 +- e monochrome 1 +- e bayer_and_mono 2 +min_even_inc_mono 0x11cc 16 v1.1 +max_even_inc_mono 0x11ce 16 v1.1 +min_odd_inc_mono 0x11d0 16 v1.1 +max_odd_inc_mono 0x11d2 16 v1.1 +min_even_inc_bc2 0x11d4 16 v1.1 +max_even_inc_bc2 0x11d6 16 v1.1 +min_odd_inc_bc2 0x11d8 16 v1.1 +max_odd_inc_bc2 0x11da 16 v1.1 +min_even_inc_mono_bc2 0x11dc 16 v1.1 +max_even_inc_mono_bc2 0x11de 16 v1.1 +min_odd_inc_mono_bc2 0x11f0 16 v1.1 +max_odd_inc_mono_bc2 0x11f2 16 v1.1 + +# image scaling limit parameters +scaling_capability 0x1200 16 +- e none 0 +- e horizontal 1 +- e reserved 2 +scaler_m_min 0x1204 16 +scaler_m_max 0x1206 16 +scaler_n_min 0x1208 16 +scaler_n_max 0x120a 16 +digital_crop_capability 0x120e +- e none 0 +- e input_crop 1 + +# hdr limit registers +hdr_capability_1 0x1210 +- b 2x2_binning 0 +- b combined_analog_gain 1 +- b separate_analog_gain 2 +- b upscaling 3 +- b reset_sync 4 +- b direct_short_exp_timing 5 +- b direct_short_exp_synthesis 6 +min_hdr_bit_depth 0x1211 +hdr_resolution_sub_types 0x1212 +hdr_resolution_sub_type(n) 0x1213 +- l n 0 1 1 +- f row 0 3 +- f column 4 7 +hdr_capability_2 0x121b +- b combined_digital_gain 0 +- b separate_digital_gain 1 +- b timing_mode 3 +- b synthesis_mode 4 +max_hdr_bit_depth 0x121c + +# usl capability register +usl_support_capability 0x1230 v1.1 +- b clock_tree 0 +- b rev_clock_tree 1 +- b rev_clock_calc 2 +usl_clock_mode_d_capability 0x1231 v1.1 +- b cont_clock_standby 0 +- b cont_clock_vblank 1 +- b cont_clock_hblank 2 +- b noncont_clock_standby 3 +- b noncont_clock_vblank 4 +- b noncont_clock_hblank 5 +min_op_sys_clk_div_rev 0x1234 v1.1 +max_op_sys_clk_div_rev 0x1236 v1.1 +min_op_pix_clk_div_rev 0x1238 v1.1 +max_op_pix_clk_div_rev 0x123a v1.1 +min_op_sys_clk_freq_rev_mhz 0x123c 32 v1.1 float_ireal +max_op_sys_clk_freq_rev_mhz 0x1240 32 v1.1 float_ireal +min_op_pix_clk_freq_rev_mhz 0x1244 32 v1.1 float_ireal +max_op_pix_clk_freq_rev_mhz 0x1248 32 v1.1 float_ireal +max_bitrate_rev_d_mode_mbps 0x124c 32 v1.1 ireal +max_symrate_rev_c_mode_msps 0x1250 32 v1.1 ireal + +# image compression capability registers +compression_capability 0x1300 +- b dpcm_pcm_simple 0 + +# test mode capability registers +test_mode_capability 0x1310 16 +- b solid_color 0 +- b color_bars 1 +- b fade_to_grey 2 +- b pn9 3 +- b color_tile 5 +pn9_data_format1 0x1312 +pn9_data_format2 0x1313 +pn9_data_format3 0x1314 +pn9_data_format4 0x1315 +pn9_misc_capability 0x1316 +- f num_pixels 0 2 +- b compression 3 +test_pattern_capability 0x1317 v1.1 +- b no_repeat 1 +pattern_size_div_m1 0x1318 v1.1 + +# fifo capability registers +fifo_support_capability 0x1502 +- e none 0 +- e derating 1 +- e derating_overrating 2 + +# csi-2 capability registers +phy_ctrl_capability 0x1600 +- b auto_phy_ctl 0 +- b ui_phy_ctl 1 +- b dphy_time_ui_reg_1_ctl 2 +- b dphy_time_ui_reg_2_ctl 3 +- b dphy_time_ctl 4 +- b dphy_ext_time_ui_reg_1_ctl 5 +- b dphy_ext_time_ui_reg_2_ctl 6 +- b dphy_ext_time_ctl 7 +csi_dphy_lane_mode_capability 0x1601 +- b 1_lane 0 +- b 2_lane 1 +- b 3_lane 2 +- b 4_lane 3 +- b 5_lane 4 +- b 6_lane 5 +- b 7_lane 6 +- b 8_lane 7 +csi_signaling_mode_capability 0x1602 +- b csi_dphy 2 +- b csi_cphy 3 +fast_standby_capability 0x1603 +- e no_frame_truncation 0 +- e frame_truncation 1 +csi_address_control_capability 0x1604 +- b cci_addr_change 0 +- b 2nd_cci_addr 1 +- b sw_changeable_2nd_cci_addr 2 +data_type_capability 0x1605 +- b dpcm_programmable 0 +- b bottom_embedded_dt_programmable 1 +- b bottom_embedded_vc_programmable 2 +- b ext_vc_range 3 +csi_cphy_lane_mode_capability 0x1606 +- b 1_lane 0 +- b 2_lane 1 +- b 3_lane 2 +- b 4_lane 3 +- b 5_lane 4 +- b 6_lane 5 +- b 7_lane 6 +- b 8_lane 7 +emb_data_capability 0x1607 v1.1 +- b two_bytes_per_raw16 0 +- b two_bytes_per_raw20 1 +- b two_bytes_per_raw24 2 +- b no_one_byte_per_raw16 3 +- b no_one_byte_per_raw20 4 +- b no_one_byte_per_raw24 5 +max_per_lane_bitrate_lane_d_mode_mbps(n) 0x1608 32 ireal +- l n 0 7 4 4,0x32 +temp_sensor_capability 0x1618 +- b supported 0 +- b CCS_format 1 +- b reset_0x80 2 +max_per_lane_bitrate_lane_c_mode_mbps(n) 0x161a 32 ireal +- l n 0 7 4 4,0x30 +dphy_equalization_capability 0x162b +- b equalization_ctrl 0 +- b eq1 1 +- b eq2 2 +cphy_equalization_capability 0x162c +- b equalization_ctrl 0 +dphy_preamble_capability 0x162d +- b preamble_seq_ctrl 0 +dphy_ssc_capability 0x162e +- b supported 0 +cphy_calibration_capability 0x162f +- b manual 0 +- b manual_streaming 1 +- b format_1_ctrl 2 +- b format_2_ctrl 3 +- b format_3_ctrl 4 +dphy_calibration_capability 0x1630 +- b manual 0 +- b manual_streaming 1 +- b alternate_seq 2 +phy_ctrl_capability_2 0x1631 +- b tgr_length 0 +- b tgr_preamble_prog_seq 1 +- b extra_cphy_manual_timing 2 +- b clock_based_manual_cdphy 3 +- b clock_based_manual_dphy 4 +- b clock_based_manual_cphy 5 +- b manual_lp_dphy 6 +- b manual_lp_cphy 7 +lrte_cphy_capability 0x1632 +- b pdq_short 0 +- b spacer_short 1 +- b pdq_long 2 +- b spacer_long 3 +- b spacer_no_pdq 4 +lrte_dphy_capability 0x1633 +- b pdq_short_opt1 0 +- b spacer_short_opt1 1 +- b pdq_long_opt1 2 +- b spacer_long_opt1 3 +- b spacer_short_opt2 4 +- b spacer_long_opt2 5 +- b spacer_no_pdq_opt1 6 +- b spacer_variable_opt2 7 +alps_capability_dphy 0x1634 +- e lvlp_not_supported 0 0x3 +- e lvlp_supported 1 0x3 +- e controllable_lvlp 2 0x3 +alps_capability_cphy 0x1635 +- e lvlp_not_supported 0 0x3 +- e lvlp_supported 1 0x3 +- e controllable_lvlp 2 0x3 +- e alp_not_supported 0xc 0xc +- e alp_supported 0xd 0xc +- e controllable_alp 0xe 0xc +scrambling_capability 0x1636 +- b scrambling_supported 0 +- f max_seeds_per_lane_c 1 2 +- e 1 0 +- e 4 3 +- f num_seed_regs 3 5 +- e 0 0 +- e 1 1 +- e 4 4 +- b num_seed_per_lane 6 +dphy_manual_constant 0x1637 +cphy_manual_constant 0x1638 +CSI2_interface_capability_misc 0x1639 v1.1 +- b eotp_short_pkt_opt2 0 +PHY_ctrl_capability_3 0x165c v1.1 +- b dphy_timing_not_multiple 0 +- b dphy_min_timing_value_1 1 +- b twakeup_supported 2 +- b tinit_supported 3 +- b ths_exit_supported 4 +- b cphy_timing_not_multiple 5 +- b cphy_min_timing_value_1 6 +dphy_sf 0x165d v1.1 +cphy_sf 0x165e v1.1 +- f twakeup 0 3 +- f tinit 4 7 +dphy_limits_1 0x165f v1.1 +- f ths_prepare 0 3 +- f ths_zero 4 7 +dphy_limits_2 0x1660 v1.1 +- f ths_trail 0 3 +- f tclk_trail_min 4 7 +dphy_limits_3 0x1661 v1.1 +- f tclk_prepare 0 3 +- f tclk_zero 4 7 +dphy_limits_4 0x1662 v1.1 +- f tclk_post 0 3 +- f tlpx 4 7 +dphy_limits_5 0x1663 v1.1 +- f ths_exit 0 3 +- f twakeup 4 7 +dphy_limits_6 0x1664 v1.1 +- f tinit 0 3 +cphy_limits_1 0x1665 v1.1 +- f t3_prepare_max 0 3 +- f t3_lpx_max 4 7 +cphy_limits_2 0x1666 v1.1 +- f ths_exit_max 0 3 +- f twakeup_max 4 7 +cphy_limits_3 0x1667 v1.1 +- f tinit_max 0 3 + +# binning capability registers +min_frame_length_lines_bin 0x1700 16 +max_frame_length_lines_bin 0x1702 16 +min_line_length_pck_bin 0x1704 16 +max_line_length_pck_bin 0x1706 16 +min_line_blanking_pck_bin 0x1708 16 +fine_integration_time_min_bin 0x170a 16 +fine_integration_time_max_margin_bin 0x170c 16 +binning_capability 0x1710 +- e unsupported 0 +- e binning_then_subsampling 1 +- e subsampling_then_binning 2 +binning_weighting_capability 0x1711 +- b averaged 0 +- b summed 1 +- b bayer_corrected 2 +- b module_specific_weight 3 +binning_sub_types 0x1712 +binning_sub_type(n) 0x1713 +- l n 0 63 1 +- f row 0 3 +- f column 4 7 +binning_weighting_mono_capability 0x1771 v1.1 +- b averaged 0 +- b summed 1 +- b bayer_corrected 2 +- b module_specific_weight 3 +binning_sub_types_mono 0x1772 v1.1 +binning_sub_type_mono(n) 0x1773 v1.1 f +- l n 0 63 1 + +# data transfer interface capability registers +data_transfer_if_capability 0x1800 +- b supported 0 +- b polling 2 + +# sensor correction capability registers +shading_correction_capability 0x1900 +- b color_shading 0 +- b luminance_correction 1 +green_imbalance_capability 0x1901 +- b supported 0 +module_specific_correction_capability 0x1903 +defect_correction_capability 0x1904 16 +- b mapped_defect 0 +- b dynamic_couplet 2 +- b dynamic_single 5 +- b combined_dynamic 8 +defect_correction_capability_2 0x1906 16 +- b dynamic_triplet 3 +nf_capability 0x1908 +- b luma 0 +- b chroma 1 +- b combined 2 + +# optical black readout capability registers +ob_readout_capability 0x1980 +- b controllable_readout 0 +- b visible_pixel_readout 1 +- b different_vc_readout 2 +- b different_dt_readout 3 +- b prog_data_format 4 + +# color feedback capability registers +color_feedback_capability 0x1987 +- b kelvin 0 +- b awb_gain 1 + +# cfa pattern capability registers +CFA_pattern_capability 0x1990 v1.1 +- e bayer 0 +- e monochrome 1 +- e 4x4_quad_bayer 2 +- e vendor_specific 3 +CFA_pattern_conversion_capability 0x1991 v1.1 +- b bayer 0 + +# timer capability registers +flash_mode_capability 0x1a02 +- b single_strobe 0 +sa_strobe_mode_capability 0x1a03 +- b fixed_width 0 +- b edge_ctrl 1 + +# soft reset capability registers +reset_max_delay 0x1a10 v1.1 +reset_min_time 0x1a11 v1.1 + +# pdaf capability registers +pdaf_capability_1 0x1b80 +- b supported 0 +- b processed_bottom_embedded 1 +- b processed_interleaved 2 +- b raw_bottom_embedded 3 +- b raw_interleaved 4 +- b visible_pdaf_correction 5 +- b vc_interleaving 6 +- b dt_interleaving 7 +pdaf_capability_2 0x1b81 +- b ROI 0 +- b after_digital_crop 1 +- b ctrl_retimed 2 + +# bracketing interface capability registers +bracketing_lut_capability_1 0x1c00 +- b coarse_integration 0 +- b global_analog_gain 1 +- b flash 4 +- b global_digital_gain 5 +- b alternate_global_analog_gain 6 +bracketing_lut_capability_2 0x1c01 +- b single_bracketing_mode 0 +- b looped_bracketing_mode 1 +bracketing_lut_size 0x1c02 diff --git a/Documentation/driver-api/media/drivers/ccs/ccs.rst b/Documentation/driver-api/media/drivers/ccs/ccs.rst new file mode 100644 index 0000000000..7389204afc --- /dev/null +++ b/Documentation/driver-api/media/drivers/ccs/ccs.rst @@ -0,0 +1,117 @@ +.. SPDX-License-Identifier: GPL-2.0-only OR BSD-3-Clause + +.. include:: <isonum.txt> + +MIPI CCS camera sensor driver +============================= + +The MIPI CCS camera sensor driver is a generic driver for `MIPI CCS +<https://www.mipi.org/specifications/camera-command-set>`_ compliant +camera sensors. It exposes three sub-devices representing the pixel array, +the binner and the scaler. + +As the capabilities of individual devices vary, the driver exposes +interfaces based on the capabilities that exist in hardware. + +Pixel Array sub-device +---------------------- + +The pixel array sub-device represents the camera sensor's pixel matrix, as well +as analogue crop functionality present in many compliant devices. The analogue +crop is configured using the ``V4L2_SEL_TGT_CROP`` on the source pad (0) of the +entity. The size of the pixel matrix can be obtained by getting the +``V4L2_SEL_TGT_NATIVE_SIZE`` target. + +Binner +------ + +The binner sub-device represents the binning functionality on the sensor. For +that purpose, selection target ``V4L2_SEL_TGT_COMPOSE`` is supported on the +sink pad (0). + +Additionally, if a device has no scaler or digital crop functionality, the +source pad (1) expses another digital crop selection rectangle that can only +crop at the end of the lines and frames. + +Scaler +------ + +The scaler sub-device represents the digital crop and scaling functionality of +the sensor. The V4L2 selection target ``V4L2_SEL_TGT_CROP`` is used to +configure the digital crop on the sink pad (0) when digital crop is supported. +Scaling is configured using selection target ``V4L2_SEL_TGT_COMPOSE`` on the +sink pad (0) as well. + +Additionally, if the scaler sub-device exists, its source pad (1) exposes +another digital crop selection rectangle that can only crop at the end of the +lines and frames. + +Digital and analogue crop +------------------------- + +Digital crop functionality is referred to as cropping that effectively works by +dropping some data on the floor. Analogue crop, on the other hand, means that +the cropped information is never retrieved. In case of camera sensors, the +analogue data is never read from the pixel matrix that are outside the +configured selection rectangle that designates crop. The difference has an +effect in device timing and likely also in power consumption. + +CCS static data +--------------- + +The MIPI CCS driver supports CCS static data for all compliant devices, +including not just those compliant with CCS 1.1 but also CCS 1.0 and SMIA(++). +For CCS the file names are formed as + + ccs/ccs-sensor-vvvv-mmmm-rrrr.fw (sensor) and + ccs/ccs-module-vvvv-mmmm-rrrr.fw (module). + +For SMIA++ compliant devices the corresponding file names are + + ccs/smiapp-sensor-vv-mmmm-rr.fw (sensor) and + ccs/smiapp-module-vv-mmmm-rrrr.fw (module). + +For SMIA (non-++) compliant devices the static data file name is + + ccs/smia-sensor-vv-mmmm-rr.fw (sensor). + +vvvv or vv denotes MIPI and SMIA manufacturer IDs respectively, mmmm model ID +and rrrr or rr revision number. + +Register definition generator +----------------------------- + +The ccs-regs.asc file contains MIPI CCS register definitions that are used +to produce C source code files for definitions that can be better used by +programs written in C language. As there are many dependencies between the +produced files, please do not modify them manually as it's error-prone and +in vain, but instead change the script producing them. + +Usage +~~~~~ + +Conventionally the script is called this way to update the CCS driver +definitions: + +.. code-block:: none + + $ Documentation/driver-api/media/drivers/ccs/mk-ccs-regs -k \ + -e drivers/media/i2c/ccs/ccs-regs.h \ + -L drivers/media/i2c/ccs/ccs-limits.h \ + -l drivers/media/i2c/ccs/ccs-limits.c \ + -c Documentation/driver-api/media/drivers/ccs/ccs-regs.asc + +CCS PLL calculator +================== + +The CCS PLL calculator is used to compute the PLL configuration, given sensor's +capabilities as well as board configuration and user specified configuration. As +the configuration space that encompasses all these configurations is vast, the +PLL calculator isn't entirely trivial. Yet it is relatively simple to use for a +driver. + +The PLL model implemented by the PLL calculator corresponds to MIPI CCS 1.1. + +.. kernel-doc:: drivers/media/i2c/ccs-pll.h + +**Copyright** |copy| 2020 Intel Corporation diff --git a/Documentation/driver-api/media/drivers/ccs/mk-ccs-regs b/Documentation/driver-api/media/drivers/ccs/mk-ccs-regs new file mode 100755 index 0000000000..2a4edc7e05 --- /dev/null +++ b/Documentation/driver-api/media/drivers/ccs/mk-ccs-regs @@ -0,0 +1,434 @@ +#!/usr/bin/perl -w +# SPDX-License-Identifier: GPL-2.0-only OR BSD-3-Clause +# Copyright (C) 2019--2020 Intel Corporation + +use Getopt::Long qw(:config no_ignore_case); +use File::Basename; + +my $ccsregs = "ccs-regs.asc"; +my $header; +my $regarray; +my $limitc; +my $limith; +my $kernel; +my $help; + +GetOptions("ccsregs|c=s" => \$ccsregs, + "header|e=s" => \$header, + "regarray|r=s" => \$regarray, + "limitc|l=s" => \$limitc, + "limith|L=s" => \$limith, + "kernel|k" => \$kernel, + "help|h" => \$help) or die "can't parse options"; + +$help = 1 if ! defined $header || ! defined $limitc || ! defined $limith; + +if (defined $help) { + print <<EOH +$0 - Create CCS register definitions for C + +usage: $0 -c ccs-regs.asc -e header -r regarray -l limit-c -L limit-header [-k] + + -c ccs register file + -e header file name + -r register description array file name + -l limit and capability array file name + -L limit and capability header file name + -k generate files for kernel space consumption +EOH + ; + exit 0; +} + +my $lh_hdr = ! defined $kernel + ? '#include "ccs-os.h"' . "\n" + : "#include <linux/bits.h>\n#include <linux/types.h>\n"; +my $uint32_t = ! defined $kernel ? 'uint32_t' : 'u32'; +my $uint16_t = ! defined $kernel ? 'uint16_t' : 'u16'; + +open(my $R, "< $ccsregs") or die "can't open $ccsregs"; + +open(my $H, "> $header") or die "can't open $header"; +my $A; +if (defined $regarray) { + open($A, "> $regarray") or die "can't open $regarray"; +} +open(my $LC, "> $limitc") or die "can't open $limitc"; +open(my $LH, "> $limith") or die "can't open $limith"; + +my %this; + +sub is_limit_reg($) { + my $addr = hex $_[0]; + + return 0 if $addr < 0x40; # weed out status registers + return 0 if $addr >= 0x100 && $addr < 0xfff; # weed out configuration registers + + return 1; +} + +my $uc_header = basename uc $header; +$uc_header =~ s/[^A-Z0-9]/_/g; + +my $copyright = "/* Copyright (C) 2019--2020 Intel Corporation */\n"; +my $license = "SPDX-License-Identifier: GPL-2.0-only OR BSD-3-Clause"; +my $note = "/*\n * Generated by $0;\n * do not modify.\n */\n"; + +for my $fh ($A, $LC) { + print $fh "// $license\n$copyright$note\n" if defined $fh; +} + +for my $fh ($H, $LH) { + print $fh "/* $license */\n$copyright$note\n"; +} + +sub bit_def($) { + my $bit = shift @_; + + return "BIT($bit)" if defined $kernel; + return "(1U << $bit)" if $bit =~ /^[a-zA-Z0-9_]+$/; + return "(1U << ($bit))"; +} + +print $H <<EOF +#ifndef __${uc_header}__ +#define __${uc_header}__ + +EOF + ; + +print $H "#include <linux/bits.h>\n\n" if defined $kernel; + +print $H <<EOF +#define CCS_FL_BASE 16 +EOF + ; + +print $H "#define CCS_FL_16BIT " . bit_def("CCS_FL_BASE") . "\n"; +print $H "#define CCS_FL_32BIT " . bit_def("CCS_FL_BASE + 1") . "\n"; +print $H "#define CCS_FL_FLOAT_IREAL " . bit_def("CCS_FL_BASE + 2") . "\n"; +print $H "#define CCS_FL_IREAL " . bit_def("CCS_FL_BASE + 3") . "\n"; + +print $H <<EOF +#define CCS_R_ADDR(r) ((r) & 0xffff) + +EOF + ; + +print $A <<EOF +#include <stdint.h> +#include <stdio.h> +#include "ccs-extra.h" +#include "ccs-regs.h" + +EOF + if defined $A; + +my $uc_limith = basename uc $limith; +$uc_limith =~ s/[^A-Z0-9]/_/g; + +print $LH <<EOF +#ifndef __${uc_limith}__ +#define __${uc_limith}__ + +$lh_hdr +struct ccs_limit { + $uint32_t reg; + $uint16_t size; + $uint16_t flags; + const char *name; +}; + +EOF + ; +print $LH "#define CCS_L_FL_SAME_REG " . bit_def(0) . "\n\n"; + +print $LH <<EOF +extern const struct ccs_limit ccs_limits[]; + +EOF + ; + +print $LC <<EOF +#include "ccs-limits.h" +#include "ccs-regs.h" + +const struct ccs_limit ccs_limits[] = { +EOF + ; + +my $limitcount = 0; +my $argdescs; +my $reglist = "const struct ccs_reg_desc ccs_reg_desc[] = {\n"; + +sub name_split($$) { + my ($name, $addr) = @_; + my $args; + + $name =~ /([^\(]+?)(\(.*)/; + ($name, $args) = ($1, $2); + $args = [split /,\s*/, $args]; + foreach my $t (@$args) { + $t =~ s/[\(\)]//g; + $t =~ s/\//\\\//g; + } + + return ($name, $addr, $args); +} + +sub tabconv($) { + $_ = shift; + + my @l = split "\n", $_; + + map { + s/ {8,8}/\t/g; + s/\t\K +//; + } @l; + + return (join "\n", @l) . "\n"; +} + +sub elem_size(@) { + my @flags = @_; + + return 2 if grep /^16$/, @flags; + return 4 if grep /^32$/, @flags; + return 1; +} + +sub arr_size($) { + my $this = $_[0]; + my $size = $this->{elsize}; + my $h = $this->{argparams}; + + foreach my $arg (@{$this->{args}}) { + my $apref = $h->{$arg}; + + $size *= $apref->{max} - $apref->{min} + 1; + } + + return $size; +} + +sub print_args($$$) { + my ($this, $postfix, $is_same_reg) = @_; + my ($args, $argparams, $name) = + ($this->{args}, $this->{argparams}, $this->{name}); + my $varname = "ccs_reg_arg_" . (lc $name) . $postfix; + my @mins; + my @sorted_args = @{$this->{sorted_args}}; + my $lim_arg; + my $size = arr_size($this); + + $argdescs .= "static const struct ccs_reg_arg " . $varname . "[] = {\n"; + + foreach my $sorted_arg (@sorted_args) { + push @mins, $argparams->{$sorted_arg}->{min}; + } + + foreach my $sorted_arg (@sorted_args) { + my $h = $argparams->{$sorted_arg}; + + $argdescs .= "\t{ \"$sorted_arg\", $h->{min}, $h->{max}, $h->{elsize} },\n"; + + $lim_arg .= defined $lim_arg ? ", $h->{min}" : "$h->{min}"; + } + + $argdescs .= "};\n\n"; + + $reglist .= "\t{ CCS_R_" . (uc $name) . "(" . (join ",", (@mins)) . + "), $size, sizeof($varname) / sizeof(*$varname)," . + " \"" . (lc $name) . "\", $varname },\n"; + + print $LC tabconv sprintf "\t{ CCS_R_" . (uc $name) . "($lim_arg), " . + $size . ", " . ($is_same_reg ? "CCS_L_FL_SAME_REG" : "0") . + ", \"$name" . (defined $this->{discontig} ? " $lim_arg" : "") . "\" },\n" + if is_limit_reg $this->{base_addr}; +} + +my $hdr_data; + +while (<$R>) { + chop; + s/^\s*//; + next if /^[#;]/ || /^$/; + if (s/^-\s*//) { + if (s/^b\s*//) { + my ($bit, $addr) = split /\t+/; + $bit = uc $bit; + $hdr_data .= sprintf "#define %-62s %s", "CCS_" . (uc ${this{name}}) ."_$bit", bit_def($addr) . "\n"; + } elsif (s/^f\s*//) { + s/[,\.-]/_/g; + my @a = split /\s+/; + my ($msb, $lsb, $this_field) = reverse @a; + @a = ( { "name" => "SHIFT", "addr" => $lsb, "fmt" => "%uU", }, + { "name" => "MASK", "addr" => (1 << ($msb + 1)) - 1 - ((1 << $lsb) - 1), "fmt" => "0x%" . join(".", ($this{"elsize"} >> 2) x 2) . "x" } ); + $this{"field"} = $this_field; + foreach my $ar (@a) { + #print $ar->{fmt}."\n"; + $hdr_data .= sprintf "#define %-62s " . $ar->{"fmt"} . "\n", "CCS_" . (uc $this{"name"}) . (defined $this_field ? "_" . uc $this_field : "") . "_" . $ar->{"name"}, $ar->{"addr"} . "\n"; + } + } elsif (s/^e\s*//) { + s/[,\.-]/_/g; + my ($enum, $addr) = split /\s+/; + $enum = uc $enum; + $hdr_data .= sprintf "#define %-62s %s", "CCS_" . (uc ${this{name}}) . (defined $this{"field"} ? "_" . uc $this{"field"} : "") ."_$enum", $addr . ($addr =~ /0x/i ? "" : "U") . "\n"; + } elsif (s/^l\s*//) { + my ($arg, $min, $max, $elsize, @discontig) = split /\s+/; + my $size; + + foreach my $num ($min, $max) { + $num = hex $num if $num =~ /0x/i; + } + + $hdr_data .= sprintf "#define %-62s %s", "CCS_LIM_" . (uc ${this{name}} . "_MIN_$arg"), $min . ($min =~ /0x/i ? "" : "U") . "\n"; + $hdr_data .= sprintf "#define %-62s %s", "CCS_LIM_" . (uc ${this{name}} . "_MAX_$arg"), $max . ($max =~ /0x/i ? "" : "U") . "\n"; + + my $h = $this{argparams}; + + $h->{$arg} = { "min" => $min, + "max" => $max, + "elsize" => $elsize =~ /^0x/ ? hex $elsize : $elsize, + "discontig" => \@discontig }; + + $this{discontig} = $arg if @discontig; + + next if $#{$this{args}} + 1 != scalar keys %{$this{argparams}}; + + my $reg_formula = "($this{addr}"; + my $lim_formula; + + foreach my $arg (@{$this{args}}) { + my $d = $h->{$arg}->{discontig}; + my $times = $h->{$arg}->{elsize} != 1 ? + " * " . $h->{$arg}->{elsize} : ""; + + if (@$d) { + my ($lim, $offset) = split /,/, $d->[0]; + + $reg_formula .= " + (($arg) < $lim ? ($arg)$times : $offset + (($arg) - $lim)$times)"; + } else { + $reg_formula .= " + ($arg)$times"; + } + + $lim_formula .= (defined $lim_formula ? " + " : "") . "($arg)$times"; + } + + $reg_formula .= ")\n"; + $lim_formula =~ s/^\(([a-z0-9]+)\)$/$1/i; + + print $H tabconv sprintf("#define %-62s %s", "CCS_R_" . (uc $this{name}) . + $this{arglist}, $reg_formula); + + print $H tabconv $hdr_data; + undef $hdr_data; + + # Sort arguments in descending order by size + @{$this{sorted_args}} = sort { + $h->{$a}->{elsize} <= $h->{$b}->{elsize} + } @{$this{args}}; + + if (defined $this{discontig}) { + my $da = $this{argparams}->{$this{discontig}}; + my ($first_discontig) = split /,/, $da->{discontig}->[0]; + my $max = $da->{max}; + + $da->{max} = $first_discontig - 1; + print_args(\%this, "", 0); + + $da->{min} = $da->{max} + 1; + $da->{max} = $max; + print_args(\%this, $first_discontig, 1); + } else { + print_args(\%this, "", 0); + } + + next unless is_limit_reg $this{base_addr}; + + print $LH tabconv sprintf "#define %-63s%s\n", + "CCS_L_" . (uc $this{name}) . "_OFFSET(" . + (join ", ", @{$this{args}}) . ")", "($lim_formula)"; + } + + if (! @{$this{args}}) { + print $H tabconv($hdr_data); + undef $hdr_data; + } + + next; + } + + my ($name, $addr, @flags) = split /\t+/, $_; + my $args = []; + + my $sp; + + ($name, $addr, $args) = name_split($name, $addr) if /\(.*\)/; + + $name =~ s/[,\.-]/_/g; + + my $flagstring = ""; + my $size = elem_size(@flags); + $flagstring .= "| CCS_FL_16BIT " if $size eq "2"; + $flagstring .= "| CCS_FL_32BIT " if $size eq "4"; + $flagstring .= "| CCS_FL_FLOAT_IREAL " if grep /^float_ireal$/, @flags; + $flagstring .= "| CCS_FL_IREAL " if grep /^ireal$/, @flags; + $flagstring =~ s/^\| //; + $flagstring =~ s/ $//; + $flagstring = "($flagstring)" if $flagstring =~ /\|/; + my $base_addr = $addr; + $addr = "($addr | $flagstring)" if $flagstring ne ""; + + my $arglist = @$args ? "(" . (join ", ", @$args) . ")" : ""; + $hdr_data .= sprintf "#define %-62s %s\n", "CCS_R_" . (uc $name), $addr + if !@$args; + + $name =~ s/\(.*//; + + %this = ( name => $name, + addr => $addr, + base_addr => $base_addr, + argparams => {}, + args => $args, + arglist => $arglist, + elsize => $size, + ); + + if (!@$args) { + $reglist .= "\t{ CCS_R_" . (uc $name) . ", 1, 0, \"" . (lc $name) . "\", NULL },\n"; + print $H tabconv $hdr_data; + undef $hdr_data; + + print $LC tabconv sprintf "\t{ CCS_R_" . (uc $name) . ", " . + $this{elsize} . ", 0, \"$name\" },\n" + if is_limit_reg $this{base_addr}; + } + + print $LH tabconv sprintf "#define %-63s%s\n", + "CCS_L_" . (uc $this{name}), $limitcount++ + if is_limit_reg $this{base_addr}; +} + +if (defined $A) { + print $A $argdescs, $reglist; + + print $A "\t{ 0 }\n"; + + print $A "};\n"; +} + +print $H "\n#endif /* __${uc_header}__ */\n"; + +print $LH tabconv sprintf "#define %-63s%s\n", "CCS_L_LAST", $limitcount; + +print $LH "\n#endif /* __${uc_limith}__ */\n"; + +print $LC "\t{ 0 } /* Guardian */\n"; +print $LC "};\n"; + +close($R); +close($H); +close($A) if defined $A; +close($LC); +close($LH); diff --git a/Documentation/driver-api/media/drivers/contributors.rst b/Documentation/driver-api/media/drivers/contributors.rst new file mode 100644 index 0000000000..f23b6e6faf --- /dev/null +++ b/Documentation/driver-api/media/drivers/contributors.rst @@ -0,0 +1,131 @@ +.. SPDX-License-Identifier: GPL-2.0 + +Contributors +============ + +.. note:: + + This documentation is outdated. There are several other DVB contributors + that aren't listed below. + +Thanks go to the following people for patches and contributions: + +- Michael Hunold <m.hunold@gmx.de> + + - for the initial saa7146 driver and its recent overhaul + +- Christian Theiss + + - for his work on the initial Linux DVB driver + +- Marcus Metzler <mocm@metzlerbros.de> and + Ralph Metzler <rjkm@metzlerbros.de> + + - for their continuing work on the DVB driver + +- Michael Holzt <kju@debian.org> + + - for his contributions to the dvb-net driver + +- Diego Picciani <d.picciani@novacomp.it> + + - for CyberLogin for Linux which allows logging onto EON + (in case you are wondering where CyberLogin is, EON changed its login + procedure and CyberLogin is no longer used.) + +- Martin Schaller <martin@smurf.franken.de> + + - for patching the cable card decoder driver + +- Klaus Schmidinger <Klaus.Schmidinger@cadsoft.de> + + - for various fixes regarding tuning, OSD and CI stuff and his work on VDR + +- Steve Brown <sbrown@cortland.com> + + - for his AFC kernel thread + +- Christoph Martin <martin@uni-mainz.de> + + - for his LIRC infrared handler + +- Andreas Oberritter <obi@linuxtv.org>, + Dennis Noermann <dennis.noermann@noernet.de>, + Felix Domke <tmbinc@elitedvb.net>, + Florian Schirmer <jolt@tuxbox.org>, + Ronny Strutz <3des@elitedvb.de>, + Wolfram Joost <dbox2@frokaschwei.de> + and all the other dbox2 people + + - for many bugfixes in the generic DVB Core, frontend drivers and + their work on the dbox2 port of the DVB driver + +- Oliver Endriss <o.endriss@gmx.de> + + - for many bugfixes + +- Andrew de Quincey <adq_dvb@lidskialf.net> + + - for the tda1004x frontend driver, and various bugfixes + +- Peter Schildmann <peter.schildmann@web.de> + + - for the driver for the Technisat SkyStar2 PCI DVB card + +- Vadim Catana <skystar@moldova.cc>, + Roberto Ragusa <r.ragusa@libero.it> and + Augusto Cardoso <augusto@carhil.net> + + - for all the work for the FlexCopII chipset by B2C2,Inc. + +- Davor Emard <emard@softhome.net> + + - for his work on the budget drivers, the demux code, + the module unloading problems, ... + +- Hans-Frieder Vogt <hfvogt@arcor.de> + + - for his work on calculating and checking the crc's for the + TechnoTrend/Hauppauge DEC driver firmware + +- Michael Dreher <michael@5dot1.de> and + Andreas 'randy' Weinberger + + - for the support of the Fujitsu-Siemens Activy budget DVB-S + +- Kenneth Aafløy <ke-aa@frisurf.no> + + - for adding support for Typhoon DVB-S budget card + +- Ernst Peinlich <e.peinlich@inode.at> + + - for tuning/DiSEqC support for the DEC 3000-s + +- Peter Beutner <p.beutner@gmx.net> + + - for the IR code for the ttusb-dec driver + +- Wilson Michaels <wilsonmichaels@earthlink.net> + + - for the lgdt330x frontend driver, and various bugfixes + +- Michael Krufky <mkrufky@linuxtv.org> + + - for maintaining v4l/dvb inter-tree dependencies + +- Taylor Jacob <rtjacob@earthlink.net> + + - for the nxt2002 frontend driver + +- Jean-Francois Thibert <jeanfrancois@sagetv.com> + + - for the nxt2004 frontend driver + +- Kirk Lapray <kirk.lapray@gmail.com> + + - for the or51211 and or51132 frontend drivers, and + for merging the nxt2002 and nxt2004 modules into a + single nxt200x frontend driver. + +(If you think you should be in this list, but you are not, drop a +line to the DVB mailing list) diff --git a/Documentation/driver-api/media/drivers/cx2341x-devel.rst b/Documentation/driver-api/media/drivers/cx2341x-devel.rst new file mode 100644 index 0000000000..97699df6ea --- /dev/null +++ b/Documentation/driver-api/media/drivers/cx2341x-devel.rst @@ -0,0 +1,3685 @@ +.. SPDX-License-Identifier: GPL-2.0 + +The cx2341x driver +================== + +Memory at cx2341x chips +----------------------- + +This section describes the cx2341x memory map and documents some of the +register space. + +.. note:: the memory long words are little-endian ('intel format'). + +.. warning:: + + This information was figured out from searching through the memory + and registers, this information may not be correct and is certainly + not complete, and was not derived from anything more than searching + through the memory space with commands like: + + .. code-block:: none + + ivtvctl -O min=0x02000000,max=0x020000ff + + So take this as is, I'm always searching for more stuff, it's a large + register space :-). + +Memory Map +~~~~~~~~~~ + +The cx2341x exposes its entire 64M memory space to the PCI host via the PCI BAR0 +(Base Address Register 0). The addresses here are offsets relative to the +address held in BAR0. + +.. code-block:: none + + 0x00000000-0x00ffffff Encoder memory space + 0x00000000-0x0003ffff Encode.rom + ???-??? MPEG buffer(s) + ???-??? Raw video capture buffer(s) + ???-??? Raw audio capture buffer(s) + ???-??? Display buffers (6 or 9) + + 0x01000000-0x01ffffff Decoder memory space + 0x01000000-0x0103ffff Decode.rom + ???-??? MPEG buffers(s) + 0x0114b000-0x0115afff Audio.rom (deprecated?) + + 0x02000000-0x0200ffff Register Space + +Registers +~~~~~~~~~ + +The registers occupy the 64k space starting at the 0x02000000 offset from BAR0. +All of these registers are 32 bits wide. + +.. code-block:: none + + DMA Registers 0x000-0xff: + + 0x00 - Control: + 0=reset/cancel, 1=read, 2=write, 4=stop + 0x04 - DMA status: + 1=read busy, 2=write busy, 4=read error, 8=write error, 16=link list error + 0x08 - pci DMA pointer for read link list + 0x0c - pci DMA pointer for write link list + 0x10 - read/write DMA enable: + 1=read enable, 2=write enable + 0x14 - always 0xffffffff, if set any lower instability occurs, 0x00 crashes + 0x18 - ?? + 0x1c - always 0x20 or 32, smaller values slow down DMA transactions + 0x20 - always value of 0x780a010a + 0x24-0x3c - usually just random values??? + 0x40 - Interrupt status + 0x44 - Write a bit here and shows up in Interrupt status 0x40 + 0x48 - Interrupt Mask + 0x4C - always value of 0xfffdffff, + if changed to 0xffffffff DMA write interrupts break. + 0x50 - always 0xffffffff + 0x54 - always 0xffffffff (0x4c, 0x50, 0x54 seem like interrupt masks, are + 3 processors on chip, Java ones, VPU, SPU, APU, maybe these are the + interrupt masks???). + 0x60-0x7C - random values + 0x80 - first write linked list reg, for Encoder Memory addr + 0x84 - first write linked list reg, for pci memory addr + 0x88 - first write linked list reg, for length of buffer in memory addr + (|0x80000000 or this for last link) + 0x8c-0xdc - rest of write linked list reg, 8 sets of 3 total, DMA goes here + from linked list addr in reg 0x0c, firmware must push through or + something. + 0xe0 - first (and only) read linked list reg, for pci memory addr + 0xe4 - first (and only) read linked list reg, for Decoder memory addr + 0xe8 - first (and only) read linked list reg, for length of buffer + 0xec-0xff - Nothing seems to be in these registers, 0xec-f4 are 0x00000000. + +Memory locations for Encoder Buffers 0x700-0x7ff: + +These registers show offsets of memory locations pertaining to each +buffer area used for encoding, have to shift them by <<1 first. + +- 0x07F8: Encoder SDRAM refresh +- 0x07FC: Encoder SDRAM pre-charge + +Memory locations for Decoder Buffers 0x800-0x8ff: + +These registers show offsets of memory locations pertaining to each +buffer area used for decoding, have to shift them by <<1 first. + +- 0x08F8: Decoder SDRAM refresh +- 0x08FC: Decoder SDRAM pre-charge + +Other memory locations: + +- 0x2800: Video Display Module control +- 0x2D00: AO (audio output?) control +- 0x2D24: Bytes Flushed +- 0x7000: LSB I2C write clock bit (inverted) +- 0x7004: LSB I2C write data bit (inverted) +- 0x7008: LSB I2C read clock bit +- 0x700c: LSB I2C read data bit +- 0x9008: GPIO get input state +- 0x900c: GPIO set output state +- 0x9020: GPIO direction (Bit7 (GPIO 0..7) - 0:input, 1:output) +- 0x9050: SPU control +- 0x9054: Reset HW blocks +- 0x9058: VPU control +- 0xA018: Bit6: interrupt pending? +- 0xA064: APU command + + +Interrupt Status Register +~~~~~~~~~~~~~~~~~~~~~~~~~ + +The definition of the bits in the interrupt status register 0x0040, and the +interrupt mask 0x0048. If a bit is cleared in the mask, then we want our ISR to +execute. + +- bit 31 Encoder Start Capture +- bit 30 Encoder EOS +- bit 29 Encoder VBI capture +- bit 28 Encoder Video Input Module reset event +- bit 27 Encoder DMA complete +- bit 24 Decoder audio mode change detection event (through event notification) +- bit 22 Decoder data request +- bit 20 Decoder DMA complete +- bit 19 Decoder VBI re-insertion +- bit 18 Decoder DMA err (linked-list bad) + +Missing documentation +--------------------- + +- Encoder API post(?) +- Decoder API post(?) +- Decoder VTRACE event + + +The cx2341x firmware upload +--------------------------- + +This document describes how to upload the cx2341x firmware to the card. + +How to find +~~~~~~~~~~~ + +See the web pages of the various projects that uses this chip for information +on how to obtain the firmware. + +The firmware stored in a Windows driver can be detected as follows: + +- Each firmware image is 256k bytes. +- The 1st 32-bit word of the Encoder image is 0x0000da7 +- The 1st 32-bit word of the Decoder image is 0x00003a7 +- The 2nd 32-bit word of both images is 0xaa55bb66 + +How to load +~~~~~~~~~~~ + +- Issue the FWapi command to stop the encoder if it is running. Wait for the + command to complete. +- Issue the FWapi command to stop the decoder if it is running. Wait for the + command to complete. +- Issue the I2C command to the digitizer to stop emitting VSYNC events. +- Issue the FWapi command to halt the encoder's firmware. +- Sleep for 10ms. +- Issue the FWapi command to halt the decoder's firmware. +- Sleep for 10ms. +- Write 0x00000000 to register 0x2800 to stop the Video Display Module. +- Write 0x00000005 to register 0x2D00 to stop the AO (audio output?). +- Write 0x00000000 to register 0xA064 to ping? the APU. +- Write 0xFFFFFFFE to register 0x9058 to stop the VPU. +- Write 0xFFFFFFFF to register 0x9054 to reset the HW blocks. +- Write 0x00000001 to register 0x9050 to stop the SPU. +- Sleep for 10ms. +- Write 0x0000001A to register 0x07FC to init the Encoder SDRAM's pre-charge. +- Write 0x80000640 to register 0x07F8 to init the Encoder SDRAM's refresh to 1us. +- Write 0x0000001A to register 0x08FC to init the Decoder SDRAM's pre-charge. +- Write 0x80000640 to register 0x08F8 to init the Decoder SDRAM's refresh to 1us. +- Sleep for 512ms. (600ms is recommended) +- Transfer the encoder's firmware image to offset 0 in Encoder memory space. +- Transfer the decoder's firmware image to offset 0 in Decoder memory space. +- Use a read-modify-write operation to Clear bit 0 of register 0x9050 to + re-enable the SPU. +- Sleep for 1 second. +- Use a read-modify-write operation to Clear bits 3 and 0 of register 0x9058 + to re-enable the VPU. +- Sleep for 1 second. +- Issue status API commands to both firmware images to verify. + + +How to call the firmware API +---------------------------- + +The preferred calling convention is known as the firmware mailbox. The +mailboxes are basically a fixed length array that serves as the call-stack. + +Firmware mailboxes can be located by searching the encoder and decoder memory +for a 16 byte signature. That signature will be located on a 256-byte boundary. + +Signature: + +.. code-block:: none + + 0x78, 0x56, 0x34, 0x12, 0x12, 0x78, 0x56, 0x34, + 0x34, 0x12, 0x78, 0x56, 0x56, 0x34, 0x12, 0x78 + +The firmware implements 20 mailboxes of 20 32-bit words. The first 10 are +reserved for API calls. The second 10 are used by the firmware for event +notification. + + ====== ================= + Index Name + ====== ================= + 0 Flags + 1 Command + 2 Return value + 3 Timeout + 4-19 Parameter/Result + ====== ================= + + +The flags are defined in the following table. The direction is from the +perspective of the firmware. + + ==== ========== ============================================ + Bit Direction Purpose + ==== ========== ============================================ + 2 O Firmware has processed the command. + 1 I Driver has finished setting the parameters. + 0 I Driver is using this mailbox. + ==== ========== ============================================ + +The command is a 32-bit enumerator. The API specifics may be found in this +chapter. + +The return value is a 32-bit enumerator. Only two values are currently defined: + +- 0=success +- -1=command undefined. + +There are 16 parameters/results 32-bit fields. The driver populates these fields +with values for all the parameters required by the call. The driver overwrites +these fields with result values returned by the call. + +The timeout value protects the card from a hung driver thread. If the driver +doesn't handle the completed call within the timeout specified, the firmware +will reset that mailbox. + +To make an API call, the driver iterates over each mailbox looking for the +first one available (bit 0 has been cleared). The driver sets that bit, fills +in the command enumerator, the timeout value and any required parameters. The +driver then sets the parameter ready bit (bit 1). The firmware scans the +mailboxes for pending commands, processes them, sets the result code, populates +the result value array with that call's return values and sets the call +complete bit (bit 2). Once bit 2 is set, the driver should retrieve the results +and clear all the flags. If the driver does not perform this task within the +time set in the timeout register, the firmware will reset that mailbox. + +Event notifications are sent from the firmware to the host. The host tells the +firmware which events it is interested in via an API call. That call tells the +firmware which notification mailbox to use. The firmware signals the host via +an interrupt. Only the 16 Results fields are used, the Flags, Command, Return +value and Timeout words are not used. + + +OSD firmware API description +---------------------------- + +.. note:: this API is part of the decoder firmware, so it's cx23415 only. + + + +CX2341X_OSD_GET_FRAMEBUFFER +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Enum: 65/0x41 + +Description +^^^^^^^^^^^ + +Return base and length of contiguous OSD memory. + +Result[0] +^^^^^^^^^ + +OSD base address + +Result[1] +^^^^^^^^^ + +OSD length + + + +CX2341X_OSD_GET_PIXEL_FORMAT +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Enum: 66/0x42 + +Description +^^^^^^^^^^^ + +Query OSD format + +Result[0] +^^^^^^^^^ + +0=8bit index +1=16bit RGB 5:6:5 +2=16bit ARGB 1:5:5:5 +3=16bit ARGB 1:4:4:4 +4=32bit ARGB 8:8:8:8 + + + +CX2341X_OSD_SET_PIXEL_FORMAT +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Enum: 67/0x43 + +Description +^^^^^^^^^^^ + +Assign pixel format + +Param[0] +^^^^^^^^ + +- 0=8bit index +- 1=16bit RGB 5:6:5 +- 2=16bit ARGB 1:5:5:5 +- 3=16bit ARGB 1:4:4:4 +- 4=32bit ARGB 8:8:8:8 + + + +CX2341X_OSD_GET_STATE +~~~~~~~~~~~~~~~~~~~~~ + +Enum: 68/0x44 + +Description +^^^^^^^^^^^ + +Query OSD state + +Result[0] +^^^^^^^^^ + +- Bit 0 0=off, 1=on +- Bits 1:2 alpha control +- Bits 3:5 pixel format + + + +CX2341X_OSD_SET_STATE +~~~~~~~~~~~~~~~~~~~~~ + +Enum: 69/0x45 + +Description +^^^^^^^^^^^ + +OSD switch + +Param[0] +^^^^^^^^ + +0=off, 1=on + + + +CX2341X_OSD_GET_OSD_COORDS +~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Enum: 70/0x46 + +Description +^^^^^^^^^^^ + +Retrieve coordinates of OSD area blended with video + +Result[0] +^^^^^^^^^ + +OSD buffer address + +Result[1] +^^^^^^^^^ + +Stride in pixels + +Result[2] +^^^^^^^^^ + +Lines in OSD buffer + +Result[3] +^^^^^^^^^ + +Horizontal offset in buffer + +Result[4] +^^^^^^^^^ + +Vertical offset in buffer + + + +CX2341X_OSD_SET_OSD_COORDS +~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Enum: 71/0x47 + +Description +^^^^^^^^^^^ + +Assign the coordinates of the OSD area to blend with video + +Param[0] +^^^^^^^^ + +buffer address + +Param[1] +^^^^^^^^ + +buffer stride in pixels + +Param[2] +^^^^^^^^ + +lines in buffer + +Param[3] +^^^^^^^^ + +horizontal offset + +Param[4] +^^^^^^^^ + +vertical offset + + + +CX2341X_OSD_GET_SCREEN_COORDS +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Enum: 72/0x48 + +Description +^^^^^^^^^^^ + +Retrieve OSD screen area coordinates + +Result[0] +^^^^^^^^^ + +top left horizontal offset + +Result[1] +^^^^^^^^^ + +top left vertical offset + +Result[2] +^^^^^^^^^ + +bottom right horizontal offset + +Result[3] +^^^^^^^^^ + +bottom right vertical offset + + + +CX2341X_OSD_SET_SCREEN_COORDS +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Enum: 73/0x49 + +Description +^^^^^^^^^^^ + +Assign the coordinates of the screen area to blend with video + +Param[0] +^^^^^^^^ + +top left horizontal offset + +Param[1] +^^^^^^^^ + +top left vertical offset + +Param[2] +^^^^^^^^ + +bottom left horizontal offset + +Param[3] +^^^^^^^^ + +bottom left vertical offset + + + +CX2341X_OSD_GET_GLOBAL_ALPHA +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Enum: 74/0x4A + +Description +^^^^^^^^^^^ + +Retrieve OSD global alpha + +Result[0] +^^^^^^^^^ + +global alpha: 0=off, 1=on + +Result[1] +^^^^^^^^^ + +bits 0:7 global alpha + + + +CX2341X_OSD_SET_GLOBAL_ALPHA +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Enum: 75/0x4B + +Description +^^^^^^^^^^^ + +Update global alpha + +Param[0] +^^^^^^^^ + +global alpha: 0=off, 1=on + +Param[1] +^^^^^^^^ + +global alpha (8 bits) + +Param[2] +^^^^^^^^ + +local alpha: 0=on, 1=off + + + +CX2341X_OSD_SET_BLEND_COORDS +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Enum: 78/0x4C + +Description +^^^^^^^^^^^ + +Move start of blending area within display buffer + +Param[0] +^^^^^^^^ + +horizontal offset in buffer + +Param[1] +^^^^^^^^ + +vertical offset in buffer + + + +CX2341X_OSD_GET_FLICKER_STATE +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Enum: 79/0x4F + +Description +^^^^^^^^^^^ + +Retrieve flicker reduction module state + +Result[0] +^^^^^^^^^ + +flicker state: 0=off, 1=on + + + +CX2341X_OSD_SET_FLICKER_STATE +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Enum: 80/0x50 + +Description +^^^^^^^^^^^ + +Set flicker reduction module state + +Param[0] +^^^^^^^^ + +State: 0=off, 1=on + + + +CX2341X_OSD_BLT_COPY +~~~~~~~~~~~~~~~~~~~~ + +Enum: 82/0x52 + +Description +^^^^^^^^^^^ + +BLT copy + +Param[0] +^^^^^^^^ + +.. code-block:: none + + '0000' zero + '0001' ~destination AND ~source + '0010' ~destination AND source + '0011' ~destination + '0100' destination AND ~source + '0101' ~source + '0110' destination XOR source + '0111' ~destination OR ~source + '1000' ~destination AND ~source + '1001' destination XNOR source + '1010' source + '1011' ~destination OR source + '1100' destination + '1101' destination OR ~source + '1110' destination OR source + '1111' one + + +Param[1] +^^^^^^^^ + +Resulting alpha blending + +- '01' source_alpha +- '10' destination_alpha +- '11' source_alpha*destination_alpha+1 + (zero if both source and destination alpha are zero) + +Param[2] +^^^^^^^^ + +.. code-block:: none + + '00' output_pixel = source_pixel + + '01' if source_alpha=0: + output_pixel = destination_pixel + if 256 > source_alpha > 1: + output_pixel = ((source_alpha + 1)*source_pixel + + (255 - source_alpha)*destination_pixel)/256 + + '10' if destination_alpha=0: + output_pixel = source_pixel + if 255 > destination_alpha > 0: + output_pixel = ((255 - destination_alpha)*source_pixel + + (destination_alpha + 1)*destination_pixel)/256 + + '11' if source_alpha=0: + source_temp = 0 + if source_alpha=255: + source_temp = source_pixel*256 + if 255 > source_alpha > 0: + source_temp = source_pixel*(source_alpha + 1) + if destination_alpha=0: + destination_temp = 0 + if destination_alpha=255: + destination_temp = destination_pixel*256 + if 255 > destination_alpha > 0: + destination_temp = destination_pixel*(destination_alpha + 1) + output_pixel = (source_temp + destination_temp)/256 + +Param[3] +^^^^^^^^ + +width + +Param[4] +^^^^^^^^ + +height + +Param[5] +^^^^^^^^ + +destination pixel mask + +Param[6] +^^^^^^^^ + +destination rectangle start address + +Param[7] +^^^^^^^^ + +destination stride in dwords + +Param[8] +^^^^^^^^ + +source stride in dwords + +Param[9] +^^^^^^^^ + +source rectangle start address + + + +CX2341X_OSD_BLT_FILL +~~~~~~~~~~~~~~~~~~~~ + +Enum: 83/0x53 + +Description +^^^^^^^^^^^ + +BLT fill color + +Param[0] +^^^^^^^^ + +Same as Param[0] on API 0x52 + +Param[1] +^^^^^^^^ + +Same as Param[1] on API 0x52 + +Param[2] +^^^^^^^^ + +Same as Param[2] on API 0x52 + +Param[3] +^^^^^^^^ + +width + +Param[4] +^^^^^^^^ + +height + +Param[5] +^^^^^^^^ + +destination pixel mask + +Param[6] +^^^^^^^^ + +destination rectangle start address + +Param[7] +^^^^^^^^ + +destination stride in dwords + +Param[8] +^^^^^^^^ + +color fill value + + + +CX2341X_OSD_BLT_TEXT +~~~~~~~~~~~~~~~~~~~~ + +Enum: 84/0x54 + +Description +^^^^^^^^^^^ + +BLT for 8 bit alpha text source + +Param[0] +^^^^^^^^ + +Same as Param[0] on API 0x52 + +Param[1] +^^^^^^^^ + +Same as Param[1] on API 0x52 + +Param[2] +^^^^^^^^ + +Same as Param[2] on API 0x52 + +Param[3] +^^^^^^^^ + +width + +Param[4] +^^^^^^^^ + +height + +Param[5] +^^^^^^^^ + +destination pixel mask + +Param[6] +^^^^^^^^ + +destination rectangle start address + +Param[7] +^^^^^^^^ + +destination stride in dwords + +Param[8] +^^^^^^^^ + +source stride in dwords + +Param[9] +^^^^^^^^ + +source rectangle start address + +Param[10] +^^^^^^^^^ + +color fill value + + + +CX2341X_OSD_SET_FRAMEBUFFER_WINDOW +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Enum: 86/0x56 + +Description +^^^^^^^^^^^ + +Positions the main output window on the screen. The coordinates must be +such that the entire window fits on the screen. + +Param[0] +^^^^^^^^ + +window width + +Param[1] +^^^^^^^^ + +window height + +Param[2] +^^^^^^^^ + +top left window corner horizontal offset + +Param[3] +^^^^^^^^ + +top left window corner vertical offset + + + +CX2341X_OSD_SET_CHROMA_KEY +~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Enum: 96/0x60 + +Description +^^^^^^^^^^^ + +Chroma key switch and color + +Param[0] +^^^^^^^^ + +state: 0=off, 1=on + +Param[1] +^^^^^^^^ + +color + + + +CX2341X_OSD_GET_ALPHA_CONTENT_INDEX +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Enum: 97/0x61 + +Description +^^^^^^^^^^^ + +Retrieve alpha content index + +Result[0] +^^^^^^^^^ + +alpha content index, Range 0:15 + + + +CX2341X_OSD_SET_ALPHA_CONTENT_INDEX +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Enum: 98/0x62 + +Description +^^^^^^^^^^^ + +Assign alpha content index + +Param[0] +^^^^^^^^ + +alpha content index, range 0:15 + + +Encoder firmware API description +-------------------------------- + +CX2341X_ENC_PING_FW +~~~~~~~~~~~~~~~~~~~ + +Enum: 128/0x80 + +Description +^^^^^^^^^^^ + +Does nothing. Can be used to check if the firmware is responding. + + + +CX2341X_ENC_START_CAPTURE +~~~~~~~~~~~~~~~~~~~~~~~~~ + +Enum: 129/0x81 + +Description +^^^^^^^^^^^ + +Commences the capture of video, audio and/or VBI data. All encoding +parameters must be initialized prior to this API call. Captures frames +continuously or until a predefined number of frames have been captured. + +Param[0] +^^^^^^^^ + +Capture stream type: + + - 0=MPEG + - 1=Raw + - 2=Raw passthrough + - 3=VBI + + +Param[1] +^^^^^^^^ + +Bitmask: + + - Bit 0 when set, captures YUV + - Bit 1 when set, captures PCM audio + - Bit 2 when set, captures VBI (same as param[0]=3) + - Bit 3 when set, the capture destination is the decoder + (same as param[0]=2) + - Bit 4 when set, the capture destination is the host + +.. note:: this parameter is only meaningful for RAW capture type. + + + +CX2341X_ENC_STOP_CAPTURE +~~~~~~~~~~~~~~~~~~~~~~~~ + +Enum: 130/0x82 + +Description +^^^^^^^^^^^ + +Ends a capture in progress + +Param[0] +^^^^^^^^ + +- 0=stop at end of GOP (generates IRQ) +- 1=stop immediate (no IRQ) + +Param[1] +^^^^^^^^ + +Stream type to stop, see param[0] of API 0x81 + +Param[2] +^^^^^^^^ + +Subtype, see param[1] of API 0x81 + + + +CX2341X_ENC_SET_AUDIO_ID +~~~~~~~~~~~~~~~~~~~~~~~~ + +Enum: 137/0x89 + +Description +^^^^^^^^^^^ + +Assigns the transport stream ID of the encoded audio stream + +Param[0] +^^^^^^^^ + +Audio Stream ID + + + +CX2341X_ENC_SET_VIDEO_ID +~~~~~~~~~~~~~~~~~~~~~~~~ + +Enum: 139/0x8B + +Description +^^^^^^^^^^^ + +Set video transport stream ID + +Param[0] +^^^^^^^^ + +Video stream ID + + + +CX2341X_ENC_SET_PCR_ID +~~~~~~~~~~~~~~~~~~~~~~ + +Enum: 141/0x8D + +Description +^^^^^^^^^^^ + +Assigns the transport stream ID for PCR packets + +Param[0] +^^^^^^^^ + +PCR Stream ID + + + +CX2341X_ENC_SET_FRAME_RATE +~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Enum: 143/0x8F + +Description +^^^^^^^^^^^ + +Set video frames per second. Change occurs at start of new GOP. + +Param[0] +^^^^^^^^ + +- 0=30fps +- 1=25fps + + + +CX2341X_ENC_SET_FRAME_SIZE +~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Enum: 145/0x91 + +Description +^^^^^^^^^^^ + +Select video stream encoding resolution. + +Param[0] +^^^^^^^^ + +Height in lines. Default 480 + +Param[1] +^^^^^^^^ + +Width in pixels. Default 720 + + + +CX2341X_ENC_SET_BIT_RATE +~~~~~~~~~~~~~~~~~~~~~~~~ + +Enum: 149/0x95 + +Description +^^^^^^^^^^^ + +Assign average video stream bitrate. + +Param[0] +^^^^^^^^ + +0=variable bitrate, 1=constant bitrate + +Param[1] +^^^^^^^^ + +bitrate in bits per second + +Param[2] +^^^^^^^^ + +peak bitrate in bits per second, divided by 400 + +Param[3] +^^^^^^^^ + +Mux bitrate in bits per second, divided by 400. May be 0 (default). + +Param[4] +^^^^^^^^ + +Rate Control VBR Padding + +Param[5] +^^^^^^^^ + +VBV Buffer used by encoder + +.. note:: + + #) Param\[3\] and Param\[4\] seem to be always 0 + #) Param\[5\] doesn't seem to be used. + + + +CX2341X_ENC_SET_GOP_PROPERTIES +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Enum: 151/0x97 + +Description +^^^^^^^^^^^ + +Setup the GOP structure + +Param[0] +^^^^^^^^ + +GOP size (maximum is 34) + +Param[1] +^^^^^^^^ + +Number of B frames between the I and P frame, plus 1. +For example: IBBPBBPBBPBB --> GOP size: 12, number of B frames: 2+1 = 3 + +.. note:: + + GOP size must be a multiple of (B-frames + 1). + + + +CX2341X_ENC_SET_ASPECT_RATIO +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Enum: 153/0x99 + +Description +^^^^^^^^^^^ + +Sets the encoding aspect ratio. Changes in the aspect ratio take effect +at the start of the next GOP. + +Param[0] +^^^^^^^^ + +- '0000' forbidden +- '0001' 1:1 square +- '0010' 4:3 +- '0011' 16:9 +- '0100' 2.21:1 +- '0101' to '1111' reserved + + + +CX2341X_ENC_SET_DNR_FILTER_MODE +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Enum: 155/0x9B + +Description +^^^^^^^^^^^ + +Assign Dynamic Noise Reduction operating mode + +Param[0] +^^^^^^^^ + +Bit0: Spatial filter, set=auto, clear=manual +Bit1: Temporal filter, set=auto, clear=manual + +Param[1] +^^^^^^^^ + +Median filter: + +- 0=Disabled +- 1=Horizontal +- 2=Vertical +- 3=Horiz/Vert +- 4=Diagonal + + + +CX2341X_ENC_SET_DNR_FILTER_PROPS +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Enum: 157/0x9D + +Description +^^^^^^^^^^^ + +These Dynamic Noise Reduction filter values are only meaningful when +the respective filter is set to "manual" (See API 0x9B) + +Param[0] +^^^^^^^^ + +Spatial filter: default 0, range 0:15 + +Param[1] +^^^^^^^^ + +Temporal filter: default 0, range 0:31 + + + +CX2341X_ENC_SET_CORING_LEVELS +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Enum: 159/0x9F + +Description +^^^^^^^^^^^ + +Assign Dynamic Noise Reduction median filter properties. + +Param[0] +^^^^^^^^ + +Threshold above which the luminance median filter is enabled. +Default: 0, range 0:255 + +Param[1] +^^^^^^^^ + +Threshold below which the luminance median filter is enabled. +Default: 255, range 0:255 + +Param[2] +^^^^^^^^ + +Threshold above which the chrominance median filter is enabled. +Default: 0, range 0:255 + +Param[3] +^^^^^^^^ + +Threshold below which the chrominance median filter is enabled. +Default: 255, range 0:255 + + + +CX2341X_ENC_SET_SPATIAL_FILTER_TYPE +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Enum: 161/0xA1 + +Description +^^^^^^^^^^^ + +Assign spatial prefilter parameters + +Param[0] +^^^^^^^^ + +Luminance filter + +- 0=Off +- 1=1D Horizontal +- 2=1D Vertical +- 3=2D H/V Separable (default) +- 4=2D Symmetric non-separable + +Param[1] +^^^^^^^^ + +Chrominance filter + +- 0=Off +- 1=1D Horizontal (default) + + + +CX2341X_ENC_SET_VBI_LINE +~~~~~~~~~~~~~~~~~~~~~~~~ + +Enum: 183/0xB7 + +Description +^^^^^^^^^^^ + +Selects VBI line number. + +Param[0] +^^^^^^^^ + +- Bits 0:4 line number +- Bit 31 0=top_field, 1=bottom_field +- Bits 0:31 all set specifies "all lines" + +Param[1] +^^^^^^^^ + +VBI line information features: 0=disabled, 1=enabled + +Param[2] +^^^^^^^^ + +Slicing: 0=None, 1=Closed Caption +Almost certainly not implemented. Set to 0. + +Param[3] +^^^^^^^^ + +Luminance samples in this line. +Almost certainly not implemented. Set to 0. + +Param[4] +^^^^^^^^ + +Chrominance samples in this line +Almost certainly not implemented. Set to 0. + + + +CX2341X_ENC_SET_STREAM_TYPE +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Enum: 185/0xB9 + +Description +^^^^^^^^^^^ + +Assign stream type + +.. note:: + + Transport stream is not working in recent firmwares. + And in older firmwares the timestamps in the TS seem to be + unreliable. + +Param[0] +^^^^^^^^ + +- 0=Program stream +- 1=Transport stream +- 2=MPEG1 stream +- 3=PES A/V stream +- 5=PES Video stream +- 7=PES Audio stream +- 10=DVD stream +- 11=VCD stream +- 12=SVCD stream +- 13=DVD_S1 stream +- 14=DVD_S2 stream + + + +CX2341X_ENC_SET_OUTPUT_PORT +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Enum: 187/0xBB + +Description +^^^^^^^^^^^ + +Assign stream output port. Normally 0 when the data is copied through +the PCI bus (DMA), and 1 when the data is streamed to another chip +(pvrusb and cx88-blackbird). + +Param[0] +^^^^^^^^ + +- 0=Memory (default) +- 1=Streaming +- 2=Serial + +Param[1] +^^^^^^^^ + +Unknown, but leaving this to 0 seems to work best. Indications are that +this might have to do with USB support, although passing anything but 0 +only breaks things. + + + +CX2341X_ENC_SET_AUDIO_PROPERTIES +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Enum: 189/0xBD + +Description +^^^^^^^^^^^ + +Set audio stream properties, may be called while encoding is in progress. + +.. note:: + + All bitfields are consistent with ISO11172 documentation except + bits 2:3 which ISO docs define as: + + - '11' Layer I + - '10' Layer II + - '01' Layer III + - '00' Undefined + + This discrepancy may indicate a possible error in the documentation. + Testing indicated that only Layer II is actually working, and that + the minimum bitrate should be 192 kbps. + +Param[0] +^^^^^^^^ + +Bitmask: + +.. code-block:: none + + 0:1 '00' 44.1Khz + '01' 48Khz + '10' 32Khz + '11' reserved + + 2:3 '01'=Layer I + '10'=Layer II + + 4:7 Bitrate: + Index | Layer I | Layer II + ------+-------------+------------ + '0000' | free format | free format + '0001' | 32 kbit/s | 32 kbit/s + '0010' | 64 kbit/s | 48 kbit/s + '0011' | 96 kbit/s | 56 kbit/s + '0100' | 128 kbit/s | 64 kbit/s + '0101' | 160 kbit/s | 80 kbit/s + '0110' | 192 kbit/s | 96 kbit/s + '0111' | 224 kbit/s | 112 kbit/s + '1000' | 256 kbit/s | 128 kbit/s + '1001' | 288 kbit/s | 160 kbit/s + '1010' | 320 kbit/s | 192 kbit/s + '1011' | 352 kbit/s | 224 kbit/s + '1100' | 384 kbit/s | 256 kbit/s + '1101' | 416 kbit/s | 320 kbit/s + '1110' | 448 kbit/s | 384 kbit/s + + .. note:: + + For Layer II, not all combinations of total bitrate + and mode are allowed. See ISO11172-3 3-Annex B, + Table 3-B.2 + + 8:9 '00'=Stereo + '01'=JointStereo + '10'=Dual + '11'=Mono + + .. note:: + + The cx23415 cannot decode Joint Stereo properly. + + 10:11 Mode Extension used in joint_stereo mode. + In Layer I and II they indicate which subbands are in + intensity_stereo. All other subbands are coded in stereo. + '00' subbands 4-31 in intensity_stereo, bound==4 + '01' subbands 8-31 in intensity_stereo, bound==8 + '10' subbands 12-31 in intensity_stereo, bound==12 + '11' subbands 16-31 in intensity_stereo, bound==16 + + 12:13 Emphasis: + '00' None + '01' 50/15uS + '10' reserved + '11' CCITT J.17 + + 14 CRC: + '0' off + '1' on + + 15 Copyright: + '0' off + '1' on + + 16 Generation: + '0' copy + '1' original + + + +CX2341X_ENC_HALT_FW +~~~~~~~~~~~~~~~~~~~ + +Enum: 195/0xC3 + +Description +^^^^^^^^^^^ + +The firmware is halted and no further API calls are serviced until the +firmware is uploaded again. + + + +CX2341X_ENC_GET_VERSION +~~~~~~~~~~~~~~~~~~~~~~~ + +Enum: 196/0xC4 + +Description +^^^^^^^^^^^ + +Returns the version of the encoder firmware. + +Result[0] +^^^^^^^^^ + +Version bitmask: +- Bits 0:15 build +- Bits 16:23 minor +- Bits 24:31 major + + + +CX2341X_ENC_SET_GOP_CLOSURE +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Enum: 197/0xC5 + +Description +^^^^^^^^^^^ + +Assigns the GOP open/close property. + +Param[0] +^^^^^^^^ + +- 0=Open +- 1=Closed + + + +CX2341X_ENC_GET_SEQ_END +~~~~~~~~~~~~~~~~~~~~~~~ + +Enum: 198/0xC6 + +Description +^^^^^^^^^^^ + +Obtains the sequence end code of the encoder's buffer. When a capture +is started a number of interrupts are still generated, the last of +which will have Result[0] set to 1 and Result[1] will contain the size +of the buffer. + +Result[0] +^^^^^^^^^ + +State of the transfer (1 if last buffer) + +Result[1] +^^^^^^^^^ + +If Result[0] is 1, this contains the size of the last buffer, undefined +otherwise. + + + +CX2341X_ENC_SET_PGM_INDEX_INFO +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Enum: 199/0xC7 + +Description +^^^^^^^^^^^ + +Sets the Program Index Information. +The information is stored as follows: + +.. code-block:: c + + struct info { + u32 length; // Length of this frame + u32 offset_low; // Offset in the file of the + u32 offset_high; // start of this frame + u32 mask1; // Bits 0-2 are the type mask: + // 1=I, 2=P, 4=B + // 0=End of Program Index, other fields + // are invalid. + u32 pts; // The PTS of the frame + u32 mask2; // Bit 0 is bit 32 of the pts. + }; + u32 table_ptr; + struct info index[400]; + +The table_ptr is the encoder memory address in the table were +*new* entries will be written. + +.. note:: This is a ringbuffer, so the table_ptr will wraparound. + +Param[0] +^^^^^^^^ + +Picture Mask: +- 0=No index capture +- 1=I frames +- 3=I,P frames +- 7=I,P,B frames + +(Seems to be ignored, it always indexes I, P and B frames) + +Param[1] +^^^^^^^^ + +Elements requested (up to 400) + +Result[0] +^^^^^^^^^ + +Offset in the encoder memory of the start of the table. + +Result[1] +^^^^^^^^^ + +Number of allocated elements up to a maximum of Param[1] + + + +CX2341X_ENC_SET_VBI_CONFIG +~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Enum: 200/0xC8 + +Description +^^^^^^^^^^^ + +Configure VBI settings + +Param[0] +^^^^^^^^ + +Bitmap: + +.. code-block:: none + + 0 Mode '0' Sliced, '1' Raw + 1:3 Insertion: + '000' insert in extension & user data + '001' insert in private packets + '010' separate stream and user data + '111' separate stream and private data + 8:15 Stream ID (normally 0xBD) + +Param[1] +^^^^^^^^ + +Frames per interrupt (max 8). Only valid in raw mode. + +Param[2] +^^^^^^^^ + +Total raw VBI frames. Only valid in raw mode. + +Param[3] +^^^^^^^^ + +Start codes + +Param[4] +^^^^^^^^ + +Stop codes + +Param[5] +^^^^^^^^ + +Lines per frame + +Param[6] +^^^^^^^^ + +Byte per line + +Result[0] +^^^^^^^^^ + +Observed frames per interrupt in raw mode only. Rage 1 to Param[1] + +Result[1] +^^^^^^^^^ + +Observed number of frames in raw mode. Range 1 to Param[2] + +Result[2] +^^^^^^^^^ + +Memory offset to start or raw VBI data + + + +CX2341X_ENC_SET_DMA_BLOCK_SIZE +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Enum: 201/0xC9 + +Description +^^^^^^^^^^^ + +Set DMA transfer block size + +Param[0] +^^^^^^^^ + +DMA transfer block size in bytes or frames. When unit is bytes, +supported block sizes are 2^7, 2^8 and 2^9 bytes. + +Param[1] +^^^^^^^^ + +Unit: 0=bytes, 1=frames + + + +CX2341X_ENC_GET_PREV_DMA_INFO_MB_10 +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Enum: 202/0xCA + +Description +^^^^^^^^^^^ + +Returns information on the previous DMA transfer in conjunction with +bit 27 of the interrupt mask. Uses mailbox 10. + +Result[0] +^^^^^^^^^ + +Type of stream + +Result[1] +^^^^^^^^^ + +Address Offset + +Result[2] +^^^^^^^^^ + +Maximum size of transfer + + + +CX2341X_ENC_GET_PREV_DMA_INFO_MB_9 +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Enum: 203/0xCB + +Description +^^^^^^^^^^^ + +Returns information on the previous DMA transfer in conjunction with +bit 27 or 18 of the interrupt mask. Uses mailbox 9. + +Result[0] +^^^^^^^^^ + +Status bits: +- 0 read completed +- 1 write completed +- 2 DMA read error +- 3 DMA write error +- 4 Scatter-Gather array error + +Result[1] +^^^^^^^^^ + +DMA type + +Result[2] +^^^^^^^^^ + +Presentation Time Stamp bits 0..31 + +Result[3] +^^^^^^^^^ + +Presentation Time Stamp bit 32 + + + +CX2341X_ENC_SCHED_DMA_TO_HOST +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Enum: 204/0xCC + +Description +^^^^^^^^^^^ + +Setup DMA to host operation + +Param[0] +^^^^^^^^ + +Memory address of link list + +Param[1] +^^^^^^^^ + +Length of link list (wtf: what units ???) + +Param[2] +^^^^^^^^ + +DMA type (0=MPEG) + + + +CX2341X_ENC_INITIALIZE_INPUT +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Enum: 205/0xCD + +Description +^^^^^^^^^^^ + +Initializes the video input + + + +CX2341X_ENC_SET_FRAME_DROP_RATE +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Enum: 208/0xD0 + +Description +^^^^^^^^^^^ + +For each frame captured, skip specified number of frames. + +Param[0] +^^^^^^^^ + +Number of frames to skip + + + +CX2341X_ENC_PAUSE_ENCODER +~~~~~~~~~~~~~~~~~~~~~~~~~ + +Enum: 210/0xD2 + +Description +^^^^^^^^^^^ + +During a pause condition, all frames are dropped instead of being encoded. + +Param[0] +^^^^^^^^ + +- 0=Pause encoding +- 1=Continue encoding + + + +CX2341X_ENC_REFRESH_INPUT +~~~~~~~~~~~~~~~~~~~~~~~~~ + +Enum: 211/0xD3 + +Description +^^^^^^^^^^^ + +Refreshes the video input + + + +CX2341X_ENC_SET_COPYRIGHT +~~~~~~~~~~~~~~~~~~~~~~~~~ + +Enum: 212/0xD4 + +Description +^^^^^^^^^^^ + +Sets stream copyright property + +Param[0] +^^^^^^^^ + + +- 0=Stream is not copyrighted +- 1=Stream is copyrighted + + + +CX2341X_ENC_SET_EVENT_NOTIFICATION +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Enum: 213/0xD5 + +Description +^^^^^^^^^^^ + +Setup firmware to notify the host about a particular event. Host must +unmask the interrupt bit. + +Param[0] +^^^^^^^^ + +Event (0=refresh encoder input) + +Param[1] +^^^^^^^^ + +Notification 0=disabled 1=enabled + +Param[2] +^^^^^^^^ + +Interrupt bit + +Param[3] +^^^^^^^^ + +Mailbox slot, -1 if no mailbox required. + + + +CX2341X_ENC_SET_NUM_VSYNC_LINES +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Enum: 214/0xD6 + +Description +^^^^^^^^^^^ + +Depending on the analog video decoder used, this assigns the number +of lines for field 1 and 2. + +Param[0] +^^^^^^^^ + +Field 1 number of lines: +- 0x00EF for SAA7114 +- 0x00F0 for SAA7115 +- 0x0105 for Micronas + +Param[1] +^^^^^^^^ + +Field 2 number of lines: +- 0x00EF for SAA7114 +- 0x00F0 for SAA7115 +- 0x0106 for Micronas + + + +CX2341X_ENC_SET_PLACEHOLDER +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Enum: 215/0xD7 + +Description +^^^^^^^^^^^ + +Provides a mechanism of inserting custom user data in the MPEG stream. + +Param[0] +^^^^^^^^ + +- 0=extension & user data +- 1=private packet with stream ID 0xBD + +Param[1] +^^^^^^^^ + +Rate at which to insert data, in units of frames (for private packet) +or GOPs (for ext. & user data) + +Param[2] +^^^^^^^^ + +Number of data DWORDs (below) to insert + +Param[3] +^^^^^^^^ + +Custom data 0 + +Param[4] +^^^^^^^^ + +Custom data 1 + +Param[5] +^^^^^^^^ + +Custom data 2 + +Param[6] +^^^^^^^^ + +Custom data 3 + +Param[7] +^^^^^^^^ + +Custom data 4 + +Param[8] +^^^^^^^^ + +Custom data 5 + +Param[9] +^^^^^^^^ + +Custom data 6 + +Param[10] +^^^^^^^^^ + +Custom data 7 + +Param[11] +^^^^^^^^^ + +Custom data 8 + + + +CX2341X_ENC_MUTE_VIDEO +~~~~~~~~~~~~~~~~~~~~~~ + +Enum: 217/0xD9 + +Description +^^^^^^^^^^^ + +Video muting + +Param[0] +^^^^^^^^ + +Bit usage: + +.. code-block:: none + + 0 '0'=video not muted + '1'=video muted, creates frames with the YUV color defined below + 1:7 Unused + 8:15 V chrominance information + 16:23 U chrominance information + 24:31 Y luminance information + + + +CX2341X_ENC_MUTE_AUDIO +~~~~~~~~~~~~~~~~~~~~~~ + +Enum: 218/0xDA + +Description +^^^^^^^^^^^ + +Audio muting + +Param[0] +^^^^^^^^ + +- 0=audio not muted +- 1=audio muted (produces silent mpeg audio stream) + + + +CX2341X_ENC_SET_VERT_CROP_LINE +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Enum: 219/0xDB + +Description +^^^^^^^^^^^ + +Something to do with 'Vertical Crop Line' + +Param[0] +^^^^^^^^ + +If saa7114 and raw VBI capture and 60 Hz, then set to 10001. +Else 0. + + + +CX2341X_ENC_MISC +~~~~~~~~~~~~~~~~ + +Enum: 220/0xDC + +Description +^^^^^^^^^^^ + +Miscellaneous actions. Not known for 100% what it does. It's really a +sort of ioctl call. The first parameter is a command number, the second +the value. + +Param[0] +^^^^^^^^ + +Command number: + +.. code-block:: none + + 1=set initial SCR value when starting encoding (works). + 2=set quality mode (apparently some test setting). + 3=setup advanced VIM protection handling. + Always 1 for the cx23416 and 0 for cx23415. + 4=generate DVD compatible PTS timestamps + 5=USB flush mode + 6=something to do with the quantization matrix + 7=set navigation pack insertion for DVD: adds 0xbf (private stream 2) + packets to the MPEG. The size of these packets is 2048 bytes (including + the header of 6 bytes: 0x000001bf + length). The payload is zeroed and + it is up to the application to fill them in. These packets are apparently + inserted every four frames. + 8=enable scene change detection (seems to be a failure) + 9=set history parameters of the video input module + 10=set input field order of VIM + 11=set quantization matrix + 12=reset audio interface after channel change or input switch (has no argument). + Needed for the cx2584x, not needed for the mspx4xx, but it doesn't seem to + do any harm calling it regardless. + 13=set audio volume delay + 14=set audio delay + + +Param[1] +^^^^^^^^ + +Command value. + +Decoder firmware API description +-------------------------------- + +.. note:: this API is part of the decoder firmware, so it's cx23415 only. + + + +CX2341X_DEC_PING_FW +~~~~~~~~~~~~~~~~~~~ + +Enum: 0/0x00 + +Description +^^^^^^^^^^^ + +This API call does nothing. It may be used to check if the firmware +is responding. + + + +CX2341X_DEC_START_PLAYBACK +~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Enum: 1/0x01 + +Description +^^^^^^^^^^^ + +Begin or resume playback. + +Param[0] +^^^^^^^^ + +0 based frame number in GOP to begin playback from. + +Param[1] +^^^^^^^^ + +Specifies the number of muted audio frames to play before normal +audio resumes. (This is not implemented in the firmware, leave at 0) + + + +CX2341X_DEC_STOP_PLAYBACK +~~~~~~~~~~~~~~~~~~~~~~~~~ + +Enum: 2/0x02 + +Description +^^^^^^^^^^^ + +Ends playback and clears all decoder buffers. If PTS is not zero, +playback stops at specified PTS. + +Param[0] +^^^^^^^^ + +Display 0=last frame, 1=black + +.. note:: + + this takes effect immediately, so if you want to wait for a PTS, + then use '0', otherwise the screen goes to black at once. + You can call this later (even if there is no playback) with a 1 value + to set the screen to black. + +Param[1] +^^^^^^^^ + +PTS low + +Param[2] +^^^^^^^^ + +PTS high + + + +CX2341X_DEC_SET_PLAYBACK_SPEED +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Enum: 3/0x03 + +Description +^^^^^^^^^^^ + +Playback stream at speed other than normal. There are two modes of +operation: + + - Smooth: host transfers entire stream and firmware drops unused + frames. + - Coarse: host drops frames based on indexing as required to achieve + desired speed. + +Param[0] +^^^^^^^^ + +.. code-block:: none + + Bitmap: + 0:7 0 normal + 1 fast only "1.5 times" + n nX fast, 1/nX slow + 30 Framedrop: + '0' during 1.5 times play, every other B frame is dropped + '1' during 1.5 times play, stream is unchanged (bitrate + must not exceed 8mbps) + 31 Speed: + '0' slow + '1' fast + +.. note:: + + n is limited to 2. Anything higher does not result in + faster playback. Instead the host should start dropping frames. + +Param[1] +^^^^^^^^ + +Direction: 0=forward, 1=reverse + +.. note:: + + to make reverse playback work you have to write full GOPs in + reverse order. + +Param[2] +^^^^^^^^ + +.. code-block:: none + + Picture mask: + 1=I frames + 3=I, P frames + 7=I, P, B frames + +Param[3] +^^^^^^^^ + +B frames per GOP (for reverse play only) + +.. note:: + + for reverse playback the Picture Mask should be set to I or I, P. + Adding B frames to the mask will result in corrupt video. This field + has to be set to the correct value in order to keep the timing correct. + +Param[4] +^^^^^^^^ + +Mute audio: 0=disable, 1=enable + +Param[5] +^^^^^^^^ + +Display 0=frame, 1=field + +Param[6] +^^^^^^^^ + +Specifies the number of muted audio frames to play before normal audio +resumes. (Not implemented in the firmware, leave at 0) + + + +CX2341X_DEC_STEP_VIDEO +~~~~~~~~~~~~~~~~~~~~~~ + +Enum: 5/0x05 + +Description +^^^^^^^^^^^ + +Each call to this API steps the playback to the next unit defined below +in the current playback direction. + +Param[0] +^^^^^^^^ + +0=frame, 1=top field, 2=bottom field + + + +CX2341X_DEC_SET_DMA_BLOCK_SIZE +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Enum: 8/0x08 + +Description +^^^^^^^^^^^ + +Set DMA transfer block size. Counterpart to API 0xC9 + +Param[0] +^^^^^^^^ + +DMA transfer block size in bytes. A different size may be specified +when issuing the DMA transfer command. + + + +CX2341X_DEC_GET_XFER_INFO +~~~~~~~~~~~~~~~~~~~~~~~~~ + +Enum: 9/0x09 + +Description +^^^^^^^^^^^ + +This API call may be used to detect an end of stream condition. + +Result[0] +^^^^^^^^^ + +Stream type + +Result[1] +^^^^^^^^^ + +Address offset + +Result[2] +^^^^^^^^^ + +Maximum bytes to transfer + +Result[3] +^^^^^^^^^ + +Buffer fullness + + + +CX2341X_DEC_GET_DMA_STATUS +~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Enum: 10/0x0A + +Description +^^^^^^^^^^^ + +Status of the last DMA transfer + +Result[0] +^^^^^^^^^ + +Bit 1 set means transfer complete +Bit 2 set means DMA error +Bit 3 set means linked list error + +Result[1] +^^^^^^^^^ + +DMA type: 0=MPEG, 1=OSD, 2=YUV + + + +CX2341X_DEC_SCHED_DMA_FROM_HOST +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Enum: 11/0x0B + +Description +^^^^^^^^^^^ + +Setup DMA from host operation. Counterpart to API 0xCC + +Param[0] +^^^^^^^^ + +Memory address of link list + +Param[1] +^^^^^^^^ + +Total # of bytes to transfer + +Param[2] +^^^^^^^^ + +DMA type (0=MPEG, 1=OSD, 2=YUV) + + + +CX2341X_DEC_PAUSE_PLAYBACK +~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Enum: 13/0x0D + +Description +^^^^^^^^^^^ + +Freeze playback immediately. In this mode, when internal buffers are +full, no more data will be accepted and data request IRQs will be +masked. + +Param[0] +^^^^^^^^ + +Display: 0=last frame, 1=black + + + +CX2341X_DEC_HALT_FW +~~~~~~~~~~~~~~~~~~~ + +Enum: 14/0x0E + +Description +^^^^^^^^^^^ + +The firmware is halted and no further API calls are serviced until +the firmware is uploaded again. + + + +CX2341X_DEC_SET_STANDARD +~~~~~~~~~~~~~~~~~~~~~~~~ + +Enum: 16/0x10 + +Description +^^^^^^^^^^^ + +Selects display standard + +Param[0] +^^^^^^^^ + +0=NTSC, 1=PAL + + + +CX2341X_DEC_GET_VERSION +~~~~~~~~~~~~~~~~~~~~~~~ + +Enum: 17/0x11 + +Description +^^^^^^^^^^^ + +Returns decoder firmware version information + +Result[0] +^^^^^^^^^ + +Version bitmask: + - Bits 0:15 build + - Bits 16:23 minor + - Bits 24:31 major + + + +CX2341X_DEC_SET_STREAM_INPUT +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Enum: 20/0x14 + +Description +^^^^^^^^^^^ + +Select decoder stream input port + +Param[0] +^^^^^^^^ + +0=memory (default), 1=streaming + + + +CX2341X_DEC_GET_TIMING_INFO +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Enum: 21/0x15 + +Description +^^^^^^^^^^^ + +Returns timing information from start of playback + +Result[0] +^^^^^^^^^ + +Frame count by decode order + +Result[1] +^^^^^^^^^ + +Video PTS bits 0:31 by display order + +Result[2] +^^^^^^^^^ + +Video PTS bit 32 by display order + +Result[3] +^^^^^^^^^ + +SCR bits 0:31 by display order + +Result[4] +^^^^^^^^^ + +SCR bit 32 by display order + + + +CX2341X_DEC_SET_AUDIO_MODE +~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Enum: 22/0x16 + +Description +^^^^^^^^^^^ + +Select audio mode + +Param[0] +^^^^^^^^ + +Dual mono mode action + 0=Stereo, 1=Left, 2=Right, 3=Mono, 4=Swap, -1=Unchanged + +Param[1] +^^^^^^^^ + +Stereo mode action: + 0=Stereo, 1=Left, 2=Right, 3=Mono, 4=Swap, -1=Unchanged + + + +CX2341X_DEC_SET_EVENT_NOTIFICATION +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Enum: 23/0x17 + +Description +^^^^^^^^^^^ + +Setup firmware to notify the host about a particular event. +Counterpart to API 0xD5 + +Param[0] +^^^^^^^^ + +Event: + - 0=Audio mode change between mono, (joint) stereo and dual channel. + - 3=Decoder started + - 4=Unknown: goes off 10-15 times per second while decoding. + - 5=Some sync event: goes off once per frame. + +Param[1] +^^^^^^^^ + +Notification 0=disabled, 1=enabled + +Param[2] +^^^^^^^^ + +Interrupt bit + +Param[3] +^^^^^^^^ + +Mailbox slot, -1 if no mailbox required. + + + +CX2341X_DEC_SET_DISPLAY_BUFFERS +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Enum: 24/0x18 + +Description +^^^^^^^^^^^ + +Number of display buffers. To decode all frames in reverse playback you +must use nine buffers. + +Param[0] +^^^^^^^^ + +0=six buffers, 1=nine buffers + + + +CX2341X_DEC_EXTRACT_VBI +~~~~~~~~~~~~~~~~~~~~~~~ + +Enum: 25/0x19 + +Description +^^^^^^^^^^^ + +Extracts VBI data + +Param[0] +^^^^^^^^ + +0=extract from extension & user data, 1=extract from private packets + +Result[0] +^^^^^^^^^ + +VBI table location + +Result[1] +^^^^^^^^^ + +VBI table size + + + +CX2341X_DEC_SET_DECODER_SOURCE +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Enum: 26/0x1A + +Description +^^^^^^^^^^^ + +Selects decoder source. Ensure that the parameters passed to this +API match the encoder settings. + +Param[0] +^^^^^^^^ + +Mode: 0=MPEG from host, 1=YUV from encoder, 2=YUV from host + +Param[1] +^^^^^^^^ + +YUV picture width + +Param[2] +^^^^^^^^ + +YUV picture height + +Param[3] +^^^^^^^^ + +Bitmap: see Param[0] of API 0xBD + + + +CX2341X_DEC_SET_PREBUFFERING +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Enum: 30/0x1E + +Description +^^^^^^^^^^^ + +Decoder prebuffering, when enabled up to 128KB are buffered for +streams <8mpbs or 640KB for streams >8mbps + +Param[0] +^^^^^^^^ + +0=off, 1=on + +PVR350 Video decoder registers 0x02002800 -> 0x02002B00 +------------------------------------------------------- + +Author: Ian Armstrong <ian@iarmst.demon.co.uk> + +Version: v0.4 + +Date: 12 March 2007 + + +This list has been worked out through trial and error. There will be mistakes +and omissions. Some registers have no obvious effect so it's hard to say what +they do, while others interact with each other, or require a certain load +sequence. Horizontal filter setup is one example, with six registers working +in unison and requiring a certain load sequence to correctly configure. The +indexed colour palette is much easier to set at just two registers, but again +it requires a certain load sequence. + +Some registers are fussy about what they are set to. Load in a bad value & the +decoder will fail. A firmware reload will often recover, but sometimes a reset +is required. For registers containing size information, setting them to 0 is +generally a bad idea. For other control registers i.e. 2878, you'll only find +out what values are bad when it hangs. + +.. code-block:: none + + -------------------------------------------------------------------------------- + 2800 + bit 0 + Decoder enable + 0 = disable + 1 = enable + -------------------------------------------------------------------------------- + 2804 + bits 0:31 + Decoder horizontal Y alias register 1 + --------------- + 2808 + bits 0:31 + Decoder horizontal Y alias register 2 + --------------- + 280C + bits 0:31 + Decoder horizontal Y alias register 3 + --------------- + 2810 + bits 0:31 + Decoder horizontal Y alias register 4 + --------------- + 2814 + bits 0:31 + Decoder horizontal Y alias register 5 + --------------- + 2818 + bits 0:31 + Decoder horizontal Y alias trigger + + These six registers control the horizontal aliasing filter for the Y plane. + The first five registers must all be loaded before accessing the trigger + (2818), as this register actually clocks the data through for the first + five. + + To correctly program set the filter, this whole procedure must be done 16 + times. The actual register contents are copied from a lookup-table in the + firmware which contains 4 different filter settings. + + -------------------------------------------------------------------------------- + 281C + bits 0:31 + Decoder horizontal UV alias register 1 + --------------- + 2820 + bits 0:31 + Decoder horizontal UV alias register 2 + --------------- + 2824 + bits 0:31 + Decoder horizontal UV alias register 3 + --------------- + 2828 + bits 0:31 + Decoder horizontal UV alias register 4 + --------------- + 282C + bits 0:31 + Decoder horizontal UV alias register 5 + --------------- + 2830 + bits 0:31 + Decoder horizontal UV alias trigger + + These six registers control the horizontal aliasing for the UV plane. + Operation is the same as the Y filter, with 2830 being the trigger + register. + + -------------------------------------------------------------------------------- + 2834 + bits 0:15 + Decoder Y source width in pixels + + bits 16:31 + Decoder Y destination width in pixels + --------------- + 2838 + bits 0:15 + Decoder UV source width in pixels + + bits 16:31 + Decoder UV destination width in pixels + + NOTE: For both registers, the resulting image must be fully visible on + screen. If the image exceeds the right edge both the source and destination + size must be adjusted to reflect the visible portion. For the source width, + you must take into account the scaling when calculating the new value. + -------------------------------------------------------------------------------- + + 283C + bits 0:31 + Decoder Y horizontal scaling + Normally = Reg 2854 >> 2 + --------------- + 2840 + bits 0:31 + Decoder ?? unknown - horizontal scaling + Usually 0x00080514 + --------------- + 2844 + bits 0:31 + Decoder UV horizontal scaling + Normally = Reg 2854 >> 2 + --------------- + 2848 + bits 0:31 + Decoder ?? unknown - horizontal scaling + Usually 0x00100514 + --------------- + 284C + bits 0:31 + Decoder ?? unknown - Y plane + Usually 0x00200020 + --------------- + 2850 + bits 0:31 + Decoder ?? unknown - UV plane + Usually 0x00200020 + --------------- + 2854 + bits 0:31 + Decoder 'master' value for horizontal scaling + --------------- + 2858 + bits 0:31 + Decoder ?? unknown + Usually 0 + --------------- + 285C + bits 0:31 + Decoder ?? unknown + Normally = Reg 2854 >> 1 + --------------- + 2860 + bits 0:31 + Decoder ?? unknown + Usually 0 + --------------- + 2864 + bits 0:31 + Decoder ?? unknown + Normally = Reg 2854 >> 1 + --------------- + 2868 + bits 0:31 + Decoder ?? unknown + Usually 0 + + Most of these registers either control horizontal scaling, or appear linked + to it in some way. Register 2854 contains the 'master' value & the other + registers can be calculated from that one. You must also remember to + correctly set the divider in Reg 2874. + + To enlarge: + Reg 2854 = (source_width * 0x00200000) / destination_width + Reg 2874 = No divide + + To reduce from full size down to half size: + Reg 2854 = (source_width/2 * 0x00200000) / destination width + Reg 2874 = Divide by 2 + + To reduce from half size down to quarter size: + Reg 2854 = (source_width/4 * 0x00200000) / destination width + Reg 2874 = Divide by 4 + + The result is always rounded up. + + -------------------------------------------------------------------------------- + 286C + bits 0:15 + Decoder horizontal Y buffer offset + + bits 15:31 + Decoder horizontal UV buffer offset + + Offset into the video image buffer. If the offset is gradually incremented, + the on screen image will move left & wrap around higher up on the right. + + -------------------------------------------------------------------------------- + 2870 + bits 0:15 + Decoder horizontal Y output offset + + bits 16:31 + Decoder horizontal UV output offset + + Offsets the actual video output. Controls output alignment of the Y & UV + planes. The higher the value, the greater the shift to the left. Use + reg 2890 to move the image right. + + -------------------------------------------------------------------------------- + 2874 + bits 0:1 + Decoder horizontal Y output size divider + 00 = No divide + 01 = Divide by 2 + 10 = Divide by 3 + + bits 4:5 + Decoder horizontal UV output size divider + 00 = No divide + 01 = Divide by 2 + 10 = Divide by 3 + + bit 8 + Decoder ?? unknown + 0 = Normal + 1 = Affects video output levels + + bit 16 + Decoder ?? unknown + 0 = Normal + 1 = Disable horizontal filter + + -------------------------------------------------------------------------------- + 2878 + bit 0 + ?? unknown + + bit 1 + osd on/off + 0 = osd off + 1 = osd on + + bit 2 + Decoder + osd video timing + 0 = NTSC + 1 = PAL + + bits 3:4 + ?? unknown + + bit 5 + Decoder + osd + Swaps upper & lower fields + + -------------------------------------------------------------------------------- + 287C + bits 0:10 + Decoder & osd ?? unknown + Moves entire screen horizontally. Starts at 0x005 with the screen + shifted heavily to the right. Incrementing in steps of 0x004 will + gradually shift the screen to the left. + + bits 11:31 + ?? unknown + + Normally contents are 0x00101111 (NTSC) or 0x1010111d (PAL) + + -------------------------------------------------------------------------------- + 2880 -------- ?? unknown + 2884 -------- ?? unknown + -------------------------------------------------------------------------------- + 2888 + bit 0 + Decoder + osd ?? unknown + 0 = Normal + 1 = Misaligned fields (Correctable through 289C & 28A4) + + bit 4 + ?? unknown + + bit 8 + ?? unknown + + Warning: Bad values will require a firmware reload to recover. + Known to be bad are 0x000,0x011,0x100,0x111 + -------------------------------------------------------------------------------- + 288C + bits 0:15 + osd ?? unknown + Appears to affect the osd position stability. The higher the value the + more unstable it becomes. Decoder output remains stable. + + bits 16:31 + osd ?? unknown + Same as bits 0:15 + + -------------------------------------------------------------------------------- + 2890 + bits 0:11 + Decoder output horizontal offset. + + Horizontal offset moves the video image right. A small left shift is + possible, but it's better to use reg 2870 for that due to its greater + range. + + NOTE: Video corruption will occur if video window is shifted off the right + edge. To avoid this read the notes for 2834 & 2838. + -------------------------------------------------------------------------------- + 2894 + bits 0:23 + Decoder output video surround colour. + + Contains the colour (in yuv) used to fill the screen when the video is + running in a window. + -------------------------------------------------------------------------------- + 2898 + bits 0:23 + Decoder video window colour + Contains the colour (in yuv) used to fill the video window when the + video is turned off. + + bit 24 + Decoder video output + 0 = Video on + 1 = Video off + + bit 28 + Decoder plane order + 0 = Y,UV + 1 = UV,Y + + bit 29 + Decoder second plane byte order + 0 = Normal (UV) + 1 = Swapped (VU) + + In normal usage, the first plane is Y & the second plane is UV. Though the + order of the planes can be swapped, only the byte order of the second plane + can be swapped. This isn't much use for the Y plane, but can be useful for + the UV plane. + + -------------------------------------------------------------------------------- + 289C + bits 0:15 + Decoder vertical field offset 1 + + bits 16:31 + Decoder vertical field offset 2 + + Controls field output vertical alignment. The higher the number, the lower + the image on screen. Known starting values are 0x011E0017 (NTSC) & + 0x01500017 (PAL) + -------------------------------------------------------------------------------- + 28A0 + bits 0:15 + Decoder & osd width in pixels + + bits 16:31 + Decoder & osd height in pixels + + All output from the decoder & osd are disabled beyond this area. Decoder + output will simply go black outside of this region. If the osd tries to + exceed this area it will become corrupt. + -------------------------------------------------------------------------------- + 28A4 + bits 0:11 + osd left shift. + + Has a range of 0x770->0x7FF. With the exception of 0, any value outside of + this range corrupts the osd. + -------------------------------------------------------------------------------- + 28A8 + bits 0:15 + osd vertical field offset 1 + + bits 16:31 + osd vertical field offset 2 + + Controls field output vertical alignment. The higher the number, the lower + the image on screen. Known starting values are 0x011E0017 (NTSC) & + 0x01500017 (PAL) + -------------------------------------------------------------------------------- + 28AC -------- ?? unknown + | + V + 28BC -------- ?? unknown + -------------------------------------------------------------------------------- + 28C0 + bit 0 + Current output field + 0 = first field + 1 = second field + + bits 16:31 + Current scanline + The scanline counts from the top line of the first field + through to the last line of the second field. + -------------------------------------------------------------------------------- + 28C4 -------- ?? unknown + | + V + 28F8 -------- ?? unknown + -------------------------------------------------------------------------------- + 28FC + bit 0 + ?? unknown + 0 = Normal + 1 = Breaks decoder & osd output + -------------------------------------------------------------------------------- + 2900 + bits 0:31 + Decoder vertical Y alias register 1 + --------------- + 2904 + bits 0:31 + Decoder vertical Y alias register 2 + --------------- + 2908 + bits 0:31 + Decoder vertical Y alias trigger + + These three registers control the vertical aliasing filter for the Y plane. + Operation is similar to the horizontal Y filter (2804). The only real + difference is that there are only two registers to set before accessing + the trigger register (2908). As for the horizontal filter, the values are + taken from a lookup table in the firmware, and the procedure must be + repeated 16 times to fully program the filter. + -------------------------------------------------------------------------------- + 290C + bits 0:31 + Decoder vertical UV alias register 1 + --------------- + 2910 + bits 0:31 + Decoder vertical UV alias register 2 + --------------- + 2914 + bits 0:31 + Decoder vertical UV alias trigger + + These three registers control the vertical aliasing filter for the UV + plane. Operation is the same as the Y filter, with 2914 being the trigger. + -------------------------------------------------------------------------------- + 2918 + bits 0:15 + Decoder Y source height in pixels + + bits 16:31 + Decoder Y destination height in pixels + --------------- + 291C + bits 0:15 + Decoder UV source height in pixels divided by 2 + + bits 16:31 + Decoder UV destination height in pixels + + NOTE: For both registers, the resulting image must be fully visible on + screen. If the image exceeds the bottom edge both the source and + destination size must be adjusted to reflect the visible portion. For the + source height, you must take into account the scaling when calculating the + new value. + -------------------------------------------------------------------------------- + 2920 + bits 0:31 + Decoder Y vertical scaling + Normally = Reg 2930 >> 2 + --------------- + 2924 + bits 0:31 + Decoder Y vertical scaling + Normally = Reg 2920 + 0x514 + --------------- + 2928 + bits 0:31 + Decoder UV vertical scaling + When enlarging = Reg 2930 >> 2 + When reducing = Reg 2930 >> 3 + --------------- + 292C + bits 0:31 + Decoder UV vertical scaling + Normally = Reg 2928 + 0x514 + --------------- + 2930 + bits 0:31 + Decoder 'master' value for vertical scaling + --------------- + 2934 + bits 0:31 + Decoder ?? unknown - Y vertical scaling + --------------- + 2938 + bits 0:31 + Decoder Y vertical scaling + Normally = Reg 2930 + --------------- + 293C + bits 0:31 + Decoder ?? unknown - Y vertical scaling + --------------- + 2940 + bits 0:31 + Decoder UV vertical scaling + When enlarging = Reg 2930 >> 1 + When reducing = Reg 2930 + --------------- + 2944 + bits 0:31 + Decoder ?? unknown - UV vertical scaling + --------------- + 2948 + bits 0:31 + Decoder UV vertical scaling + Normally = Reg 2940 + --------------- + 294C + bits 0:31 + Decoder ?? unknown - UV vertical scaling + + Most of these registers either control vertical scaling, or appear linked + to it in some way. Register 2930 contains the 'master' value & all other + registers can be calculated from that one. You must also remember to + correctly set the divider in Reg 296C + + To enlarge: + Reg 2930 = (source_height * 0x00200000) / destination_height + Reg 296C = No divide + + To reduce from full size down to half size: + Reg 2930 = (source_height/2 * 0x00200000) / destination height + Reg 296C = Divide by 2 + + To reduce from half down to quarter. + Reg 2930 = (source_height/4 * 0x00200000) / destination height + Reg 296C = Divide by 4 + + -------------------------------------------------------------------------------- + 2950 + bits 0:15 + Decoder Y line index into display buffer, first field + + bits 16:31 + Decoder Y vertical line skip, first field + -------------------------------------------------------------------------------- + 2954 + bits 0:15 + Decoder Y line index into display buffer, second field + + bits 16:31 + Decoder Y vertical line skip, second field + -------------------------------------------------------------------------------- + 2958 + bits 0:15 + Decoder UV line index into display buffer, first field + + bits 16:31 + Decoder UV vertical line skip, first field + -------------------------------------------------------------------------------- + 295C + bits 0:15 + Decoder UV line index into display buffer, second field + + bits 16:31 + Decoder UV vertical line skip, second field + -------------------------------------------------------------------------------- + 2960 + bits 0:15 + Decoder destination height minus 1 + + bits 16:31 + Decoder destination height divided by 2 + -------------------------------------------------------------------------------- + 2964 + bits 0:15 + Decoder Y vertical offset, second field + + bits 16:31 + Decoder Y vertical offset, first field + + These two registers shift the Y plane up. The higher the number, the + greater the shift. + -------------------------------------------------------------------------------- + 2968 + bits 0:15 + Decoder UV vertical offset, second field + + bits 16:31 + Decoder UV vertical offset, first field + + These two registers shift the UV plane up. The higher the number, the + greater the shift. + -------------------------------------------------------------------------------- + 296C + bits 0:1 + Decoder vertical Y output size divider + 00 = No divide + 01 = Divide by 2 + 10 = Divide by 4 + + bits 8:9 + Decoder vertical UV output size divider + 00 = No divide + 01 = Divide by 2 + 10 = Divide by 4 + -------------------------------------------------------------------------------- + 2970 + bit 0 + Decoder ?? unknown + 0 = Normal + 1 = Affect video output levels + + bit 16 + Decoder ?? unknown + 0 = Normal + 1 = Disable vertical filter + + -------------------------------------------------------------------------------- + 2974 -------- ?? unknown + | + V + 29EF -------- ?? unknown + -------------------------------------------------------------------------------- + 2A00 + bits 0:2 + osd colour mode + 000 = 8 bit indexed + 001 = 16 bit (565) + 010 = 15 bit (555) + 011 = 12 bit (444) + 100 = 32 bit (8888) + + bits 4:5 + osd display bpp + 01 = 8 bit + 10 = 16 bit + 11 = 32 bit + + bit 8 + osd global alpha + 0 = Off + 1 = On + + bit 9 + osd local alpha + 0 = Off + 1 = On + + bit 10 + osd colour key + 0 = Off + 1 = On + + bit 11 + osd ?? unknown + Must be 1 + + bit 13 + osd colour space + 0 = ARGB + 1 = AYVU + + bits 16:31 + osd ?? unknown + Must be 0x001B (some kind of buffer pointer ?) + + When the bits-per-pixel is set to 8, the colour mode is ignored and + assumed to be 8 bit indexed. For 16 & 32 bits-per-pixel the colour depth + is honoured, and when using a colour depth that requires fewer bytes than + allocated the extra bytes are used as padding. So for a 32 bpp with 8 bit + index colour, there are 3 padding bytes per pixel. It's also possible to + select 16bpp with a 32 bit colour mode. This results in the pixel width + being doubled, but the color key will not work as expected in this mode. + + Colour key is as it suggests. You designate a colour which will become + completely transparent. When using 565, 555 or 444 colour modes, the + colour key is always 16 bits wide. The colour to key on is set in Reg 2A18. + + Local alpha works differently depending on the colour mode. For 32bpp & 8 + bit indexed, local alpha is a per-pixel 256 step transparency, with 0 being + transparent and 255 being solid. For the 16bpp modes 555 & 444, the unused + bit(s) act as a simple transparency switch, with 0 being solid & 1 being + fully transparent. There is no local alpha support for 16bit 565. + + Global alpha is a 256 step transparency that applies to the entire osd, + with 0 being transparent & 255 being solid. + + It's possible to combine colour key, local alpha & global alpha. + -------------------------------------------------------------------------------- + 2A04 + bits 0:15 + osd x coord for left edge + + bits 16:31 + osd y coord for top edge + --------------- + 2A08 + bits 0:15 + osd x coord for right edge + + bits 16:31 + osd y coord for bottom edge + + For both registers, (0,0) = top left corner of the display area. These + registers do not control the osd size, only where it's positioned & how + much is visible. The visible osd area cannot exceed the right edge of the + display, otherwise the osd will become corrupt. See reg 2A10 for + setting osd width. + -------------------------------------------------------------------------------- + 2A0C + bits 0:31 + osd buffer index + + An index into the osd buffer. Slowly incrementing this moves the osd left, + wrapping around onto the right edge + -------------------------------------------------------------------------------- + 2A10 + bits 0:11 + osd buffer 32 bit word width + + Contains the width of the osd measured in 32 bit words. This means that all + colour modes are restricted to a byte width which is divisible by 4. + -------------------------------------------------------------------------------- + 2A14 + bits 0:15 + osd height in pixels + + bits 16:32 + osd line index into buffer + osd will start displaying from this line. + -------------------------------------------------------------------------------- + 2A18 + bits 0:31 + osd colour key + + Contains the colour value which will be transparent. + -------------------------------------------------------------------------------- + 2A1C + bits 0:7 + osd global alpha + + Contains the global alpha value (equiv ivtvfbctl --alpha XX) + -------------------------------------------------------------------------------- + 2A20 -------- ?? unknown + | + V + 2A2C -------- ?? unknown + -------------------------------------------------------------------------------- + 2A30 + bits 0:7 + osd colour to change in indexed palette + --------------- + 2A34 + bits 0:31 + osd colour for indexed palette + + To set the new palette, first load the index of the colour to change into + 2A30, then load the new colour into 2A34. The full palette is 256 colours, + so the index range is 0x00-0xFF + -------------------------------------------------------------------------------- + 2A38 -------- ?? unknown + 2A3C -------- ?? unknown + -------------------------------------------------------------------------------- + 2A40 + bits 0:31 + osd ?? unknown + + Affects overall brightness, wrapping around to black + -------------------------------------------------------------------------------- + 2A44 + bits 0:31 + osd ?? unknown + + Green tint + -------------------------------------------------------------------------------- + 2A48 + bits 0:31 + osd ?? unknown + + Red tint + -------------------------------------------------------------------------------- + 2A4C + bits 0:31 + osd ?? unknown + + Affects overall brightness, wrapping around to black + -------------------------------------------------------------------------------- + 2A50 + bits 0:31 + osd ?? unknown + + Colour shift + -------------------------------------------------------------------------------- + 2A54 + bits 0:31 + osd ?? unknown + + Colour shift + -------------------------------------------------------------------------------- + 2A58 -------- ?? unknown + | + V + 2AFC -------- ?? unknown + -------------------------------------------------------------------------------- + 2B00 + bit 0 + osd filter control + 0 = filter off + 1 = filter on + + bits 1:4 + osd ?? unknown + + -------------------------------------------------------------------------------- + +The cx231xx DMA engine +---------------------- + + +This page describes the structures and procedures used by the cx2341x DMA +engine. + +Introduction +~~~~~~~~~~~~ + +The cx2341x PCI interface is busmaster capable. This means it has a DMA +engine to efficiently transfer large volumes of data between the card and main +memory without requiring help from a CPU. Like most hardware, it must operate +on contiguous physical memory. This is difficult to come by in large quantities +on virtual memory machines. + +Therefore, it also supports a technique called "scatter-gather". The card can +transfer multiple buffers in one operation. Instead of allocating one large +contiguous buffer, the driver can allocate several smaller buffers. + +In practice, I've seen the average transfer to be roughly 80K, but transfers +above 128K were not uncommon, particularly at startup. The 128K figure is +important, because that is the largest block that the kernel can normally +allocate. Even still, 128K blocks are hard to come by, so the driver writer is +urged to choose a smaller block size and learn the scatter-gather technique. + +Mailbox #10 is reserved for DMA transfer information. + +Note: the hardware expects little-endian data ('intel format'). + +Flow +~~~~ + +This section describes, in general, the order of events when handling DMA +transfers. Detailed information follows this section. + +- The card raises the Encoder interrupt. +- The driver reads the transfer type, offset and size from Mailbox #10. +- The driver constructs the scatter-gather array from enough free dma buffers + to cover the size. +- The driver schedules the DMA transfer via the ScheduleDMAtoHost API call. +- The card raises the DMA Complete interrupt. +- The driver checks the DMA status register for any errors. +- The driver post-processes the newly transferred buffers. + +NOTE! It is possible that the Encoder and DMA Complete interrupts get raised +simultaneously. (End of the last, start of the next, etc.) + +Mailbox #10 +~~~~~~~~~~~ + +The Flags, Command, Return Value and Timeout fields are ignored. + +- Name: Mailbox #10 +- Results[0]: Type: 0: MPEG. +- Results[1]: Offset: The position relative to the card's memory space. +- Results[2]: Size: The exact number of bytes to transfer. + +My speculation is that since the StartCapture API has a capture type of "RAW" +available, that the type field will have other values that correspond to YUV +and PCM data. + +Scatter-Gather Array +~~~~~~~~~~~~~~~~~~~~ + +The scatter-gather array is a contiguously allocated block of memory that +tells the card the source and destination of each data-block to transfer. +Card "addresses" are derived from the offset supplied by Mailbox #10. Host +addresses are the physical memory location of the target DMA buffer. + +Each S-G array element is a struct of three 32-bit words. The first word is +the source address, the second is the destination address. Both take up the +entire 32 bits. The lowest 18 bits of the third word is the transfer byte +count. The high-bit of the third word is the "last" flag. The last-flag tells +the card to raise the DMA_DONE interrupt. From hard personal experience, if +you forget to set this bit, the card will still "work" but the stream will +most likely get corrupted. + +The transfer count must be a multiple of 256. Therefore, the driver will need +to track how much data in the target buffer is valid and deal with it +accordingly. + +Array Element: + +- 32-bit Source Address +- 32-bit Destination Address +- 14-bit reserved (high bit is the last flag) +- 18-bit byte count + +DMA Transfer Status +~~~~~~~~~~~~~~~~~~~ + +Register 0x0004 holds the DMA Transfer Status: + +- bit 0: read completed +- bit 1: write completed +- bit 2: DMA read error +- bit 3: DMA write error +- bit 4: Scatter-Gather array error diff --git a/Documentation/driver-api/media/drivers/cx88-devel.rst b/Documentation/driver-api/media/drivers/cx88-devel.rst new file mode 100644 index 0000000000..cfe7c03f49 --- /dev/null +++ b/Documentation/driver-api/media/drivers/cx88-devel.rst @@ -0,0 +1,113 @@ +.. SPDX-License-Identifier: GPL-2.0 + +The cx88 driver +=============== + +Author: Gerd Hoffmann + +Documentation missing at the cx88 datasheet +------------------------------------------- + +MO_OUTPUT_FORMAT (0x310164) + +.. code-block:: none + + Previous default from DScaler: 0x1c1f0008 + Digit 8: 31-28 + 28: PREVREMOD = 1 + + Digit 7: 27-24 (0xc = 12 = b1100 ) + 27: COMBALT = 1 + 26: PAL_INV_PHASE + (DScaler apparently set this to 1, resulted in sucky picture) + + Digits 6,5: 23-16 + 25-16: COMB_RANGE = 0x1f [default] (9 bits -> max 512) + + Digit 4: 15-12 + 15: DISIFX = 0 + 14: INVCBF = 0 + 13: DISADAPT = 0 + 12: NARROWADAPT = 0 + + Digit 3: 11-8 + 11: FORCE2H + 10: FORCEREMD + 9: NCHROMAEN + 8: NREMODEN + + Digit 2: 7-4 + 7-6: YCORE + 5-4: CCORE + + Digit 1: 3-0 + 3: RANGE = 1 + 2: HACTEXT + 1: HSFMT + +0x47 is the sync byte for MPEG-2 transport stream packets. +Datasheet incorrectly states to use 47 decimal. 188 is the length. +All DVB compliant frontends output packets with this start code. + +Hauppauge WinTV cx88 IR information +----------------------------------- + +The controls for the mux are GPIO [0,1] for source, and GPIO 2 for muting. + +====== ======== ================================================= +GPIO0 GPIO1 +====== ======== ================================================= + 0 0 TV Audio + 1 0 FM radio + 0 1 Line-In + 1 1 Mono tuner bypass or CD passthru (tuner specific) +====== ======== ================================================= + +GPIO 16(I believe) is tied to the IR port (if present). + + +From the data sheet: + +- Register 24'h20004 PCI Interrupt Status + + - bit [18] IR_SMP_INT Set when 32 input samples have been collected over + - gpio[16] pin into GP_SAMPLE register. + +What's missing from the data sheet: + +- Setup 4KHz sampling rate (roughly 2x oversampled; good enough for our RC5 + compat remote) +- set register 0x35C050 to 0xa80a80 +- enable sampling +- set register 0x35C054 to 0x5 +- enable the IRQ bit 18 in the interrupt mask register (and + provide for a handler) + +GP_SAMPLE register is at 0x35C058 + +Bits are then right shifted into the GP_SAMPLE register at the specified +rate; you get an interrupt when a full DWORD is received. +You need to recover the actual RC5 bits out of the (oversampled) IR sensor +bits. (Hint: look for the 0/1and 1/0 crossings of the RC5 bi-phase data) An +actual raw RC5 code will span 2-3 DWORDS, depending on the actual alignment. + +I'm pretty sure when no IR signal is present the receiver is always in a +marking state(1); but stray light, etc can cause intermittent noise values +as well. Remember, this is a free running sample of the IR receiver state +over time, so don't assume any sample starts at any particular place. + +Additional info +~~~~~~~~~~~~~~~ + +This data sheet (google search) seems to have a lovely description of the +RC5 basics: +http://www.atmel.com/dyn/resources/prod_documents/doc2817.pdf + +This document has more data: +http://www.nenya.be/beor/electronics/rc5.htm + +This document has a how to decode a bi-phase data stream: +http://www.ee.washington.edu/circuit_archive/text/ir_decode.txt + +This document has still more info: +http://www.xs4all.nl/~sbp/knowledge/ir/rc5.htm diff --git a/Documentation/driver-api/media/drivers/dvb-usb.rst b/Documentation/driver-api/media/drivers/dvb-usb.rst new file mode 100644 index 0000000000..b2d5d9e62b --- /dev/null +++ b/Documentation/driver-api/media/drivers/dvb-usb.rst @@ -0,0 +1,357 @@ +.. SPDX-License-Identifier: GPL-2.0 + +Idea behind the dvb-usb-framework +================================= + +.. note:: + + #) This documentation is outdated. Please check at the DVB wiki + at https://linuxtv.org/wiki for more updated info. + + #) **deprecated:** Newer DVB USB drivers should use the dvb-usb-v2 framework. + +In March 2005 I got the new Twinhan USB2.0 DVB-T device. They provided specs +and a firmware. + +Quite keen I wanted to put the driver (with some quirks of course) into dibusb. +After reading some specs and doing some USB snooping, it realized, that the +dibusb-driver would be a complete mess afterwards. So I decided to do it in a +different way: With the help of a dvb-usb-framework. + +The framework provides generic functions (mostly kernel API calls), such as: + +- Transport Stream URB handling in conjunction with dvb-demux-feed-control + (bulk and isoc are supported) +- registering the device for the DVB-API +- registering an I2C-adapter if applicable +- remote-control/input-device handling +- firmware requesting and loading (currently just for the Cypress USB + controllers) +- other functions/methods which can be shared by several drivers (such as + functions for bulk-control-commands) +- TODO: a I2C-chunker. It creates device-specific chunks of register-accesses + depending on length of a register and the number of values that can be + multi-written and multi-read. + +The source code of the particular DVB USB devices does just the communication +with the device via the bus. The connection between the DVB-API-functionality +is done via callbacks, assigned in a static device-description (struct +dvb_usb_device) each device-driver has to have. + +For an example have a look in drivers/media/usb/dvb-usb/vp7045*. + +Objective is to migrate all the usb-devices (dibusb, cinergyT2, maybe the +ttusb; flexcop-usb already benefits from the generic flexcop-device) to use +the dvb-usb-lib. + +TODO: dynamic enabling and disabling of the pid-filter in regard to number of +feeds requested. + +Supported devices +----------------- + +See the LinuxTV DVB Wiki at https://linuxtv.org for a complete list of +cards/drivers/firmwares: +https://linuxtv.org/wiki/index.php/DVB_USB + +0. History & News: + + 2005-06-30 + + - added support for WideView WT-220U (Thanks to Steve Chang) + + 2005-05-30 + + - added basic isochronous support to the dvb-usb-framework + - added support for Conexant Hybrid reference design and Nebula + DigiTV USB + + 2005-04-17 + + - all dibusb devices ported to make use of the dvb-usb-framework + + 2005-04-02 + + - re-enabled and improved remote control code. + + 2005-03-31 + + - ported the Yakumo/Hama/Typhoon DVB-T USB2.0 device to dvb-usb. + + 2005-03-30 + + - first commit of the dvb-usb-module based on the dibusb-source. + First device is a new driver for the + TwinhanDTV Alpha / MagicBox II USB2.0-only DVB-T device. + - (change from dvb-dibusb to dvb-usb) + + 2005-03-28 + + - added support for the AVerMedia AverTV DVB-T USB2.0 device + (Thanks to Glen Harris and Jiun-Kuei Jung, AVerMedia) + + 2005-03-14 + + - added support for the Typhoon/Yakumo/HAMA DVB-T mobile USB2.0 + + 2005-02-11 + + - added support for the KWorld/ADSTech Instant DVB-T USB2.0. + Thanks a lot to Joachim von Caron + + 2005-02-02 + - added support for the Hauppauge Win-TV Nova-T USB2 + + 2005-01-31 + - distorted streaming is gone for USB1.1 devices + + 2005-01-13 + + - moved the mirrored pid_filter_table back to dvb-dibusb + first almost working version for HanfTek UMT-010 + found out, that Yakumo/HAMA/Typhoon are predecessors of the HanfTek UMT-010 + + 2005-01-10 + + - refactoring completed, now everything is very delightful + + - tuner quirks for some weird devices (Artec T1 AN2235 device has sometimes a + Panasonic Tuner assembled). Tunerprobing implemented. + Thanks a lot to Gunnar Wittich. + + 2004-12-29 + + - after several days of struggling around bug of no returning URBs fixed. + + 2004-12-26 + + - refactored the dibusb-driver, split into separate files + - i2c-probing enabled + + 2004-12-06 + + - possibility for demod i2c-address probing + - new usb IDs (Compro, Artec) + + 2004-11-23 + + - merged changes from DiB3000MC_ver2.1 + - revised the debugging + - possibility to deliver the complete TS for USB2.0 + + 2004-11-21 + + - first working version of the dib3000mc/p frontend driver. + + 2004-11-12 + + - added additional remote control keys. Thanks to Uwe Hanke. + + 2004-11-07 + + - added remote control support. Thanks to David Matthews. + + 2004-11-05 + + - added support for a new devices (Grandtec/Avermedia/Artec) + - merged my changes (for dib3000mb/dibusb) to the FE_REFACTORING, because it became HEAD + - moved transfer control (pid filter, fifo control) from usb driver to frontend, it seems + better settled there (added xfer_ops-struct) + - created a common files for frontends (mc/p/mb) + + 2004-09-28 + + - added support for a new device (Unknown, vendor ID is Hyper-Paltek) + + 2004-09-20 + + - added support for a new device (Compro DVB-U2000), thanks + to Amaury Demol for reporting + - changed usb TS transfer method (several urbs, stopping transfer + before setting a new pid) + + 2004-09-13 + + - added support for a new device (Artec T1 USB TVBOX), thanks + to Christian Motschke for reporting + + 2004-09-05 + + - released the dibusb device and dib3000mb-frontend driver + (old news for vp7041.c) + + 2004-07-15 + + - found out, by accident, that the device has a TUA6010XS for PLL + + 2004-07-12 + + - figured out, that the driver should also work with the + CTS Portable (Chinese Television System) + + 2004-07-08 + + - firmware-extraction-2.422-problem solved, driver is now working + properly with firmware extracted from 2.422 + - #if for 2.6.4 (dvb), compile issue + - changed firmware handling, see vp7041.txt sec 1.1 + + 2004-07-02 + + - some tuner modifications, v0.1, cleanups, first public + + 2004-06-28 + + - now using the dvb_dmx_swfilter_packets, everything runs fine now + + 2004-06-27 + + - able to watch and switching channels (pre-alpha) + - no section filtering yet + + 2004-06-06 + + - first TS received, but kernel oops :/ + + 2004-05-14 + + - firmware loader is working + + 2004-05-11 + + - start writing the driver + +How to use? +----------- + +Firmware +~~~~~~~~ + +Most of the USB drivers need to download a firmware to the device before start +working. + +Have a look at the Wikipage for the DVB-USB-drivers to find out, which firmware +you need for your device: + +https://linuxtv.org/wiki/index.php/DVB_USB + +Compiling +~~~~~~~~~ + +Since the driver is in the linux kernel, activating the driver in +your favorite config-environment should sufficient. I recommend +to compile the driver as module. Hotplug does the rest. + +If you use dvb-kernel enter the build-2.6 directory run 'make' and 'insmod.sh +load' afterwards. + +Loading the drivers +~~~~~~~~~~~~~~~~~~~ + +Hotplug is able to load the driver, when it is needed (because you plugged +in the device). + +If you want to enable debug output, you have to load the driver manually and +from within the dvb-kernel cvs repository. + +first have a look, which debug level are available: + +.. code-block:: none + + # modinfo dvb-usb + # modinfo dvb-usb-vp7045 + + etc. + +.. code-block:: none + + modprobe dvb-usb debug=<level> + modprobe dvb-usb-vp7045 debug=<level> + etc. + +should do the trick. + +When the driver is loaded successfully, the firmware file was in +the right place and the device is connected, the "Power"-LED should be +turned on. + +At this point you should be able to start a dvb-capable application. I'm use +(t|s)zap, mplayer and dvbscan to test the basics. VDR-xine provides the +long-term test scenario. + +Known problems and bugs +----------------------- + +- Don't remove the USB device while running an DVB application, your system + will go crazy or die most likely. + +Adding support for devices +~~~~~~~~~~~~~~~~~~~~~~~~~~ + +TODO + +USB1.1 Bandwidth limitation +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +A lot of the currently supported devices are USB1.1 and thus they have a +maximum bandwidth of about 5-6 MBit/s when connected to a USB2.0 hub. +This is not enough for receiving the complete transport stream of a +DVB-T channel (which is about 16 MBit/s). Normally this is not a +problem, if you only want to watch TV (this does not apply for HDTV), +but watching a channel while recording another channel on the same +frequency simply does not work very well. This applies to all USB1.1 +DVB-T devices, not just the dvb-usb-devices) + +The bug, where the TS is distorted by a heavy usage of the device is gone +definitely. All dvb-usb-devices I was using (Twinhan, Kworld, DiBcom) are +working like charm now with VDR. Sometimes I even was able to record a channel +and watch another one. + +Comments +~~~~~~~~ + +Patches, comments and suggestions are very very welcome. + +3. Acknowledgements +------------------- + + Amaury Demol (Amaury.Demol@parrot.com) and Francois Kanounnikoff from DiBcom for + providing specs, code and help, on which the dvb-dibusb, dib3000mb and + dib3000mc are based. + + David Matthews for identifying a new device type (Artec T1 with AN2235) + and for extending dibusb with remote control event handling. Thank you. + + Alex Woods for frequently answering question about usb and dvb + stuff, a big thank you. + + Bernd Wagner for helping with huge bug reports and discussions. + + Gunnar Wittich and Joachim von Caron for their trust for providing + root-shells on their machines to implement support for new devices. + + Allan Third and Michael Hutchinson for their help to write the Nebula + digitv-driver. + + Glen Harris for bringing up, that there is a new dibusb-device and Jiun-Kuei + Jung from AVerMedia who kindly provided a special firmware to get the device + up and running in Linux. + + Jennifer Chen, Jeff and Jack from Twinhan for kindly supporting by + writing the vp7045-driver. + + Steve Chang from WideView for providing information for new devices and + firmware files. + + Michael Paxton for submitting remote control keymaps. + + Some guys on the linux-dvb mailing list for encouraging me. + + Peter Schildmann >peter.schildmann-nospam-at-web.de< for his + user-level firmware loader, which saves a lot of time + (when writing the vp7041 driver) + + Ulf Hermenau for helping me out with traditional chinese. + + André Smoktun and Christian Frömmel for supporting me with + hardware and listening to my problems very patiently. diff --git a/Documentation/driver-api/media/drivers/fimc-devel.rst b/Documentation/driver-api/media/drivers/fimc-devel.rst new file mode 100644 index 0000000000..4c6b7c8be1 --- /dev/null +++ b/Documentation/driver-api/media/drivers/fimc-devel.rst @@ -0,0 +1,33 @@ +.. SPDX-License-Identifier: GPL-2.0 + +.. include:: <isonum.txt> + +The Samsung S5P/EXYNOS4 FIMC driver +=================================== + +Copyright |copy| 2012 - 2013 Samsung Electronics Co., Ltd. + +Files partitioning +------------------ + +- media device driver + + drivers/media/platform/samsung/exynos4-is/media-dev.[ch] + +- camera capture video device driver + + drivers/media/platform/samsung/exynos4-is/fimc-capture.c + +- MIPI-CSI2 receiver subdev + + drivers/media/platform/samsung/exynos4-is/mipi-csis.[ch] + +- video post-processor (mem-to-mem) + + drivers/media/platform/samsung/exynos4-is/fimc-core.c + +- common files + + drivers/media/platform/samsung/exynos4-is/fimc-core.h + drivers/media/platform/samsung/exynos4-is/fimc-reg.h + drivers/media/platform/samsung/exynos4-is/regs-fimc.h diff --git a/Documentation/driver-api/media/drivers/frontends.rst b/Documentation/driver-api/media/drivers/frontends.rst new file mode 100644 index 0000000000..7b8336ece6 --- /dev/null +++ b/Documentation/driver-api/media/drivers/frontends.rst @@ -0,0 +1,32 @@ +.. SPDX-License-Identifier: GPL-2.0 + +**************** +Frontend drivers +**************** + +Frontend attach headers +*********************** + +.. Keep it on alphabetic order + +.. kernel-doc:: drivers/media/dvb-frontends/a8293.h +.. kernel-doc:: drivers/media/dvb-frontends/af9013.h +.. kernel-doc:: drivers/media/dvb-frontends/ascot2e.h +.. kernel-doc:: drivers/media/dvb-frontends/cxd2820r.h +.. kernel-doc:: drivers/media/dvb-frontends/drxk.h +.. kernel-doc:: drivers/media/dvb-frontends/dvb-pll.h +.. kernel-doc:: drivers/media/dvb-frontends/helene.h +.. kernel-doc:: drivers/media/dvb-frontends/horus3a.h +.. kernel-doc:: drivers/media/dvb-frontends/ix2505v.h +.. kernel-doc:: drivers/media/dvb-frontends/m88ds3103.h +.. kernel-doc:: drivers/media/dvb-frontends/mb86a20s.h +.. kernel-doc:: drivers/media/dvb-frontends/mn88472.h +.. kernel-doc:: drivers/media/dvb-frontends/rtl2830.h +.. kernel-doc:: drivers/media/dvb-frontends/rtl2832.h +.. kernel-doc:: drivers/media/dvb-frontends/rtl2832_sdr.h +.. kernel-doc:: drivers/media/dvb-frontends/stb6000.h +.. kernel-doc:: drivers/media/dvb-frontends/tda10071.h +.. kernel-doc:: drivers/media/dvb-frontends/tda826x.h +.. kernel-doc:: drivers/media/dvb-frontends/zd1301_demod.h +.. kernel-doc:: drivers/media/dvb-frontends/zl10036.h + diff --git a/Documentation/driver-api/media/drivers/index.rst b/Documentation/driver-api/media/drivers/index.rst new file mode 100644 index 0000000000..c4123a16b5 --- /dev/null +++ b/Documentation/driver-api/media/drivers/index.rst @@ -0,0 +1,40 @@ +.. SPDX-License-Identifier: GPL-2.0 + +.. include:: <isonum.txt> + +=================================== +Media driver-specific documentation +=================================== + +Video4Linux (V4L) drivers +========================= + +.. toctree:: + :maxdepth: 5 + + bttv-devel + cx2341x-devel + cx88-devel + fimc-devel + pvrusb2 + pxa_camera + radiotrack + rkisp1 + saa7134-devel + sh_mobile_ceu_camera + tuners + vimc-devel + zoran + ccs/ccs + + +Digital TV drivers +================== + +.. toctree:: + :maxdepth: 5 + + dvb-usb + frontends + vidtv + contributors diff --git a/Documentation/driver-api/media/drivers/pvrusb2.rst b/Documentation/driver-api/media/drivers/pvrusb2.rst new file mode 100644 index 0000000000..cbd9359c24 --- /dev/null +++ b/Documentation/driver-api/media/drivers/pvrusb2.rst @@ -0,0 +1,202 @@ +.. SPDX-License-Identifier: GPL-2.0 + +The pvrusb2 driver +================== + +Author: Mike Isely <isely@pobox.com> + +Background +---------- + +This driver is intended for the "Hauppauge WinTV PVR USB 2.0", which +is a USB 2.0 hosted TV Tuner. This driver is a work in progress. +Its history started with the reverse-engineering effort by Björn +Danielsson <pvrusb2@dax.nu> whose web page can be found here: +http://pvrusb2.dax.nu/ + +From there Aurelien Alleaume <slts@free.fr> began an effort to +create a video4linux compatible driver. I began with Aurelien's +last known snapshot and evolved the driver to the state it is in +here. + +More information on this driver can be found at: +https://www.isely.net/pvrusb2.html + + +This driver has a strong separation of layers. They are very +roughly: + +1. Low level wire-protocol implementation with the device. + +2. I2C adaptor implementation and corresponding I2C client drivers + implemented elsewhere in V4L. + +3. High level hardware driver implementation which coordinates all + activities that ensure correct operation of the device. + +4. A "context" layer which manages instancing of driver, setup, + tear-down, arbitration, and interaction with high level + interfaces appropriately as devices are hotplugged in the + system. + +5. High level interfaces which glue the driver to various published + Linux APIs (V4L, sysfs, maybe DVB in the future). + +The most important shearing layer is between the top 2 layers. A +lot of work went into the driver to ensure that any kind of +conceivable API can be laid on top of the core driver. (Yes, the +driver internally leverages V4L to do its work but that really has +nothing to do with the API published by the driver to the outside +world.) The architecture allows for different APIs to +simultaneously access the driver. I have a strong sense of fairness +about APIs and also feel that it is a good design principle to keep +implementation and interface isolated from each other. Thus while +right now the V4L high level interface is the most complete, the +sysfs high level interface will work equally well for similar +functions, and there's no reason I see right now why it shouldn't be +possible to produce a DVB high level interface that can sit right +alongside V4L. + +Building +-------- + +To build these modules essentially amounts to just running "Make", +but you need the kernel source tree nearby and you will likely also +want to set a few controlling environment variables first in order +to link things up with that source tree. Please see the Makefile +here for comments that explain how to do that. + +Source file list / functional overview +-------------------------------------- + +(Note: The term "module" used below generally refers to loosely +defined functional units within the pvrusb2 driver and bears no +relation to the Linux kernel's concept of a loadable module.) + +pvrusb2-audio.[ch] - This is glue logic that resides between this + driver and the msp3400.ko I2C client driver (which is found + elsewhere in V4L). + +pvrusb2-context.[ch] - This module implements the context for an + instance of the driver. Everything else eventually ties back to + or is otherwise instanced within the data structures implemented + here. Hotplugging is ultimately coordinated here. All high level + interfaces tie into the driver through this module. This module + helps arbitrate each interface's access to the actual driver core, + and is designed to allow concurrent access through multiple + instances of multiple interfaces (thus you can for example change + the tuner's frequency through sysfs while simultaneously streaming + video through V4L out to an instance of mplayer). + +pvrusb2-debug.h - This header defines a printk() wrapper and a mask + of debugging bit definitions for the various kinds of debug + messages that can be enabled within the driver. + +pvrusb2-debugifc.[ch] - This module implements a crude command line + oriented debug interface into the driver. Aside from being part + of the process for implementing manual firmware extraction (see + the pvrusb2 web site mentioned earlier), probably I'm the only one + who has ever used this. It is mainly a debugging aid. + +pvrusb2-eeprom.[ch] - This is glue logic that resides between this + driver the tveeprom.ko module, which is itself implemented + elsewhere in V4L. + +pvrusb2-encoder.[ch] - This module implements all protocol needed to + interact with the Conexant mpeg2 encoder chip within the pvrusb2 + device. It is a crude echo of corresponding logic in ivtv, + however the design goals (strict isolation) and physical layer + (proxy through USB instead of PCI) are enough different that this + implementation had to be completely different. + +pvrusb2-hdw-internal.h - This header defines the core data structure + in the driver used to track ALL internal state related to control + of the hardware. Nobody outside of the core hardware-handling + modules should have any business using this header. All external + access to the driver should be through one of the high level + interfaces (e.g. V4L, sysfs, etc), and in fact even those high + level interfaces are restricted to the API defined in + pvrusb2-hdw.h and NOT this header. + +pvrusb2-hdw.h - This header defines the full internal API for + controlling the hardware. High level interfaces (e.g. V4L, sysfs) + will work through here. + +pvrusb2-hdw.c - This module implements all the various bits of logic + that handle overall control of a specific pvrusb2 device. + (Policy, instantiation, and arbitration of pvrusb2 devices fall + within the jurisdiction of pvrusb-context not here). + +pvrusb2-i2c-chips-\*.c - These modules implement the glue logic to + tie together and configure various I2C modules as they attach to + the I2C bus. There are two versions of this file. The "v4l2" + version is intended to be used in-tree alongside V4L, where we + implement just the logic that makes sense for a pure V4L + environment. The "all" version is intended for use outside of + V4L, where we might encounter other possibly "challenging" modules + from ivtv or older kernel snapshots (or even the support modules + in the standalone snapshot). + +pvrusb2-i2c-cmd-v4l1.[ch] - This module implements generic V4L1 + compatible commands to the I2C modules. It is here where state + changes inside the pvrusb2 driver are translated into V4L1 + commands that are in turn send to the various I2C modules. + +pvrusb2-i2c-cmd-v4l2.[ch] - This module implements generic V4L2 + compatible commands to the I2C modules. It is here where state + changes inside the pvrusb2 driver are translated into V4L2 + commands that are in turn send to the various I2C modules. + +pvrusb2-i2c-core.[ch] - This module provides an implementation of a + kernel-friendly I2C adaptor driver, through which other external + I2C client drivers (e.g. msp3400, tuner, lirc) may connect and + operate corresponding chips within the pvrusb2 device. It is + through here that other V4L modules can reach into this driver to + operate specific pieces (and those modules are in turn driven by + glue logic which is coordinated by pvrusb2-hdw, doled out by + pvrusb2-context, and then ultimately made available to users + through one of the high level interfaces). + +pvrusb2-io.[ch] - This module implements a very low level ring of + transfer buffers, required in order to stream data from the + device. This module is *very* low level. It only operates the + buffers and makes no attempt to define any policy or mechanism for + how such buffers might be used. + +pvrusb2-ioread.[ch] - This module layers on top of pvrusb2-io.[ch] + to provide a streaming API usable by a read() system call style of + I/O. Right now this is the only layer on top of pvrusb2-io.[ch], + however the underlying architecture here was intended to allow for + other styles of I/O to be implemented with additional modules, like + mmap()'ed buffers or something even more exotic. + +pvrusb2-main.c - This is the top level of the driver. Module level + and USB core entry points are here. This is our "main". + +pvrusb2-sysfs.[ch] - This is the high level interface which ties the + pvrusb2 driver into sysfs. Through this interface you can do + everything with the driver except actually stream data. + +pvrusb2-tuner.[ch] - This is glue logic that resides between this + driver and the tuner.ko I2C client driver (which is found + elsewhere in V4L). + +pvrusb2-util.h - This header defines some common macros used + throughout the driver. These macros are not really specific to + the driver, but they had to go somewhere. + +pvrusb2-v4l2.[ch] - This is the high level interface which ties the + pvrusb2 driver into video4linux. It is through here that V4L + applications can open and operate the driver in the usual V4L + ways. Note that **ALL** V4L functionality is published only + through here and nowhere else. + +pvrusb2-video-\*.[ch] - This is glue logic that resides between this + driver and the saa711x.ko I2C client driver (which is found + elsewhere in V4L). Note that saa711x.ko used to be known as + saa7115.ko in ivtv. There are two versions of this; one is + selected depending on the particular saa711[5x].ko that is found. + +pvrusb2.h - This header contains compile time tunable parameters + (and at the moment the driver has very little that needs to be + tuned). diff --git a/Documentation/driver-api/media/drivers/pxa_camera.rst b/Documentation/driver-api/media/drivers/pxa_camera.rst new file mode 100644 index 0000000000..46919919ba --- /dev/null +++ b/Documentation/driver-api/media/drivers/pxa_camera.rst @@ -0,0 +1,194 @@ +.. SPDX-License-Identifier: GPL-2.0 + +PXA-Camera Host Driver +====================== + +Author: Robert Jarzmik <robert.jarzmik@free.fr> + +Constraints +----------- + +a) Image size for YUV422P format + All YUV422P images are enforced to have width x height % 16 = 0. + This is due to DMA constraints, which transfers only planes of 8 byte + multiples. + + +Global video workflow +--------------------- + +a) QCI stopped + Initially, the QCI interface is stopped. + When a buffer is queued, start_streaming is called and the QCI starts. + +b) QCI started + More buffers can be queued while the QCI is started without halting the + capture. The new buffers are "appended" at the tail of the DMA chain, and + smoothly captured one frame after the other. + + Once a buffer is filled in the QCI interface, it is marked as "DONE" and + removed from the active buffers list. It can be then requeud or dequeued by + userland application. + + Once the last buffer is filled in, the QCI interface stops. + +c) Capture global finite state machine schema + +.. code-block:: none + + +----+ +---+ +----+ + | DQ | | Q | | DQ | + | v | v | v + +-----------+ +------------------------+ + | STOP | | Wait for capture start | + +-----------+ Q +------------------------+ + +-> | QCI: stop | ------------------> | QCI: run | <------------+ + | | DMA: stop | | DMA: stop | | + | +-----------+ +-----> +------------------------+ | + | / | | + | / +---+ +----+ | | + |capture list empty / | Q | | DQ | | QCI Irq EOF | + | / | v | v v | + | +--------------------+ +----------------------+ | + | | DMA hotlink missed | | Capture running | | + | +--------------------+ +----------------------+ | + | | QCI: run | +-----> | QCI: run | <-+ | + | | DMA: stop | / | DMA: run | | | + | +--------------------+ / +----------------------+ | Other | + | ^ /DMA still | | channels | + | | capture list / running | DMA Irq End | not | + | | not empty / | | finished | + | | / v | yet | + | +----------------------+ +----------------------+ | | + | | Videobuf released | | Channel completed | | | + | +----------------------+ +----------------------+ | | + +-- | QCI: run | | QCI: run | --+ | + | DMA: run | | DMA: run | | + +----------------------+ +----------------------+ | + ^ / | | + | no overrun / | overrun | + | / v | + +--------------------+ / +----------------------+ | + | Frame completed | / | Frame overran | | + +--------------------+ <-----+ +----------------------+ restart frame | + | QCI: run | | QCI: stop | --------------+ + | DMA: run | | DMA: stop | + +--------------------+ +----------------------+ + + Legend: - each box is a FSM state + - each arrow is the condition to transition to another state + - an arrow with a comment is a mandatory transition (no condition) + - arrow "Q" means : a buffer was enqueued + - arrow "DQ" means : a buffer was dequeued + - "QCI: stop" means the QCI interface is not enabled + - "DMA: stop" means all 3 DMA channels are stopped + - "DMA: run" means at least 1 DMA channel is still running + +DMA usage +--------- + +a) DMA flow + - first buffer queued for capture + Once a first buffer is queued for capture, the QCI is started, but data + transfer is not started. On "End Of Frame" interrupt, the irq handler + starts the DMA chain. + - capture of one videobuffer + The DMA chain starts transferring data into videobuffer RAM pages. + When all pages are transferred, the DMA irq is raised on "ENDINTR" status + - finishing one videobuffer + The DMA irq handler marks the videobuffer as "done", and removes it from + the active running queue + Meanwhile, the next videobuffer (if there is one), is transferred by DMA + - finishing the last videobuffer + On the DMA irq of the last videobuffer, the QCI is stopped. + +b) DMA prepared buffer will have this structure + +.. code-block:: none + + +------------+-----+---------------+-----------------+ + | desc-sg[0] | ... | desc-sg[last] | finisher/linker | + +------------+-----+---------------+-----------------+ + +This structure is pointed by dma->sg_cpu. +The descriptors are used as follows: + +- desc-sg[i]: i-th descriptor, transferring the i-th sg + element to the video buffer scatter gather +- finisher: has ddadr=DADDR_STOP, dcmd=ENDIRQEN +- linker: has ddadr= desc-sg[0] of next video buffer, dcmd=0 + +For the next schema, let's assume d0=desc-sg[0] .. dN=desc-sg[N], +"f" stands for finisher and "l" for linker. +A typical running chain is : + +.. code-block:: none + + Videobuffer 1 Videobuffer 2 + +---------+----+---+ +----+----+----+---+ + | d0 | .. | dN | l | | d0 | .. | dN | f | + +---------+----+-|-+ ^----+----+----+---+ + | | + +----+ + +After the chaining is finished, the chain looks like : + +.. code-block:: none + + Videobuffer 1 Videobuffer 2 Videobuffer 3 + +---------+----+---+ +----+----+----+---+ +----+----+----+---+ + | d0 | .. | dN | l | | d0 | .. | dN | l | | d0 | .. | dN | f | + +---------+----+-|-+ ^----+----+----+-|-+ ^----+----+----+---+ + | | | | + +----+ +----+ + new_link + +c) DMA hot chaining timeslice issue + +As DMA chaining is done while DMA _is_ running, the linking may be done +while the DMA jumps from one Videobuffer to another. On the schema, that +would be a problem if the following sequence is encountered : + +- DMA chain is Videobuffer1 + Videobuffer2 +- pxa_videobuf_queue() is called to queue Videobuffer3 +- DMA controller finishes Videobuffer2, and DMA stops + +.. code-block:: none + + => + Videobuffer 1 Videobuffer 2 + +---------+----+---+ +----+----+----+---+ + | d0 | .. | dN | l | | d0 | .. | dN | f | + +---------+----+-|-+ ^----+----+----+-^-+ + | | | + +----+ +-- DMA DDADR loads DDADR_STOP + +- pxa_dma_add_tail_buf() is called, the Videobuffer2 "finisher" is + replaced by a "linker" to Videobuffer3 (creation of new_link) +- pxa_videobuf_queue() finishes +- the DMA irq handler is called, which terminates Videobuffer2 +- Videobuffer3 capture is not scheduled on DMA chain (as it stopped !!!) + +.. code-block:: none + + Videobuffer 1 Videobuffer 2 Videobuffer 3 + +---------+----+---+ +----+----+----+---+ +----+----+----+---+ + | d0 | .. | dN | l | | d0 | .. | dN | l | | d0 | .. | dN | f | + +---------+----+-|-+ ^----+----+----+-|-+ ^----+----+----+---+ + | | | | + +----+ +----+ + new_link + DMA DDADR still is DDADR_STOP + +- pxa_camera_check_link_miss() is called + This checks if the DMA is finished and a buffer is still on the + pcdev->capture list. If that's the case, the capture will be restarted, + and Videobuffer3 is scheduled on DMA chain. +- the DMA irq handler finishes + +.. note:: + + If DMA stops just after pxa_camera_check_link_miss() reads DDADR() + value, we have the guarantee that the DMA irq handler will be called back + when the DMA will finish the buffer, and pxa_camera_check_link_miss() will + be called again, to reschedule Videobuffer3. diff --git a/Documentation/driver-api/media/drivers/radiotrack.rst b/Documentation/driver-api/media/drivers/radiotrack.rst new file mode 100644 index 0000000000..a85cb6205d --- /dev/null +++ b/Documentation/driver-api/media/drivers/radiotrack.rst @@ -0,0 +1,168 @@ +.. SPDX-License-Identifier: GPL-2.0 + +The Radiotrack radio driver +=========================== + +Author: Stephen M. Benoit <benoits@servicepro.com> + +Date: Dec 14, 1996 + +ACKNOWLEDGMENTS +---------------- + +This document was made based on 'C' code for Linux from Gideon le Grange +(legrang@active.co.za or legrang@cs.sun.ac.za) in 1994, and elaborations from +Frans Brinkman (brinkman@esd.nl) in 1996. The results reported here are from +experiments that the author performed on his own setup, so your mileage may +vary... I make no guarantees, claims or warranties to the suitability or +validity of this information. No other documentation on the AIMS +Lab (http://www.aimslab.com/) RadioTrack card was made available to the +author. This document is offered in the hopes that it might help users who +want to use the RadioTrack card in an environment other than MS Windows. + +WHY THIS DOCUMENT? +------------------ + +I have a RadioTrack card from back when I ran an MS-Windows platform. After +converting to Linux, I found Gideon le Grange's command-line software for +running the card, and found that it was good! Frans Brinkman made a +comfortable X-windows interface, and added a scanning feature. For hack +value, I wanted to see if the tuner could be tuned beyond the usual FM radio +broadcast band, so I could pick up the audio carriers from North American +broadcast TV channels, situated just below and above the 87.0-109.0 MHz range. +I did not get much success, but I learned about programming ioports under +Linux and gained some insights about the hardware design used for the card. + +So, without further delay, here are the details. + + +PHYSICAL DESCRIPTION +-------------------- + +The RadioTrack card is an ISA 8-bit FM radio card. The radio frequency (RF) +input is simply an antenna lead, and the output is a power audio signal +available through a miniature phone plug. Its RF frequencies of operation are +more or less limited from 87.0 to 109.0 MHz (the commercial FM broadcast +band). Although the registers can be programmed to request frequencies beyond +these limits, experiments did not give promising results. The variable +frequency oscillator (VFO) that demodulates the intermediate frequency (IF) +signal probably has a small range of useful frequencies, and wraps around or +gets clipped beyond the limits mentioned above. + + +CONTROLLING THE CARD WITH IOPORT +-------------------------------- + +The RadioTrack (base) ioport is configurable for 0x30c or 0x20c. Only one +ioport seems to be involved. The ioport decoding circuitry must be pretty +simple, as individual ioport bits are directly matched to specific functions +(or blocks) of the radio card. This way, many functions can be changed in +parallel with one write to the ioport. The only feedback available through +the ioports appears to be the "Stereo Detect" bit. + +The bits of the ioport are arranged as follows: + +.. code-block:: none + + MSb LSb + +------+------+------+--------+--------+-------+---------+--------+ + | VolA | VolB | ???? | Stereo | Radio | TuneA | TuneB | Tune | + | (+) | (-) | | Detect | Audio | (bit) | (latch) | Update | + | | | | Enable | Enable | | | Enable | + +------+------+------+--------+--------+-------+---------+--------+ + + +==== ==== ================================= +VolA VolB Description +==== ==== ================================= +0 0 audio mute +0 1 volume + (some delay required) +1 0 volume - (some delay required) +1 1 stay at present volume +==== ==== ================================= + +==================== =========== +Stereo Detect Enable Description +==================== =========== +0 No Detect +1 Detect +==================== =========== + +Results available by reading ioport >60 msec after last port write. + + 0xff ==> no stereo detected, 0xfd ==> stereo detected. + +============================= ============================= +Radio to Audio (path) Enable Description +============================= ============================= +0 Disable path (silence) +1 Enable path (audio produced) +============================= ============================= + +===== ===== ================== +TuneA TuneB Description +===== ===== ================== +0 0 "zero" bit phase 1 +0 1 "zero" bit phase 2 +1 0 "one" bit phase 1 +1 1 "one" bit phase 2 +===== ===== ================== + + +24-bit code, where bits = (freq*40) + 10486188. +The Most Significant 11 bits must be 1010 xxxx 0x0 to be valid. +The bits are shifted in LSb first. + +================== =========================== +Tune Update Enable Description +================== =========================== +0 Tuner held constant +1 Tuner updating in progress +================== =========================== + + +PROGRAMMING EXAMPLES +-------------------- + +.. code-block:: none + + Default: BASE <-- 0xc8 (current volume, no stereo detect, + radio enable, tuner adjust disable) + + Card Off: BASE <-- 0x00 (audio mute, no stereo detect, + radio disable, tuner adjust disable) + + Card On: BASE <-- 0x00 (see "Card Off", clears any unfinished business) + BASE <-- 0xc8 (see "Default") + + Volume Down: BASE <-- 0x48 (volume down, no stereo detect, + radio enable, tuner adjust disable) + wait 10 msec + BASE <-- 0xc8 (see "Default") + + Volume Up: BASE <-- 0x88 (volume up, no stereo detect, + radio enable, tuner adjust disable) + wait 10 msec + BASE <-- 0xc8 (see "Default") + + Check Stereo: BASE <-- 0xd8 (current volume, stereo detect, + radio enable, tuner adjust disable) + wait 100 msec + x <-- BASE (read ioport) + BASE <-- 0xc8 (see "Default") + + x=0xff ==> "not stereo", x=0xfd ==> "stereo detected" + + Set Frequency: code = (freq*40) + 10486188 + foreach of the 24 bits in code, + (from Least to Most Significant): + to write a "zero" bit, + BASE <-- 0x01 (audio mute, no stereo detect, radio + disable, "zero" bit phase 1, tuner adjust) + BASE <-- 0x03 (audio mute, no stereo detect, radio + disable, "zero" bit phase 2, tuner adjust) + to write a "one" bit, + BASE <-- 0x05 (audio mute, no stereo detect, radio + disable, "one" bit phase 1, tuner adjust) + BASE <-- 0x07 (audio mute, no stereo detect, radio + disable, "one" bit phase 2, tuner adjust) diff --git a/Documentation/driver-api/media/drivers/rkisp1.rst b/Documentation/driver-api/media/drivers/rkisp1.rst new file mode 100644 index 0000000000..ea336958a3 --- /dev/null +++ b/Documentation/driver-api/media/drivers/rkisp1.rst @@ -0,0 +1,43 @@ +.. SPDX-License-Identifier: GPL-2.0 + +The Rockchip Image Signal Processor Driver (rkisp1) +=================================================== + +Versions and their differences +------------------------------ + +The rkisp1 block underwent some changes between SoC implementations. +The vendor designates them as: + +- V10: used at least in rk3288 and rk3399 +- V11: declared in the original vendor code, but not used +- V12: used at least in rk3326 and px30 +- V13: used at least in rk1808 +- V20: used in rk3568 and beyond + +Right now the kernel supports rkisp1 implementations based +on V10 and V12 variants. V11 does not seem to be actually used +and V13 will need some more additions but isn't researched yet, +especially as it seems to be limited to the rk1808 which hasn't +reached much market spread. + +V20 on the other hand will probably be used in future SoCs and +has seen really big changes in the vendor kernel, so will need +quite a bit of research. + +Changes from V10 to V12 +----------------------- + +- V12 supports a new CSI-host implementation but can still + also use the same implementation from V10 +- The module for lens shading correction got changed + from 12bit to 13bit width +- The AWB and AEC modules got replaced to support finer + grained data collection + +Changes from V12 to V13 +----------------------- + +The list for V13 is incomplete and needs further investigation. + +- V13 does not support the old CSI-host implementation anymore diff --git a/Documentation/driver-api/media/drivers/saa7134-devel.rst b/Documentation/driver-api/media/drivers/saa7134-devel.rst new file mode 100644 index 0000000000..167fd729bc --- /dev/null +++ b/Documentation/driver-api/media/drivers/saa7134-devel.rst @@ -0,0 +1,67 @@ +.. SPDX-License-Identifier: GPL-2.0 + +The saa7134 driver +================== + +Author Gerd Hoffmann + + +Card Variations: +---------------- + +Cards can use either of these two crystals (xtal): + +- 32.11 MHz -> .audio_clock=0x187de7 +- 24.576MHz -> .audio_clock=0x200000 (xtal * .audio_clock = 51539600) + +Some details about 30/34/35: + +- saa7130 - low-price chip, doesn't have mute, that is why all those + cards should have .mute field defined in their tuner structure. + +- saa7134 - usual chip + +- saa7133/35 - saa7135 is probably a marketing decision, since all those + chips identifies itself as 33 on pci. + +LifeView GPIOs +-------------- + +This section was authored by: Peter Missel <peter.missel@onlinehome.de> + +- LifeView FlyTV Platinum FM (LR214WF) + + - GP27 MDT2005 PB4 pin 10 + - GP26 MDT2005 PB3 pin 9 + - GP25 MDT2005 PB2 pin 8 + - GP23 MDT2005 PB1 pin 7 + - GP22 MDT2005 PB0 pin 6 + - GP21 MDT2005 PB5 pin 11 + - GP20 MDT2005 PB6 pin 12 + - GP19 MDT2005 PB7 pin 13 + - nc MDT2005 PA3 pin 2 + - Remote MDT2005 PA2 pin 1 + - GP18 MDT2005 PA1 pin 18 + - nc MDT2005 PA0 pin 17 strap low + - GP17 Strap "GP7"=High + - GP16 Strap "GP6"=High + + - 0=Radio 1=TV + - Drives SA630D ENCH1 and HEF4052 A1 pinsto do FM radio through + SIF input + + - GP15 nc + - GP14 nc + - GP13 nc + - GP12 Strap "GP5" = High + - GP11 Strap "GP4" = High + - GP10 Strap "GP3" = High + - GP09 Strap "GP2" = Low + - GP08 Strap "GP1" = Low + - GP07.00 nc + +Credits +------- + +andrew.stevens@philips.com + werner.leeb@philips.com for providing +saa7134 hardware specs and sample board. diff --git a/Documentation/driver-api/media/drivers/sh_mobile_ceu_camera.rst b/Documentation/driver-api/media/drivers/sh_mobile_ceu_camera.rst new file mode 100644 index 0000000000..822fcb8368 --- /dev/null +++ b/Documentation/driver-api/media/drivers/sh_mobile_ceu_camera.rst @@ -0,0 +1,142 @@ +.. SPDX-License-Identifier: GPL-2.0 + +Cropping and Scaling algorithm, used in the sh_mobile_ceu_camera driver +======================================================================= + +Author: Guennadi Liakhovetski <g.liakhovetski@gmx.de> + +Terminology +----------- + +sensor scales: horizontal and vertical scales, configured by the sensor driver +host scales: -"- host driver +combined scales: sensor_scale * host_scale + + +Generic scaling / cropping scheme +--------------------------------- + +.. code-block:: none + + -1-- + | + -2-- -\ + | --\ + | --\ + +-5-- . -- -3-- -\ + | `... -\ + | `... -4-- . - -7.. + | `. + | `. .6-- + | + | . .6'- + | .´ + | ... -4'- .´ + | ...´ - -7'. + +-5'- .´ -/ + | -- -3'- -/ + | --/ + | --/ + -2'- -/ + | + | + -1'- + +In the above chart minuses and slashes represent "real" data amounts, points and +accents represent "useful" data, basically, CEU scaled and cropped output, +mapped back onto the client's source plane. + +Such a configuration can be produced by user requests: + +S_CROP(left / top = (5) - (1), width / height = (5') - (5)) +S_FMT(width / height = (6') - (6)) + +Here: + +(1) to (1') - whole max width or height +(1) to (2) - sensor cropped left or top +(2) to (2') - sensor cropped width or height +(3) to (3') - sensor scale +(3) to (4) - CEU cropped left or top +(4) to (4') - CEU cropped width or height +(5) to (5') - reverse sensor scale applied to CEU cropped width or height +(2) to (5) - reverse sensor scale applied to CEU cropped left or top +(6) to (6') - CEU scale - user window + + +S_FMT +----- + +Do not touch input rectangle - it is already optimal. + +1. Calculate current sensor scales: + + scale_s = ((2') - (2)) / ((3') - (3)) + +2. Calculate "effective" input crop (sensor subwindow) - CEU crop scaled back at +current sensor scales onto input window - this is user S_CROP: + + width_u = (5') - (5) = ((4') - (4)) * scale_s + +3. Calculate new combined scales from "effective" input window to requested user +window: + + scale_comb = width_u / ((6') - (6)) + +4. Calculate sensor output window by applying combined scales to real input +window: + + width_s_out = ((7') - (7)) = ((2') - (2)) / scale_comb + +5. Apply iterative sensor S_FMT for sensor output window. + + subdev->video_ops->s_fmt(.width = width_s_out) + +6. Retrieve sensor output window (g_fmt) + +7. Calculate new sensor scales: + + scale_s_new = ((3')_new - (3)_new) / ((2') - (2)) + +8. Calculate new CEU crop - apply sensor scales to previously calculated +"effective" crop: + + width_ceu = (4')_new - (4)_new = width_u / scale_s_new + left_ceu = (4)_new - (3)_new = ((5) - (2)) / scale_s_new + +9. Use CEU cropping to crop to the new window: + + ceu_crop(.width = width_ceu, .left = left_ceu) + +10. Use CEU scaling to scale to the requested user window: + + scale_ceu = width_ceu / width + + +S_CROP +------ + +The :ref:`V4L2 crop API <crop-scale>` says: + +"...specification does not define an origin or units. However by convention +drivers should horizontally count unscaled samples relative to 0H." + +We choose to follow the advise and interpret cropping units as client input +pixels. + +Cropping is performed in the following 6 steps: + +1. Request exactly user rectangle from the sensor. + +2. If smaller - iterate until a larger one is obtained. Result: sensor cropped + to 2 : 2', target crop 5 : 5', current output format 6' - 6. + +3. In the previous step the sensor has tried to preserve its output frame as + good as possible, but it could have changed. Retrieve it again. + +4. Sensor scaled to 3 : 3'. Sensor's scale is (2' - 2) / (3' - 3). Calculate + intermediate window: 4' - 4 = (5' - 5) * (3' - 3) / (2' - 2) + +5. Calculate and apply host scale = (6' - 6) / (4' - 4) + +6. Calculate and apply host crop: 6 - 7 = (5 - 2) * (6' - 6) / (5' - 5) diff --git a/Documentation/driver-api/media/drivers/tuners.rst b/Documentation/driver-api/media/drivers/tuners.rst new file mode 100644 index 0000000000..d7924141c5 --- /dev/null +++ b/Documentation/driver-api/media/drivers/tuners.rst @@ -0,0 +1,133 @@ +.. SPDX-License-Identifier: GPL-2.0 + +Tuner drivers +============= + +Simple tuner Programming +------------------------ + +There are some flavors of Tuner programming APIs. +These differ mainly by the bandswitch byte. + +- L= LG_API (VHF_LO=0x01, VHF_HI=0x02, UHF=0x08, radio=0x04) +- P= PHILIPS_API (VHF_LO=0xA0, VHF_HI=0x90, UHF=0x30, radio=0x04) +- T= TEMIC_API (VHF_LO=0x02, VHF_HI=0x04, UHF=0x01) +- A= ALPS_API (VHF_LO=0x14, VHF_HI=0x12, UHF=0x11) +- M= PHILIPS_MK3 (VHF_LO=0x01, VHF_HI=0x02, UHF=0x04, radio=0x19) + +Tuner Manufacturers +------------------- + +- Samsung Tuner identification: (e.g. TCPM9091PD27) + +.. code-block:: none + + TCP [ABCJLMNQ] 90[89][125] [DP] [ACD] 27 [ABCD] + [ABCJLMNQ]: + A= BG+DK + B= BG + C= I+DK + J= NTSC-Japan + L= Secam LL + M= BG+I+DK + N= NTSC + Q= BG+I+DK+LL + [89]: ? + [125]: + 2: No FM + 5: With FM + [DP]: + D= NTSC + P= PAL + [ACD]: + A= F-connector + C= Phono connector + D= Din Jack + [ABCD]: + 3-wire/I2C tuning, 2-band/3-band + +These Tuners are PHILIPS_API compatible. + +Philips Tuner identification: (e.g. FM1216MF) + +.. code-block:: none + + F[IRMQ]12[1345]6{MF|ME|MP} + F[IRMQ]: + FI12x6: Tuner Series + FR12x6: Tuner + Radio IF + FM12x6: Tuner + FM + FQ12x6: special + FMR12x6: special + TD15xx: Digital Tuner ATSC + 12[1345]6: + 1216: PAL BG + 1236: NTSC + 1246: PAL I + 1256: Pal DK + {MF|ME|MP} + MF: BG LL w/ Secam (Multi France) + ME: BG DK I LL (Multi Europe) + MP: BG DK I (Multi PAL) + MR: BG DK M (?) + MG: BG DKI M (?) + MK2 series PHILIPS_API, most tuners are compatible to this one ! + MK3 series introduced in 2002 w/ PHILIPS_MK3_API + +Temic Tuner identification: (.e.g 4006FH5) + +.. code-block:: none + + 4[01][0136][269]F[HYNR]5 + 40x2: Tuner (5V/33V), TEMIC_API. + 40x6: Tuner 5V + 41xx: Tuner compact + 40x9: Tuner+FM compact + [0136] + xx0x: PAL BG + xx1x: Pal DK, Secam LL + xx3x: NTSC + xx6x: PAL I + F[HYNR]5 + FH5: Pal BG + FY5: others + FN5: multistandard + FR5: w/ FM radio + 3X xxxx: order number with specific connector + Note: Only 40x2 series has TEMIC_API, all newer tuners have PHILIPS_API. + +LG Innotek Tuner: + +- TPI8NSR11 : NTSC J/M (TPI8NSR01 w/FM) (P,210/497) +- TPI8PSB11 : PAL B/G (TPI8PSB01 w/FM) (P,170/450) +- TAPC-I701 : PAL I (TAPC-I001 w/FM) (P,170/450) +- TPI8PSB12 : PAL D/K+B/G (TPI8PSB02 w/FM) (P,170/450) +- TAPC-H701P: NTSC_JP (TAPC-H001P w/FM) (L,170/450) +- TAPC-G701P: PAL B/G (TAPC-G001P w/FM) (L,170/450) +- TAPC-W701P: PAL I (TAPC-W001P w/FM) (L,170/450) +- TAPC-Q703P: PAL D/K (TAPC-Q001P w/FM) (L,170/450) +- TAPC-Q704P: PAL D/K+I (L,170/450) +- TAPC-G702P: PAL D/K+B/G (L,170/450) + +- TADC-H002F: NTSC (L,175/410?; 2-B, C-W+11, W+12-69) +- TADC-M201D: PAL D/K+B/G+I (L,143/425) (sound control at I2C address 0xc8) +- TADC-T003F: NTSC Taiwan (L,175/410?; 2-B, C-W+11, W+12-69) + +Suffix: + - P= Standard phono female socket + - D= IEC female socket + - F= F-connector + +Other Tuners: + +- TCL2002MB-1 : PAL BG + DK =TUNER_LG_PAL_NEW_TAPC +- TCL2002MB-1F: PAL BG + DK w/FM =PHILIPS_PAL +- TCL2002MI-2 : PAL I = ?? + +ALPS Tuners: + +- Most are LG_API compatible +- TSCH6 has ALPS_API (TSCH5 ?) +- TSBE1 has extra API 05,02,08 Control_byte=0xCB Source:[#f1]_ + +.. [#f1] conexant100029b-PCI-Decoder-ApplicationNote.pdf diff --git a/Documentation/driver-api/media/drivers/vidtv.rst b/Documentation/driver-api/media/drivers/vidtv.rst new file mode 100644 index 0000000000..54f269f478 --- /dev/null +++ b/Documentation/driver-api/media/drivers/vidtv.rst @@ -0,0 +1,513 @@ +.. SPDX-License-Identifier: GPL-2.0 + +================================ +vidtv: Virtual Digital TV driver +================================ + +Author: Daniel W. S. Almeida <dwlsalmeida@gmail.com>, June 2020. + +Background +---------- + +Vidtv is a virtual DVB driver that aims to serve as a reference for driver +writers by serving as a template. It also validates the existing media DVB +APIs, thus helping userspace application writers. + +Currently, it consists of: + +- A fake tuner driver, which will report a bad signal quality if the chosen + frequency is too far away from a table of valid frequencies for a + particular delivery system. + +- A fake demod driver, which will constantly poll the fake signal quality + returned by the tuner, simulating a device that can lose/reacquire a lock + on the signal depending on the CNR levels. + +- A fake bridge driver, which is the module responsible for modprobing the + fake tuner and demod modules and implementing the demux logic. This module + takes parameters at initialization that will dictate how the simulation + behaves. + +- Code responsible for encoding a valid MPEG Transport Stream, which is then + passed to the bridge driver. This fake stream contains some hardcoded content. + For now, we have a single, audio-only channel containing a single MPEG + Elementary Stream, which in turn contains a SMPTE 302m encoded sine-wave. + Note that this particular encoder was chosen because it is the easiest + way to encode PCM audio data in a MPEG Transport Stream. + +Building vidtv +-------------- +vidtv is a test driver and thus is **not** enabled by default when +compiling the kernel. + +In order to enable compilation of vidtv: + +- Enable **DVB_TEST_DRIVERS**, then +- Enable **DVB_VIDTV** + +When compiled as a module, expect the following .ko files: + +- dvb_vidtv_tuner.ko + +- dvb_vidtv_demod.ko + +- dvb_vidtv_bridge.ko + +Running vidtv +------------- +When compiled as a module, run:: + + modprobe vidtv + +That's it! The bridge driver will initialize the tuner and demod drivers as +part of its own initialization. + +By default, it will accept the following frequencies: + + - 474 MHz for DVB-T/T2/C; + - 11,362 GHz for DVB-S/S2. + +For satellite systems, the driver simulates an universal extended +LNBf, with frequencies at Ku-Band, ranging from 10.7 GHz to 12.75 GHz. + +You can optionally define some command-line arguments to vidtv. + +Command-line arguments to vidtv +------------------------------- +Below is a list of all arguments that can be supplied to vidtv: + +drop_tslock_prob_on_low_snr + Probability of losing the TS lock if the signal quality is bad. + This probability be used by the fake demodulator driver to + eventually return a status of 0 when the signal quality is not + good. + +recover_tslock_prob_on_good_snr: + Probability recovering the TS lock when the signal improves. This + probability be used by the fake demodulator driver to eventually + return a status of 0x1f when/if the signal quality improves. + +mock_power_up_delay_msec + Simulate a power up delay. Default: 0. + +mock_tune_delay_msec + Simulate a tune delay. Default 0. + +vidtv_valid_dvb_t_freqs + Valid DVB-T frequencies to simulate, in Hz. + +vidtv_valid_dvb_c_freqs + Valid DVB-C frequencies to simulate, in Hz. + +vidtv_valid_dvb_s_freqs + Valid DVB-S/S2 frequencies to simulate at Ku-Band, in kHz. + +max_frequency_shift_hz, + Maximum shift in HZ allowed when tuning in a channel. + +si_period_msec + How often to send SI packets. Default: 40ms. + +pcr_period_msec + How often to send PCR packets. Default: 40ms. + +mux_rate_kbytes_sec + Attempt to maintain this bit rate by inserting TS null packets, if + necessary. Default: 4096. + +pcr_pid, + PCR PID for all channels. Default: 0x200. + +mux_buf_sz_pkts, + Size for the mux buffer in multiples of 188 bytes. + +vidtv internal structure +------------------------ +The kernel modules are split in the following way: + +vidtv_tuner.[ch] + Implements a fake tuner DVB driver. + +vidtv_demod.[ch] + Implements a fake demodulator DVB driver. + +vidtv_bridge.[ch] + Implements a bridge driver. + +The MPEG related code is split in the following way: + +vidtv_ts.[ch] + Code to work with MPEG TS packets, such as TS headers, adaptation + fields, PCR packets and NULL packets. + +vidtv_psi.[ch] + This is the PSI generator. PSI packets contain general information + about a MPEG Transport Stream. A PSI generator is needed so + userspace apps can retrieve information about the Transport Stream + and eventually tune into a (dummy) channel. + + Because the generator is implemented in a separate file, it can be + reused elsewhere in the media subsystem. + + Currently vidtv supports working with 5 PSI tables: PAT, PMT, + SDT, NIT and EIT. + + The specification for PAT and PMT can be found in *ISO 13818-1: + Systems*, while the specification for the SDT, NIT, EIT can be found in *ETSI + EN 300 468: Specification for Service Information (SI) in DVB + systems*. + + It isn't strictly necessary, but using a real TS file helps when + debugging PSI tables. Vidtv currently tries to replicate the PSI + structure found in this file: `TS1Globo.ts + <https://tsduck.io/streams/brazil-isdb-tb/TS1globo.ts>`_. + + A good way to visualize the structure of streams is by using + `DVBInspector <https://sourceforge.net/projects/dvbinspector/>`_. + +vidtv_pes.[ch] + Implements the PES logic to convert encoder data into MPEG TS + packets. These can then be fed into a TS multiplexer and eventually + into userspace. + +vidtv_encoder.h + An interface for vidtv encoders. New encoders can be added to this + driver by implementing the calls in this file. + +vidtv_s302m.[ch] + Implements a S302M encoder to make it possible to insert PCM audio + data in the generated MPEG Transport Stream. The relevant + specification is available online as *SMPTE 302M-2007: Television - + Mapping of AES3 Data into MPEG-2 Transport Stream*. + + + The resulting MPEG Elementary Stream is conveyed in a private + stream with a S302M registration descriptor attached. + + This shall enable passing an audio signal into userspace so it can + be decoded and played by media software. The corresponding decoder + in ffmpeg is located in 'libavcodec/s302m.c' and is experimental. + +vidtv_channel.[ch] + Implements a 'channel' abstraction. + + When vidtv boots, it will create some hardcoded channels: + + #. Their services will be concatenated to populate the SDT. + + #. Their programs will be concatenated to populate the PAT + + #. Their events will be concatenated to populate the EIT + + #. For each program in the PAT, a PMT section will be created + + #. The PMT section for a channel will be assigned its streams. + + #. Every stream will have its corresponding encoder polled in a + loop to produce TS packets. + These packets may be interleaved by the muxer and then delivered + to the bridge. + +vidtv_mux.[ch] + Implements a MPEG TS mux, loosely based on the ffmpeg + implementation in "libavcodec/mpegtsenc.c" + + The muxer runs a loop which is responsible for: + + #. Keeping track of the amount of time elapsed since the last + iteration. + + #. Polling encoders in order to fetch 'elapsed_time' worth of data. + + #. Inserting PSI and/or PCR packets, if needed. + + #. Padding the resulting stream with NULL packets if + necessary in order to maintain the chosen bit rate. + + #. Delivering the resulting TS packets to the bridge + driver so it can pass them to the demux. + +Testing vidtv with v4l-utils +---------------------------- + +Using the tools in v4l-utils is a great way to test and inspect the output of +vidtv. It is hosted here: `v4l-utils Documentation +<https://linuxtv.org/wiki/index.php/V4l-utils>`_. + +From its webpage:: + + The v4l-utils are a series of packages for handling media devices. + + It is hosted at http://git.linuxtv.org/v4l-utils.git, and packaged + on most distributions. + + It provides a series of libraries and utilities to be used to + control several aspect of the media boards. + + +Start by installing v4l-utils and then modprobing vidtv:: + + modprobe dvb_vidtv_bridge + +If the driver is OK, it should load and its probing code will run. This will +pull in the tuner and demod drivers. + +Using dvb-fe-tool +~~~~~~~~~~~~~~~~~ + +The first step to check whether the demod loaded successfully is to run:: + + $ dvb-fe-tool + Device Dummy demod for DVB-T/T2/C/S/S2 (/dev/dvb/adapter0/frontend0) capabilities: + CAN_FEC_1_2 + CAN_FEC_2_3 + CAN_FEC_3_4 + CAN_FEC_4_5 + CAN_FEC_5_6 + CAN_FEC_6_7 + CAN_FEC_7_8 + CAN_FEC_8_9 + CAN_FEC_AUTO + CAN_GUARD_INTERVAL_AUTO + CAN_HIERARCHY_AUTO + CAN_INVERSION_AUTO + CAN_QAM_16 + CAN_QAM_32 + CAN_QAM_64 + CAN_QAM_128 + CAN_QAM_256 + CAN_QAM_AUTO + CAN_QPSK + CAN_TRANSMISSION_MODE_AUTO + DVB API Version 5.11, Current v5 delivery system: DVBC/ANNEX_A + Supported delivery systems: + DVBT + DVBT2 + [DVBC/ANNEX_A] + DVBS + DVBS2 + Frequency range for the current standard: + From: 51.0 MHz + To: 2.15 GHz + Step: 62.5 kHz + Tolerance: 29.5 MHz + Symbol rate ranges for the current standard: + From: 1.00 MBauds + To: 45.0 MBauds + +This should return what is currently set up at the demod struct, i.e.:: + + static const struct dvb_frontend_ops vidtv_demod_ops = { + .delsys = { + SYS_DVBT, + SYS_DVBT2, + SYS_DVBC_ANNEX_A, + SYS_DVBS, + SYS_DVBS2, + }, + + .info = { + .name = "Dummy demod for DVB-T/T2/C/S/S2", + .frequency_min_hz = 51 * MHz, + .frequency_max_hz = 2150 * MHz, + .frequency_stepsize_hz = 62500, + .frequency_tolerance_hz = 29500 * kHz, + .symbol_rate_min = 1000000, + .symbol_rate_max = 45000000, + + .caps = FE_CAN_FEC_1_2 | + FE_CAN_FEC_2_3 | + FE_CAN_FEC_3_4 | + FE_CAN_FEC_4_5 | + FE_CAN_FEC_5_6 | + FE_CAN_FEC_6_7 | + FE_CAN_FEC_7_8 | + FE_CAN_FEC_8_9 | + FE_CAN_QAM_16 | + FE_CAN_QAM_64 | + FE_CAN_QAM_32 | + FE_CAN_QAM_128 | + FE_CAN_QAM_256 | + FE_CAN_QAM_AUTO | + FE_CAN_QPSK | + FE_CAN_FEC_AUTO | + FE_CAN_INVERSION_AUTO | + FE_CAN_TRANSMISSION_MODE_AUTO | + FE_CAN_GUARD_INTERVAL_AUTO | + FE_CAN_HIERARCHY_AUTO, + } + + .... + +For more information on dvb-fe-tools check its online documentation here: +`dvb-fe-tool Documentation +<https://www.linuxtv.org/wiki/index.php/Dvb-fe-tool>`_. + +Using dvb-scan +~~~~~~~~~~~~~~ + +In order to tune into a channel and read the PSI tables, we can use dvb-scan. + +For this, one should provide a configuration file known as a 'scan file', +here's an example:: + + [Channel] + FREQUENCY = 474000000 + MODULATION = QAM/AUTO + SYMBOL_RATE = 6940000 + INNER_FEC = AUTO + DELIVERY_SYSTEM = DVBC/ANNEX_A + +.. note:: + The parameters depend on the video standard you're testing. + +.. note:: + Vidtv is a fake driver and does not validate much of the information + in the scan file. Just specifying 'FREQUENCY' and 'DELIVERY_SYSTEM' + should be enough for DVB-T/DVB-T2. For DVB-S/DVB-C however, you + should also provide 'SYMBOL_RATE'. + +You can browse scan tables online here: `dvb-scan-tables +<https://git.linuxtv.org/dtv-scan-tables.git>`_. + +Assuming this channel is named 'channel.conf', you can then run:: + + $ dvbv5-scan channel.conf + dvbv5-scan ~/vidtv.conf + ERROR command BANDWIDTH_HZ (5) not found during retrieve + Cannot calc frequency shift. Either bandwidth/symbol-rate is unavailable (yet). + Scanning frequency #1 330000000 + (0x00) Signal= -68.00dBm + Scanning frequency #2 474000000 + Lock (0x1f) Signal= -34.45dBm C/N= 33.74dB UCB= 0 + Service Beethoven, provider LinuxTV.org: digital television + +For more information on dvb-scan, check its documentation online here: +`dvb-scan Documentation <https://www.linuxtv.org/wiki/index.php/Dvbscan>`_. + +Using dvb-zap +~~~~~~~~~~~~~ + +dvbv5-zap is a command line tool that can be used to record MPEG-TS to disk. The +typical use is to tune into a channel and put it into record mode. The example +below - which is taken from the documentation - illustrates that\ [1]_:: + + $ dvbv5-zap -c dvb_channel.conf "beethoven" -o music.ts -P -t 10 + using demux 'dvb0.demux0' + reading channels from file 'dvb_channel.conf' + tuning to 474000000 Hz + pass all PID's to TS + dvb_set_pesfilter 8192 + dvb_dev_set_bufsize: buffer set to 6160384 + Lock (0x1f) Quality= Good Signal= -34.66dBm C/N= 33.41dB UCB= 0 postBER= 0 preBER= 1.05x10^-3 PER= 0 + Lock (0x1f) Quality= Good Signal= -34.57dBm C/N= 33.46dB UCB= 0 postBER= 0 preBER= 1.05x10^-3 PER= 0 + Record to file 'music.ts' started + received 24587768 bytes (2401 Kbytes/sec) + Lock (0x1f) Quality= Good Signal= -34.42dBm C/N= 33.89dB UCB= 0 postBER= 0 preBER= 2.44x10^-3 PER= 0 + +.. [1] In this example, it records 10 seconds with all program ID's stored + at the music.ts file. + + +The channel can be watched by playing the contents of the stream with some +player that recognizes the MPEG-TS format, such as ``mplayer`` or ``vlc``. + +By playing the contents of the stream one can visually inspect the workings of +vidtv, e.g., to play a recorded TS file with:: + + $ mplayer music.ts + +or, alternatively, running this command on one terminal:: + + $ dvbv5-zap -c dvb_channel.conf "beethoven" -P -r & + +And, on a second terminal, playing the contents from DVR interface with:: + + $ mplayer /dev/dvb/adapter0/dvr0 + +For more information on dvb-zap check its online documentation here: +`dvb-zap Documentation +<https://www.linuxtv.org/wiki/index.php/Dvbv5-zap>`_. +See also: `zap <https://www.linuxtv.org/wiki/index.php/Zap>`_. + + +What can still be improved in vidtv +----------------------------------- + +Add *debugfs* integration +~~~~~~~~~~~~~~~~~~~~~~~~~ + +Although frontend drivers provide DVBv5 statistics via the .read_status +call, a nice addition would be to make additional statistics available to +userspace via debugfs, which is a simple-to-use, RAM-based filesystem +specifically designed for debug purposes. + +The logic for this would be implemented on a separate file so as not to +pollute the frontend driver. These statistics are driver-specific and can +be useful during tests. + +The Siano driver is one example of a driver using +debugfs to convey driver-specific statistics to userspace and it can be +used as a reference. + +This should be further enabled and disabled via a Kconfig +option for convenience. + +Add a way to test video +~~~~~~~~~~~~~~~~~~~~~~~ + +Currently, vidtv can only encode PCM audio. It would be great to implement +a barebones version of MPEG-2 video encoding so we can also test video. The +first place to look into is *ISO 13818-2: Information technology — Generic +coding of moving pictures and associated audio information — Part 2: Video*, +which covers the encoding of compressed video in MPEG Transport Streams. + +This might optionally use the Video4Linux2 Test Pattern Generator, v4l2-tpg, +which resides at:: + + drivers/media/common/v4l2-tpg/ + + +Add white noise simulation +~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The vidtv tuner already has code to identify whether the chosen frequency +is too far away from a table of valid frequencies. For now, this means that +the demodulator can eventually lose the lock on the signal, since the tuner will +report a bad signal quality. + +A nice addition is to simulate some noise when the signal quality is bad by: + +- Randomly dropping some TS packets. This will trigger a continuity error if the + continuity counter is updated but the packet is not passed on to the demux. + +- Updating the error statistics accordingly (e.g. BER, etc). + +- Simulating some noise in the encoded data. + +Functions and structs used within vidtv +--------------------------------------- + +.. kernel-doc:: drivers/media/test-drivers/vidtv/vidtv_bridge.h + +.. kernel-doc:: drivers/media/test-drivers/vidtv/vidtv_channel.h + +.. kernel-doc:: drivers/media/test-drivers/vidtv/vidtv_demod.h + +.. kernel-doc:: drivers/media/test-drivers/vidtv/vidtv_encoder.h + +.. kernel-doc:: drivers/media/test-drivers/vidtv/vidtv_mux.h + +.. kernel-doc:: drivers/media/test-drivers/vidtv/vidtv_pes.h + +.. kernel-doc:: drivers/media/test-drivers/vidtv/vidtv_psi.h + +.. kernel-doc:: drivers/media/test-drivers/vidtv/vidtv_s302m.h + +.. kernel-doc:: drivers/media/test-drivers/vidtv/vidtv_ts.h + +.. kernel-doc:: drivers/media/test-drivers/vidtv/vidtv_tuner.h + +.. kernel-doc:: drivers/media/test-drivers/vidtv/vidtv_common.c + +.. kernel-doc:: drivers/media/test-drivers/vidtv/vidtv_tuner.c diff --git a/Documentation/driver-api/media/drivers/vimc-devel.rst b/Documentation/driver-api/media/drivers/vimc-devel.rst new file mode 100644 index 0000000000..9e984f914b --- /dev/null +++ b/Documentation/driver-api/media/drivers/vimc-devel.rst @@ -0,0 +1,15 @@ +.. SPDX-License-Identifier: GPL-2.0 + +The Virtual Media Controller Driver (vimc) +========================================== + +Source code documentation +------------------------- + +vimc-streamer +~~~~~~~~~~~~~ + +.. kernel-doc:: drivers/media/test-drivers/vimc/vimc-streamer.h + :internal: + +.. kernel-doc:: drivers/media/test-drivers/vimc/vimc-streamer.c diff --git a/Documentation/driver-api/media/drivers/zoran.rst b/Documentation/driver-api/media/drivers/zoran.rst new file mode 100644 index 0000000000..b205e10c31 --- /dev/null +++ b/Documentation/driver-api/media/drivers/zoran.rst @@ -0,0 +1,575 @@ +.. SPDX-License-Identifier: GPL-2.0 + +The Zoran driver +================ + +unified zoran driver (zr360x7, zoran, buz, dc10(+), dc30(+), lml33) + +website: http://mjpeg.sourceforge.net/driver-zoran/ + + +Frequently Asked Questions +-------------------------- + +What cards are supported +------------------------ + +Iomega Buz, Linux Media Labs LML33/LML33R10, Pinnacle/Miro +DC10/DC10+/DC30/DC30+ and related boards (available under various names). + +Iomega Buz +~~~~~~~~~~ + +* Zoran zr36067 PCI controller +* Zoran zr36060 MJPEG codec +* Philips saa7111 TV decoder +* Philips saa7185 TV encoder + +Drivers to use: videodev, i2c-core, i2c-algo-bit, +videocodec, saa7111, saa7185, zr36060, zr36067 + +Inputs/outputs: Composite and S-video + +Norms: PAL, SECAM (720x576 @ 25 fps), NTSC (720x480 @ 29.97 fps) + +Card number: 7 + +AverMedia 6 Eyes AVS6EYES +~~~~~~~~~~~~~~~~~~~~~~~~~ + +* Zoran zr36067 PCI controller +* Zoran zr36060 MJPEG codec +* Samsung ks0127 TV decoder +* Conexant bt866 TV encoder + +Drivers to use: videodev, i2c-core, i2c-algo-bit, +videocodec, ks0127, bt866, zr36060, zr36067 + +Inputs/outputs: + Six physical inputs. 1-6 are composite, + 1-2, 3-4, 5-6 doubles as S-video, + 1-3 triples as component. + One composite output. + +Norms: PAL, SECAM (720x576 @ 25 fps), NTSC (720x480 @ 29.97 fps) + +Card number: 8 + +.. note:: + + Not autodetected, card=8 is necessary. + +Linux Media Labs LML33 +~~~~~~~~~~~~~~~~~~~~~~ + +* Zoran zr36067 PCI controller +* Zoran zr36060 MJPEG codec +* Brooktree bt819 TV decoder +* Brooktree bt856 TV encoder + +Drivers to use: videodev, i2c-core, i2c-algo-bit, +videocodec, bt819, bt856, zr36060, zr36067 + +Inputs/outputs: Composite and S-video + +Norms: PAL (720x576 @ 25 fps), NTSC (720x480 @ 29.97 fps) + +Card number: 5 + +Linux Media Labs LML33R10 +~~~~~~~~~~~~~~~~~~~~~~~~~ + +* Zoran zr36067 PCI controller +* Zoran zr36060 MJPEG codec +* Philips saa7114 TV decoder +* Analog Devices adv7170 TV encoder + +Drivers to use: videodev, i2c-core, i2c-algo-bit, +videocodec, saa7114, adv7170, zr36060, zr36067 + +Inputs/outputs: Composite and S-video + +Norms: PAL (720x576 @ 25 fps), NTSC (720x480 @ 29.97 fps) + +Card number: 6 + +Pinnacle/Miro DC10(new) +~~~~~~~~~~~~~~~~~~~~~~~ + +* Zoran zr36057 PCI controller +* Zoran zr36060 MJPEG codec +* Philips saa7110a TV decoder +* Analog Devices adv7176 TV encoder + +Drivers to use: videodev, i2c-core, i2c-algo-bit, +videocodec, saa7110, adv7175, zr36060, zr36067 + +Inputs/outputs: Composite, S-video and Internal + +Norms: PAL, SECAM (768x576 @ 25 fps), NTSC (640x480 @ 29.97 fps) + +Card number: 1 + +Pinnacle/Miro DC10+ +~~~~~~~~~~~~~~~~~~~ + +* Zoran zr36067 PCI controller +* Zoran zr36060 MJPEG codec +* Philips saa7110a TV decoder +* Analog Devices adv7176 TV encoder + +Drivers to use: videodev, i2c-core, i2c-algo-bit, +videocodec, saa7110, adv7175, zr36060, zr36067 + +Inputs/outputs: Composite, S-video and Internal + +Norms: PAL, SECAM (768x576 @ 25 fps), NTSC (640x480 @ 29.97 fps) + +Card number: 2 + +Pinnacle/Miro DC10(old) +~~~~~~~~~~~~~~~~~~~~~~~ + +* Zoran zr36057 PCI controller +* Zoran zr36050 MJPEG codec +* Zoran zr36016 Video Front End or Fuji md0211 Video Front End (clone?) +* Micronas vpx3220a TV decoder +* mse3000 TV encoder or Analog Devices adv7176 TV encoder + +Drivers to use: videodev, i2c-core, i2c-algo-bit, +videocodec, vpx3220, mse3000/adv7175, zr36050, zr36016, zr36067 + +Inputs/outputs: Composite, S-video and Internal + +Norms: PAL, SECAM (768x576 @ 25 fps), NTSC (640x480 @ 29.97 fps) + +Card number: 0 + +Pinnacle/Miro DC30 +~~~~~~~~~~~~~~~~~~ + +* Zoran zr36057 PCI controller +* Zoran zr36050 MJPEG codec +* Zoran zr36016 Video Front End +* Micronas vpx3225d/vpx3220a/vpx3216b TV decoder +* Analog Devices adv7176 TV encoder + +Drivers to use: videodev, i2c-core, i2c-algo-bit, +videocodec, vpx3220/vpx3224, adv7175, zr36050, zr36016, zr36067 + +Inputs/outputs: Composite, S-video and Internal + +Norms: PAL, SECAM (768x576 @ 25 fps), NTSC (640x480 @ 29.97 fps) + +Card number: 3 + +Pinnacle/Miro DC30+ +~~~~~~~~~~~~~~~~~~~ + +* Zoran zr36067 PCI controller +* Zoran zr36050 MJPEG codec +* Zoran zr36016 Video Front End +* Micronas vpx3225d/vpx3220a/vpx3216b TV decoder +* Analog Devices adv7176 TV encoder + +Drivers to use: videodev, i2c-core, i2c-algo-bit, +videocodec, vpx3220/vpx3224, adv7175, zr36050, zr36015, zr36067 + +Inputs/outputs: Composite, S-video and Internal + +Norms: PAL, SECAM (768x576 @ 25 fps), NTSC (640x480 @ 29.97 fps) + +Card number: 4 + +.. note:: + + #) No module for the mse3000 is available yet + #) No module for the vpx3224 is available yet + +1.1 What the TV decoder can do an what not +------------------------------------------ + +The best know TV standards are NTSC/PAL/SECAM. but for decoding a frame that +information is not enough. There are several formats of the TV standards. +And not every TV decoder is able to handle every format. Also the every +combination is supported by the driver. There are currently 11 different +tv broadcast formats all aver the world. + +The CCIR defines parameters needed for broadcasting the signal. +The CCIR has defined different standards: A,B,D,E,F,G,D,H,I,K,K1,L,M,N,... +The CCIR says not much about the colorsystem used !!! +And talking about a colorsystem says not to much about how it is broadcast. + +The CCIR standards A,E,F are not used any more. + +When you speak about NTSC, you usually mean the standard: CCIR - M using +the NTSC colorsystem which is used in the USA, Japan, Mexico, Canada +and a few others. + +When you talk about PAL, you usually mean: CCIR - B/G using the PAL +colorsystem which is used in many Countries. + +When you talk about SECAM, you mean: CCIR - L using the SECAM Colorsystem +which is used in France, and a few others. + +There the other version of SECAM, CCIR - D/K is used in Bulgaria, China, +Slovakai, Hungary, Korea (Rep.), Poland, Rumania and a others. + +The CCIR - H uses the PAL colorsystem (sometimes SECAM) and is used in +Egypt, Libya, Sri Lanka, Syrain Arab. Rep. + +The CCIR - I uses the PAL colorsystem, and is used in Great Britain, Hong Kong, +Ireland, Nigeria, South Africa. + +The CCIR - N uses the PAL colorsystem and PAL frame size but the NTSC framerate, +and is used in Argentinia, Uruguay, an a few others + +We do not talk about how the audio is broadcast ! + +A rather good sites about the TV standards are: +http://www.sony.jp/support/ +http://info.electronicwerkstatt.de/bereiche/fernsehtechnik/frequenzen_und_normen/Fernsehnormen/ +and http://www.cabl.com/restaurant/channel.html + +Other weird things around: NTSC 4.43 is a modificated NTSC, which is mainly +used in PAL VCR's that are able to play back NTSC. PAL 60 seems to be the same +as NTSC 4.43 . The Datasheets also talk about NTSC 44, It seems as if it would +be the same as NTSC 4.43. +NTSC Combs seems to be a decoder mode where the decoder uses a comb filter +to split coma and luma instead of a Delay line. + +But I did not defiantly find out what NTSC Comb is. + +Philips saa7111 TV decoder +~~~~~~~~~~~~~~~~~~~~~~~~~~ + +- was introduced in 1997, is used in the BUZ and +- can handle: PAL B/G/H/I, PAL N, PAL M, NTSC M, NTSC N, NTSC 4.43 and SECAM + +Philips saa7110a TV decoder +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +- was introduced in 1995, is used in the Pinnacle/Miro DC10(new), DC10+ and +- can handle: PAL B/G, NTSC M and SECAM + +Philips saa7114 TV decoder +~~~~~~~~~~~~~~~~~~~~~~~~~~ + +- was introduced in 2000, is used in the LML33R10 and +- can handle: PAL B/G/D/H/I/N, PAL N, PAL M, NTSC M, NTSC 4.43 and SECAM + +Brooktree bt819 TV decoder +~~~~~~~~~~~~~~~~~~~~~~~~~~ + +- was introduced in 1996, and is used in the LML33 and +- can handle: PAL B/D/G/H/I, NTSC M + +Micronas vpx3220a TV decoder +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +- was introduced in 1996, is used in the DC30 and DC30+ and +- can handle: PAL B/G/H/I, PAL N, PAL M, NTSC M, NTSC 44, PAL 60, SECAM,NTSC Comb + +Samsung ks0127 TV decoder +~~~~~~~~~~~~~~~~~~~~~~~~~ + +- is used in the AVS6EYES card and +- can handle: NTSC-M/N/44, PAL-M/N/B/G/H/I/D/K/L and SECAM + + +What the TV encoder can do an what not +-------------------------------------- + +The TV encoder is doing the "same" as the decoder, but in the other direction. +You feed them digital data and the generate a Composite or SVHS signal. +For information about the colorsystems and TV norm take a look in the +TV decoder section. + +Philips saa7185 TV Encoder +~~~~~~~~~~~~~~~~~~~~~~~~~~ + +- was introduced in 1996, is used in the BUZ +- can generate: PAL B/G, NTSC M + +Brooktree bt856 TV Encoder +~~~~~~~~~~~~~~~~~~~~~~~~~~ + +- was introduced in 1994, is used in the LML33 +- can generate: PAL B/D/G/H/I/N, PAL M, NTSC M, PAL-N (Argentina) + +Analog Devices adv7170 TV Encoder +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +- was introduced in 2000, is used in the LML300R10 +- can generate: PAL B/D/G/H/I/N, PAL M, NTSC M, PAL 60 + +Analog Devices adv7175 TV Encoder +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +- was introduced in 1996, is used in the DC10, DC10+, DC10 old, DC30, DC30+ +- can generate: PAL B/D/G/H/I/N, PAL M, NTSC M + +ITT mse3000 TV encoder +~~~~~~~~~~~~~~~~~~~~~~ + +- was introduced in 1991, is used in the DC10 old +- can generate: PAL , NTSC , SECAM + +Conexant bt866 TV encoder +~~~~~~~~~~~~~~~~~~~~~~~~~ + +- is used in AVS6EYES, and +- can generate: NTSC/PAL, PAL-M, PAL-N + +The adv717x, should be able to produce PAL N. But you find nothing PAL N +specific in the registers. Seem that you have to reuse a other standard +to generate PAL N, maybe it would work if you use the PAL M settings. + +How do I get this damn thing to work +------------------------------------ + +Load zr36067.o. If it can't autodetect your card, use the card=X insmod +option with X being the card number as given in the previous section. +To have more than one card, use card=X1[,X2[,X3,[X4[..]]]] + +To automate this, add the following to your /etc/modprobe.d/zoran.conf: + +options zr36067 card=X1[,X2[,X3[,X4[..]]]] +alias char-major-81-0 zr36067 + +One thing to keep in mind is that this doesn't load zr36067.o itself yet. It +just automates loading. If you start using xawtv, the device won't load on +some systems, since you're trying to load modules as a user, which is not +allowed ("permission denied"). A quick workaround is to add 'Load "v4l"' to +XF86Config-4 when you use X by default, or to run 'v4l-conf -c <device>' in +one of your startup scripts (normally rc.local) if you don't use X. Both +make sure that the modules are loaded on startup, under the root account. + +What mainboard should I use (or why doesn't my card work) +--------------------------------------------------------- + + +<insert lousy disclaimer here>. In short: good=SiS/Intel, bad=VIA. + +Experience tells us that people with a Buz, on average, have more problems +than users with a DC10+/LML33. Also, it tells us that people owning a VIA- +based mainboard (ktXXX, MVP3) have more problems than users with a mainboard +based on a different chipset. Here's some notes from Andrew Stevens: + +Here's my experience of using LML33 and Buz on various motherboards: + +- VIA MVP3 + - Forget it. Pointless. Doesn't work. +- Intel 430FX (Pentium 200) + - LML33 perfect, Buz tolerable (3 or 4 frames dropped per movie) +- Intel 440BX (early stepping) + - LML33 tolerable. Buz starting to get annoying (6-10 frames/hour) +- Intel 440BX (late stepping) + - Buz tolerable, LML3 almost perfect (occasional single frame drops) +- SiS735 + - LML33 perfect, Buz tolerable. +- VIA KT133(*) + - LML33 starting to get annoying, Buz poor enough that I have up. + +- Both 440BX boards were dual CPU versions. + +Bernhard Praschinger later added: + +- AMD 751 + - Buz perfect-tolerable +- AMD 760 + - Buz perfect-tolerable + +In general, people on the user mailinglist won't give you much of a chance +if you have a VIA-based motherboard. They may be cheap, but sometimes, you'd +rather want to spend some more money on better boards. In general, VIA +mainboard's IDE/PCI performance will also suck badly compared to others. +You'll noticed the DC10+/DC30+ aren't mentioned anywhere in the overview. +Basically, you can assume that if the Buz works, the LML33 will work too. If +the LML33 works, the DC10+/DC30+ will work too. They're most tolerant to +different mainboard chipsets from all of the supported cards. + +If you experience timeouts during capture, buy a better mainboard or lower +the quality/buffersize during capture (see 'Concerning buffer sizes, quality, +output size etc.'). If it hangs, there's little we can do as of now. Check +your IRQs and make sure the card has its own interrupts. + +Programming interface +--------------------- + +This driver conforms to video4linux2. Support for V4L1 and for the custom +zoran ioctls has been removed in kernel 2.6.38. + +For programming example, please, look at lavrec.c and lavplay.c code in +the MJPEG-tools (http://mjpeg.sf.net/). + +Additional notes for software developers: + + The driver returns maxwidth and maxheight parameters according to + the current TV standard (norm). Therefore, the software which + communicates with the driver and "asks" for these parameters should + first set the correct norm. Well, it seems logically correct: TV + standard is "more constant" for current country than geometry + settings of a variety of TV capture cards which may work in ITU or + square pixel format. + +Applications +------------ + +Applications known to work with this driver: + +TV viewing: + +* xawtv +* kwintv +* probably any TV application that supports video4linux or video4linux2. + +MJPEG capture/playback: + +* mjpegtools/lavtools (or Linux Video Studio) +* gstreamer +* mplayer + +General raw capture: + +* xawtv +* gstreamer +* probably any application that supports video4linux or video4linux2 + +Video editing: + +* Cinelerra +* MainActor +* mjpegtools (or Linux Video Studio) + + +Concerning buffer sizes, quality, output size etc. +-------------------------------------------------- + + +The zr36060 can do 1:2 JPEG compression. This is really the theoretical +maximum that the chipset can reach. The driver can, however, limit compression +to a maximum (size) of 1:4. The reason for this is that some cards (e.g. Buz) +can't handle 1:2 compression without stopping capture after only a few minutes. +With 1:4, it'll mostly work. If you have a Buz, use 'low_bitrate=1' to go into +1:4 max. compression mode. + +100% JPEG quality is thus 1:2 compression in practice. So for a full PAL frame +(size 720x576). The JPEG fields are stored in YUY2 format, so the size of the +fields are 720x288x16/2 bits/field (2 fields/frame) = 207360 bytes/field x 2 = +414720 bytes/frame (add some more bytes for headers and DHT (huffman)/DQT +(quantization) tables, and you'll get to something like 512kB per frame for +1:2 compression. For 1:4 compression, you'd have frames of half this size. + +Some additional explanation by Martin Samuelsson, which also explains the +importance of buffer sizes: +-- +> Hmm, I do not think it is really that way. With the current (downloaded +> at 18:00 Monday) driver I get that output sizes for 10 sec: +> -q 50 -b 128 : 24.283.332 Bytes +> -q 50 -b 256 : 48.442.368 +> -q 25 -b 128 : 24.655.992 +> -q 25 -b 256 : 25.859.820 + +I woke up, and can't go to sleep again. I'll kill some time explaining why +this doesn't look strange to me. + +Let's do some math using a width of 704 pixels. I'm not sure whether the Buz +actually use that number or not, but that's not too important right now. + +704x288 pixels, one field, is 202752 pixels. Divided by 64 pixels per block; +3168 blocks per field. Each pixel consist of two bytes; 128 bytes per block; +1024 bits per block. 100% in the new driver mean 1:2 compression; the maximum +output becomes 512 bits per block. Actually 510, but 512 is simpler to use +for calculations. + +Let's say that we specify d1q50. We thus want 256 bits per block; times 3168 +becomes 811008 bits; 101376 bytes per field. We're talking raw bits and bytes +here, so we don't need to do any fancy corrections for bits-per-pixel or such +things. 101376 bytes per field. + +d1 video contains two fields per frame. Those sum up to 202752 bytes per +frame, and one of those frames goes into each buffer. + +But wait a second! -b128 gives 128kB buffers! It's not possible to cram +202752 bytes of JPEG data into 128kB! + +This is what the driver notice and automatically compensate for in your +examples. Let's do some math using this information: + +128kB is 131072 bytes. In this buffer, we want to store two fields, which +leaves 65536 bytes for each field. Using 3168 blocks per field, we get +20.68686868... available bytes per block; 165 bits. We can't allow the +request for 256 bits per block when there's only 165 bits available! The -q50 +option is silently overridden, and the -b128 option takes precedence, leaving +us with the equivalence of -q32. + +This gives us a data rate of 165 bits per block, which, times 3168, sums up +to 65340 bytes per field, out of the allowed 65536. The current driver has +another level of rate limiting; it won't accept -q values that fill more than +6/8 of the specified buffers. (I'm not sure why. "Playing it safe" seem to be +a safe bet. Personally, I think I would have lowered requested-bits-per-block +by one, or something like that.) We can't use 165 bits per block, but have to +lower it again, to 6/8 of the available buffer space: We end up with 124 bits +per block, the equivalence of -q24. With 128kB buffers, you can't use greater +than -q24 at -d1. (And PAL, and 704 pixels width...) + +The third example is limited to -q24 through the same process. The second +example, using very similar calculations, is limited to -q48. The only +example that actually grab at the specified -q value is the last one, which +is clearly visible, looking at the file size. +-- + +Conclusion: the quality of the resulting movie depends on buffer size, quality, +whether or not you use 'low_bitrate=1' as insmod option for the zr36060.c +module to do 1:4 instead of 1:2 compression, etc. + +If you experience timeouts, lowering the quality/buffersize or using +'low_bitrate=1 as insmod option for zr36060.o might actually help, as is +proven by the Buz. + +It hangs/crashes/fails/whatevers! Help! +--------------------------------------- + +Make sure that the card has its own interrupts (see /proc/interrupts), check +the output of dmesg at high verbosity (load zr36067.o with debug=2, +load all other modules with debug=1). Check that your mainboard is favorable +(see question 2) and if not, test the card in another computer. Also see the +notes given in question 3 and try lowering quality/buffersize/capturesize +if recording fails after a period of time. + +If all this doesn't help, give a clear description of the problem including +detailed hardware information (memory+brand, mainboard+chipset+brand, which +MJPEG card, processor, other PCI cards that might be of interest), give the +system PnP information (/proc/interrupts, /proc/dma, /proc/devices), and give +the kernel version, driver version, glibc version, gcc version and any other +information that might possibly be of interest. Also provide the dmesg output +at high verbosity. See 'Contacting' on how to contact the developers. + +Maintainers/Contacting +---------------------- + +Previous maintainers/developers of this driver are +- Laurent Pinchart <laurent.pinchart@skynet.be> +- Ronald Bultje rbultje@ronald.bitfreak.net +- Serguei Miridonov <mirsev@cicese.mx> +- Wolfgang Scherr <scherr@net4you.net> +- Dave Perks <dperks@ibm.net> +- Rainer Johanni <Rainer@Johanni.de> + +Driver's License +---------------- + + This driver is distributed under the terms of the General Public License. + + 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. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + +See http://www.gnu.org/ for more information. diff --git a/Documentation/driver-api/media/dtv-ca.rst b/Documentation/driver-api/media/dtv-ca.rst new file mode 100644 index 0000000000..8a09862b42 --- /dev/null +++ b/Documentation/driver-api/media/dtv-ca.rst @@ -0,0 +1,6 @@ +.. SPDX-License-Identifier: GPL-2.0 + +Digital TV Conditional Access kABI +---------------------------------- + +.. kernel-doc:: include/media/dvb_ca_en50221.h diff --git a/Documentation/driver-api/media/dtv-common.rst b/Documentation/driver-api/media/dtv-common.rst new file mode 100644 index 0000000000..207a22bcaf --- /dev/null +++ b/Documentation/driver-api/media/dtv-common.rst @@ -0,0 +1,53 @@ +.. SPDX-License-Identifier: GPL-2.0 + +Digital TV Common functions +--------------------------- + +DVB devices +~~~~~~~~~~~ + +Those functions are responsible for handling the DVB device nodes. + +.. kernel-doc:: include/media/dvbdev.h + +Digital TV Ring buffer +~~~~~~~~~~~~~~~~~~~~~~ + +Those routines implement ring buffers used to handle digital TV data and +copy it from/to userspace. + +.. note:: + + 1) For performance reasons read and write routines don't check buffer sizes + and/or number of bytes free/available. This has to be done before these + routines are called. For example: + + .. code-block:: c + + /* write @buflen: bytes */ + free = dvb_ringbuffer_free(rbuf); + if (free >= buflen) + count = dvb_ringbuffer_write(rbuf, buffer, buflen); + else + /* do something */ + + /* read min. 1000, max. @bufsize: bytes */ + avail = dvb_ringbuffer_avail(rbuf); + if (avail >= 1000) + count = dvb_ringbuffer_read(rbuf, buffer, min(avail, bufsize)); + else + /* do something */ + + 2) If there is exactly one reader and one writer, there is no need + to lock read or write operations. + Two or more readers must be locked against each other. + Flushing the buffer counts as a read operation. + Resetting the buffer counts as a read and write operation. + Two or more writers must be locked against each other. + +.. kernel-doc:: include/media/dvb_ringbuffer.h + +Digital TV VB2 handler +~~~~~~~~~~~~~~~~~~~~~~ + +.. kernel-doc:: include/media/dvb_vb2.h diff --git a/Documentation/driver-api/media/dtv-core.rst b/Documentation/driver-api/media/dtv-core.rst new file mode 100644 index 0000000000..82c5b85ed9 --- /dev/null +++ b/Documentation/driver-api/media/dtv-core.rst @@ -0,0 +1,39 @@ +.. SPDX-License-Identifier: GPL-2.0 + +Digital TV (DVB) devices +------------------------ + +Digital TV devices are implemented by several different drivers: + +- A bridge driver that is responsible to talk with the bus where the other + devices are connected (PCI, USB, SPI), bind to the other drivers and + implement the digital demux logic (either in software or in hardware); + +- Frontend drivers that are usually implemented as two separate drivers: + + - A tuner driver that implements the logic which commands the part of + the hardware responsible for tuning into a digital TV transponder or + physical channel. The output of a tuner is usually a baseband or + Intermediate Frequency (IF) signal; + + - A demodulator driver (a.k.a "demod") that implements the logic which + commands the digital TV decoding hardware. The output of a demod is + a digital stream, with multiple audio, video and data channels typically + multiplexed using MPEG Transport Stream [#f1]_. + +On most hardware, the frontend drivers talk with the bridge driver using an +I2C bus. + +.. [#f1] Some standards use TCP/IP for multiplexing data, like DVB-H (an + abandoned standard, not used anymore) and ATSC version 3.0 current + proposals. Currently, the DVB subsystem doesn't implement those standards. + + +.. toctree:: + :maxdepth: 1 + + dtv-common + dtv-frontend + dtv-demux + dtv-ca + dtv-net diff --git a/Documentation/driver-api/media/dtv-demux.rst b/Documentation/driver-api/media/dtv-demux.rst new file mode 100644 index 0000000000..1441241426 --- /dev/null +++ b/Documentation/driver-api/media/dtv-demux.rst @@ -0,0 +1,84 @@ +.. SPDX-License-Identifier: GPL-2.0 + +Digital TV Demux kABI +--------------------- + +Digital TV Demux +~~~~~~~~~~~~~~~~ + +The Kernel Digital TV Demux kABI defines a driver-internal interface for +registering low-level, hardware specific driver to a hardware independent +demux layer. It is only of interest for Digital TV device driver writers. +The header file for this kABI is named ``demux.h`` and located in +``include/media``. + +The demux kABI should be implemented for each demux in the system. It is +used to select the TS source of a demux and to manage the demux resources. +When the demux client allocates a resource via the demux kABI, it receives +a pointer to the kABI of that resource. + +Each demux receives its TS input from a DVB front-end or from memory, as +set via this demux kABI. In a system with more than one front-end, the kABI +can be used to select one of the DVB front-ends as a TS source for a demux, +unless this is fixed in the HW platform. + +The demux kABI only controls front-ends regarding to their connections with +demuxes; the kABI used to set the other front-end parameters, such as +tuning, are defined via the Digital TV Frontend kABI. + +The functions that implement the abstract interface demux should be defined +static or module private and registered to the Demux core for external +access. It is not necessary to implement every function in the struct +:c:type:`dmx_demux`. For example, a demux interface might support Section filtering, +but not PES filtering. The kABI client is expected to check the value of any +function pointer before calling the function: the value of ``NULL`` means +that the function is not available. + +Whenever the functions of the demux API modify shared data, the +possibilities of lost update and race condition problems should be +addressed, e.g. by protecting parts of code with mutexes. + +Note that functions called from a bottom half context must not sleep. +Even a simple memory allocation without using ``GFP_ATOMIC`` can result in a +kernel thread being put to sleep if swapping is needed. For example, the +Linux Kernel calls the functions of a network device interface from a +bottom half context. Thus, if a demux kABI function is called from network +device code, the function must not sleep. + +Demux Callback API +~~~~~~~~~~~~~~~~~~ + +This kernel-space API comprises the callback functions that deliver filtered +data to the demux client. Unlike the other DVB kABIs, these functions are +provided by the client and called from the demux code. + +The function pointers of this abstract interface are not packed into a +structure as in the other demux APIs, because the callback functions are +registered and used independent of each other. As an example, it is possible +for the API client to provide several callback functions for receiving TS +packets and no callbacks for PES packets or sections. + +The functions that implement the callback API need not be re-entrant: when +a demux driver calls one of these functions, the driver is not allowed to +call the function again before the original call returns. If a callback is +triggered by a hardware interrupt, it is recommended to use the Linux +bottom half mechanism or start a tasklet instead of making the callback +function call directly from a hardware interrupt. + +This mechanism is implemented by :c:func:`dmx_ts_cb()` and :c:func:`dmx_section_cb()` +callbacks. + +Digital TV Demux device registration functions and data structures +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. kernel-doc:: include/media/dmxdev.h + +High-level Digital TV demux interface +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. kernel-doc:: include/media/dvb_demux.h + +Driver-internal low-level hardware specific driver demux interface +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. kernel-doc:: include/media/demux.h diff --git a/Documentation/driver-api/media/dtv-frontend.rst b/Documentation/driver-api/media/dtv-frontend.rst new file mode 100644 index 0000000000..ea43cdb5b0 --- /dev/null +++ b/Documentation/driver-api/media/dtv-frontend.rst @@ -0,0 +1,445 @@ +.. SPDX-License-Identifier: GPL-2.0 + +Digital TV Frontend kABI +------------------------ + +Digital TV Frontend +~~~~~~~~~~~~~~~~~~~ + +The Digital TV Frontend kABI defines a driver-internal interface for +registering low-level, hardware specific driver to a hardware independent +frontend layer. It is only of interest for Digital TV device driver writers. +The header file for this API is named ``dvb_frontend.h`` and located in +``include/media/``. + +Demodulator driver +^^^^^^^^^^^^^^^^^^ + +The demodulator driver is responsible for talking with the decoding part of the +hardware. Such driver should implement :c:type:`dvb_frontend_ops`, which +tells what type of digital TV standards are supported, and points to a +series of functions that allow the DVB core to command the hardware via +the code under ``include/media/dvb_frontend.c``. + +A typical example of such struct in a driver ``foo`` is:: + + static struct dvb_frontend_ops foo_ops = { + .delsys = { SYS_DVBT, SYS_DVBT2, SYS_DVBC_ANNEX_A }, + .info = { + .name = "foo DVB-T/T2/C driver", + .caps = FE_CAN_FEC_1_2 | + FE_CAN_FEC_2_3 | + FE_CAN_FEC_3_4 | + FE_CAN_FEC_5_6 | + FE_CAN_FEC_7_8 | + FE_CAN_FEC_AUTO | + FE_CAN_QPSK | + FE_CAN_QAM_16 | + FE_CAN_QAM_32 | + FE_CAN_QAM_64 | + FE_CAN_QAM_128 | + FE_CAN_QAM_256 | + FE_CAN_QAM_AUTO | + FE_CAN_TRANSMISSION_MODE_AUTO | + FE_CAN_GUARD_INTERVAL_AUTO | + FE_CAN_HIERARCHY_AUTO | + FE_CAN_MUTE_TS | + FE_CAN_2G_MODULATION, + .frequency_min = 42000000, /* Hz */ + .frequency_max = 1002000000, /* Hz */ + .symbol_rate_min = 870000, + .symbol_rate_max = 11700000 + }, + .init = foo_init, + .sleep = foo_sleep, + .release = foo_release, + .set_frontend = foo_set_frontend, + .get_frontend = foo_get_frontend, + .read_status = foo_get_status_and_stats, + .tune = foo_tune, + .i2c_gate_ctrl = foo_i2c_gate_ctrl, + .get_frontend_algo = foo_get_algo, + }; + +A typical example of such struct in a driver ``bar`` meant to be used on +Satellite TV reception is:: + + static const struct dvb_frontend_ops bar_ops = { + .delsys = { SYS_DVBS, SYS_DVBS2 }, + .info = { + .name = "Bar DVB-S/S2 demodulator", + .frequency_min = 500000, /* KHz */ + .frequency_max = 2500000, /* KHz */ + .frequency_stepsize = 0, + .symbol_rate_min = 1000000, + .symbol_rate_max = 45000000, + .symbol_rate_tolerance = 500, + .caps = FE_CAN_INVERSION_AUTO | + FE_CAN_FEC_AUTO | + FE_CAN_QPSK, + }, + .init = bar_init, + .sleep = bar_sleep, + .release = bar_release, + .set_frontend = bar_set_frontend, + .get_frontend = bar_get_frontend, + .read_status = bar_get_status_and_stats, + .i2c_gate_ctrl = bar_i2c_gate_ctrl, + .get_frontend_algo = bar_get_algo, + .tune = bar_tune, + + /* Satellite-specific */ + .diseqc_send_master_cmd = bar_send_diseqc_msg, + .diseqc_send_burst = bar_send_burst, + .set_tone = bar_set_tone, + .set_voltage = bar_set_voltage, + }; + +.. note:: + + #) For satellite digital TV standards (DVB-S, DVB-S2, ISDB-S), the + frequencies are specified in kHz, while, for terrestrial and cable + standards, they're specified in Hz. Due to that, if the same frontend + supports both types, you'll need to have two separate + :c:type:`dvb_frontend_ops` structures, one for each standard. + #) The ``.i2c_gate_ctrl`` field is present only when the hardware has + allows controlling an I2C gate (either directly of via some GPIO pin), + in order to remove the tuner from the I2C bus after a channel is + tuned. + #) All new drivers should implement the + :ref:`DVBv5 statistics <dvbv5_stats>` via ``.read_status``. + Yet, there are a number of callbacks meant to get statistics for + signal strength, S/N and UCB. Those are there to provide backward + compatibility with legacy applications that don't support the DVBv5 + API. Implementing those callbacks are optional. Those callbacks may be + removed in the future, after we have all existing drivers supporting + DVBv5 stats. + #) Other callbacks are required for satellite TV standards, in order to + control LNBf and DiSEqC: ``.diseqc_send_master_cmd``, + ``.diseqc_send_burst``, ``.set_tone``, ``.set_voltage``. + +.. |delta| unicode:: U+00394 + +The ``include/media/dvb_frontend.c`` has a kernel thread which is +responsible for tuning the device. It supports multiple algorithms to +detect a channel, as defined at enum :c:func:`dvbfe_algo`. + +The algorithm to be used is obtained via ``.get_frontend_algo``. If the driver +doesn't fill its field at struct dvb_frontend_ops, it will default to +``DVBFE_ALGO_SW``, meaning that the dvb-core will do a zigzag when tuning, +e. g. it will try first to use the specified center frequency ``f``, +then, it will do ``f`` + |delta|, ``f`` - |delta|, ``f`` + 2 x |delta|, +``f`` - 2 x |delta| and so on. + +If the hardware has internally a some sort of zigzag algorithm, you should +define a ``.get_frontend_algo`` function that would return ``DVBFE_ALGO_HW``. + +.. note:: + + The core frontend support also supports + a third type (``DVBFE_ALGO_CUSTOM``), in order to allow the driver to + define its own hardware-assisted algorithm. Very few hardware need to + use it nowadays. Using ``DVBFE_ALGO_CUSTOM`` require to provide other + function callbacks at struct dvb_frontend_ops. + +Attaching frontend driver to the bridge driver +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Before using the Digital TV frontend core, the bridge driver should attach +the frontend demod, tuner and SEC devices and call +:c:func:`dvb_register_frontend()`, +in order to register the new frontend at the subsystem. At device +detach/removal, the bridge driver should call +:c:func:`dvb_unregister_frontend()` to +remove the frontend from the core and then :c:func:`dvb_frontend_detach()` +to free the memory allocated by the frontend drivers. + +The drivers should also call :c:func:`dvb_frontend_suspend()` as part of +their handler for the :c:type:`device_driver`.\ ``suspend()``, and +:c:func:`dvb_frontend_resume()` as +part of their handler for :c:type:`device_driver`.\ ``resume()``. + +A few other optional functions are provided to handle some special cases. + +.. _dvbv5_stats: + +Digital TV Frontend statistics +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Introduction +^^^^^^^^^^^^ + +Digital TV frontends provide a range of +:ref:`statistics <frontend-stat-properties>` meant to help tuning the device +and measuring the quality of service. + +For each statistics measurement, the driver should set the type of scale used, +or ``FE_SCALE_NOT_AVAILABLE`` if the statistics is not available on a given +time. Drivers should also provide the number of statistics for each type. +that's usually 1 for most video standards [#f2]_. + +Drivers should initialize each statistic counters with length and +scale at its init code. For example, if the frontend provides signal +strength, it should have, on its init code:: + + struct dtv_frontend_properties *c = &state->fe.dtv_property_cache; + + c->strength.len = 1; + c->strength.stat[0].scale = FE_SCALE_NOT_AVAILABLE; + +And, when the statistics got updated, set the scale:: + + c->strength.stat[0].scale = FE_SCALE_DECIBEL; + c->strength.stat[0].uvalue = strength; + +.. [#f2] For ISDB-T, it may provide both a global statistics and a per-layer + set of statistics. On such cases, len should be equal to 4. The first + value corresponds to the global stat; the other ones to each layer, e. g.: + + - c->cnr.stat[0] for global S/N carrier ratio, + - c->cnr.stat[1] for Layer A S/N carrier ratio, + - c->cnr.stat[2] for layer B S/N carrier ratio, + - c->cnr.stat[3] for layer C S/N carrier ratio. + +.. note:: Please prefer to use ``FE_SCALE_DECIBEL`` instead of + ``FE_SCALE_RELATIVE`` for signal strength and CNR measurements. + +Groups of statistics +^^^^^^^^^^^^^^^^^^^^ + +There are several groups of statistics currently supported: + +Signal strength (:ref:`DTV-STAT-SIGNAL-STRENGTH`) + - Measures the signal strength level at the analog part of the tuner or + demod. + + - Typically obtained from the gain applied to the tuner and/or frontend + in order to detect the carrier. When no carrier is detected, the gain is + at the maximum value (so, strength is on its minimal). + + - As the gain is visible through the set of registers that adjust the gain, + typically, this statistics is always available [#f3]_. + + - Drivers should try to make it available all the times, as these statistics + can be used when adjusting an antenna position and to check for troubles + at the cabling. + + .. [#f3] On a few devices, the gain keeps floating if there is no carrier. + On such devices, strength report should check first if carrier is + detected at the tuner (``FE_HAS_CARRIER``, see :c:type:`fe_status`), + and otherwise return the lowest possible value. + +Carrier Signal to Noise ratio (:ref:`DTV-STAT-CNR`) + - Signal to Noise ratio for the main carrier. + + - Signal to Noise measurement depends on the device. On some hardware, it is + available when the main carrier is detected. On those hardware, CNR + measurement usually comes from the tuner (e. g. after ``FE_HAS_CARRIER``, + see :c:type:`fe_status`). + + On other devices, it requires inner FEC decoding, + as the frontend measures it indirectly from other parameters (e. g. after + ``FE_HAS_VITERBI``, see :c:type:`fe_status`). + + Having it available after inner FEC is more common. + +Bit counts post-FEC (:ref:`DTV-STAT-POST-ERROR-BIT-COUNT` and :ref:`DTV-STAT-POST-TOTAL-BIT-COUNT`) + - Those counters measure the number of bits and bit errors after + the forward error correction (FEC) on the inner coding block + (after Viterbi, LDPC or other inner code). + + - Due to its nature, those statistics depend on full coding lock + (e. g. after ``FE_HAS_SYNC`` or after ``FE_HAS_LOCK``, + see :c:type:`fe_status`). + +Bit counts pre-FEC (:ref:`DTV-STAT-PRE-ERROR-BIT-COUNT` and :ref:`DTV-STAT-PRE-TOTAL-BIT-COUNT`) + - Those counters measure the number of bits and bit errors before + the forward error correction (FEC) on the inner coding block + (before Viterbi, LDPC or other inner code). + + - Not all frontends provide this kind of statistics. + + - Due to its nature, those statistics depend on inner coding lock (e. g. + after ``FE_HAS_VITERBI``, see :c:type:`fe_status`). + +Block counts (:ref:`DTV-STAT-ERROR-BLOCK-COUNT` and :ref:`DTV-STAT-TOTAL-BLOCK-COUNT`) + - Those counters measure the number of blocks and block errors after + the forward error correction (FEC) on the inner coding block + (before Viterbi, LDPC or other inner code). + + - Due to its nature, those statistics depend on full coding lock + (e. g. after ``FE_HAS_SYNC`` or after + ``FE_HAS_LOCK``, see :c:type:`fe_status`). + +.. note:: All counters should be monotonically increased as they're + collected from the hardware. + +A typical example of the logic that handle status and statistics is:: + + static int foo_get_status_and_stats(struct dvb_frontend *fe) + { + struct foo_state *state = fe->demodulator_priv; + struct dtv_frontend_properties *c = &fe->dtv_property_cache; + + int rc; + enum fe_status *status; + + /* Both status and strength are always available */ + rc = foo_read_status(fe, &status); + if (rc < 0) + return rc; + + rc = foo_read_strength(fe); + if (rc < 0) + return rc; + + /* Check if CNR is available */ + if (!(fe->status & FE_HAS_CARRIER)) + return 0; + + rc = foo_read_cnr(fe); + if (rc < 0) + return rc; + + /* Check if pre-BER stats are available */ + if (!(fe->status & FE_HAS_VITERBI)) + return 0; + + rc = foo_get_pre_ber(fe); + if (rc < 0) + return rc; + + /* Check if post-BER stats are available */ + if (!(fe->status & FE_HAS_SYNC)) + return 0; + + rc = foo_get_post_ber(fe); + if (rc < 0) + return rc; + } + + static const struct dvb_frontend_ops ops = { + /* ... */ + .read_status = foo_get_status_and_stats, + }; + +Statistics collection +^^^^^^^^^^^^^^^^^^^^^ + +On almost all frontend hardware, the bit and byte counts are stored by +the hardware after a certain amount of time or after the total bit/block +counter reaches a certain value (usually programmable), for example, on +every 1000 ms or after receiving 1,000,000 bits. + +So, if you read the registers too soon, you'll end by reading the same +value as in the previous reading, causing the monotonic value to be +incremented too often. + +Drivers should take the responsibility to avoid too often reads. That +can be done using two approaches: + +if the driver have a bit that indicates when a collected data is ready +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +Driver should check such bit before making the statistics available. + +An example of such behavior can be found at this code snippet (adapted +from mb86a20s driver's logic):: + + static int foo_get_pre_ber(struct dvb_frontend *fe) + { + struct foo_state *state = fe->demodulator_priv; + struct dtv_frontend_properties *c = &fe->dtv_property_cache; + int rc, bit_error; + + /* Check if the BER measures are already available */ + rc = foo_read_u8(state, 0x54); + if (rc < 0) + return rc; + + if (!rc) + return 0; + + /* Read Bit Error Count */ + bit_error = foo_read_u32(state, 0x55); + if (bit_error < 0) + return bit_error; + + /* Read Total Bit Count */ + rc = foo_read_u32(state, 0x51); + if (rc < 0) + return rc; + + c->pre_bit_error.stat[0].scale = FE_SCALE_COUNTER; + c->pre_bit_error.stat[0].uvalue += bit_error; + c->pre_bit_count.stat[0].scale = FE_SCALE_COUNTER; + c->pre_bit_count.stat[0].uvalue += rc; + + return 0; + } + +If the driver doesn't provide a statistics available check bit +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +A few devices, however, may not provide a way to check if the stats are +available (or the way to check it is unknown). They may not even provide +a way to directly read the total number of bits or blocks. + +On those devices, the driver need to ensure that it won't be reading from +the register too often and/or estimate the total number of bits/blocks. + +On such drivers, a typical routine to get statistics would be like +(adapted from dib8000 driver's logic):: + + struct foo_state { + /* ... */ + + unsigned long per_jiffies_stats; + } + + static int foo_get_pre_ber(struct dvb_frontend *fe) + { + struct foo_state *state = fe->demodulator_priv; + struct dtv_frontend_properties *c = &fe->dtv_property_cache; + int rc, bit_error; + u64 bits; + + /* Check if time for stats was elapsed */ + if (!time_after(jiffies, state->per_jiffies_stats)) + return 0; + + /* Next stat should be collected in 1000 ms */ + state->per_jiffies_stats = jiffies + msecs_to_jiffies(1000); + + /* Read Bit Error Count */ + bit_error = foo_read_u32(state, 0x55); + if (bit_error < 0) + return bit_error; + + /* + * On this particular frontend, there's no register that + * would provide the number of bits per 1000ms sample. So, + * some function would calculate it based on DTV properties + */ + bits = get_number_of_bits_per_1000ms(fe); + + c->pre_bit_error.stat[0].scale = FE_SCALE_COUNTER; + c->pre_bit_error.stat[0].uvalue += bit_error; + c->pre_bit_count.stat[0].scale = FE_SCALE_COUNTER; + c->pre_bit_count.stat[0].uvalue += bits; + + return 0; + } + +Please notice that, on both cases, we're getting the statistics using the +:c:type:`dvb_frontend_ops` ``.read_status`` callback. The rationale is that +the frontend core will automatically call this function periodically +(usually, 3 times per second, when the frontend is locked). + +That warrants that we won't miss to collect a counter and increment the +monotonic stats at the right time. + +Digital TV Frontend functions and types +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. kernel-doc:: include/media/dvb_frontend.h diff --git a/Documentation/driver-api/media/dtv-net.rst b/Documentation/driver-api/media/dtv-net.rst new file mode 100644 index 0000000000..deb6bffe96 --- /dev/null +++ b/Documentation/driver-api/media/dtv-net.rst @@ -0,0 +1,6 @@ +.. SPDX-License-Identifier: GPL-2.0 + +Digital TV Network kABI +----------------------- + +.. kernel-doc:: include/media/dvb_net.h diff --git a/Documentation/driver-api/media/index.rst b/Documentation/driver-api/media/index.rst new file mode 100644 index 0000000000..08e2065674 --- /dev/null +++ b/Documentation/driver-api/media/index.rst @@ -0,0 +1,59 @@ +.. SPDX-License-Identifier: GPL-2.0 + +.. include:: <isonum.txt> + +=================================== +Media subsystem kernel internal API +=================================== + +This section contains usage information about media subsystem and +its supported drivers. + +Please see: + +Documentation/admin-guide/media/index.rst + + - for usage information about media subsystem and supported drivers; + +Documentation/userspace-api/media/index.rst + + - for the userspace APIs used on media devices. + + +.. only:: html + + .. class:: toc-title + + Table of Contents + +.. toctree:: + :maxdepth: 5 + :numbered: + + maintainer-entry-profile + + v4l2-core + dtv-core + rc-core + mc-core + cec-core + tx-rx + camera-sensor + + drivers/index + +**Copyright** |copy| 2009-2020 : LinuxTV Developers + +:: + + This documentation 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. + + This program is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + For more details see the file COPYING in the source distribution of Linux. diff --git a/Documentation/driver-api/media/maintainer-entry-profile.rst b/Documentation/driver-api/media/maintainer-entry-profile.rst new file mode 100644 index 0000000000..ffc712a5f6 --- /dev/null +++ b/Documentation/driver-api/media/maintainer-entry-profile.rst @@ -0,0 +1,206 @@ +Media Subsystem Profile +======================= + +Overview +-------- + +The media subsystem covers support for a variety of devices: stream +capture, analog and digital TV streams, cameras, remote controllers, HDMI CEC +and media pipeline control. + +It covers, mainly, the contents of those directories: + + - drivers/media + - drivers/staging/media + - Documentation/admin-guide/media + - Documentation/driver-api/media + - Documentation/userspace-api/media + - Documentation/devicetree/bindings/media/\ [1]_ + - include/media + +.. [1] Device tree bindings are maintained by the + OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS maintainers + (see the MAINTAINERS file). So, changes there must be reviewed + by them before being merged via the media subsystem's development + tree. + +Both media userspace and Kernel APIs are documented and the documentation +must be kept in sync with the API changes. It means that all patches that +add new features to the subsystem must also bring changes to the +corresponding API files. + +Due to the size and wide scope of the media subsystem, media's +maintainership model is to have sub-maintainers that have a broad +knowledge of a specific aspect of the subsystem. It is the sub-maintainers' +task to review the patches, providing feedback to users if the patches are +following the subsystem rules and are properly using the media kernel and +userspace APIs. + +Patches for the media subsystem must be sent to the media mailing list +at linux-media@vger.kernel.org as plain text only e-mail. Emails with +HTML will be automatically rejected by the mail server. It could be wise +to also copy the sub-maintainer(s). + +Media's workflow is heavily based on Patchwork, meaning that, once a patch +is submitted, the e-mail will first be accepted by the mailing list +server, and, after a while, it should appear at: + + - https://patchwork.linuxtv.org/project/linux-media/list/ + +If it doesn't automatically appear there after a few minutes, then +probably something went wrong on your submission. Please check if the +email is in plain text\ [2]_ only and if your emailer is not mangling +whitespaces before complaining or submitting them again. + +You can check if the mailing list server accepted your patch, by looking at: + + - https://lore.kernel.org/linux-media/ + +.. [2] If your email contains HTML, the mailing list server will simply + drop it, without any further notice. + + +Media maintainers ++++++++++++++++++ + +At the media subsystem, we have a group of senior developers that +are responsible for doing the code reviews at the drivers (also known as +sub-maintainers), and another senior developer responsible for the +subsystem as a whole. For core changes, whenever possible, multiple +media maintainers do the review. + +The media maintainers that work on specific areas of the subsystem are: + +- Remote Controllers (infrared): + Sean Young <sean@mess.org> + +- HDMI CEC: + Hans Verkuil <hverkuil@xs4all.nl> + +- Media controller drivers: + Laurent Pinchart <laurent.pinchart@ideasonboard.com> + +- ISP, v4l2-async, v4l2-fwnode, v4l2-flash-led-class and Sensor drivers: + Sakari Ailus <sakari.ailus@linux.intel.com> + +- V4L2 drivers and core V4L2 frameworks: + Hans Verkuil <hverkuil@xs4all.nl> + +The subsystem maintainer is: + Mauro Carvalho Chehab <mchehab@kernel.org> + +Media maintainers may delegate a patch to other media maintainers as needed. +On such case, checkpatch's ``delegate`` field indicates who's currently +responsible for reviewing a patch. + +Submit Checklist Addendum +------------------------- + +Patches that change the Open Firmware/Device Tree bindings must be +reviewed by the Device Tree maintainers. So, DT maintainers should be +Cc:ed when those are submitted via devicetree@vger.kernel.org mailing +list. + +There is a set of compliance tools at https://git.linuxtv.org/v4l-utils.git/ +that should be used in order to check if the drivers are properly +implementing the media APIs: + +==================== ======================================================= +Type Tool +==================== ======================================================= +V4L2 drivers\ [3]_ ``v4l2-compliance`` +V4L2 virtual drivers ``contrib/test/test-media`` +CEC drivers ``cec-compliance`` +==================== ======================================================= + +.. [3] The ``v4l2-compliance`` also covers the media controller usage inside + V4L2 drivers. + +Other compilance tools are under development to check other parts of the +subsystem. + +Those tests need to pass before the patches go upstream. + +Also, please notice that we build the Kernel with:: + + make CF=-D__CHECK_ENDIAN__ CONFIG_DEBUG_SECTION_MISMATCH=y C=1 W=1 CHECK=check_script + +Where the check script is:: + + #!/bin/bash + /devel/smatch/smatch -p=kernel $@ >&2 + /devel/sparse/sparse $@ >&2 + +Be sure to not introduce new warnings on your patches without a +very good reason. + +Style Cleanup Patches ++++++++++++++++++++++ + +Style cleanups are welcome when they come together with other changes +at the files where the style changes will affect. + +We may accept pure standalone style cleanups, but they should ideally +be one patch for the whole subsystem (if the cleanup is low volume), +or at least be grouped per directory. So, for example, if you're doing a +big cleanup change set at drivers under drivers/media, please send a single +patch for all drivers under drivers/media/pci, another one for +drivers/media/usb and so on. + +Coding Style Addendum ++++++++++++++++++++++ + +Media development uses ``checkpatch.pl`` on strict mode to verify the code +style, e.g.:: + + $ ./scripts/checkpatch.pl --strict --max-line-length=80 + +In principle, patches should follow the coding style rules, but exceptions +are allowed if there are good reasons. On such case, maintainers and reviewers +may question about the rationale for not addressing the ``checkpatch.pl``. + +Please notice that the goal here is to improve code readability. On +a few cases, ``checkpatch.pl`` may actually point to something that would +look worse. So, you should use good sense. + +Note that addressing one ``checkpatch.pl`` issue (of any kind) alone may lead +to having longer lines than 80 characters per line. While this is not +strictly prohibited, efforts should be made towards staying within 80 +characters per line. This could include using re-factoring code that leads +to less indentation, shorter variable or function names and last but not +least, simply wrapping the lines. + +In particular, we accept lines with more than 80 columns: + + - on strings, as they shouldn't be broken due to line length limits; + - when a function or variable name need to have a big identifier name, + which keeps hard to honor the 80 columns limit; + - on arithmetic expressions, when breaking lines makes them harder to + read; + - when they avoid a line to end with an open parenthesis or an open + bracket. + +Key Cycle Dates +--------------- + +New submissions can be sent at any time, but if they intend to hit the +next merge window they should be sent before -rc5, and ideally stabilized +in the linux-media branch by -rc6. + +Review Cadence +-------------- + +Provided that your patch is at https://patchwork.linuxtv.org, it should +be sooner or later handled, so you don't need to re-submit a patch. + +Except for bug fixes, we don't usually add new patches to the development +tree between -rc6 and the next -rc1. + +Please notice that the media subsystem is a high traffic one, so it +could take a while for us to be able to review your patches. Feel free +to ping if you don't get a feedback in a couple of weeks or to ask +other developers to publicly add Reviewed-by and, more importantly, +``Tested-by:`` tags. + +Please note that we expect a detailed description for ``Tested-by:``, +identifying what boards were used at the test and what it was tested. diff --git a/Documentation/driver-api/media/mc-core.rst b/Documentation/driver-api/media/mc-core.rst new file mode 100644 index 0000000000..2456950ce8 --- /dev/null +++ b/Documentation/driver-api/media/mc-core.rst @@ -0,0 +1,326 @@ +.. SPDX-License-Identifier: GPL-2.0 + +Media Controller devices +------------------------ + +Media Controller +~~~~~~~~~~~~~~~~ + +The media controller userspace API is documented in +:ref:`the Media Controller uAPI book <media_controller>`. This document focus +on the kernel-side implementation of the media framework. + +Abstract media device model +^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Discovering a device internal topology, and configuring it at runtime, is one +of the goals of the media framework. To achieve this, hardware devices are +modelled as an oriented graph of building blocks called entities connected +through pads. + +An entity is a basic media hardware building block. It can correspond to +a large variety of logical blocks such as physical hardware devices +(CMOS sensor for instance), logical hardware devices (a building block +in a System-on-Chip image processing pipeline), DMA channels or physical +connectors. + +A pad is a connection endpoint through which an entity can interact with +other entities. Data (not restricted to video) produced by an entity +flows from the entity's output to one or more entity inputs. Pads should +not be confused with physical pins at chip boundaries. + +A link is a point-to-point oriented connection between two pads, either +on the same entity or on different entities. Data flows from a source +pad to a sink pad. + +Media device +^^^^^^^^^^^^ + +A media device is represented by a struct media_device +instance, defined in ``include/media/media-device.h``. +Allocation of the structure is handled by the media device driver, usually by +embedding the :c:type:`media_device` instance in a larger driver-specific +structure. + +Drivers initialise media device instances by calling +:c:func:`media_device_init()`. After initialising a media device instance, it is +registered by calling :c:func:`__media_device_register()` via the macro +``media_device_register()`` and unregistered by calling +:c:func:`media_device_unregister()`. An initialised media device must be +eventually cleaned up by calling :c:func:`media_device_cleanup()`. + +Note that it is not allowed to unregister a media device instance that was not +previously registered, or clean up a media device instance that was not +previously initialised. + +Entities +^^^^^^^^ + +Entities are represented by a struct media_entity +instance, defined in ``include/media/media-entity.h``. The structure is usually +embedded into a higher-level structure, such as +:c:type:`v4l2_subdev` or :c:type:`video_device` +instances, although drivers can allocate entities directly. + +Drivers initialize entity pads by calling +:c:func:`media_entity_pads_init()`. + +Drivers register entities with a media device by calling +:c:func:`media_device_register_entity()` +and unregistered by calling +:c:func:`media_device_unregister_entity()`. + +Interfaces +^^^^^^^^^^ + +Interfaces are represented by a +struct media_interface instance, defined in +``include/media/media-entity.h``. Currently, only one type of interface is +defined: a device node. Such interfaces are represented by a +struct media_intf_devnode. + +Drivers initialize and create device node interfaces by calling +:c:func:`media_devnode_create()` +and remove them by calling: +:c:func:`media_devnode_remove()`. + +Pads +^^^^ +Pads are represented by a struct media_pad instance, +defined in ``include/media/media-entity.h``. Each entity stores its pads in +a pads array managed by the entity driver. Drivers usually embed the array in +a driver-specific structure. + +Pads are identified by their entity and their 0-based index in the pads +array. + +Both information are stored in the struct media_pad, +making the struct media_pad pointer the canonical way +to store and pass link references. + +Pads have flags that describe the pad capabilities and state. + +``MEDIA_PAD_FL_SINK`` indicates that the pad supports sinking data. +``MEDIA_PAD_FL_SOURCE`` indicates that the pad supports sourcing data. + +.. note:: + + One and only one of ``MEDIA_PAD_FL_SINK`` or ``MEDIA_PAD_FL_SOURCE`` must + be set for each pad. + +Links +^^^^^ + +Links are represented by a struct media_link instance, +defined in ``include/media/media-entity.h``. There are two types of links: + +**1. pad to pad links**: + +Associate two entities via their PADs. Each entity has a list that points +to all links originating at or targeting any of its pads. +A given link is thus stored twice, once in the source entity and once in +the target entity. + +Drivers create pad to pad links by calling: +:c:func:`media_create_pad_link()` and remove with +:c:func:`media_entity_remove_links()`. + +**2. interface to entity links**: + +Associate one interface to a Link. + +Drivers create interface to entity links by calling: +:c:func:`media_create_intf_link()` and remove with +:c:func:`media_remove_intf_links()`. + +.. note:: + + Links can only be created after having both ends already created. + +Links have flags that describe the link capabilities and state. The +valid values are described at :c:func:`media_create_pad_link()` and +:c:func:`media_create_intf_link()`. + +Graph traversal +^^^^^^^^^^^^^^^ + +The media framework provides APIs to iterate over entities in a graph. + +To iterate over all entities belonging to a media device, drivers can use +the media_device_for_each_entity macro, defined in +``include/media/media-device.h``. + +.. code-block:: c + + struct media_entity *entity; + + media_device_for_each_entity(entity, mdev) { + // entity will point to each entity in turn + ... + } + +Drivers might also need to iterate over all entities in a graph that can be +reached only through enabled links starting at a given entity. The media +framework provides a depth-first graph traversal API for that purpose. + +.. note:: + + Graphs with cycles (whether directed or undirected) are **NOT** + supported by the graph traversal API. To prevent infinite loops, the graph + traversal code limits the maximum depth to ``MEDIA_ENTITY_ENUM_MAX_DEPTH``, + currently defined as 16. + +Drivers initiate a graph traversal by calling +:c:func:`media_graph_walk_start()` + +The graph structure, provided by the caller, is initialized to start graph +traversal at the given entity. + +Drivers can then retrieve the next entity by calling +:c:func:`media_graph_walk_next()` + +When the graph traversal is complete the function will return ``NULL``. + +Graph traversal can be interrupted at any moment. No cleanup function call +is required and the graph structure can be freed normally. + +Helper functions can be used to find a link between two given pads, or a pad +connected to another pad through an enabled link +(:c:func:`media_entity_find_link()`, :c:func:`media_pad_remote_pad_first()`, +:c:func:`media_entity_remote_source_pad_unique()` and +:c:func:`media_pad_remote_pad_unique()`). + +Use count and power handling +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Due to the wide differences between drivers regarding power management +needs, the media controller does not implement power management. However, +the struct media_entity includes a ``use_count`` +field that media drivers +can use to track the number of users of every entity for power management +needs. + +The :c:type:`media_entity<media_entity>`.\ ``use_count`` field is owned by +media drivers and must not be +touched by entity drivers. Access to the field must be protected by the +:c:type:`media_device`.\ ``graph_mutex`` lock. + +Links setup +^^^^^^^^^^^ + +Link properties can be modified at runtime by calling +:c:func:`media_entity_setup_link()`. + +Pipelines and media streams +^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +A media stream is a stream of pixels or metadata originating from one or more +source devices (such as a sensors) and flowing through media entity pads +towards the final sinks. The stream can be modified on the route by the +devices (e.g. scaling or pixel format conversions), or it can be split into +multiple branches, or multiple branches can be merged. + +A media pipeline is a set of media streams which are interdependent. This +interdependency can be caused by the hardware (e.g. configuration of a second +stream cannot be changed if the first stream has been enabled) or by the driver +due to the software design. Most commonly a media pipeline consists of a single +stream which does not branch. + +When starting streaming, drivers must notify all entities in the pipeline to +prevent link states from being modified during streaming by calling +:c:func:`media_pipeline_start()`. + +The function will mark all the pads which are part of the pipeline as streaming. + +The struct media_pipeline instance pointed to by the pipe argument will be +stored in every pad in the pipeline. Drivers should embed the struct +media_pipeline in higher-level pipeline structures and can then access the +pipeline through the struct media_pad pipe field. + +Calls to :c:func:`media_pipeline_start()` can be nested. +The pipeline pointer must be identical for all nested calls to the function. + +:c:func:`media_pipeline_start()` may return an error. In that case, +it will clean up any of the changes it did by itself. + +When stopping the stream, drivers must notify the entities with +:c:func:`media_pipeline_stop()`. + +If multiple calls to :c:func:`media_pipeline_start()` have been +made the same number of :c:func:`media_pipeline_stop()` calls +are required to stop streaming. +The :c:type:`media_entity`.\ ``pipe`` field is reset to ``NULL`` on the last +nested stop call. + +Link configuration will fail with ``-EBUSY`` by default if either end of the +link is a streaming entity. Links that can be modified while streaming must +be marked with the ``MEDIA_LNK_FL_DYNAMIC`` flag. + +If other operations need to be disallowed on streaming entities (such as +changing entities configuration parameters) drivers can explicitly check the +media_entity stream_count field to find out if an entity is streaming. This +operation must be done with the media_device graph_mutex held. + +Link validation +^^^^^^^^^^^^^^^ + +Link validation is performed by :c:func:`media_pipeline_start()` +for any entity which has sink pads in the pipeline. The +:c:type:`media_entity`.\ ``link_validate()`` callback is used for that +purpose. In ``link_validate()`` callback, entity driver should check +that the properties of the source pad of the connected entity and its own +sink pad match. It is up to the type of the entity (and in the end, the +properties of the hardware) what matching actually means. + +Subsystems should facilitate link validation by providing subsystem specific +helper functions to provide easy access for commonly needed information, and +in the end provide a way to use driver-specific callbacks. + +Media Controller Device Allocator API +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +When the media device belongs to more than one driver, the shared media +device is allocated with the shared struct device as the key for look ups. + +The shared media device should stay in registered state until the last +driver unregisters it. In addition, the media device should be released when +all the references are released. Each driver gets a reference to the media +device during probe, when it allocates the media device. If media device is +already allocated, the allocate API bumps up the refcount and returns the +existing media device. The driver puts the reference back in its disconnect +routine when it calls :c:func:`media_device_delete()`. + +The media device is unregistered and cleaned up from the kref put handler to +ensure that the media device stays in registered state until the last driver +unregisters the media device. + +**Driver Usage** + +Drivers should use the appropriate media-core routines to manage the shared +media device life-time handling the two states: +1. allocate -> register -> delete +2. get reference to already registered device -> delete + +call :c:func:`media_device_delete()` routine to make sure the shared media +device delete is handled correctly. + +**driver probe:** +Call :c:func:`media_device_usb_allocate()` to allocate or get a reference +Call :c:func:`media_device_register()`, if media devnode isn't registered + +**driver disconnect:** +Call :c:func:`media_device_delete()` to free the media_device. Freeing is +handled by the kref put handler. + +API Definitions +^^^^^^^^^^^^^^^ + +.. kernel-doc:: include/media/media-device.h + +.. kernel-doc:: include/media/media-devnode.h + +.. kernel-doc:: include/media/media-entity.h + +.. kernel-doc:: include/media/media-request.h + +.. kernel-doc:: include/media/media-dev-allocator.h diff --git a/Documentation/driver-api/media/rc-core.rst b/Documentation/driver-api/media/rc-core.rst new file mode 100644 index 0000000000..53f5e643b6 --- /dev/null +++ b/Documentation/driver-api/media/rc-core.rst @@ -0,0 +1,88 @@ +.. SPDX-License-Identifier: GPL-2.0 + +Remote Controller devices +------------------------- + +Remote Controller core +~~~~~~~~~~~~~~~~~~~~~~ + +The remote controller core implements infrastructure to receive and send +remote controller keyboard keystrokes and mouse events. + +Every time a key is pressed on a remote controller, a scan code is produced. +Also, on most hardware, keeping a key pressed for more than a few dozens of +milliseconds produce a repeat key event. That's somewhat similar to what +a normal keyboard or mouse is handled internally on Linux\ [#f1]_. So, the +remote controller core is implemented on the top of the linux input/evdev +interface. + +.. [#f1] + + The main difference is that, on keyboard events, the keyboard controller + produces one event for a key press and another one for key release. On + infrared-based remote controllers, there's no key release event. Instead, + an extra code is produced to indicate key repeats. + +However, most of the remote controllers use infrared (IR) to transmit signals. +As there are several protocols used to modulate infrared signals, one +important part of the core is dedicated to adjust the driver and the core +system to support the infrared protocol used by the emitter. + +The infrared transmission is done by blinking a infrared emitter using a +carrier. The carrier can be switched on or off by the IR transmitter +hardware. When the carrier is switched on, it is called *PULSE*. +When the carrier is switched off, it is called *SPACE*. + +In other words, a typical IR transmission can be viewed as a sequence of +*PULSE* and *SPACE* events, each with a given duration. + +The carrier parameters (frequency, duty cycle) and the intervals for +*PULSE* and *SPACE* events depend on the protocol. +For example, the NEC protocol uses a carrier of 38kHz, and transmissions +start with a 9ms *PULSE* and a 4.5ms SPACE. It then transmits 16 bits of +scan code, being 8 bits for address (usually it is a fixed number for a +given remote controller), followed by 8 bits of code. A bit "1" is modulated +with 560µs *PULSE* followed by 1690µs *SPACE* and a bit "0" is modulated +with 560µs *PULSE* followed by 560µs *SPACE*. + +At receiver, a simple low-pass filter can be used to convert the received +signal in a sequence of *PULSE/SPACE* events, filtering out the carrier +frequency. Due to that, the receiver doesn't care about the carrier's +actual frequency parameters: all it has to do is to measure the amount +of time it receives *PULSE/SPACE* events. +So, a simple IR receiver hardware will just provide a sequence of timings +for those events to the Kernel. The drivers for hardware with such kind of +receivers are identified by ``RC_DRIVER_IR_RAW``, as defined by +:c:type:`rc_driver_type`\ [#f2]_. Other hardware come with a +microcontroller that decode the *PULSE/SPACE* sequence and return scan +codes to the Kernel. Such kind of receivers are identified +by ``RC_DRIVER_SCANCODE``. + +.. [#f2] + + The RC core also supports devices that have just IR emitters, + without any receivers. Right now, all such devices work only in + raw TX mode. Such kind of hardware is identified as + ``RC_DRIVER_IR_RAW_TX``. + +When the RC core receives events produced by ``RC_DRIVER_IR_RAW`` IR +receivers, it needs to decode the IR protocol, in order to obtain the +corresponding scan code. The protocols supported by the RC core are +defined at enum :c:type:`rc_proto`. + +When the RC code receives a scan code (either directly, by a driver +of the type ``RC_DRIVER_SCANCODE``, or via its IR decoders), it needs +to convert into a Linux input event code. This is done via a mapping +table. + +The Kernel has support for mapping tables available on most media +devices. It also supports loading a table in runtime, via some +sysfs nodes. See the :ref:`RC userspace API <Remote_controllers_Intro>` +for more details. + +Remote controller data structures and functions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. kernel-doc:: include/media/rc-core.h + +.. kernel-doc:: include/media/rc-map.h diff --git a/Documentation/driver-api/media/tx-rx.rst b/Documentation/driver-api/media/tx-rx.rst new file mode 100644 index 0000000000..e1e9258dd8 --- /dev/null +++ b/Documentation/driver-api/media/tx-rx.rst @@ -0,0 +1,133 @@ +.. SPDX-License-Identifier: GPL-2.0 + +.. _transmitter-receiver: + +Pixel data transmitter and receiver drivers +=========================================== + +V4L2 supports various devices that transmit and receive pixel data. Examples of +these devices include a camera sensor, a TV tuner and a parallel or a CSI-2 +receiver in an SoC. + +Bus types +--------- + +The following busses are the most common. This section discusses these two only. + +MIPI CSI-2 +^^^^^^^^^^ + +CSI-2 is a data bus intended for transferring images from cameras to +the host SoC. It is defined by the `MIPI alliance`_. + +.. _`MIPI alliance`: https://www.mipi.org/ + +Parallel +^^^^^^^^ + +`BT.601`_ and `BT.656`_ are the most common parallel busses. + +.. _`BT.601`: https://en.wikipedia.org/wiki/Rec._601 +.. _`BT.656`: https://en.wikipedia.org/wiki/ITU-R_BT.656 + +Transmitter drivers +------------------- + +Transmitter drivers generally need to provide the receiver drivers with the +configuration of the transmitter. What is required depends on the type of the +bus. These are common for both busses. + +Media bus pixel code +^^^^^^^^^^^^^^^^^^^^ + +See :ref:`v4l2-mbus-pixelcode`. + +Link frequency +^^^^^^^^^^^^^^ + +The :ref:`V4L2_CID_LINK_FREQ <v4l2-cid-link-freq>` control is used to tell the +receiver the frequency of the bus (i.e. it is not the same as the symbol rate). + +``.s_stream()`` callback +^^^^^^^^^^^^^^^^^^^^^^^^ + +The struct struct v4l2_subdev_video_ops->s_stream() callback is used by the +receiver driver to control the transmitter driver's streaming state. + + +CSI-2 transmitter drivers +------------------------- + +Pixel rate +^^^^^^^^^^ + +The pixel rate on the bus is calculated as follows:: + + pixel_rate = link_freq * 2 * nr_of_lanes * 16 / k / bits_per_sample + +where + +.. list-table:: variables in pixel rate calculation + :header-rows: 1 + + * - variable or constant + - description + * - link_freq + - The value of the ``V4L2_CID_LINK_FREQ`` integer64 menu item. + * - nr_of_lanes + - Number of data lanes used on the CSI-2 link. This can + be obtained from the OF endpoint configuration. + * - 2 + - Data is transferred on both rising and falling edge of the signal. + * - bits_per_sample + - Number of bits per sample. + * - k + - 16 for D-PHY and 7 for C-PHY + +.. note:: + + The pixel rate calculated this way is **not** the same thing as the + pixel rate on the camera sensor's pixel array which is indicated by the + :ref:`V4L2_CID_PIXEL_RATE <v4l2-cid-pixel-rate>` control. + +LP-11 and LP-111 modes +^^^^^^^^^^^^^^^^^^^^^^ + +As part of transitioning to high speed mode, a CSI-2 transmitter typically +briefly sets the bus to LP-11 or LP-111 state, depending on the PHY. This period +may be as short as 100 µs, during which the receiver observes this state and +proceeds its own part of high speed mode transition. + +Most receivers are capable of autonomously handling this once the software has +configured them to do so, but there are receivers which require software +involvement in observing LP-11 or LP-111 state. 100 µs is a brief period to hit +in software, especially when there is no interrupt telling something is +happening. + +One way to address this is to configure the transmitter side explicitly to LP-11 +or LP-111 mode, which requires support from the transmitter hardware. This is +not universally available. Many devices return to this state once streaming is +stopped while the state after power-on is LP-00 or LP-000. + +The ``.pre_streamon()`` callback may be used to prepare a transmitter for +transitioning to streaming state, but not yet start streaming. Similarly, the +``.post_streamoff()`` callback is used to undo what was done by the +``.pre_streamon()`` callback. The caller of ``.pre_streamon()`` is thus required +to call ``.post_streamoff()`` for each successful call of ``.pre_streamon()``. + +In the context of CSI-2, the ``.pre_streamon()`` callback is used to transition +the transmitter to the LP-11 or LP-111 mode. This also requires powering on the +device, so this should be only done when it is needed. + +Receiver drivers that do not need explicit LP-11 or LP-111 mode setup are waived +from calling the two callbacks. + +Stopping the transmitter +^^^^^^^^^^^^^^^^^^^^^^^^ + +A transmitter stops sending the stream of images as a result of +calling the ``.s_stream()`` callback. Some transmitters may stop the +stream at a frame boundary whereas others stop immediately, +effectively leaving the current frame unfinished. The receiver driver +should not make assumptions either way, but function properly in both +cases. diff --git a/Documentation/driver-api/media/v4l2-async.rst b/Documentation/driver-api/media/v4l2-async.rst new file mode 100644 index 0000000000..3422330b3b --- /dev/null +++ b/Documentation/driver-api/media/v4l2-async.rst @@ -0,0 +1,5 @@ +.. SPDX-License-Identifier: GPL-2.0 + +V4L2 async kAPI +^^^^^^^^^^^^^^^ +.. kernel-doc:: include/media/v4l2-async.h diff --git a/Documentation/driver-api/media/v4l2-cci.rst b/Documentation/driver-api/media/v4l2-cci.rst new file mode 100644 index 0000000000..dd297a40ed --- /dev/null +++ b/Documentation/driver-api/media/v4l2-cci.rst @@ -0,0 +1,5 @@ +.. SPDX-License-Identifier: GPL-2.0 + +V4L2 CCI kAPI +^^^^^^^^^^^^^ +.. kernel-doc:: include/media/v4l2-cci.h diff --git a/Documentation/driver-api/media/v4l2-common.rst b/Documentation/driver-api/media/v4l2-common.rst new file mode 100644 index 0000000000..b1e70eb56a --- /dev/null +++ b/Documentation/driver-api/media/v4l2-common.rst @@ -0,0 +1,8 @@ +.. SPDX-License-Identifier: GPL-2.0 + +V4L2 common functions and data structures +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. kernel-doc:: include/media/v4l2-common.h + +.. kernel-doc:: include/media/v4l2-ioctl.h diff --git a/Documentation/driver-api/media/v4l2-controls.rst b/Documentation/driver-api/media/v4l2-controls.rst new file mode 100644 index 0000000000..b2e9180482 --- /dev/null +++ b/Documentation/driver-api/media/v4l2-controls.rst @@ -0,0 +1,823 @@ +.. SPDX-License-Identifier: GPL-2.0 + +V4L2 Controls +============= + +Introduction +------------ + +The V4L2 control API seems simple enough, but quickly becomes very hard to +implement correctly in drivers. But much of the code needed to handle controls +is actually not driver specific and can be moved to the V4L core framework. + +After all, the only part that a driver developer is interested in is: + +1) How do I add a control? +2) How do I set the control's value? (i.e. s_ctrl) + +And occasionally: + +3) How do I get the control's value? (i.e. g_volatile_ctrl) +4) How do I validate the user's proposed control value? (i.e. try_ctrl) + +All the rest is something that can be done centrally. + +The control framework was created in order to implement all the rules of the +V4L2 specification with respect to controls in a central place. And to make +life as easy as possible for the driver developer. + +Note that the control framework relies on the presence of a struct +:c:type:`v4l2_device` for V4L2 drivers and struct v4l2_subdev for +sub-device drivers. + + +Objects in the framework +------------------------ + +There are two main objects: + +The :c:type:`v4l2_ctrl` object describes the control properties and keeps +track of the control's value (both the current value and the proposed new +value). + +:c:type:`v4l2_ctrl_handler` is the object that keeps track of controls. It +maintains a list of v4l2_ctrl objects that it owns and another list of +references to controls, possibly to controls owned by other handlers. + + +Basic usage for V4L2 and sub-device drivers +------------------------------------------- + +1) Prepare the driver: + +.. code-block:: c + + #include <media/v4l2-ctrls.h> + +1.1) Add the handler to your driver's top-level struct: + +For V4L2 drivers: + +.. code-block:: c + + struct foo_dev { + ... + struct v4l2_device v4l2_dev; + ... + struct v4l2_ctrl_handler ctrl_handler; + ... + }; + +For sub-device drivers: + +.. code-block:: c + + struct foo_dev { + ... + struct v4l2_subdev sd; + ... + struct v4l2_ctrl_handler ctrl_handler; + ... + }; + +1.2) Initialize the handler: + +.. code-block:: c + + v4l2_ctrl_handler_init(&foo->ctrl_handler, nr_of_controls); + +The second argument is a hint telling the function how many controls this +handler is expected to handle. It will allocate a hashtable based on this +information. It is a hint only. + +1.3) Hook the control handler into the driver: + +For V4L2 drivers: + +.. code-block:: c + + foo->v4l2_dev.ctrl_handler = &foo->ctrl_handler; + +For sub-device drivers: + +.. code-block:: c + + foo->sd.ctrl_handler = &foo->ctrl_handler; + +1.4) Clean up the handler at the end: + +.. code-block:: c + + v4l2_ctrl_handler_free(&foo->ctrl_handler); + + +2) Add controls: + +You add non-menu controls by calling :c:func:`v4l2_ctrl_new_std`: + +.. code-block:: c + + struct v4l2_ctrl *v4l2_ctrl_new_std(struct v4l2_ctrl_handler *hdl, + const struct v4l2_ctrl_ops *ops, + u32 id, s32 min, s32 max, u32 step, s32 def); + +Menu and integer menu controls are added by calling +:c:func:`v4l2_ctrl_new_std_menu`: + +.. code-block:: c + + struct v4l2_ctrl *v4l2_ctrl_new_std_menu(struct v4l2_ctrl_handler *hdl, + const struct v4l2_ctrl_ops *ops, + u32 id, s32 max, s32 skip_mask, s32 def); + +Menu controls with a driver specific menu are added by calling +:c:func:`v4l2_ctrl_new_std_menu_items`: + +.. code-block:: c + + struct v4l2_ctrl *v4l2_ctrl_new_std_menu_items( + struct v4l2_ctrl_handler *hdl, + const struct v4l2_ctrl_ops *ops, u32 id, s32 max, + s32 skip_mask, s32 def, const char * const *qmenu); + +Standard compound controls can be added by calling +:c:func:`v4l2_ctrl_new_std_compound`: + +.. code-block:: c + + struct v4l2_ctrl *v4l2_ctrl_new_std_compound(struct v4l2_ctrl_handler *hdl, + const struct v4l2_ctrl_ops *ops, u32 id, + const union v4l2_ctrl_ptr p_def); + +Integer menu controls with a driver specific menu can be added by calling +:c:func:`v4l2_ctrl_new_int_menu`: + +.. code-block:: c + + struct v4l2_ctrl *v4l2_ctrl_new_int_menu(struct v4l2_ctrl_handler *hdl, + const struct v4l2_ctrl_ops *ops, + u32 id, s32 max, s32 def, const s64 *qmenu_int); + +These functions are typically called right after the +:c:func:`v4l2_ctrl_handler_init`: + +.. code-block:: c + + static const s64 exp_bias_qmenu[] = { + -2, -1, 0, 1, 2 + }; + static const char * const test_pattern[] = { + "Disabled", + "Vertical Bars", + "Solid Black", + "Solid White", + }; + + v4l2_ctrl_handler_init(&foo->ctrl_handler, nr_of_controls); + v4l2_ctrl_new_std(&foo->ctrl_handler, &foo_ctrl_ops, + V4L2_CID_BRIGHTNESS, 0, 255, 1, 128); + v4l2_ctrl_new_std(&foo->ctrl_handler, &foo_ctrl_ops, + V4L2_CID_CONTRAST, 0, 255, 1, 128); + v4l2_ctrl_new_std_menu(&foo->ctrl_handler, &foo_ctrl_ops, + V4L2_CID_POWER_LINE_FREQUENCY, + V4L2_CID_POWER_LINE_FREQUENCY_60HZ, 0, + V4L2_CID_POWER_LINE_FREQUENCY_DISABLED); + v4l2_ctrl_new_int_menu(&foo->ctrl_handler, &foo_ctrl_ops, + V4L2_CID_EXPOSURE_BIAS, + ARRAY_SIZE(exp_bias_qmenu) - 1, + ARRAY_SIZE(exp_bias_qmenu) / 2 - 1, + exp_bias_qmenu); + v4l2_ctrl_new_std_menu_items(&foo->ctrl_handler, &foo_ctrl_ops, + V4L2_CID_TEST_PATTERN, ARRAY_SIZE(test_pattern) - 1, 0, + 0, test_pattern); + ... + if (foo->ctrl_handler.error) { + int err = foo->ctrl_handler.error; + + v4l2_ctrl_handler_free(&foo->ctrl_handler); + return err; + } + +The :c:func:`v4l2_ctrl_new_std` function returns the v4l2_ctrl pointer to +the new control, but if you do not need to access the pointer outside the +control ops, then there is no need to store it. + +The :c:func:`v4l2_ctrl_new_std` function will fill in most fields based on +the control ID except for the min, max, step and default values. These are +passed in the last four arguments. These values are driver specific while +control attributes like type, name, flags are all global. The control's +current value will be set to the default value. + +The :c:func:`v4l2_ctrl_new_std_menu` function is very similar but it is +used for menu controls. There is no min argument since that is always 0 for +menu controls, and instead of a step there is a skip_mask argument: if bit +X is 1, then menu item X is skipped. + +The :c:func:`v4l2_ctrl_new_int_menu` function creates a new standard +integer menu control with driver-specific items in the menu. It differs +from v4l2_ctrl_new_std_menu in that it doesn't have the mask argument and +takes as the last argument an array of signed 64-bit integers that form an +exact menu item list. + +The :c:func:`v4l2_ctrl_new_std_menu_items` function is very similar to +v4l2_ctrl_new_std_menu but takes an extra parameter qmenu, which is the +driver specific menu for an otherwise standard menu control. A good example +for this control is the test pattern control for capture/display/sensors +devices that have the capability to generate test patterns. These test +patterns are hardware specific, so the contents of the menu will vary from +device to device. + +Note that if something fails, the function will return NULL or an error and +set ctrl_handler->error to the error code. If ctrl_handler->error was already +set, then it will just return and do nothing. This is also true for +v4l2_ctrl_handler_init if it cannot allocate the internal data structure. + +This makes it easy to init the handler and just add all controls and only check +the error code at the end. Saves a lot of repetitive error checking. + +It is recommended to add controls in ascending control ID order: it will be +a bit faster that way. + +3) Optionally force initial control setup: + +.. code-block:: c + + v4l2_ctrl_handler_setup(&foo->ctrl_handler); + +This will call s_ctrl for all controls unconditionally. Effectively this +initializes the hardware to the default control values. It is recommended +that you do this as this ensures that both the internal data structures and +the hardware are in sync. + +4) Finally: implement the :c:type:`v4l2_ctrl_ops` + +.. code-block:: c + + static const struct v4l2_ctrl_ops foo_ctrl_ops = { + .s_ctrl = foo_s_ctrl, + }; + +Usually all you need is s_ctrl: + +.. code-block:: c + + static int foo_s_ctrl(struct v4l2_ctrl *ctrl) + { + struct foo *state = container_of(ctrl->handler, struct foo, ctrl_handler); + + switch (ctrl->id) { + case V4L2_CID_BRIGHTNESS: + write_reg(0x123, ctrl->val); + break; + case V4L2_CID_CONTRAST: + write_reg(0x456, ctrl->val); + break; + } + return 0; + } + +The control ops are called with the v4l2_ctrl pointer as argument. +The new control value has already been validated, so all you need to do is +to actually update the hardware registers. + +You're done! And this is sufficient for most of the drivers we have. No need +to do any validation of control values, or implement QUERYCTRL, QUERY_EXT_CTRL +and QUERYMENU. And G/S_CTRL as well as G/TRY/S_EXT_CTRLS are automatically supported. + + +.. note:: + + The remainder sections deal with more advanced controls topics and scenarios. + In practice the basic usage as described above is sufficient for most drivers. + + +Inheriting Sub-device Controls +------------------------------ + +When a sub-device is registered with a V4L2 driver by calling +v4l2_device_register_subdev() and the ctrl_handler fields of both v4l2_subdev +and v4l2_device are set, then the controls of the subdev will become +automatically available in the V4L2 driver as well. If the subdev driver +contains controls that already exist in the V4L2 driver, then those will be +skipped (so a V4L2 driver can always override a subdev control). + +What happens here is that v4l2_device_register_subdev() calls +v4l2_ctrl_add_handler() adding the controls of the subdev to the controls +of v4l2_device. + + +Accessing Control Values +------------------------ + +The following union is used inside the control framework to access control +values: + +.. code-block:: c + + union v4l2_ctrl_ptr { + s32 *p_s32; + s64 *p_s64; + char *p_char; + void *p; + }; + +The v4l2_ctrl struct contains these fields that can be used to access both +current and new values: + +.. code-block:: c + + s32 val; + struct { + s32 val; + } cur; + + + union v4l2_ctrl_ptr p_new; + union v4l2_ctrl_ptr p_cur; + +If the control has a simple s32 type, then: + +.. code-block:: c + + &ctrl->val == ctrl->p_new.p_s32 + &ctrl->cur.val == ctrl->p_cur.p_s32 + +For all other types use ctrl->p_cur.p<something>. Basically the val +and cur.val fields can be considered an alias since these are used so often. + +Within the control ops you can freely use these. The val and cur.val speak for +themselves. The p_char pointers point to character buffers of length +ctrl->maximum + 1, and are always 0-terminated. + +Unless the control is marked volatile the p_cur field points to the +current cached control value. When you create a new control this value is made +identical to the default value. After calling v4l2_ctrl_handler_setup() this +value is passed to the hardware. It is generally a good idea to call this +function. + +Whenever a new value is set that new value is automatically cached. This means +that most drivers do not need to implement the g_volatile_ctrl() op. The +exception is for controls that return a volatile register such as a signal +strength read-out that changes continuously. In that case you will need to +implement g_volatile_ctrl like this: + +.. code-block:: c + + static int foo_g_volatile_ctrl(struct v4l2_ctrl *ctrl) + { + switch (ctrl->id) { + case V4L2_CID_BRIGHTNESS: + ctrl->val = read_reg(0x123); + break; + } + } + +Note that you use the 'new value' union as well in g_volatile_ctrl. In general +controls that need to implement g_volatile_ctrl are read-only controls. If they +are not, a V4L2_EVENT_CTRL_CH_VALUE will not be generated when the control +changes. + +To mark a control as volatile you have to set V4L2_CTRL_FLAG_VOLATILE: + +.. code-block:: c + + ctrl = v4l2_ctrl_new_std(&sd->ctrl_handler, ...); + if (ctrl) + ctrl->flags |= V4L2_CTRL_FLAG_VOLATILE; + +For try/s_ctrl the new values (i.e. as passed by the user) are filled in and +you can modify them in try_ctrl or set them in s_ctrl. The 'cur' union +contains the current value, which you can use (but not change!) as well. + +If s_ctrl returns 0 (OK), then the control framework will copy the new final +values to the 'cur' union. + +While in g_volatile/s/try_ctrl you can access the value of all controls owned +by the same handler since the handler's lock is held. If you need to access +the value of controls owned by other handlers, then you have to be very careful +not to introduce deadlocks. + +Outside of the control ops you have to go through to helper functions to get +or set a single control value safely in your driver: + +.. code-block:: c + + s32 v4l2_ctrl_g_ctrl(struct v4l2_ctrl *ctrl); + int v4l2_ctrl_s_ctrl(struct v4l2_ctrl *ctrl, s32 val); + +These functions go through the control framework just as VIDIOC_G/S_CTRL ioctls +do. Don't use these inside the control ops g_volatile/s/try_ctrl, though, that +will result in a deadlock since these helpers lock the handler as well. + +You can also take the handler lock yourself: + +.. code-block:: c + + mutex_lock(&state->ctrl_handler.lock); + pr_info("String value is '%s'\n", ctrl1->p_cur.p_char); + pr_info("Integer value is '%s'\n", ctrl2->cur.val); + mutex_unlock(&state->ctrl_handler.lock); + + +Menu Controls +------------- + +The v4l2_ctrl struct contains this union: + +.. code-block:: c + + union { + u32 step; + u32 menu_skip_mask; + }; + +For menu controls menu_skip_mask is used. What it does is that it allows you +to easily exclude certain menu items. This is used in the VIDIOC_QUERYMENU +implementation where you can return -EINVAL if a certain menu item is not +present. Note that VIDIOC_QUERYCTRL always returns a step value of 1 for +menu controls. + +A good example is the MPEG Audio Layer II Bitrate menu control where the +menu is a list of standardized possible bitrates. But in practice hardware +implementations will only support a subset of those. By setting the skip +mask you can tell the framework which menu items should be skipped. Setting +it to 0 means that all menu items are supported. + +You set this mask either through the v4l2_ctrl_config struct for a custom +control, or by calling v4l2_ctrl_new_std_menu(). + + +Custom Controls +--------------- + +Driver specific controls can be created using v4l2_ctrl_new_custom(): + +.. code-block:: c + + static const struct v4l2_ctrl_config ctrl_filter = { + .ops = &ctrl_custom_ops, + .id = V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER, + .name = "Spatial Filter", + .type = V4L2_CTRL_TYPE_INTEGER, + .flags = V4L2_CTRL_FLAG_SLIDER, + .max = 15, + .step = 1, + }; + + ctrl = v4l2_ctrl_new_custom(&foo->ctrl_handler, &ctrl_filter, NULL); + +The last argument is the priv pointer which can be set to driver-specific +private data. + +The v4l2_ctrl_config struct also has a field to set the is_private flag. + +If the name field is not set, then the framework will assume this is a standard +control and will fill in the name, type and flags fields accordingly. + + +Active and Grabbed Controls +--------------------------- + +If you get more complex relationships between controls, then you may have to +activate and deactivate controls. For example, if the Chroma AGC control is +on, then the Chroma Gain control is inactive. That is, you may set it, but +the value will not be used by the hardware as long as the automatic gain +control is on. Typically user interfaces can disable such input fields. + +You can set the 'active' status using v4l2_ctrl_activate(). By default all +controls are active. Note that the framework does not check for this flag. +It is meant purely for GUIs. The function is typically called from within +s_ctrl. + +The other flag is the 'grabbed' flag. A grabbed control means that you cannot +change it because it is in use by some resource. Typical examples are MPEG +bitrate controls that cannot be changed while capturing is in progress. + +If a control is set to 'grabbed' using v4l2_ctrl_grab(), then the framework +will return -EBUSY if an attempt is made to set this control. The +v4l2_ctrl_grab() function is typically called from the driver when it +starts or stops streaming. + + +Control Clusters +---------------- + +By default all controls are independent from the others. But in more +complex scenarios you can get dependencies from one control to another. +In that case you need to 'cluster' them: + +.. code-block:: c + + struct foo { + struct v4l2_ctrl_handler ctrl_handler; + #define AUDIO_CL_VOLUME (0) + #define AUDIO_CL_MUTE (1) + struct v4l2_ctrl *audio_cluster[2]; + ... + }; + + state->audio_cluster[AUDIO_CL_VOLUME] = + v4l2_ctrl_new_std(&state->ctrl_handler, ...); + state->audio_cluster[AUDIO_CL_MUTE] = + v4l2_ctrl_new_std(&state->ctrl_handler, ...); + v4l2_ctrl_cluster(ARRAY_SIZE(state->audio_cluster), state->audio_cluster); + +From now on whenever one or more of the controls belonging to the same +cluster is set (or 'gotten', or 'tried'), only the control ops of the first +control ('volume' in this example) is called. You effectively create a new +composite control. Similar to how a 'struct' works in C. + +So when s_ctrl is called with V4L2_CID_AUDIO_VOLUME as argument, you should set +all two controls belonging to the audio_cluster: + +.. code-block:: c + + static int foo_s_ctrl(struct v4l2_ctrl *ctrl) + { + struct foo *state = container_of(ctrl->handler, struct foo, ctrl_handler); + + switch (ctrl->id) { + case V4L2_CID_AUDIO_VOLUME: { + struct v4l2_ctrl *mute = ctrl->cluster[AUDIO_CL_MUTE]; + + write_reg(0x123, mute->val ? 0 : ctrl->val); + break; + } + case V4L2_CID_CONTRAST: + write_reg(0x456, ctrl->val); + break; + } + return 0; + } + +In the example above the following are equivalent for the VOLUME case: + +.. code-block:: c + + ctrl == ctrl->cluster[AUDIO_CL_VOLUME] == state->audio_cluster[AUDIO_CL_VOLUME] + ctrl->cluster[AUDIO_CL_MUTE] == state->audio_cluster[AUDIO_CL_MUTE] + +In practice using cluster arrays like this becomes very tiresome. So instead +the following equivalent method is used: + +.. code-block:: c + + struct { + /* audio cluster */ + struct v4l2_ctrl *volume; + struct v4l2_ctrl *mute; + }; + +The anonymous struct is used to clearly 'cluster' these two control pointers, +but it serves no other purpose. The effect is the same as creating an +array with two control pointers. So you can just do: + +.. code-block:: c + + state->volume = v4l2_ctrl_new_std(&state->ctrl_handler, ...); + state->mute = v4l2_ctrl_new_std(&state->ctrl_handler, ...); + v4l2_ctrl_cluster(2, &state->volume); + +And in foo_s_ctrl you can use these pointers directly: state->mute->val. + +Note that controls in a cluster may be NULL. For example, if for some +reason mute was never added (because the hardware doesn't support that +particular feature), then mute will be NULL. So in that case we have a +cluster of 2 controls, of which only 1 is actually instantiated. The +only restriction is that the first control of the cluster must always be +present, since that is the 'master' control of the cluster. The master +control is the one that identifies the cluster and that provides the +pointer to the v4l2_ctrl_ops struct that is used for that cluster. + +Obviously, all controls in the cluster array must be initialized to either +a valid control or to NULL. + +In rare cases you might want to know which controls of a cluster actually +were set explicitly by the user. For this you can check the 'is_new' flag of +each control. For example, in the case of a volume/mute cluster the 'is_new' +flag of the mute control would be set if the user called VIDIOC_S_CTRL for +mute only. If the user would call VIDIOC_S_EXT_CTRLS for both mute and volume +controls, then the 'is_new' flag would be 1 for both controls. + +The 'is_new' flag is always 1 when called from v4l2_ctrl_handler_setup(). + + +Handling autogain/gain-type Controls with Auto Clusters +------------------------------------------------------- + +A common type of control cluster is one that handles 'auto-foo/foo'-type +controls. Typical examples are autogain/gain, autoexposure/exposure, +autowhitebalance/red balance/blue balance. In all cases you have one control +that determines whether another control is handled automatically by the hardware, +or whether it is under manual control from the user. + +If the cluster is in automatic mode, then the manual controls should be +marked inactive and volatile. When the volatile controls are read the +g_volatile_ctrl operation should return the value that the hardware's automatic +mode set up automatically. + +If the cluster is put in manual mode, then the manual controls should become +active again and the volatile flag is cleared (so g_volatile_ctrl is no longer +called while in manual mode). In addition just before switching to manual mode +the current values as determined by the auto mode are copied as the new manual +values. + +Finally the V4L2_CTRL_FLAG_UPDATE should be set for the auto control since +changing that control affects the control flags of the manual controls. + +In order to simplify this a special variation of v4l2_ctrl_cluster was +introduced: + +.. code-block:: c + + void v4l2_ctrl_auto_cluster(unsigned ncontrols, struct v4l2_ctrl **controls, + u8 manual_val, bool set_volatile); + +The first two arguments are identical to v4l2_ctrl_cluster. The third argument +tells the framework which value switches the cluster into manual mode. The +last argument will optionally set V4L2_CTRL_FLAG_VOLATILE for the non-auto controls. +If it is false, then the manual controls are never volatile. You would typically +use that if the hardware does not give you the option to read back to values as +determined by the auto mode (e.g. if autogain is on, the hardware doesn't allow +you to obtain the current gain value). + +The first control of the cluster is assumed to be the 'auto' control. + +Using this function will ensure that you don't need to handle all the complex +flag and volatile handling. + + +VIDIOC_LOG_STATUS Support +------------------------- + +This ioctl allow you to dump the current status of a driver to the kernel log. +The v4l2_ctrl_handler_log_status(ctrl_handler, prefix) can be used to dump the +value of the controls owned by the given handler to the log. You can supply a +prefix as well. If the prefix didn't end with a space, then ': ' will be added +for you. + + +Different Handlers for Different Video Nodes +-------------------------------------------- + +Usually the V4L2 driver has just one control handler that is global for +all video nodes. But you can also specify different control handlers for +different video nodes. You can do that by manually setting the ctrl_handler +field of struct video_device. + +That is no problem if there are no subdevs involved but if there are, then +you need to block the automatic merging of subdev controls to the global +control handler. You do that by simply setting the ctrl_handler field in +struct v4l2_device to NULL. Now v4l2_device_register_subdev() will no longer +merge subdev controls. + +After each subdev was added, you will then have to call v4l2_ctrl_add_handler +manually to add the subdev's control handler (sd->ctrl_handler) to the desired +control handler. This control handler may be specific to the video_device or +for a subset of video_device's. For example: the radio device nodes only have +audio controls, while the video and vbi device nodes share the same control +handler for the audio and video controls. + +If you want to have one handler (e.g. for a radio device node) have a subset +of another handler (e.g. for a video device node), then you should first add +the controls to the first handler, add the other controls to the second +handler and finally add the first handler to the second. For example: + +.. code-block:: c + + v4l2_ctrl_new_std(&radio_ctrl_handler, &radio_ops, V4L2_CID_AUDIO_VOLUME, ...); + v4l2_ctrl_new_std(&radio_ctrl_handler, &radio_ops, V4L2_CID_AUDIO_MUTE, ...); + v4l2_ctrl_new_std(&video_ctrl_handler, &video_ops, V4L2_CID_BRIGHTNESS, ...); + v4l2_ctrl_new_std(&video_ctrl_handler, &video_ops, V4L2_CID_CONTRAST, ...); + v4l2_ctrl_add_handler(&video_ctrl_handler, &radio_ctrl_handler, NULL); + +The last argument to v4l2_ctrl_add_handler() is a filter function that allows +you to filter which controls will be added. Set it to NULL if you want to add +all controls. + +Or you can add specific controls to a handler: + +.. code-block:: c + + volume = v4l2_ctrl_new_std(&video_ctrl_handler, &ops, V4L2_CID_AUDIO_VOLUME, ...); + v4l2_ctrl_new_std(&video_ctrl_handler, &ops, V4L2_CID_BRIGHTNESS, ...); + v4l2_ctrl_new_std(&video_ctrl_handler, &ops, V4L2_CID_CONTRAST, ...); + +What you should not do is make two identical controls for two handlers. +For example: + +.. code-block:: c + + v4l2_ctrl_new_std(&radio_ctrl_handler, &radio_ops, V4L2_CID_AUDIO_MUTE, ...); + v4l2_ctrl_new_std(&video_ctrl_handler, &video_ops, V4L2_CID_AUDIO_MUTE, ...); + +This would be bad since muting the radio would not change the video mute +control. The rule is to have one control for each hardware 'knob' that you +can twiddle. + + +Finding Controls +---------------- + +Normally you have created the controls yourself and you can store the struct +v4l2_ctrl pointer into your own struct. + +But sometimes you need to find a control from another handler that you do +not own. For example, if you have to find a volume control from a subdev. + +You can do that by calling v4l2_ctrl_find: + +.. code-block:: c + + struct v4l2_ctrl *volume; + + volume = v4l2_ctrl_find(sd->ctrl_handler, V4L2_CID_AUDIO_VOLUME); + +Since v4l2_ctrl_find will lock the handler you have to be careful where you +use it. For example, this is not a good idea: + +.. code-block:: c + + struct v4l2_ctrl_handler ctrl_handler; + + v4l2_ctrl_new_std(&ctrl_handler, &video_ops, V4L2_CID_BRIGHTNESS, ...); + v4l2_ctrl_new_std(&ctrl_handler, &video_ops, V4L2_CID_CONTRAST, ...); + +...and in video_ops.s_ctrl: + +.. code-block:: c + + case V4L2_CID_BRIGHTNESS: + contrast = v4l2_find_ctrl(&ctrl_handler, V4L2_CID_CONTRAST); + ... + +When s_ctrl is called by the framework the ctrl_handler.lock is already taken, so +attempting to find another control from the same handler will deadlock. + +It is recommended not to use this function from inside the control ops. + + +Preventing Controls inheritance +------------------------------- + +When one control handler is added to another using v4l2_ctrl_add_handler, then +by default all controls from one are merged to the other. But a subdev might +have low-level controls that make sense for some advanced embedded system, but +not when it is used in consumer-level hardware. In that case you want to keep +those low-level controls local to the subdev. You can do this by simply +setting the 'is_private' flag of the control to 1: + +.. code-block:: c + + static const struct v4l2_ctrl_config ctrl_private = { + .ops = &ctrl_custom_ops, + .id = V4L2_CID_..., + .name = "Some Private Control", + .type = V4L2_CTRL_TYPE_INTEGER, + .max = 15, + .step = 1, + .is_private = 1, + }; + + ctrl = v4l2_ctrl_new_custom(&foo->ctrl_handler, &ctrl_private, NULL); + +These controls will now be skipped when v4l2_ctrl_add_handler is called. + + +V4L2_CTRL_TYPE_CTRL_CLASS Controls +---------------------------------- + +Controls of this type can be used by GUIs to get the name of the control class. +A fully featured GUI can make a dialog with multiple tabs with each tab +containing the controls belonging to a particular control class. The name of +each tab can be found by querying a special control with ID <control class | 1>. + +Drivers do not have to care about this. The framework will automatically add +a control of this type whenever the first control belonging to a new control +class is added. + + +Adding Notify Callbacks +----------------------- + +Sometimes the platform or bridge driver needs to be notified when a control +from a sub-device driver changes. You can set a notify callback by calling +this function: + +.. code-block:: c + + void v4l2_ctrl_notify(struct v4l2_ctrl *ctrl, + void (*notify)(struct v4l2_ctrl *ctrl, void *priv), void *priv); + +Whenever the give control changes value the notify callback will be called +with a pointer to the control and the priv pointer that was passed with +v4l2_ctrl_notify. Note that the control's handler lock is held when the +notify function is called. + +There can be only one notify function per control handler. Any attempt +to set another notify function will cause a WARN_ON. + +v4l2_ctrl functions and data structures +--------------------------------------- + +.. kernel-doc:: include/media/v4l2-ctrls.h diff --git a/Documentation/driver-api/media/v4l2-core.rst b/Documentation/driver-api/media/v4l2-core.rst new file mode 100644 index 0000000000..239045ecc8 --- /dev/null +++ b/Documentation/driver-api/media/v4l2-core.rst @@ -0,0 +1,29 @@ +.. SPDX-License-Identifier: GPL-2.0 + +Video4Linux devices +------------------- + +.. toctree:: + :maxdepth: 1 + + v4l2-intro + v4l2-dev + v4l2-device + v4l2-fh + v4l2-subdev + v4l2-event + v4l2-controls + v4l2-videobuf + v4l2-videobuf2 + v4l2-dv-timings + v4l2-flash-led-class + v4l2-mc + v4l2-mediabus + v4l2-mem2mem + v4l2-async + v4l2-fwnode + v4l2-cci + v4l2-rect + v4l2-tuner + v4l2-common + v4l2-tveeprom diff --git a/Documentation/driver-api/media/v4l2-dev.rst b/Documentation/driver-api/media/v4l2-dev.rst new file mode 100644 index 0000000000..99e3b5fa74 --- /dev/null +++ b/Documentation/driver-api/media/v4l2-dev.rst @@ -0,0 +1,375 @@ +.. SPDX-License-Identifier: GPL-2.0 + +Video device' s internal representation +======================================= + +The actual device nodes in the ``/dev`` directory are created using the +:c:type:`video_device` struct (``v4l2-dev.h``). This struct can either be +allocated dynamically or embedded in a larger struct. + +To allocate it dynamically use :c:func:`video_device_alloc`: + +.. code-block:: c + + struct video_device *vdev = video_device_alloc(); + + if (vdev == NULL) + return -ENOMEM; + + vdev->release = video_device_release; + +If you embed it in a larger struct, then you must set the ``release()`` +callback to your own function: + +.. code-block:: c + + struct video_device *vdev = &my_vdev->vdev; + + vdev->release = my_vdev_release; + +The ``release()`` callback must be set and it is called when the last user +of the video device exits. + +The default :c:func:`video_device_release` callback currently +just calls ``kfree`` to free the allocated memory. + +There is also a :c:func:`video_device_release_empty` function that does +nothing (is empty) and should be used if the struct is embedded and there +is nothing to do when it is released. + +You should also set these fields of :c:type:`video_device`: + +- :c:type:`video_device`->v4l2_dev: must be set to the :c:type:`v4l2_device` + parent device. + +- :c:type:`video_device`->name: set to something descriptive and unique. + +- :c:type:`video_device`->vfl_dir: set this to ``VFL_DIR_RX`` for capture + devices (``VFL_DIR_RX`` has value 0, so this is normally already the + default), set to ``VFL_DIR_TX`` for output devices and ``VFL_DIR_M2M`` for mem2mem (codec) devices. + +- :c:type:`video_device`->fops: set to the :c:type:`v4l2_file_operations` + struct. + +- :c:type:`video_device`->ioctl_ops: if you use the :c:type:`v4l2_ioctl_ops` + to simplify ioctl maintenance (highly recommended to use this and it might + become compulsory in the future!), then set this to your + :c:type:`v4l2_ioctl_ops` struct. The :c:type:`video_device`->vfl_type and + :c:type:`video_device`->vfl_dir fields are used to disable ops that do not + match the type/dir combination. E.g. VBI ops are disabled for non-VBI nodes, + and output ops are disabled for a capture device. This makes it possible to + provide just one :c:type:`v4l2_ioctl_ops` struct for both vbi and + video nodes. + +- :c:type:`video_device`->lock: leave to ``NULL`` if you want to do all the + locking in the driver. Otherwise you give it a pointer to a struct + ``mutex_lock`` and before the :c:type:`video_device`->unlocked_ioctl + file operation is called this lock will be taken by the core and released + afterwards. See the next section for more details. + +- :c:type:`video_device`->queue: a pointer to the struct vb2_queue + associated with this device node. + If queue is not ``NULL``, and queue->lock is not ``NULL``, then queue->lock + is used for the queuing ioctls (``VIDIOC_REQBUFS``, ``CREATE_BUFS``, + ``QBUF``, ``DQBUF``, ``QUERYBUF``, ``PREPARE_BUF``, ``STREAMON`` and + ``STREAMOFF``) instead of the lock above. + That way the :ref:`vb2 <vb2_framework>` queuing framework does not have + to wait for other ioctls. This queue pointer is also used by the + :ref:`vb2 <vb2_framework>` helper functions to check for + queuing ownership (i.e. is the filehandle calling it allowed to do the + operation). + +- :c:type:`video_device`->prio: keeps track of the priorities. Used to + implement ``VIDIOC_G_PRIORITY`` and ``VIDIOC_S_PRIORITY``. + If left to ``NULL``, then it will use the struct v4l2_prio_state + in :c:type:`v4l2_device`. If you want to have a separate priority state per + (group of) device node(s), then you can point it to your own struct + :c:type:`v4l2_prio_state`. + +- :c:type:`video_device`->dev_parent: you only set this if v4l2_device was + registered with ``NULL`` as the parent ``device`` struct. This only happens + in cases where one hardware device has multiple PCI devices that all share + the same :c:type:`v4l2_device` core. + + The cx88 driver is an example of this: one core :c:type:`v4l2_device` struct, + but it is used by both a raw video PCI device (cx8800) and a MPEG PCI device + (cx8802). Since the :c:type:`v4l2_device` cannot be associated with two PCI + devices at the same time it is setup without a parent device. But when the + struct video_device is initialized you **do** know which parent + PCI device to use and so you set ``dev_device`` to the correct PCI device. + +If you use :c:type:`v4l2_ioctl_ops`, then you should set +:c:type:`video_device`->unlocked_ioctl to :c:func:`video_ioctl2` in your +:c:type:`v4l2_file_operations` struct. + +In some cases you want to tell the core that a function you had specified in +your :c:type:`v4l2_ioctl_ops` should be ignored. You can mark such ioctls by +calling this function before :c:func:`video_register_device` is called: + + :c:func:`v4l2_disable_ioctl <v4l2_disable_ioctl>` + (:c:type:`vdev <video_device>`, cmd). + +This tends to be needed if based on external factors (e.g. which card is +being used) you want to turns off certain features in :c:type:`v4l2_ioctl_ops` +without having to make a new struct. + +The :c:type:`v4l2_file_operations` struct is a subset of file_operations. +The main difference is that the inode argument is omitted since it is never +used. + +If integration with the media framework is needed, you must initialize the +:c:type:`media_entity` struct embedded in the :c:type:`video_device` struct +(entity field) by calling :c:func:`media_entity_pads_init`: + +.. code-block:: c + + struct media_pad *pad = &my_vdev->pad; + int err; + + err = media_entity_pads_init(&vdev->entity, 1, pad); + +The pads array must have been previously initialized. There is no need to +manually set the struct media_entity type and name fields. + +A reference to the entity will be automatically acquired/released when the +video device is opened/closed. + +ioctls and locking +------------------ + +The V4L core provides optional locking services. The main service is the +lock field in struct video_device, which is a pointer to a mutex. +If you set this pointer, then that will be used by unlocked_ioctl to +serialize all ioctls. + +If you are using the :ref:`videobuf2 framework <vb2_framework>`, then there +is a second lock that you can set: :c:type:`video_device`->queue->lock. If +set, then this lock will be used instead of :c:type:`video_device`->lock +to serialize all queuing ioctls (see the previous section +for the full list of those ioctls). + +The advantage of using a different lock for the queuing ioctls is that for some +drivers (particularly USB drivers) certain commands such as setting controls +can take a long time, so you want to use a separate lock for the buffer queuing +ioctls. That way your ``VIDIOC_DQBUF`` doesn't stall because the driver is busy +changing the e.g. exposure of the webcam. + +Of course, you can always do all the locking yourself by leaving both lock +pointers at ``NULL``. + +If you use the old :ref:`videobuf framework <vb_framework>` then you must +pass the :c:type:`video_device`->lock to the videobuf queue initialize +function: if videobuf has to wait for a frame to arrive, then it will +temporarily unlock the lock and relock it afterwards. If your driver also +waits in the code, then you should do the same to allow other +processes to access the device node while the first process is waiting for +something. + +In the case of :ref:`videobuf2 <vb2_framework>` you will need to implement the +``wait_prepare()`` and ``wait_finish()`` callbacks to unlock/lock if applicable. +If you use the ``queue->lock`` pointer, then you can use the helper functions +:c:func:`vb2_ops_wait_prepare` and :c:func:`vb2_ops_wait_finish`. + +The implementation of a hotplug disconnect should also take the lock from +:c:type:`video_device` before calling v4l2_device_disconnect. If you are also +using :c:type:`video_device`->queue->lock, then you have to first lock +:c:type:`video_device`->queue->lock followed by :c:type:`video_device`->lock. +That way you can be sure no ioctl is running when you call +:c:func:`v4l2_device_disconnect`. + +Video device registration +------------------------- + +Next you register the video device with :c:func:`video_register_device`. +This will create the character device for you. + +.. code-block:: c + + err = video_register_device(vdev, VFL_TYPE_VIDEO, -1); + if (err) { + video_device_release(vdev); /* or kfree(my_vdev); */ + return err; + } + +If the :c:type:`v4l2_device` parent device has a not ``NULL`` mdev field, +the video device entity will be automatically registered with the media +device. + +Which device is registered depends on the type argument. The following +types exist: + +========================== ==================== ============================== +:c:type:`vfl_devnode_type` Device name Usage +========================== ==================== ============================== +``VFL_TYPE_VIDEO`` ``/dev/videoX`` for video input/output devices +``VFL_TYPE_VBI`` ``/dev/vbiX`` for vertical blank data (i.e. + closed captions, teletext) +``VFL_TYPE_RADIO`` ``/dev/radioX`` for radio tuners +``VFL_TYPE_SUBDEV`` ``/dev/v4l-subdevX`` for V4L2 subdevices +``VFL_TYPE_SDR`` ``/dev/swradioX`` for Software Defined Radio + (SDR) tuners +``VFL_TYPE_TOUCH`` ``/dev/v4l-touchX`` for touch sensors +========================== ==================== ============================== + +The last argument gives you a certain amount of control over the device +node number used (i.e. the X in ``videoX``). Normally you will pass -1 +to let the v4l2 framework pick the first free number. But sometimes users +want to select a specific node number. It is common that drivers allow +the user to select a specific device node number through a driver module +option. That number is then passed to this function and video_register_device +will attempt to select that device node number. If that number was already +in use, then the next free device node number will be selected and it +will send a warning to the kernel log. + +Another use-case is if a driver creates many devices. In that case it can +be useful to place different video devices in separate ranges. For example, +video capture devices start at 0, video output devices start at 16. +So you can use the last argument to specify a minimum device node number +and the v4l2 framework will try to pick the first free number that is equal +or higher to what you passed. If that fails, then it will just pick the +first free number. + +Since in this case you do not care about a warning about not being able +to select the specified device node number, you can call the function +:c:func:`video_register_device_no_warn` instead. + +Whenever a device node is created some attributes are also created for you. +If you look in ``/sys/class/video4linux`` you see the devices. Go into e.g. +``video0`` and you will see 'name', 'dev_debug' and 'index' attributes. The +'name' attribute is the 'name' field of the video_device struct. The +'dev_debug' attribute can be used to enable core debugging. See the next +section for more detailed information on this. + +The 'index' attribute is the index of the device node: for each call to +:c:func:`video_register_device()` the index is just increased by 1. The +first video device node you register always starts with index 0. + +Users can setup udev rules that utilize the index attribute to make fancy +device names (e.g. '``mpegX``' for MPEG video capture device nodes). + +After the device was successfully registered, then you can use these fields: + +- :c:type:`video_device`->vfl_type: the device type passed to + :c:func:`video_register_device`. +- :c:type:`video_device`->minor: the assigned device minor number. +- :c:type:`video_device`->num: the device node number (i.e. the X in + ``videoX``). +- :c:type:`video_device`->index: the device index number. + +If the registration failed, then you need to call +:c:func:`video_device_release` to free the allocated :c:type:`video_device` +struct, or free your own struct if the :c:type:`video_device` was embedded in +it. The ``vdev->release()`` callback will never be called if the registration +failed, nor should you ever attempt to unregister the device if the +registration failed. + +video device debugging +---------------------- + +The 'dev_debug' attribute that is created for each video, vbi, radio or swradio +device in ``/sys/class/video4linux/<devX>/`` allows you to enable logging of +file operations. + +It is a bitmask and the following bits can be set: + +.. tabularcolumns:: |p{5ex}|L| + +===== ================================================================ +Mask Description +===== ================================================================ +0x01 Log the ioctl name and error code. VIDIOC_(D)QBUF ioctls are + only logged if bit 0x08 is also set. +0x02 Log the ioctl name arguments and error code. VIDIOC_(D)QBUF + ioctls are + only logged if bit 0x08 is also set. +0x04 Log the file operations open, release, read, write, mmap and + get_unmapped_area. The read and write operations are only + logged if bit 0x08 is also set. +0x08 Log the read and write file operations and the VIDIOC_QBUF and + VIDIOC_DQBUF ioctls. +0x10 Log the poll file operation. +0x20 Log error and messages in the control operations. +===== ================================================================ + +Video device cleanup +-------------------- + +When the video device nodes have to be removed, either during the unload +of the driver or because the USB device was disconnected, then you should +unregister them with: + + :c:func:`video_unregister_device` + (:c:type:`vdev <video_device>`); + +This will remove the device nodes from sysfs (causing udev to remove them +from ``/dev``). + +After :c:func:`video_unregister_device` returns no new opens can be done. +However, in the case of USB devices some application might still have one of +these device nodes open. So after the unregister all file operations (except +release, of course) will return an error as well. + +When the last user of the video device node exits, then the ``vdev->release()`` +callback is called and you can do the final cleanup there. + +Don't forget to cleanup the media entity associated with the video device if +it has been initialized: + + :c:func:`media_entity_cleanup <media_entity_cleanup>` + (&vdev->entity); + +This can be done from the release callback. + + +helper functions +---------------- + +There are a few useful helper functions: + +- file and :c:type:`video_device` private data + +You can set/get driver private data in the video_device struct using: + + :c:func:`video_get_drvdata <video_get_drvdata>` + (:c:type:`vdev <video_device>`); + + :c:func:`video_set_drvdata <video_set_drvdata>` + (:c:type:`vdev <video_device>`); + +Note that you can safely call :c:func:`video_set_drvdata` before calling +:c:func:`video_register_device`. + +And this function: + + :c:func:`video_devdata <video_devdata>` + (struct file \*file); + +returns the video_device belonging to the file struct. + +The :c:func:`video_devdata` function combines :c:func:`video_get_drvdata` +with :c:func:`video_devdata`: + + :c:func:`video_drvdata <video_drvdata>` + (struct file \*file); + +You can go from a :c:type:`video_device` struct to the v4l2_device struct using: + +.. code-block:: c + + struct v4l2_device *v4l2_dev = vdev->v4l2_dev; + +- Device node name + +The :c:type:`video_device` node kernel name can be retrieved using: + + :c:func:`video_device_node_name <video_device_node_name>` + (:c:type:`vdev <video_device>`); + +The name is used as a hint by userspace tools such as udev. The function +should be used where possible instead of accessing the video_device::num and +video_device::minor fields. + +video_device functions and data structures +------------------------------------------ + +.. kernel-doc:: include/media/v4l2-dev.h diff --git a/Documentation/driver-api/media/v4l2-device.rst b/Documentation/driver-api/media/v4l2-device.rst new file mode 100644 index 0000000000..7bd9c45f55 --- /dev/null +++ b/Documentation/driver-api/media/v4l2-device.rst @@ -0,0 +1,146 @@ +.. SPDX-License-Identifier: GPL-2.0 + +V4L2 device instance +-------------------- + +Each device instance is represented by a struct v4l2_device. +Very simple devices can just allocate this struct, but most of the time you +would embed this struct inside a larger struct. + +You must register the device instance by calling: + + :c:func:`v4l2_device_register <v4l2_device_register>` + (dev, :c:type:`v4l2_dev <v4l2_device>`). + +Registration will initialize the :c:type:`v4l2_device` struct. If the +dev->driver_data field is ``NULL``, it will be linked to +:c:type:`v4l2_dev <v4l2_device>` argument. + +Drivers that want integration with the media device framework need to set +dev->driver_data manually to point to the driver-specific device structure +that embed the struct v4l2_device instance. This is achieved by a +``dev_set_drvdata()`` call before registering the V4L2 device instance. +They must also set the struct v4l2_device mdev field to point to a +properly initialized and registered :c:type:`media_device` instance. + +If :c:type:`v4l2_dev <v4l2_device>`\ ->name is empty then it will be set to a +value derived from dev (driver name followed by the bus_id, to be precise). +If you set it up before calling :c:func:`v4l2_device_register` then it will +be untouched. If dev is ``NULL``, then you **must** setup +:c:type:`v4l2_dev <v4l2_device>`\ ->name before calling +:c:func:`v4l2_device_register`. + +You can use :c:func:`v4l2_device_set_name` to set the name based on a driver +name and a driver-global atomic_t instance. This will generate names like +``ivtv0``, ``ivtv1``, etc. If the name ends with a digit, then it will insert +a dash: ``cx18-0``, ``cx18-1``, etc. This function returns the instance number. + +The first ``dev`` argument is normally the ``struct device`` pointer of a +``pci_dev``, ``usb_interface`` or ``platform_device``. It is rare for dev to +be ``NULL``, but it happens with ISA devices or when one device creates +multiple PCI devices, thus making it impossible to associate +:c:type:`v4l2_dev <v4l2_device>` with a particular parent. + +You can also supply a ``notify()`` callback that can be called by sub-devices +to notify you of events. Whether you need to set this depends on the +sub-device. Any notifications a sub-device supports must be defined in a header +in ``include/media/subdevice.h``. + +V4L2 devices are unregistered by calling: + + :c:func:`v4l2_device_unregister` + (:c:type:`v4l2_dev <v4l2_device>`). + +If the dev->driver_data field points to :c:type:`v4l2_dev <v4l2_device>`, +it will be reset to ``NULL``. Unregistering will also automatically unregister +all subdevs from the device. + +If you have a hotpluggable device (e.g. a USB device), then when a disconnect +happens the parent device becomes invalid. Since :c:type:`v4l2_device` has a +pointer to that parent device it has to be cleared as well to mark that the +parent is gone. To do this call: + + :c:func:`v4l2_device_disconnect` + (:c:type:`v4l2_dev <v4l2_device>`). + +This does *not* unregister the subdevs, so you still need to call the +:c:func:`v4l2_device_unregister` function for that. If your driver is not +hotpluggable, then there is no need to call :c:func:`v4l2_device_disconnect`. + +Sometimes you need to iterate over all devices registered by a specific +driver. This is usually the case if multiple device drivers use the same +hardware. E.g. the ivtvfb driver is a framebuffer driver that uses the ivtv +hardware. The same is true for alsa drivers for example. + +You can iterate over all registered devices as follows: + +.. code-block:: c + + static int callback(struct device *dev, void *p) + { + struct v4l2_device *v4l2_dev = dev_get_drvdata(dev); + + /* test if this device was inited */ + if (v4l2_dev == NULL) + return 0; + ... + return 0; + } + + int iterate(void *p) + { + struct device_driver *drv; + int err; + + /* Find driver 'ivtv' on the PCI bus. + pci_bus_type is a global. For USB buses use usb_bus_type. */ + drv = driver_find("ivtv", &pci_bus_type); + /* iterate over all ivtv device instances */ + err = driver_for_each_device(drv, NULL, p, callback); + put_driver(drv); + return err; + } + +Sometimes you need to keep a running counter of the device instance. This is +commonly used to map a device instance to an index of a module option array. + +The recommended approach is as follows: + +.. code-block:: c + + static atomic_t drv_instance = ATOMIC_INIT(0); + + static int drv_probe(struct pci_dev *pdev, const struct pci_device_id *pci_id) + { + ... + state->instance = atomic_inc_return(&drv_instance) - 1; + } + +If you have multiple device nodes then it can be difficult to know when it is +safe to unregister :c:type:`v4l2_device` for hotpluggable devices. For this +purpose :c:type:`v4l2_device` has refcounting support. The refcount is +increased whenever :c:func:`video_register_device` is called and it is +decreased whenever that device node is released. When the refcount reaches +zero, then the :c:type:`v4l2_device` release() callback is called. You can +do your final cleanup there. + +If other device nodes (e.g. ALSA) are created, then you can increase and +decrease the refcount manually as well by calling: + + :c:func:`v4l2_device_get` + (:c:type:`v4l2_dev <v4l2_device>`). + +or: + + :c:func:`v4l2_device_put` + (:c:type:`v4l2_dev <v4l2_device>`). + +Since the initial refcount is 1 you also need to call +:c:func:`v4l2_device_put` in the ``disconnect()`` callback (for USB devices) +or in the ``remove()`` callback (for e.g. PCI devices), otherwise the refcount +will never reach 0. + +v4l2_device functions and data structures +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. kernel-doc:: include/media/v4l2-device.h diff --git a/Documentation/driver-api/media/v4l2-dv-timings.rst b/Documentation/driver-api/media/v4l2-dv-timings.rst new file mode 100644 index 0000000000..b178f93151 --- /dev/null +++ b/Documentation/driver-api/media/v4l2-dv-timings.rst @@ -0,0 +1,6 @@ +.. SPDX-License-Identifier: GPL-2.0 + +V4L2 DV Timings functions +^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. kernel-doc:: include/media/v4l2-dv-timings.h diff --git a/Documentation/driver-api/media/v4l2-event.rst b/Documentation/driver-api/media/v4l2-event.rst new file mode 100644 index 0000000000..52d4fbc5d8 --- /dev/null +++ b/Documentation/driver-api/media/v4l2-event.rst @@ -0,0 +1,181 @@ +.. SPDX-License-Identifier: GPL-2.0 + +V4L2 events +----------- + +The V4L2 events provide a generic way to pass events to user space. +The driver must use :c:type:`v4l2_fh` to be able to support V4L2 events. + +Events are subscribed per-filehandle. An event specification consists of a +``type`` and is optionally associated with an object identified through the +``id`` field. If unused, then the ``id`` is 0. So an event is uniquely +identified by the ``(type, id)`` tuple. + +The :c:type:`v4l2_fh` struct has a list of subscribed events on its +``subscribed`` field. + +When the user subscribes to an event, a :c:type:`v4l2_subscribed_event` +struct is added to :c:type:`v4l2_fh`\ ``.subscribed``, one for every +subscribed event. + +Each :c:type:`v4l2_subscribed_event` struct ends with a +:c:type:`v4l2_kevent` ringbuffer, with the size given by the caller +of :c:func:`v4l2_event_subscribe`. This ringbuffer is used to store any events +raised by the driver. + +So every ``(type, ID)`` event tuple will have its own +:c:type:`v4l2_kevent` ringbuffer. This guarantees that if a driver is +generating lots of events of one type in a short time, then that will +not overwrite events of another type. + +But if you get more events of one type than the size of the +:c:type:`v4l2_kevent` ringbuffer, then the oldest event will be dropped +and the new one added. + +The :c:type:`v4l2_kevent` struct links into the ``available`` +list of the :c:type:`v4l2_fh` struct so :ref:`VIDIOC_DQEVENT` will +know which event to dequeue first. + +Finally, if the event subscription is associated with a particular object +such as a V4L2 control, then that object needs to know about that as well +so that an event can be raised by that object. So the ``node`` field can +be used to link the :c:type:`v4l2_subscribed_event` struct into a list of +such objects. + +So to summarize: + +- struct v4l2_fh has two lists: one of the ``subscribed`` events, + and one of the ``available`` events. + +- struct v4l2_subscribed_event has a ringbuffer of raised + (pending) events of that particular type. + +- If struct v4l2_subscribed_event is associated with a specific + object, then that object will have an internal list of + struct v4l2_subscribed_event so it knows who subscribed an + event to that object. + +Furthermore, the internal struct v4l2_subscribed_event has +``merge()`` and ``replace()`` callbacks which drivers can set. These +callbacks are called when a new event is raised and there is no more room. + +The ``replace()`` callback allows you to replace the payload of the old event +with that of the new event, merging any relevant data from the old payload +into the new payload that replaces it. It is called when this event type has +a ringbuffer with size is one, i.e. only one event can be stored in the +ringbuffer. + +The ``merge()`` callback allows you to merge the oldest event payload into +that of the second-oldest event payload. It is called when +the ringbuffer has size is greater than one. + +This way no status information is lost, just the intermediate steps leading +up to that state. + +A good example of these ``replace``/``merge`` callbacks is in v4l2-event.c: +``ctrls_replace()`` and ``ctrls_merge()`` callbacks for the control event. + +.. note:: + these callbacks can be called from interrupt context, so they must + be fast. + +In order to queue events to video device, drivers should call: + + :c:func:`v4l2_event_queue <v4l2_event_queue>` + (:c:type:`vdev <video_device>`, :c:type:`ev <v4l2_event>`) + +The driver's only responsibility is to fill in the type and the data fields. +The other fields will be filled in by V4L2. + +Event subscription +~~~~~~~~~~~~~~~~~~ + +Subscribing to an event is via: + + :c:func:`v4l2_event_subscribe <v4l2_event_subscribe>` + (:c:type:`fh <v4l2_fh>`, :c:type:`sub <v4l2_event_subscription>` , + elems, :c:type:`ops <v4l2_subscribed_event_ops>`) + + +This function is used to implement :c:type:`video_device`-> +:c:type:`ioctl_ops <v4l2_ioctl_ops>`-> ``vidioc_subscribe_event``, +but the driver must check first if the driver is able to produce events +with specified event id, and then should call +:c:func:`v4l2_event_subscribe` to subscribe the event. + +The elems argument is the size of the event queue for this event. If it is 0, +then the framework will fill in a default value (this depends on the event +type). + +The ops argument allows the driver to specify a number of callbacks: + +.. tabularcolumns:: |p{1.5cm}|p{16.0cm}| + +======== ============================================================== +Callback Description +======== ============================================================== +add called when a new listener gets added (subscribing to the same + event twice will only cause this callback to get called once) +del called when a listener stops listening +replace replace event 'old' with event 'new'. +merge merge event 'old' into event 'new'. +======== ============================================================== + +All 4 callbacks are optional, if you don't want to specify any callbacks +the ops argument itself maybe ``NULL``. + +Unsubscribing an event +~~~~~~~~~~~~~~~~~~~~~~ + +Unsubscribing to an event is via: + + :c:func:`v4l2_event_unsubscribe <v4l2_event_unsubscribe>` + (:c:type:`fh <v4l2_fh>`, :c:type:`sub <v4l2_event_subscription>`) + +This function is used to implement :c:type:`video_device`-> +:c:type:`ioctl_ops <v4l2_ioctl_ops>`-> ``vidioc_unsubscribe_event``. +A driver may call :c:func:`v4l2_event_unsubscribe` directly unless it +wants to be involved in unsubscription process. + +The special type ``V4L2_EVENT_ALL`` may be used to unsubscribe all events. The +drivers may want to handle this in a special way. + +Check if there's a pending event +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Checking if there's a pending event is via: + + :c:func:`v4l2_event_pending <v4l2_event_pending>` + (:c:type:`fh <v4l2_fh>`) + + +This function returns the number of pending events. Useful when implementing +poll. + +How events work +~~~~~~~~~~~~~~~ + +Events are delivered to user space through the poll system call. The driver +can use :c:type:`v4l2_fh`->wait (a wait_queue_head_t) as the argument for +``poll_wait()``. + +There are standard and private events. New standard events must use the +smallest available event type. The drivers must allocate their events from +their own class starting from class base. Class base is +``V4L2_EVENT_PRIVATE_START`` + n * 1000 where n is the lowest available number. +The first event type in the class is reserved for future use, so the first +available event type is 'class base + 1'. + +An example on how the V4L2 events may be used can be found in the OMAP +3 ISP driver (``drivers/media/platform/ti/omap3isp``). + +A subdev can directly send an event to the :c:type:`v4l2_device` notify +function with ``V4L2_DEVICE_NOTIFY_EVENT``. This allows the bridge to map +the subdev that sends the event to the video node(s) associated with the +subdev that need to be informed about such an event. + +V4L2 event functions and data structures +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. kernel-doc:: include/media/v4l2-event.h + diff --git a/Documentation/driver-api/media/v4l2-fh.rst b/Documentation/driver-api/media/v4l2-fh.rst new file mode 100644 index 0000000000..3eeaa8da0c --- /dev/null +++ b/Documentation/driver-api/media/v4l2-fh.rst @@ -0,0 +1,141 @@ +.. SPDX-License-Identifier: GPL-2.0 + +V4L2 File handlers +------------------ + +struct v4l2_fh provides a way to easily keep file handle specific +data that is used by the V4L2 framework. + +.. attention:: + New drivers must use struct v4l2_fh + since it is also used to implement priority handling + (:ref:`VIDIOC_G_PRIORITY`). + +The users of :c:type:`v4l2_fh` (in the V4L2 framework, not the driver) know +whether a driver uses :c:type:`v4l2_fh` as its ``file->private_data`` pointer +by testing the ``V4L2_FL_USES_V4L2_FH`` bit in :c:type:`video_device`->flags. +This bit is set whenever :c:func:`v4l2_fh_init` is called. + +struct v4l2_fh is allocated as a part of the driver's own file handle +structure and ``file->private_data`` is set to it in the driver's ``open()`` +function by the driver. + +In many cases the struct v4l2_fh will be embedded in a larger +structure. In that case you should call: + +#) :c:func:`v4l2_fh_init` and :c:func:`v4l2_fh_add` in ``open()`` +#) :c:func:`v4l2_fh_del` and :c:func:`v4l2_fh_exit` in ``release()`` + +Drivers can extract their own file handle structure by using the container_of +macro. + +Example: + +.. code-block:: c + + struct my_fh { + int blah; + struct v4l2_fh fh; + }; + + ... + + int my_open(struct file *file) + { + struct my_fh *my_fh; + struct video_device *vfd; + int ret; + + ... + + my_fh = kzalloc(sizeof(*my_fh), GFP_KERNEL); + + ... + + v4l2_fh_init(&my_fh->fh, vfd); + + ... + + file->private_data = &my_fh->fh; + v4l2_fh_add(&my_fh->fh); + return 0; + } + + int my_release(struct file *file) + { + struct v4l2_fh *fh = file->private_data; + struct my_fh *my_fh = container_of(fh, struct my_fh, fh); + + ... + v4l2_fh_del(&my_fh->fh); + v4l2_fh_exit(&my_fh->fh); + kfree(my_fh); + return 0; + } + +Below is a short description of the :c:type:`v4l2_fh` functions used: + +:c:func:`v4l2_fh_init <v4l2_fh_init>` +(:c:type:`fh <v4l2_fh>`, :c:type:`vdev <video_device>`) + + +- Initialise the file handle. This **MUST** be performed in the driver's + :c:type:`v4l2_file_operations`->open() handler. + + +:c:func:`v4l2_fh_add <v4l2_fh_add>` +(:c:type:`fh <v4l2_fh>`) + +- Add a :c:type:`v4l2_fh` to :c:type:`video_device` file handle list. + Must be called once the file handle is completely initialized. + +:c:func:`v4l2_fh_del <v4l2_fh_del>` +(:c:type:`fh <v4l2_fh>`) + +- Unassociate the file handle from :c:type:`video_device`. The file handle + exit function may now be called. + +:c:func:`v4l2_fh_exit <v4l2_fh_exit>` +(:c:type:`fh <v4l2_fh>`) + +- Uninitialise the file handle. After uninitialisation the :c:type:`v4l2_fh` + memory can be freed. + + +If struct v4l2_fh is not embedded, then you can use these helper functions: + +:c:func:`v4l2_fh_open <v4l2_fh_open>` +(struct file \*filp) + +- This allocates a struct v4l2_fh, initializes it and adds it to + the struct video_device associated with the file struct. + +:c:func:`v4l2_fh_release <v4l2_fh_release>` +(struct file \*filp) + +- This deletes it from the struct video_device associated with the + file struct, uninitialised the :c:type:`v4l2_fh` and frees it. + +These two functions can be plugged into the v4l2_file_operation's ``open()`` +and ``release()`` ops. + +Several drivers need to do something when the first file handle is opened and +when the last file handle closes. Two helper functions were added to check +whether the :c:type:`v4l2_fh` struct is the only open filehandle of the +associated device node: + +:c:func:`v4l2_fh_is_singular <v4l2_fh_is_singular>` +(:c:type:`fh <v4l2_fh>`) + +- Returns 1 if the file handle is the only open file handle, else 0. + +:c:func:`v4l2_fh_is_singular_file <v4l2_fh_is_singular_file>` +(struct file \*filp) + +- Same, but it calls v4l2_fh_is_singular with filp->private_data. + + +V4L2 fh functions and data structures +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. kernel-doc:: include/media/v4l2-fh.h diff --git a/Documentation/driver-api/media/v4l2-flash-led-class.rst b/Documentation/driver-api/media/v4l2-flash-led-class.rst new file mode 100644 index 0000000000..2aa6bed9b8 --- /dev/null +++ b/Documentation/driver-api/media/v4l2-flash-led-class.rst @@ -0,0 +1,6 @@ +.. SPDX-License-Identifier: GPL-2.0 + +V4L2 flash functions and data structures +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. kernel-doc:: include/media/v4l2-flash-led-class.h diff --git a/Documentation/driver-api/media/v4l2-fwnode.rst b/Documentation/driver-api/media/v4l2-fwnode.rst new file mode 100644 index 0000000000..e313b6cddc --- /dev/null +++ b/Documentation/driver-api/media/v4l2-fwnode.rst @@ -0,0 +1,5 @@ +.. SPDX-License-Identifier: GPL-2.0 + +V4L2 fwnode kAPI +^^^^^^^^^^^^^^^^ +.. kernel-doc:: include/media/v4l2-fwnode.h diff --git a/Documentation/driver-api/media/v4l2-intro.rst b/Documentation/driver-api/media/v4l2-intro.rst new file mode 100644 index 0000000000..4d54fa9d7a --- /dev/null +++ b/Documentation/driver-api/media/v4l2-intro.rst @@ -0,0 +1,76 @@ +.. SPDX-License-Identifier: GPL-2.0 + +Introduction +------------ + +The V4L2 drivers tend to be very complex due to the complexity of the +hardware: most devices have multiple ICs, export multiple device nodes in +/dev, and create also non-V4L2 devices such as DVB, ALSA, FB, I2C and input +(IR) devices. + +Especially the fact that V4L2 drivers have to setup supporting ICs to +do audio/video muxing/encoding/decoding makes it more complex than most. +Usually these ICs are connected to the main bridge driver through one or +more I2C buses, but other buses can also be used. Such devices are +called 'sub-devices'. + +For a long time the framework was limited to the video_device struct for +creating V4L device nodes and video_buf for handling the video buffers +(note that this document does not discuss the video_buf framework). + +This meant that all drivers had to do the setup of device instances and +connecting to sub-devices themselves. Some of this is quite complicated +to do right and many drivers never did do it correctly. + +There is also a lot of common code that could never be refactored due to +the lack of a framework. + +So this framework sets up the basic building blocks that all drivers +need and this same framework should make it much easier to refactor +common code into utility functions shared by all drivers. + +A good example to look at as a reference is the v4l2-pci-skeleton.c +source that is available in samples/v4l/. It is a skeleton driver for +a PCI capture card, and demonstrates how to use the V4L2 driver +framework. It can be used as a template for real PCI video capture driver. + +Structure of a V4L driver +------------------------- + +All drivers have the following structure: + +1) A struct for each device instance containing the device state. + +2) A way of initializing and commanding sub-devices (if any). + +3) Creating V4L2 device nodes (/dev/videoX, /dev/vbiX and /dev/radioX) + and keeping track of device-node specific data. + +4) Filehandle-specific structs containing per-filehandle data; + +5) video buffer handling. + +This is a rough schematic of how it all relates: + +.. code-block:: none + + device instances + | + +-sub-device instances + | + \-V4L2 device nodes + | + \-filehandle instances + + +Structure of the V4L2 framework +------------------------------- + +The framework closely resembles the driver structure: it has a v4l2_device +struct for the device instance data, a v4l2_subdev struct to refer to +sub-device instances, the video_device struct stores V4L2 device node data +and the v4l2_fh struct keeps track of filehandle instances. + +The V4L2 framework also optionally integrates with the media framework. If a +driver sets the struct v4l2_device mdev field, sub-devices and video nodes +will automatically appear in the media framework as entities. diff --git a/Documentation/driver-api/media/v4l2-mc.rst b/Documentation/driver-api/media/v4l2-mc.rst new file mode 100644 index 0000000000..0c352ac588 --- /dev/null +++ b/Documentation/driver-api/media/v4l2-mc.rst @@ -0,0 +1,6 @@ +.. SPDX-License-Identifier: GPL-2.0 + +V4L2 Media Controller functions and data structures +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. kernel-doc:: include/media/v4l2-mc.h diff --git a/Documentation/driver-api/media/v4l2-mediabus.rst b/Documentation/driver-api/media/v4l2-mediabus.rst new file mode 100644 index 0000000000..1f2254cba9 --- /dev/null +++ b/Documentation/driver-api/media/v4l2-mediabus.rst @@ -0,0 +1,6 @@ +.. SPDX-License-Identifier: GPL-2.0 + +V4L2 Media Bus functions and data structures +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. kernel-doc:: include/media/v4l2-mediabus.h diff --git a/Documentation/driver-api/media/v4l2-mem2mem.rst b/Documentation/driver-api/media/v4l2-mem2mem.rst new file mode 100644 index 0000000000..a43b31cc82 --- /dev/null +++ b/Documentation/driver-api/media/v4l2-mem2mem.rst @@ -0,0 +1,6 @@ +.. SPDX-License-Identifier: GPL-2.0 + +V4L2 Memory to Memory functions and data structures +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. kernel-doc:: include/media/v4l2-mem2mem.h diff --git a/Documentation/driver-api/media/v4l2-rect.rst b/Documentation/driver-api/media/v4l2-rect.rst new file mode 100644 index 0000000000..fc315cd841 --- /dev/null +++ b/Documentation/driver-api/media/v4l2-rect.rst @@ -0,0 +1,6 @@ +.. SPDX-License-Identifier: GPL-2.0 + +V4L2 rect helper functions +^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. kernel-doc:: include/media/v4l2-rect.h diff --git a/Documentation/driver-api/media/v4l2-subdev.rst b/Documentation/driver-api/media/v4l2-subdev.rst new file mode 100644 index 0000000000..e56b50b3f2 --- /dev/null +++ b/Documentation/driver-api/media/v4l2-subdev.rst @@ -0,0 +1,637 @@ +.. SPDX-License-Identifier: GPL-2.0 + +V4L2 sub-devices +---------------- + +Many drivers need to communicate with sub-devices. These devices can do all +sort of tasks, but most commonly they handle audio and/or video muxing, +encoding or decoding. For webcams common sub-devices are sensors and camera +controllers. + +Usually these are I2C devices, but not necessarily. In order to provide the +driver with a consistent interface to these sub-devices the +:c:type:`v4l2_subdev` struct (v4l2-subdev.h) was created. + +Each sub-device driver must have a :c:type:`v4l2_subdev` struct. This struct +can be stand-alone for simple sub-devices or it might be embedded in a larger +struct if more state information needs to be stored. Usually there is a +low-level device struct (e.g. ``i2c_client``) that contains the device data as +setup by the kernel. It is recommended to store that pointer in the private +data of :c:type:`v4l2_subdev` using :c:func:`v4l2_set_subdevdata`. That makes +it easy to go from a :c:type:`v4l2_subdev` to the actual low-level bus-specific +device data. + +You also need a way to go from the low-level struct to :c:type:`v4l2_subdev`. +For the common i2c_client struct the i2c_set_clientdata() call is used to store +a :c:type:`v4l2_subdev` pointer, for other buses you may have to use other +methods. + +Bridges might also need to store per-subdev private data, such as a pointer to +bridge-specific per-subdev private data. The :c:type:`v4l2_subdev` structure +provides host private data for that purpose that can be accessed with +:c:func:`v4l2_get_subdev_hostdata` and :c:func:`v4l2_set_subdev_hostdata`. + +From the bridge driver perspective, you load the sub-device module and somehow +obtain the :c:type:`v4l2_subdev` pointer. For i2c devices this is easy: you call +``i2c_get_clientdata()``. For other buses something similar needs to be done. +Helper functions exist for sub-devices on an I2C bus that do most of this +tricky work for you. + +Each :c:type:`v4l2_subdev` contains function pointers that sub-device drivers +can implement (or leave ``NULL`` if it is not applicable). Since sub-devices can +do so many different things and you do not want to end up with a huge ops struct +of which only a handful of ops are commonly implemented, the function pointers +are sorted according to category and each category has its own ops struct. + +The top-level ops struct contains pointers to the category ops structs, which +may be NULL if the subdev driver does not support anything from that category. + +It looks like this: + +.. code-block:: c + + struct v4l2_subdev_core_ops { + int (*log_status)(struct v4l2_subdev *sd); + int (*init)(struct v4l2_subdev *sd, u32 val); + ... + }; + + struct v4l2_subdev_tuner_ops { + ... + }; + + struct v4l2_subdev_audio_ops { + ... + }; + + struct v4l2_subdev_video_ops { + ... + }; + + struct v4l2_subdev_pad_ops { + ... + }; + + struct v4l2_subdev_ops { + const struct v4l2_subdev_core_ops *core; + const struct v4l2_subdev_tuner_ops *tuner; + const struct v4l2_subdev_audio_ops *audio; + const struct v4l2_subdev_video_ops *video; + const struct v4l2_subdev_pad_ops *video; + }; + +The core ops are common to all subdevs, the other categories are implemented +depending on the sub-device. E.g. a video device is unlikely to support the +audio ops and vice versa. + +This setup limits the number of function pointers while still making it easy +to add new ops and categories. + +A sub-device driver initializes the :c:type:`v4l2_subdev` struct using: + + :c:func:`v4l2_subdev_init <v4l2_subdev_init>` + (:c:type:`sd <v4l2_subdev>`, &\ :c:type:`ops <v4l2_subdev_ops>`). + + +Afterwards you need to initialize :c:type:`sd <v4l2_subdev>`->name with a +unique name and set the module owner. This is done for you if you use the +i2c helper functions. + +If integration with the media framework is needed, you must initialize the +:c:type:`media_entity` struct embedded in the :c:type:`v4l2_subdev` struct +(entity field) by calling :c:func:`media_entity_pads_init`, if the entity has +pads: + +.. code-block:: c + + struct media_pad *pads = &my_sd->pads; + int err; + + err = media_entity_pads_init(&sd->entity, npads, pads); + +The pads array must have been previously initialized. There is no need to +manually set the struct media_entity function and name fields, but the +revision field must be initialized if needed. + +A reference to the entity will be automatically acquired/released when the +subdev device node (if any) is opened/closed. + +Don't forget to cleanup the media entity before the sub-device is destroyed: + +.. code-block:: c + + media_entity_cleanup(&sd->entity); + +If a sub-device driver implements sink pads, the subdev driver may set the +link_validate field in :c:type:`v4l2_subdev_pad_ops` to provide its own link +validation function. For every link in the pipeline, the link_validate pad +operation of the sink end of the link is called. In both cases the driver is +still responsible for validating the correctness of the format configuration +between sub-devices and video nodes. + +If link_validate op is not set, the default function +:c:func:`v4l2_subdev_link_validate_default` is used instead. This function +ensures that width, height and the media bus pixel code are equal on both source +and sink of the link. Subdev drivers are also free to use this function to +perform the checks mentioned above in addition to their own checks. + +Subdev registration +~~~~~~~~~~~~~~~~~~~ + +There are currently two ways to register subdevices with the V4L2 core. The +first (traditional) possibility is to have subdevices registered by bridge +drivers. This can be done when the bridge driver has the complete information +about subdevices connected to it and knows exactly when to register them. This +is typically the case for internal subdevices, like video data processing units +within SoCs or complex PCI(e) boards, camera sensors in USB cameras or connected +to SoCs, which pass information about them to bridge drivers, usually in their +platform data. + +There are however also situations where subdevices have to be registered +asynchronously to bridge devices. An example of such a configuration is a Device +Tree based system where information about subdevices is made available to the +system independently from the bridge devices, e.g. when subdevices are defined +in DT as I2C device nodes. The API used in this second case is described further +below. + +Using one or the other registration method only affects the probing process, the +run-time bridge-subdevice interaction is in both cases the same. + +Registering synchronous sub-devices +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +In the **synchronous** case a device (bridge) driver needs to register the +:c:type:`v4l2_subdev` with the v4l2_device: + + :c:func:`v4l2_device_register_subdev <v4l2_device_register_subdev>` + (:c:type:`v4l2_dev <v4l2_device>`, :c:type:`sd <v4l2_subdev>`). + +This can fail if the subdev module disappeared before it could be registered. +After this function was called successfully the subdev->dev field points to +the :c:type:`v4l2_device`. + +If the v4l2_device parent device has a non-NULL mdev field, the sub-device +entity will be automatically registered with the media device. + +You can unregister a sub-device using: + + :c:func:`v4l2_device_unregister_subdev <v4l2_device_unregister_subdev>` + (:c:type:`sd <v4l2_subdev>`). + +Afterwards the subdev module can be unloaded and +:c:type:`sd <v4l2_subdev>`->dev == ``NULL``. + +Registering asynchronous sub-devices +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +In the **asynchronous** case subdevice probing can be invoked independently of +the bridge driver availability. The subdevice driver then has to verify whether +all the requirements for a successful probing are satisfied. This can include a +check for a master clock availability. If any of the conditions aren't satisfied +the driver might decide to return ``-EPROBE_DEFER`` to request further reprobing +attempts. Once all conditions are met the subdevice shall be registered using +the :c:func:`v4l2_async_register_subdev` function. Unregistration is +performed using the :c:func:`v4l2_async_unregister_subdev` call. Subdevices +registered this way are stored in a global list of subdevices, ready to be +picked up by bridge drivers. + +Asynchronous sub-device notifiers +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Bridge drivers in turn have to register a notifier object. This is performed +using the :c:func:`v4l2_async_nf_register` call. To unregister the notifier the +driver has to call :c:func:`v4l2_async_nf_unregister`. Before releasing memory +of an unregister notifier, it must be cleaned up by calling +:c:func:`v4l2_async_nf_cleanup`. + +Before registering the notifier, bridge drivers must do two things: first, the +notifier must be initialized using the :c:func:`v4l2_async_nf_init`. Second, +bridge drivers can then begin to form a list of async connection descriptors +that the bridge device needs for its +operation. :c:func:`v4l2_async_nf_add_fwnode`, +:c:func:`v4l2_async_nf_add_fwnode_remote` and :c:func:`v4l2_async_nf_add_i2c` + +Async connection descriptors describe connections to external sub-devices the +drivers for which are not yet probed. Based on an async connection, a media data +or ancillary link may be created when the related sub-device becomes +available. There may be one or more async connections to a given sub-device but +this is not known at the time of adding the connections to the notifier. Async +connections are bound as matching async sub-devices are found, one by one. + +Asynchronous sub-device notifier for sub-devices +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +A driver that registers an asynchronous sub-device may also register an +asynchronous notifier. This is called an asynchronous sub-device notifier andthe +process is similar to that of a bridge driver apart from that the notifier is +initialised using :c:func:`v4l2_async_subdev_nf_init` instead. A sub-device +notifier may complete only after the V4L2 device becomes available, i.e. there's +a path via async sub-devices and notifiers to a notifier that is not an +asynchronous sub-device notifier. + +Asynchronous sub-device registration helper for camera sensor drivers +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +:c:func:`v4l2_async_register_subdev_sensor` is a helper function for sensor +drivers registering their own async connection, but it also registers a notifier +and further registers async connections for lens and flash devices found in +firmware. The notifier for the sub-device is unregistered and cleaned up with +the async sub-device, using :c:func:`v4l2_async_unregister_subdev`. + +Asynchronous sub-device notifier example +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +These functions allocate an async connection descriptor which is of type struct +:c:type:`v4l2_async_connection` embedded in a driver-specific struct. The &struct +:c:type:`v4l2_async_connection` shall be the first member of this struct: + +.. code-block:: c + + struct my_async_connection { + struct v4l2_async_connection asc; + ... + }; + + struct my_async_connection *my_asc; + struct fwnode_handle *ep; + + ... + + my_asc = v4l2_async_nf_add_fwnode_remote(¬ifier, ep, + struct my_async_connection); + fwnode_handle_put(ep); + + if (IS_ERR(my_asc)) + return PTR_ERR(my_asc); + +Asynchronous sub-device notifier callbacks +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The V4L2 core will then use these connection descriptors to match asynchronously +registered subdevices to them. If a match is detected the ``.bound()`` notifier +callback is called. After all connections have been bound the .complete() +callback is called. When a connection is removed from the system the +``.unbind()`` method is called. All three callbacks are optional. + +Drivers can store any type of custom data in their driver-specific +:c:type:`v4l2_async_connection` wrapper. If any of that data requires special +handling when the structure is freed, drivers must implement the ``.destroy()`` +notifier callback. The framework will call it right before freeing the +:c:type:`v4l2_async_connection`. + +Calling subdev operations +~~~~~~~~~~~~~~~~~~~~~~~~~ + +The advantage of using :c:type:`v4l2_subdev` is that it is a generic struct and +does not contain any knowledge about the underlying hardware. So a driver might +contain several subdevs that use an I2C bus, but also a subdev that is +controlled through GPIO pins. This distinction is only relevant when setting +up the device, but once the subdev is registered it is completely transparent. + +Once the subdev has been registered you can call an ops function either +directly: + +.. code-block:: c + + err = sd->ops->core->g_std(sd, &norm); + +but it is better and easier to use this macro: + +.. code-block:: c + + err = v4l2_subdev_call(sd, core, g_std, &norm); + +The macro will do the right ``NULL`` pointer checks and returns ``-ENODEV`` +if :c:type:`sd <v4l2_subdev>` is ``NULL``, ``-ENOIOCTLCMD`` if either +:c:type:`sd <v4l2_subdev>`->core or :c:type:`sd <v4l2_subdev>`->core->g_std is ``NULL``, or the actual result of the +:c:type:`sd <v4l2_subdev>`->ops->core->g_std ops. + +It is also possible to call all or a subset of the sub-devices: + +.. code-block:: c + + v4l2_device_call_all(v4l2_dev, 0, core, g_std, &norm); + +Any subdev that does not support this ops is skipped and error results are +ignored. If you want to check for errors use this: + +.. code-block:: c + + err = v4l2_device_call_until_err(v4l2_dev, 0, core, g_std, &norm); + +Any error except ``-ENOIOCTLCMD`` will exit the loop with that error. If no +errors (except ``-ENOIOCTLCMD``) occurred, then 0 is returned. + +The second argument to both calls is a group ID. If 0, then all subdevs are +called. If non-zero, then only those whose group ID match that value will +be called. Before a bridge driver registers a subdev it can set +:c:type:`sd <v4l2_subdev>`->grp_id to whatever value it wants (it's 0 by +default). This value is owned by the bridge driver and the sub-device driver +will never modify or use it. + +The group ID gives the bridge driver more control how callbacks are called. +For example, there may be multiple audio chips on a board, each capable of +changing the volume. But usually only one will actually be used when the +user want to change the volume. You can set the group ID for that subdev to +e.g. AUDIO_CONTROLLER and specify that as the group ID value when calling +``v4l2_device_call_all()``. That ensures that it will only go to the subdev +that needs it. + +If the sub-device needs to notify its v4l2_device parent of an event, then +it can call ``v4l2_subdev_notify(sd, notification, arg)``. This macro checks +whether there is a ``notify()`` callback defined and returns ``-ENODEV`` if not. +Otherwise the result of the ``notify()`` call is returned. + +V4L2 sub-device userspace API +----------------------------- + +Bridge drivers traditionally expose one or multiple video nodes to userspace, +and control subdevices through the :c:type:`v4l2_subdev_ops` operations in +response to video node operations. This hides the complexity of the underlying +hardware from applications. For complex devices, finer-grained control of the +device than what the video nodes offer may be required. In those cases, bridge +drivers that implement :ref:`the media controller API <media_controller>` may +opt for making the subdevice operations directly accessible from userspace. + +Device nodes named ``v4l-subdev``\ *X* can be created in ``/dev`` to access +sub-devices directly. If a sub-device supports direct userspace configuration +it must set the ``V4L2_SUBDEV_FL_HAS_DEVNODE`` flag before being registered. + +After registering sub-devices, the :c:type:`v4l2_device` driver can create +device nodes for all registered sub-devices marked with +``V4L2_SUBDEV_FL_HAS_DEVNODE`` by calling +:c:func:`v4l2_device_register_subdev_nodes`. Those device nodes will be +automatically removed when sub-devices are unregistered. + +The device node handles a subset of the V4L2 API. + +``VIDIOC_QUERYCTRL``, +``VIDIOC_QUERYMENU``, +``VIDIOC_G_CTRL``, +``VIDIOC_S_CTRL``, +``VIDIOC_G_EXT_CTRLS``, +``VIDIOC_S_EXT_CTRLS`` and +``VIDIOC_TRY_EXT_CTRLS``: + + The controls ioctls are identical to the ones defined in V4L2. They + behave identically, with the only exception that they deal only with + controls implemented in the sub-device. Depending on the driver, those + controls can be also be accessed through one (or several) V4L2 device + nodes. + +``VIDIOC_DQEVENT``, +``VIDIOC_SUBSCRIBE_EVENT`` and +``VIDIOC_UNSUBSCRIBE_EVENT`` + + The events ioctls are identical to the ones defined in V4L2. They + behave identically, with the only exception that they deal only with + events generated by the sub-device. Depending on the driver, those + events can also be reported by one (or several) V4L2 device nodes. + + Sub-device drivers that want to use events need to set the + ``V4L2_SUBDEV_FL_HAS_EVENTS`` :c:type:`v4l2_subdev`.flags before registering + the sub-device. After registration events can be queued as usual on the + :c:type:`v4l2_subdev`.devnode device node. + + To properly support events, the ``poll()`` file operation is also + implemented. + +Private ioctls + + All ioctls not in the above list are passed directly to the sub-device + driver through the core::ioctl operation. + +Read-only sub-device userspace API +---------------------------------- + +Bridge drivers that control their connected subdevices through direct calls to +the kernel API realized by :c:type:`v4l2_subdev_ops` structure do not usually +want userspace to be able to change the same parameters through the subdevice +device node and thus do not usually register any. + +It is sometimes useful to report to userspace the current subdevice +configuration through a read-only API, that does not permit applications to +change to the device parameters but allows interfacing to the subdevice device +node to inspect them. + +For instance, to implement cameras based on computational photography, userspace +needs to know the detailed camera sensor configuration (in terms of skipping, +binning, cropping and scaling) for each supported output resolution. To support +such use cases, bridge drivers may expose the subdevice operations to userspace +through a read-only API. + +To create a read-only device node for all the subdevices registered with the +``V4L2_SUBDEV_FL_HAS_DEVNODE`` set, the :c:type:`v4l2_device` driver should call +:c:func:`v4l2_device_register_ro_subdev_nodes`. + +Access to the following ioctls for userspace applications is restricted on +sub-device device nodes registered with +:c:func:`v4l2_device_register_ro_subdev_nodes`. + +``VIDIOC_SUBDEV_S_FMT``, +``VIDIOC_SUBDEV_S_CROP``, +``VIDIOC_SUBDEV_S_SELECTION``: + + These ioctls are only allowed on a read-only subdevice device node + for the :ref:`V4L2_SUBDEV_FORMAT_TRY <v4l2-subdev-format-whence>` + formats and selection rectangles. + +``VIDIOC_SUBDEV_S_FRAME_INTERVAL``, +``VIDIOC_SUBDEV_S_DV_TIMINGS``, +``VIDIOC_SUBDEV_S_STD``: + + These ioctls are not allowed on a read-only subdevice node. + +In case the ioctl is not allowed, or the format to modify is set to +``V4L2_SUBDEV_FORMAT_ACTIVE``, the core returns a negative error code and +the errno variable is set to ``-EPERM``. + +I2C sub-device drivers +---------------------- + +Since these drivers are so common, special helper functions are available to +ease the use of these drivers (``v4l2-common.h``). + +The recommended method of adding :c:type:`v4l2_subdev` support to an I2C driver +is to embed the :c:type:`v4l2_subdev` struct into the state struct that is +created for each I2C device instance. Very simple devices have no state +struct and in that case you can just create a :c:type:`v4l2_subdev` directly. + +A typical state struct would look like this (where 'chipname' is replaced by +the name of the chip): + +.. code-block:: c + + struct chipname_state { + struct v4l2_subdev sd; + ... /* additional state fields */ + }; + +Initialize the :c:type:`v4l2_subdev` struct as follows: + +.. code-block:: c + + v4l2_i2c_subdev_init(&state->sd, client, subdev_ops); + +This function will fill in all the fields of :c:type:`v4l2_subdev` ensure that +the :c:type:`v4l2_subdev` and i2c_client both point to one another. + +You should also add a helper inline function to go from a :c:type:`v4l2_subdev` +pointer to a chipname_state struct: + +.. code-block:: c + + static inline struct chipname_state *to_state(struct v4l2_subdev *sd) + { + return container_of(sd, struct chipname_state, sd); + } + +Use this to go from the :c:type:`v4l2_subdev` struct to the ``i2c_client`` +struct: + +.. code-block:: c + + struct i2c_client *client = v4l2_get_subdevdata(sd); + +And this to go from an ``i2c_client`` to a :c:type:`v4l2_subdev` struct: + +.. code-block:: c + + struct v4l2_subdev *sd = i2c_get_clientdata(client); + +Make sure to call +:c:func:`v4l2_device_unregister_subdev`\ (:c:type:`sd <v4l2_subdev>`) +when the ``remove()`` callback is called. This will unregister the sub-device +from the bridge driver. It is safe to call this even if the sub-device was +never registered. + +You need to do this because when the bridge driver destroys the i2c adapter +the ``remove()`` callbacks are called of the i2c devices on that adapter. +After that the corresponding v4l2_subdev structures are invalid, so they +have to be unregistered first. Calling +:c:func:`v4l2_device_unregister_subdev`\ (:c:type:`sd <v4l2_subdev>`) +from the ``remove()`` callback ensures that this is always done correctly. + + +The bridge driver also has some helper functions it can use: + +.. code-block:: c + + struct v4l2_subdev *sd = v4l2_i2c_new_subdev(v4l2_dev, adapter, + "module_foo", "chipid", 0x36, NULL); + +This loads the given module (can be ``NULL`` if no module needs to be loaded) +and calls :c:func:`i2c_new_client_device` with the given ``i2c_adapter`` and +chip/address arguments. If all goes well, then it registers the subdev with +the v4l2_device. + +You can also use the last argument of :c:func:`v4l2_i2c_new_subdev` to pass +an array of possible I2C addresses that it should probe. These probe addresses +are only used if the previous argument is 0. A non-zero argument means that you +know the exact i2c address so in that case no probing will take place. + +Both functions return ``NULL`` if something went wrong. + +Note that the chipid you pass to :c:func:`v4l2_i2c_new_subdev` is usually +the same as the module name. It allows you to specify a chip variant, e.g. +"saa7114" or "saa7115". In general though the i2c driver autodetects this. +The use of chipid is something that needs to be looked at more closely at a +later date. It differs between i2c drivers and as such can be confusing. +To see which chip variants are supported you can look in the i2c driver code +for the i2c_device_id table. This lists all the possibilities. + +There are one more helper function: + +:c:func:`v4l2_i2c_new_subdev_board` uses an :c:type:`i2c_board_info` struct +which is passed to the i2c driver and replaces the irq, platform_data and addr +arguments. + +If the subdev supports the s_config core ops, then that op is called with +the irq and platform_data arguments after the subdev was setup. + +The :c:func:`v4l2_i2c_new_subdev` function will call +:c:func:`v4l2_i2c_new_subdev_board`, internally filling a +:c:type:`i2c_board_info` structure using the ``client_type`` and the +``addr`` to fill it. + +Centrally managed subdev active state +------------------------------------- + +Traditionally V4L2 subdev drivers maintained internal state for the active +device configuration. This is often implemented as e.g. an array of struct +v4l2_mbus_framefmt, one entry for each pad, and similarly for crop and compose +rectangles. + +In addition to the active configuration, each subdev file handle has an array of +struct v4l2_subdev_pad_config, managed by the V4L2 core, which contains the try +configuration. + +To simplify the subdev drivers the V4L2 subdev API now optionally supports a +centrally managed active configuration represented by +:c:type:`v4l2_subdev_state`. One instance of state, which contains the active +device configuration, is stored in the sub-device itself as part of +the :c:type:`v4l2_subdev` structure, while the core associates a try state to +each open file handle, to store the try configuration related to that file +handle. + +Sub-device drivers can opt-in and use state to manage their active configuration +by initializing the subdevice state with a call to v4l2_subdev_init_finalize() +before registering the sub-device. They must also call v4l2_subdev_cleanup() +to release all the allocated resources before unregistering the sub-device. +The core automatically allocates and initializes a state for each open file +handle to store the try configurations and frees it when closing the file +handle. + +V4L2 sub-device operations that use both the :ref:`ACTIVE and TRY formats +<v4l2-subdev-format-whence>` receive the correct state to operate on through +the 'state' parameter. The state must be locked and unlocked by the +caller by calling :c:func:`v4l2_subdev_lock_state()` and +:c:func:`v4l2_subdev_unlock_state()`. The caller can do so by calling the subdev +operation through the :c:func:`v4l2_subdev_call_state_active()` macro. + +Operations that do not receive a state parameter implicitly operate on the +subdevice active state, which drivers can exclusively access by +calling :c:func:`v4l2_subdev_lock_and_get_active_state()`. The sub-device active +state must equally be released by calling :c:func:`v4l2_subdev_unlock_state()`. + +Drivers must never manually access the state stored in the :c:type:`v4l2_subdev` +or in the file handle without going through the designated helpers. + +While the V4L2 core passes the correct try or active state to the subdevice +operations, many existing device drivers pass a NULL state when calling +operations with :c:func:`v4l2_subdev_call()`. This legacy construct causes +issues with subdevice drivers that let the V4L2 core manage the active state, +as they expect to receive the appropriate state as a parameter. To help the +conversion of subdevice drivers to a managed active state without having to +convert all callers at the same time, an additional wrapper layer has been +added to v4l2_subdev_call(), which handles the NULL case by getting and locking +the callee's active state with :c:func:`v4l2_subdev_lock_and_get_active_state()`, +and unlocking the state after the call. + +The whole subdev state is in reality split into three parts: the +v4l2_subdev_state, subdev controls and subdev driver's internal state. In the +future these parts should be combined into a single state. For the time being +we need a way to handle the locking for these parts. This can be accomplished +by sharing a lock. The v4l2_ctrl_handler already supports this via its 'lock' +pointer and the same model is used with states. The driver can do the following +before calling v4l2_subdev_init_finalize(): + +.. code-block:: c + + sd->ctrl_handler->lock = &priv->mutex; + sd->state_lock = &priv->mutex; + +This shares the driver's private mutex between the controls and the states. + +Streams, multiplexed media pads and internal routing +---------------------------------------------------- + +A subdevice driver can implement support for multiplexed streams by setting +the V4L2_SUBDEV_FL_STREAMS subdev flag and implementing support for +centrally managed subdev active state, routing and stream based +configuration. + +V4L2 sub-device functions and data structures +--------------------------------------------- + +.. kernel-doc:: include/media/v4l2-subdev.h diff --git a/Documentation/driver-api/media/v4l2-tuner.rst b/Documentation/driver-api/media/v4l2-tuner.rst new file mode 100644 index 0000000000..e6caa33215 --- /dev/null +++ b/Documentation/driver-api/media/v4l2-tuner.rst @@ -0,0 +1,8 @@ +.. SPDX-License-Identifier: GPL-2.0 + +Tuner functions and data structures +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. kernel-doc:: include/media/tuner.h + +.. kernel-doc:: include/media/tuner-types.h diff --git a/Documentation/driver-api/media/v4l2-tveeprom.rst b/Documentation/driver-api/media/v4l2-tveeprom.rst new file mode 100644 index 0000000000..43fb391eda --- /dev/null +++ b/Documentation/driver-api/media/v4l2-tveeprom.rst @@ -0,0 +1,6 @@ +.. SPDX-License-Identifier: GPL-2.0 + +Hauppauge TV EEPROM functions and data structures +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. kernel-doc:: include/media/tveeprom.h diff --git a/Documentation/driver-api/media/v4l2-videobuf.rst b/Documentation/driver-api/media/v4l2-videobuf.rst new file mode 100644 index 0000000000..4b1d84eefe --- /dev/null +++ b/Documentation/driver-api/media/v4l2-videobuf.rst @@ -0,0 +1,403 @@ +.. SPDX-License-Identifier: GPL-2.0 + +.. _vb_framework: + +Videobuf Framework +================== + +Author: Jonathan Corbet <corbet@lwn.net> + +Current as of 2.6.33 + +.. note:: + + The videobuf framework was deprecated in favor of videobuf2. Shouldn't + be used on new drivers. + +Introduction +------------ + +The videobuf layer functions as a sort of glue layer between a V4L2 driver +and user space. It handles the allocation and management of buffers for +the storage of video frames. There is a set of functions which can be used +to implement many of the standard POSIX I/O system calls, including read(), +poll(), and, happily, mmap(). Another set of functions can be used to +implement the bulk of the V4L2 ioctl() calls related to streaming I/O, +including buffer allocation, queueing and dequeueing, and streaming +control. Using videobuf imposes a few design decisions on the driver +author, but the payback comes in the form of reduced code in the driver and +a consistent implementation of the V4L2 user-space API. + +Buffer types +------------ + +Not all video devices use the same kind of buffers. In fact, there are (at +least) three common variations: + + - Buffers which are scattered in both the physical and (kernel) virtual + address spaces. (Almost) all user-space buffers are like this, but it + makes great sense to allocate kernel-space buffers this way as well when + it is possible. Unfortunately, it is not always possible; working with + this kind of buffer normally requires hardware which can do + scatter/gather DMA operations. + + - Buffers which are physically scattered, but which are virtually + contiguous; buffers allocated with vmalloc(), in other words. These + buffers are just as hard to use for DMA operations, but they can be + useful in situations where DMA is not available but virtually-contiguous + buffers are convenient. + + - Buffers which are physically contiguous. Allocation of this kind of + buffer can be unreliable on fragmented systems, but simpler DMA + controllers cannot deal with anything else. + +Videobuf can work with all three types of buffers, but the driver author +must pick one at the outset and design the driver around that decision. + +[It's worth noting that there's a fourth kind of buffer: "overlay" buffers +which are located within the system's video memory. The overlay +functionality is considered to be deprecated for most use, but it still +shows up occasionally in system-on-chip drivers where the performance +benefits merit the use of this technique. Overlay buffers can be handled +as a form of scattered buffer, but there are very few implementations in +the kernel and a description of this technique is currently beyond the +scope of this document.] + +Data structures, callbacks, and initialization +---------------------------------------------- + +Depending on which type of buffers are being used, the driver should +include one of the following files: + +.. code-block:: none + + <media/videobuf-dma-sg.h> /* Physically scattered */ + <media/videobuf-vmalloc.h> /* vmalloc() buffers */ + <media/videobuf-dma-contig.h> /* Physically contiguous */ + +The driver's data structure describing a V4L2 device should include a +struct videobuf_queue instance for the management of the buffer queue, +along with a list_head for the queue of available buffers. There will also +need to be an interrupt-safe spinlock which is used to protect (at least) +the queue. + +The next step is to write four simple callbacks to help videobuf deal with +the management of buffers: + +.. code-block:: none + + struct videobuf_queue_ops { + int (*buf_setup)(struct videobuf_queue *q, + unsigned int *count, unsigned int *size); + int (*buf_prepare)(struct videobuf_queue *q, + struct videobuf_buffer *vb, + enum v4l2_field field); + void (*buf_queue)(struct videobuf_queue *q, + struct videobuf_buffer *vb); + void (*buf_release)(struct videobuf_queue *q, + struct videobuf_buffer *vb); + }; + +buf_setup() is called early in the I/O process, when streaming is being +initiated; its purpose is to tell videobuf about the I/O stream. The count +parameter will be a suggested number of buffers to use; the driver should +check it for rationality and adjust it if need be. As a practical rule, a +minimum of two buffers are needed for proper streaming, and there is +usually a maximum (which cannot exceed 32) which makes sense for each +device. The size parameter should be set to the expected (maximum) size +for each frame of data. + +Each buffer (in the form of a struct videobuf_buffer pointer) will be +passed to buf_prepare(), which should set the buffer's size, width, height, +and field fields properly. If the buffer's state field is +VIDEOBUF_NEEDS_INIT, the driver should pass it to: + +.. code-block:: none + + int videobuf_iolock(struct videobuf_queue* q, struct videobuf_buffer *vb, + struct v4l2_framebuffer *fbuf); + +Among other things, this call will usually allocate memory for the buffer. +Finally, the buf_prepare() function should set the buffer's state to +VIDEOBUF_PREPARED. + +When a buffer is queued for I/O, it is passed to buf_queue(), which should +put it onto the driver's list of available buffers and set its state to +VIDEOBUF_QUEUED. Note that this function is called with the queue spinlock +held; if it tries to acquire it as well things will come to a screeching +halt. Yes, this is the voice of experience. Note also that videobuf may +wait on the first buffer in the queue; placing other buffers in front of it +could again gum up the works. So use list_add_tail() to enqueue buffers. + +Finally, buf_release() is called when a buffer is no longer intended to be +used. The driver should ensure that there is no I/O active on the buffer, +then pass it to the appropriate free routine(s): + +.. code-block:: none + + /* Scatter/gather drivers */ + int videobuf_dma_unmap(struct videobuf_queue *q, + struct videobuf_dmabuf *dma); + int videobuf_dma_free(struct videobuf_dmabuf *dma); + + /* vmalloc drivers */ + void videobuf_vmalloc_free (struct videobuf_buffer *buf); + + /* Contiguous drivers */ + void videobuf_dma_contig_free(struct videobuf_queue *q, + struct videobuf_buffer *buf); + +One way to ensure that a buffer is no longer under I/O is to pass it to: + +.. code-block:: none + + int videobuf_waiton(struct videobuf_buffer *vb, int non_blocking, int intr); + +Here, vb is the buffer, non_blocking indicates whether non-blocking I/O +should be used (it should be zero in the buf_release() case), and intr +controls whether an interruptible wait is used. + +File operations +--------------- + +At this point, much of the work is done; much of the rest is slipping +videobuf calls into the implementation of the other driver callbacks. The +first step is in the open() function, which must initialize the +videobuf queue. The function to use depends on the type of buffer used: + +.. code-block:: none + + void videobuf_queue_sg_init(struct videobuf_queue *q, + struct videobuf_queue_ops *ops, + struct device *dev, + spinlock_t *irqlock, + enum v4l2_buf_type type, + enum v4l2_field field, + unsigned int msize, + void *priv); + + void videobuf_queue_vmalloc_init(struct videobuf_queue *q, + struct videobuf_queue_ops *ops, + struct device *dev, + spinlock_t *irqlock, + enum v4l2_buf_type type, + enum v4l2_field field, + unsigned int msize, + void *priv); + + void videobuf_queue_dma_contig_init(struct videobuf_queue *q, + struct videobuf_queue_ops *ops, + struct device *dev, + spinlock_t *irqlock, + enum v4l2_buf_type type, + enum v4l2_field field, + unsigned int msize, + void *priv); + +In each case, the parameters are the same: q is the queue structure for the +device, ops is the set of callbacks as described above, dev is the device +structure for this video device, irqlock is an interrupt-safe spinlock to +protect access to the data structures, type is the buffer type used by the +device (cameras will use V4L2_BUF_TYPE_VIDEO_CAPTURE, for example), field +describes which field is being captured (often V4L2_FIELD_NONE for +progressive devices), msize is the size of any containing structure used +around struct videobuf_buffer, and priv is a private data pointer which +shows up in the priv_data field of struct videobuf_queue. Note that these +are void functions which, evidently, are immune to failure. + +V4L2 capture drivers can be written to support either of two APIs: the +read() system call and the rather more complicated streaming mechanism. As +a general rule, it is necessary to support both to ensure that all +applications have a chance of working with the device. Videobuf makes it +easy to do that with the same code. To implement read(), the driver need +only make a call to one of: + +.. code-block:: none + + ssize_t videobuf_read_one(struct videobuf_queue *q, + char __user *data, size_t count, + loff_t *ppos, int nonblocking); + + ssize_t videobuf_read_stream(struct videobuf_queue *q, + char __user *data, size_t count, + loff_t *ppos, int vbihack, int nonblocking); + +Either one of these functions will read frame data into data, returning the +amount actually read; the difference is that videobuf_read_one() will only +read a single frame, while videobuf_read_stream() will read multiple frames +if they are needed to satisfy the count requested by the application. A +typical driver read() implementation will start the capture engine, call +one of the above functions, then stop the engine before returning (though a +smarter implementation might leave the engine running for a little while in +anticipation of another read() call happening in the near future). + +The poll() function can usually be implemented with a direct call to: + +.. code-block:: none + + unsigned int videobuf_poll_stream(struct file *file, + struct videobuf_queue *q, + poll_table *wait); + +Note that the actual wait queue eventually used will be the one associated +with the first available buffer. + +When streaming I/O is done to kernel-space buffers, the driver must support +the mmap() system call to enable user space to access the data. In many +V4L2 drivers, the often-complex mmap() implementation simplifies to a +single call to: + +.. code-block:: none + + int videobuf_mmap_mapper(struct videobuf_queue *q, + struct vm_area_struct *vma); + +Everything else is handled by the videobuf code. + +The release() function requires two separate videobuf calls: + +.. code-block:: none + + void videobuf_stop(struct videobuf_queue *q); + int videobuf_mmap_free(struct videobuf_queue *q); + +The call to videobuf_stop() terminates any I/O in progress - though it is +still up to the driver to stop the capture engine. The call to +videobuf_mmap_free() will ensure that all buffers have been unmapped; if +so, they will all be passed to the buf_release() callback. If buffers +remain mapped, videobuf_mmap_free() returns an error code instead. The +purpose is clearly to cause the closing of the file descriptor to fail if +buffers are still mapped, but every driver in the 2.6.32 kernel cheerfully +ignores its return value. + +ioctl() operations +------------------ + +The V4L2 API includes a very long list of driver callbacks to respond to +the many ioctl() commands made available to user space. A number of these +- those associated with streaming I/O - turn almost directly into videobuf +calls. The relevant helper functions are: + +.. code-block:: none + + int videobuf_reqbufs(struct videobuf_queue *q, + struct v4l2_requestbuffers *req); + int videobuf_querybuf(struct videobuf_queue *q, struct v4l2_buffer *b); + int videobuf_qbuf(struct videobuf_queue *q, struct v4l2_buffer *b); + int videobuf_dqbuf(struct videobuf_queue *q, struct v4l2_buffer *b, + int nonblocking); + int videobuf_streamon(struct videobuf_queue *q); + int videobuf_streamoff(struct videobuf_queue *q); + +So, for example, a VIDIOC_REQBUFS call turns into a call to the driver's +vidioc_reqbufs() callback which, in turn, usually only needs to locate the +proper struct videobuf_queue pointer and pass it to videobuf_reqbufs(). +These support functions can replace a great deal of buffer management +boilerplate in a lot of V4L2 drivers. + +The vidioc_streamon() and vidioc_streamoff() functions will be a bit more +complex, of course, since they will also need to deal with starting and +stopping the capture engine. + +Buffer allocation +----------------- + +Thus far, we have talked about buffers, but have not looked at how they are +allocated. The scatter/gather case is the most complex on this front. For +allocation, the driver can leave buffer allocation entirely up to the +videobuf layer; in this case, buffers will be allocated as anonymous +user-space pages and will be very scattered indeed. If the application is +using user-space buffers, no allocation is needed; the videobuf layer will +take care of calling get_user_pages() and filling in the scatterlist array. + +If the driver needs to do its own memory allocation, it should be done in +the vidioc_reqbufs() function, *after* calling videobuf_reqbufs(). The +first step is a call to: + +.. code-block:: none + + struct videobuf_dmabuf *videobuf_to_dma(struct videobuf_buffer *buf); + +The returned videobuf_dmabuf structure (defined in +<media/videobuf-dma-sg.h>) includes a couple of relevant fields: + +.. code-block:: none + + struct scatterlist *sglist; + int sglen; + +The driver must allocate an appropriately-sized scatterlist array and +populate it with pointers to the pieces of the allocated buffer; sglen +should be set to the length of the array. + +Drivers using the vmalloc() method need not (and cannot) concern themselves +with buffer allocation at all; videobuf will handle those details. The +same is normally true of contiguous-DMA drivers as well; videobuf will +allocate the buffers (with dma_alloc_coherent()) when it sees fit. That +means that these drivers may be trying to do high-order allocations at any +time, an operation which is not always guaranteed to work. Some drivers +play tricks by allocating DMA space at system boot time; videobuf does not +currently play well with those drivers. + +As of 2.6.31, contiguous-DMA drivers can work with a user-supplied buffer, +as long as that buffer is physically contiguous. Normal user-space +allocations will not meet that criterion, but buffers obtained from other +kernel drivers, or those contained within huge pages, will work with these +drivers. + +Filling the buffers +------------------- + +The final part of a videobuf implementation has no direct callback - it's +the portion of the code which actually puts frame data into the buffers, +usually in response to interrupts from the device. For all types of +drivers, this process works approximately as follows: + + - Obtain the next available buffer and make sure that somebody is actually + waiting for it. + + - Get a pointer to the memory and put video data there. + + - Mark the buffer as done and wake up the process waiting for it. + +Step (1) above is done by looking at the driver-managed list_head structure +- the one which is filled in the buf_queue() callback. Because starting +the engine and enqueueing buffers are done in separate steps, it's possible +for the engine to be running without any buffers available - in the +vmalloc() case especially. So the driver should be prepared for the list +to be empty. It is equally possible that nobody is yet interested in the +buffer; the driver should not remove it from the list or fill it until a +process is waiting on it. That test can be done by examining the buffer's +done field (a wait_queue_head_t structure) with waitqueue_active(). + +A buffer's state should be set to VIDEOBUF_ACTIVE before being mapped for +DMA; that ensures that the videobuf layer will not try to do anything with +it while the device is transferring data. + +For scatter/gather drivers, the needed memory pointers will be found in the +scatterlist structure described above. Drivers using the vmalloc() method +can get a memory pointer with: + +.. code-block:: none + + void *videobuf_to_vmalloc(struct videobuf_buffer *buf); + +For contiguous DMA drivers, the function to use is: + +.. code-block:: none + + dma_addr_t videobuf_to_dma_contig(struct videobuf_buffer *buf); + +The contiguous DMA API goes out of its way to hide the kernel-space address +of the DMA buffer from drivers. + +The final step is to set the size field of the relevant videobuf_buffer +structure to the actual size of the captured image, set state to +VIDEOBUF_DONE, then call wake_up() on the done queue. At this point, the +buffer is owned by the videobuf layer and the driver should not touch it +again. + +Developers who are interested in more information can go into the relevant +header files; there are a few low-level functions declared there which have +not been talked about here. Note also that all of these calls are exported +GPL-only, so they will not be available to non-GPL kernel modules. diff --git a/Documentation/driver-api/media/v4l2-videobuf2.rst b/Documentation/driver-api/media/v4l2-videobuf2.rst new file mode 100644 index 0000000000..1044f64ff1 --- /dev/null +++ b/Documentation/driver-api/media/v4l2-videobuf2.rst @@ -0,0 +1,12 @@ +.. SPDX-License-Identifier: GPL-2.0 + +.. _vb2_framework: + +V4L2 videobuf2 functions and data structures +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. kernel-doc:: include/media/videobuf2-core.h + +.. kernel-doc:: include/media/videobuf2-v4l2.h + +.. kernel-doc:: include/media/videobuf2-memops.h |