mirror of
https://github.com/torvalds/linux.git
synced 2026-07-31 11:37:06 +02:00
media updates for v5.19-rc1
-----BEGIN PGP SIGNATURE----- iQIzBAABCAAdFiEE+QmuaPwR3wnBdVwACF8+vY7k4RUFAmKLMPAACgkQCF8+vY7k 4RVupA//Q4U2BV3xKn9H3g/+dbSIbm0YEeWc2xMd3wbDnqokXsKxOuIfG1omIxCf hfhfnEfhRo0WHc5AGaHtbodCU3HcCrNdjH59r6nwedQg3qgFwMT4FYDNW33E8PN1 dj293GEUZ+BZGDoCatGOxlHi/I2/HcS3I6BiU/GlglALgM/8KaBvdMhY8S6lEXIK SqdiDDOsXVT+v1BB2PSSaRWU3KIccLzS2QlXQRTs2xKszXuQy6wT6IK//YqvFxQp PS9uziJhJNk2nIlZqE8U46iYv9v+HnTW/5cLrUDTj0VIxjWHgMSnpbubOABgBRYj gX1wXRqe/bx9frm1ksfBUyNmEmxF3LL2h6fnkc2RQh/T/DKwMFpE9u3P8aEIPtmk djACoQbdjJXKtez1Uw5KT1nH8EKfgeA5z/PkFw+zYMiXtNdhIgxFBg38veI+/jsB w8nUPydFWy/EpmgTbQTmvbF9c+LczqUgaMSbXKzLByVfxie/SsE/JRyLXQITByVT QmmZ3WTKjTJYa1gEz2lvIafhTxXWu7mnBo7ma1wSXVPSkwOr2m73aIfxf1h1vr/N +/sCOEeQiVT67arKbdlmf7IDvNzcRmnBTdSE//VkJGonaBAjrpUuRD4Yq61YCVon DqVh29LGeFDmkRkcvfZVT2Si/UwDAYhHa8yb0lPZpVXhKbCxLUQ= =HllR -----END PGP SIGNATURE----- Merge tag 'media/v5.19-1' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media Pull media updates from Mauro Carvalho Chehab: - dvb-usb drivers entries got reworked to avoid usage of magic numbers to refer to data position inside tables - vcodec driver has gained support for MT8186 and for vp8 and vp9 stateless codecs - hantro has gained support for Hantro G1 on RK366x - Added more h264 levels on coda960 - ccs gained support for MIPI CSI-2 28 bits per pixel raw data type - venus driver gained support for Qualcomm custom compressed pixel formats - lots of driver fixes and updates * tag 'media/v5.19-1' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media: (308 commits) media: hantro: Enable HOLD_CAPTURE_BUF for H.264 media: hantro: Add H.264 field decoding support media: hantro: h264: Make dpb entry management more robust media: hantro: Stop using H.264 parameter pic_num media: rkvdec: Enable capture buffer holding for H264 media: rkvdec-h264: Add field decoding support media: rkvdec: Ensure decoded resolution fit coded resolution media: rkvdec: h264: Fix reference frame_num wrap for second field media: rkvdec: h264: Validate and use pic width and height in mbs media: rkvdec: Move H264 SPS validation in rkvdec-h264 media: rkvdec: h264: Fix bit depth wrap in pps packet media: rkvdec: h264: Fix dpb_valid implementation media: rkvdec: Stop overclocking the decoder media: v4l2: Reorder field reflist media: h264: Sort p/b reflist using frame_num media: v4l2: Trace calculated p/b0/b1 initial reflist media: h264: Store all fields into the unordered list media: h264: Store current picture fields media: h264: Increase reference lists size to 32 media: h264: Use v4l2_h264_reference for reflist ...
This commit is contained in:
commit
827060261c
|
|
@ -9,14 +9,14 @@ digraph board {
|
||||||
n00000003:port0 -> n00000008:port0 [style=bold]
|
n00000003:port0 -> n00000008:port0 [style=bold]
|
||||||
n00000003:port0 -> n0000000f [style=bold]
|
n00000003:port0 -> n0000000f [style=bold]
|
||||||
n00000005 [label="{{<port0> 0} | Debayer A\n/dev/v4l-subdev2 | {<port1> 1}}", shape=Mrecord, style=filled, fillcolor=green]
|
n00000005 [label="{{<port0> 0} | Debayer A\n/dev/v4l-subdev2 | {<port1> 1}}", shape=Mrecord, style=filled, fillcolor=green]
|
||||||
n00000005:port1 -> n00000017:port0
|
n00000005:port1 -> n00000015:port0
|
||||||
n00000008 [label="{{<port0> 0} | Debayer B\n/dev/v4l-subdev3 | {<port1> 1}}", shape=Mrecord, style=filled, fillcolor=green]
|
n00000008 [label="{{<port0> 0} | Debayer B\n/dev/v4l-subdev3 | {<port1> 1}}", shape=Mrecord, style=filled, fillcolor=green]
|
||||||
n00000008:port1 -> n00000017:port0 [style=dashed]
|
n00000008:port1 -> n00000015:port0 [style=dashed]
|
||||||
n0000000b [label="Raw Capture 0\n/dev/video0", shape=box, style=filled, fillcolor=yellow]
|
n0000000b [label="Raw Capture 0\n/dev/video0", shape=box, style=filled, fillcolor=yellow]
|
||||||
n0000000f [label="Raw Capture 1\n/dev/video1", shape=box, style=filled, fillcolor=yellow]
|
n0000000f [label="Raw Capture 1\n/dev/video1", shape=box, style=filled, fillcolor=yellow]
|
||||||
n00000013 [label="RGB/YUV Input\n/dev/video2", shape=box, style=filled, fillcolor=yellow]
|
n00000013 [label="{{} | RGB/YUV Input\n/dev/v4l-subdev4 | {<port0> 0}}", shape=Mrecord, style=filled, fillcolor=green]
|
||||||
n00000013 -> n00000017:port0 [style=dashed]
|
n00000013:port0 -> n00000015:port0 [style=dashed]
|
||||||
n00000017 [label="{{<port0> 0} | Scaler\n/dev/v4l-subdev4 | {<port1> 1}}", shape=Mrecord, style=filled, fillcolor=green]
|
n00000015 [label="{{<port0> 0} | Scaler\n/dev/v4l-subdev5 | {<port1> 1}}", shape=Mrecord, style=filled, fillcolor=green]
|
||||||
n00000017:port1 -> n0000001a [style=bold]
|
n00000015:port1 -> n00000018 [style=bold]
|
||||||
n0000001a [label="RGB/YUV Capture\n/dev/video3", shape=box, style=filled, fillcolor=yellow]
|
n00000018 [label="RGB/YUV Capture\n/dev/video2", shape=box, style=filled, fillcolor=yellow]
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,9 +0,0 @@
|
||||||
Dongwoon Anatech DW9807 voice coil lens driver
|
|
||||||
|
|
||||||
DW9807 is a 10-bit DAC with current sink capability. It is intended for
|
|
||||||
controlling voice coil lenses.
|
|
||||||
|
|
||||||
Mandatory properties:
|
|
||||||
|
|
||||||
- compatible: "dongwoon,dw9807-vcm"
|
|
||||||
- reg: I2C slave address
|
|
||||||
|
|
@ -0,0 +1,41 @@
|
||||||
|
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||||
|
# Copyright (C) 2018, 2021 Intel Corporation
|
||||||
|
%YAML 1.2
|
||||||
|
---
|
||||||
|
$id: http://devicetree.org/schemas/media/i2c/dongwoon,dw9807-vcm.yaml#
|
||||||
|
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||||
|
|
||||||
|
title: Dongwoon Anatech DW9807 voice coil lens driver
|
||||||
|
|
||||||
|
maintainers:
|
||||||
|
- Sakari Ailus <sakari.ailus@linux.intel.com>
|
||||||
|
|
||||||
|
description: |
|
||||||
|
DW9807 is a 10-bit DAC with current sink capability. It is intended for
|
||||||
|
controlling voice coil lenses.
|
||||||
|
|
||||||
|
properties:
|
||||||
|
compatible:
|
||||||
|
const: dongwoon,dw9807-vcm
|
||||||
|
|
||||||
|
reg:
|
||||||
|
maxItems: 1
|
||||||
|
|
||||||
|
required:
|
||||||
|
- compatible
|
||||||
|
- reg
|
||||||
|
|
||||||
|
additionalProperties: false
|
||||||
|
|
||||||
|
examples:
|
||||||
|
- |
|
||||||
|
i2c {
|
||||||
|
#address-cells = <1>;
|
||||||
|
#size-cells = <0>;
|
||||||
|
|
||||||
|
lens@e {
|
||||||
|
compatible = "dongwoon,dw9807-vcm";
|
||||||
|
reg = <0x0e>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
...
|
||||||
|
|
@ -32,6 +32,15 @@ properties:
|
||||||
description: Clock frequency 6MHz, 12MHz, 18MHz, 24MHz or 27MHz
|
description: Clock frequency 6MHz, 12MHz, 18MHz, 24MHz or 27MHz
|
||||||
maxItems: 1
|
maxItems: 1
|
||||||
|
|
||||||
|
dovdd-supply:
|
||||||
|
description: Interface power supply.
|
||||||
|
|
||||||
|
avdd-supply:
|
||||||
|
description: Analog power supply.
|
||||||
|
|
||||||
|
dvdd-supply:
|
||||||
|
description: Digital power supply.
|
||||||
|
|
||||||
reset-gpios:
|
reset-gpios:
|
||||||
description: Reference to the GPIO connected to the XCLR pin, if any.
|
description: Reference to the GPIO connected to the XCLR pin, if any.
|
||||||
maxItems: 1
|
maxItems: 1
|
||||||
|
|
|
||||||
|
|
@ -63,6 +63,9 @@ properties:
|
||||||
description:
|
description:
|
||||||
Describes point to scp.
|
Describes point to scp.
|
||||||
|
|
||||||
|
power-domains:
|
||||||
|
maxItems: 1
|
||||||
|
|
||||||
required:
|
required:
|
||||||
- compatible
|
- compatible
|
||||||
- reg
|
- reg
|
||||||
|
|
|
||||||
|
|
@ -47,7 +47,9 @@ description: |
|
||||||
|
|
||||||
properties:
|
properties:
|
||||||
compatible:
|
compatible:
|
||||||
const: mediatek,mt8192-vcodec-dec
|
enum:
|
||||||
|
- mediatek,mt8192-vcodec-dec
|
||||||
|
- mediatek,mt8186-vcodec-dec
|
||||||
|
|
||||||
reg:
|
reg:
|
||||||
maxItems: 1
|
maxItems: 1
|
||||||
|
|
|
||||||
|
|
@ -67,7 +67,7 @@ properties:
|
||||||
remote-endpoint: true
|
remote-endpoint: true
|
||||||
|
|
||||||
bus-width:
|
bus-width:
|
||||||
enum: [8, 9, 10, 11, 12]
|
enum: [8, 9, 10, 11, 12, 14]
|
||||||
default: 12
|
default: 12
|
||||||
|
|
||||||
hsync-active:
|
hsync-active:
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,9 @@ properties:
|
||||||
oneOf:
|
oneOf:
|
||||||
- const: rockchip,rk3399-vdec
|
- const: rockchip,rk3399-vdec
|
||||||
- items:
|
- items:
|
||||||
- const: rockchip,rk3228-vdec
|
- enum:
|
||||||
|
- rockchip,rk3228-vdec
|
||||||
|
- rockchip,rk3328-vdec
|
||||||
- const: rockchip,rk3399-vdec
|
- const: rockchip,rk3399-vdec
|
||||||
|
|
||||||
reg:
|
reg:
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,7 @@ properties:
|
||||||
- rockchip,rk3328-vpu
|
- rockchip,rk3328-vpu
|
||||||
- rockchip,rk3399-vpu
|
- rockchip,rk3399-vpu
|
||||||
- rockchip,px30-vpu
|
- rockchip,px30-vpu
|
||||||
|
- rockchip,rk3568-vpu
|
||||||
- items:
|
- items:
|
||||||
- const: rockchip,rk3188-vpu
|
- const: rockchip,rk3188-vpu
|
||||||
- const: rockchip,rk3066-vpu
|
- const: rockchip,rk3066-vpu
|
||||||
|
|
|
||||||
|
|
@ -93,6 +93,7 @@ properties:
|
||||||
- 4 # MIPI CSI-2 D-PHY
|
- 4 # MIPI CSI-2 D-PHY
|
||||||
- 5 # Parallel
|
- 5 # Parallel
|
||||||
- 6 # BT.656
|
- 6 # BT.656
|
||||||
|
- 7 # DPI
|
||||||
description:
|
description:
|
||||||
Data bus type.
|
Data bus type.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -109,6 +109,7 @@ your driver:
|
||||||
int (*adap_monitor_all_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_monitor_pin_enable)(struct cec_adapter *adap, bool enable);
|
||||||
int (*adap_log_addr)(struct cec_adapter *adap, u8 logical_addr);
|
int (*adap_log_addr)(struct cec_adapter *adap, u8 logical_addr);
|
||||||
|
void (*adap_configured)(struct cec_adapter *adap, bool configured);
|
||||||
int (*adap_transmit)(struct cec_adapter *adap, u8 attempts,
|
int (*adap_transmit)(struct cec_adapter *adap, u8 attempts,
|
||||||
u32 signal_free_time, struct cec_msg *msg);
|
u32 signal_free_time, struct cec_msg *msg);
|
||||||
void (*adap_status)(struct cec_adapter *adap, struct seq_file *file);
|
void (*adap_status)(struct cec_adapter *adap, struct seq_file *file);
|
||||||
|
|
@ -117,7 +118,7 @@ your driver:
|
||||||
/* Error injection callbacks */
|
/* Error injection callbacks */
|
||||||
...
|
...
|
||||||
|
|
||||||
/* High-level callbacks */
|
/* High-level callback */
|
||||||
...
|
...
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -178,6 +179,16 @@ can receive directed messages to that address.
|
||||||
Note that adap_log_addr must return 0 if logical_addr is CEC_LOG_ADDR_INVALID.
|
Note that adap_log_addr must return 0 if logical_addr is CEC_LOG_ADDR_INVALID.
|
||||||
|
|
||||||
|
|
||||||
|
Called when the adapter is fully configured or unconfigured::
|
||||||
|
|
||||||
|
void (*adap_configured)(struct cec_adapter *adap, bool configured);
|
||||||
|
|
||||||
|
If configured == true, then the adapter is fully configured, i.e. all logical
|
||||||
|
addresses have been successfully claimed. If configured == false, then the
|
||||||
|
adapter is unconfigured. If the driver has to take specific actions after
|
||||||
|
(un)configuration, then that can be done through this optional callback.
|
||||||
|
|
||||||
|
|
||||||
To transmit a new message::
|
To transmit a new message::
|
||||||
|
|
||||||
int (*adap_transmit)(struct cec_adapter *adap, u8 attempts,
|
int (*adap_transmit)(struct cec_adapter *adap, u8 attempts,
|
||||||
|
|
|
||||||
|
|
@ -42,9 +42,16 @@ 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
|
embedding the :c:type:`media_device` instance in a larger driver-specific
|
||||||
structure.
|
structure.
|
||||||
|
|
||||||
Drivers register media device instances by calling
|
Drivers initialise media device instances by calling
|
||||||
:c:func:`__media_device_register()` via the macro ``media_device_register()``
|
:c:func:`media_device_init()`. After initialising a media device instance, it is
|
||||||
and unregistered by calling :c:func:`media_device_unregister()`.
|
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
|
||||||
^^^^^^^^
|
^^^^^^^^
|
||||||
|
|
|
||||||
|
|
@ -518,6 +518,75 @@ The :c:func:`v4l2_i2c_new_subdev` function will call
|
||||||
:c:type:`i2c_board_info` structure using the ``client_type`` and the
|
:c:type:`i2c_board_info` structure using the ``client_type`` and the
|
||||||
``addr`` to fill it.
|
``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 geting 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.
|
||||||
|
|
||||||
V4L2 sub-device functions and data structures
|
V4L2 sub-device functions and data structures
|
||||||
---------------------------------------------
|
---------------------------------------------
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@ This file documents some driver-specific aspects of the UVC driver, such as
|
||||||
driver-specific ioctls and implementation notes.
|
driver-specific ioctls and implementation notes.
|
||||||
|
|
||||||
Questions and remarks can be sent to the Linux UVC development mailing list at
|
Questions and remarks can be sent to the Linux UVC development mailing list at
|
||||||
linux-uvc-devel@lists.berlios.de.
|
linux-media@vger.kernel.org.
|
||||||
|
|
||||||
|
|
||||||
Extension Unit (XU) support
|
Extension Unit (XU) support
|
||||||
|
|
|
||||||
|
|
@ -33,3 +33,9 @@ are:
|
||||||
|
|
||||||
- An **interface link** is a point-to-point bidirectional control
|
- An **interface link** is a point-to-point bidirectional control
|
||||||
connection between a Linux Kernel interface and an entity.
|
connection between a Linux Kernel interface and an entity.
|
||||||
|
|
||||||
|
- An **ancillary link** is a point-to-point connection denoting that two
|
||||||
|
entities form a single logical unit. For example this could represent the
|
||||||
|
fact that a particular camera sensor and lens controller form a single
|
||||||
|
physical module, meaning this lens controller drives the lens for this
|
||||||
|
camera sensor.
|
||||||
|
|
@ -412,14 +412,21 @@ must be set for every pad.
|
||||||
is set by drivers and is read-only for applications.
|
is set by drivers and is read-only for applications.
|
||||||
|
|
||||||
* - ``MEDIA_LNK_FL_LINK_TYPE``
|
* - ``MEDIA_LNK_FL_LINK_TYPE``
|
||||||
- This is a bitmask that defines the type of the link. Currently,
|
- This is a bitmask that defines the type of the link. The following
|
||||||
two types of links are supported:
|
link types are currently supported:
|
||||||
|
|
||||||
.. _MEDIA-LNK-FL-DATA-LINK:
|
.. _MEDIA-LNK-FL-DATA-LINK:
|
||||||
|
|
||||||
``MEDIA_LNK_FL_DATA_LINK`` if the link is between two pads
|
``MEDIA_LNK_FL_DATA_LINK`` for links that represent a data connection
|
||||||
|
between two pads.
|
||||||
|
|
||||||
.. _MEDIA-LNK-FL-INTERFACE-LINK:
|
.. _MEDIA-LNK-FL-INTERFACE-LINK:
|
||||||
|
|
||||||
``MEDIA_LNK_FL_INTERFACE_LINK`` if the link is between an
|
``MEDIA_LNK_FL_INTERFACE_LINK`` for links that associate an entity to its
|
||||||
interface and an entity
|
interface.
|
||||||
|
|
||||||
|
.. _MEDIA-LNK-FL-ANCILLARY-LINK:
|
||||||
|
|
||||||
|
``MEDIA_LNK_FL_ANCILLARY_LINK`` for links that represent a physical
|
||||||
|
relationship between two entities. The link may or may not be
|
||||||
|
immutable, so applications must not assume either case.
|
||||||
|
|
|
||||||
|
|
@ -72,6 +72,12 @@ coded resolution
|
||||||
coded width
|
coded width
|
||||||
width for given coded resolution.
|
width for given coded resolution.
|
||||||
|
|
||||||
|
coding tree unit
|
||||||
|
processing unit of the HEVC codec (corresponds to macroblock units in
|
||||||
|
H.264, VP8, VP9),
|
||||||
|
can use block structures of up to 64×64 pixels.
|
||||||
|
Good at sub-partitioning the picture into variable sized structures.
|
||||||
|
|
||||||
decode order
|
decode order
|
||||||
the order in which frames are decoded; may differ from display order if the
|
the order in which frames are decoded; may differ from display order if the
|
||||||
coded format includes a feature of frame reordering; for decoders,
|
coded format includes a feature of frame reordering; for decoders,
|
||||||
|
|
@ -104,7 +110,8 @@ keyframe
|
||||||
macroblock
|
macroblock
|
||||||
a processing unit in image and video compression formats based on linear
|
a processing unit in image and video compression formats based on linear
|
||||||
block transforms (e.g. H.264, VP8, VP9); codec-specific, but for most of
|
block transforms (e.g. H.264, VP8, VP9); codec-specific, but for most of
|
||||||
popular codecs the size is 16x16 samples (pixels).
|
popular codecs the size is 16x16 samples (pixels). The HEVC codec uses a
|
||||||
|
slightly more flexible processing unit called coding tree unit (CTU).
|
||||||
|
|
||||||
OUTPUT
|
OUTPUT
|
||||||
the source buffer queue; for decoders, the queue of buffers containing
|
the source buffer queue; for decoders, the queue of buffers containing
|
||||||
|
|
|
||||||
|
|
@ -649,10 +649,16 @@ Stateless Codec Control ID
|
||||||
:c:type:`timeval` in struct :c:type:`v4l2_buffer` to a __u64.
|
:c:type:`timeval` in struct :c:type:`v4l2_buffer` to a __u64.
|
||||||
* - __u32
|
* - __u32
|
||||||
- ``pic_num``
|
- ``pic_num``
|
||||||
-
|
- For short term references, this must match the derived value PicNum
|
||||||
|
(8-28) and for long term references it must match the derived value
|
||||||
|
LongTermPicNum (8-29). When decoding frames (as opposed to fields)
|
||||||
|
pic_num is the same as FrameNumWrap.
|
||||||
* - __u16
|
* - __u16
|
||||||
- ``frame_num``
|
- ``frame_num``
|
||||||
-
|
- For short term references, this must match the frame_num value from
|
||||||
|
the slice header syntax (the driver will wrap the value if needed). For
|
||||||
|
long term references, this must be set to the value of
|
||||||
|
long_term_frame_idx described in the dec_ref_pic_marking() syntax.
|
||||||
* - __u8
|
* - __u8
|
||||||
- ``fields``
|
- ``fields``
|
||||||
- Specifies how the DPB entry is referenced. See :ref:`Reference Fields <h264_ref_fields>`
|
- Specifies how the DPB entry is referenced. See :ref:`Reference Fields <h264_ref_fields>`
|
||||||
|
|
|
||||||
|
|
@ -1180,6 +1180,28 @@ enum v4l2_mpeg_video_h264_entropy_mode -
|
||||||
is set to non zero value.
|
is set to non zero value.
|
||||||
Applicable to H264, H263 and MPEG4 encoder.
|
Applicable to H264, H263 and MPEG4 encoder.
|
||||||
|
|
||||||
|
``V4L2_CID_MPEG_VIDEO_INTRA_REFRESH_PERIOD_TYPE (enum)``
|
||||||
|
|
||||||
|
enum v4l2_mpeg_video_intra_refresh_period_type -
|
||||||
|
Sets the type of intra refresh. The period to refresh
|
||||||
|
the whole frame is specified by V4L2_CID_MPEG_VIDEO_INTRA_REFRESH_PERIOD.
|
||||||
|
Note that if this control is not present, then it is undefined what
|
||||||
|
refresh type is used and it is up to the driver to decide.
|
||||||
|
Applicable to H264 and HEVC encoders. Possible values are:
|
||||||
|
|
||||||
|
.. tabularcolumns:: |p{9.6cm}|p{7.9cm}|
|
||||||
|
|
||||||
|
.. flat-table::
|
||||||
|
:header-rows: 0
|
||||||
|
:stub-columns: 0
|
||||||
|
|
||||||
|
* - ``V4L2_MPEG_VIDEO_INTRA_REFRESH_PERIOD_TYPE_RANDOM``
|
||||||
|
- The whole frame is completely refreshed randomly
|
||||||
|
after the specified period.
|
||||||
|
* - ``V4L2_MPEG_VIDEO_INTRA_REFRESH_PERIOD_TYPE_CYCLIC``
|
||||||
|
- The whole frame MBs are completely refreshed in cyclic order
|
||||||
|
after the specified period.
|
||||||
|
|
||||||
``V4L2_CID_MPEG_VIDEO_INTRA_REFRESH_PERIOD (integer)``
|
``V4L2_CID_MPEG_VIDEO_INTRA_REFRESH_PERIOD (integer)``
|
||||||
Intra macroblock refresh period. This sets the period to refresh
|
Intra macroblock refresh period. This sets the period to refresh
|
||||||
the whole frame. In other words, this defines the number of frames
|
the whole frame. In other words, this defines the number of frames
|
||||||
|
|
|
||||||
|
|
@ -239,6 +239,25 @@ please make a proposal on the linux-media mailing list.
|
||||||
It remains an opaque intermediate format and the MDP hardware must be
|
It remains an opaque intermediate format and the MDP hardware must be
|
||||||
used to convert ``V4L2_PIX_FMT_MT21C`` to ``V4L2_PIX_FMT_NV12M``,
|
used to convert ``V4L2_PIX_FMT_MT21C`` to ``V4L2_PIX_FMT_NV12M``,
|
||||||
``V4L2_PIX_FMT_YUV420M`` or ``V4L2_PIX_FMT_YVU420``.
|
``V4L2_PIX_FMT_YUV420M`` or ``V4L2_PIX_FMT_YVU420``.
|
||||||
|
* .. _V4L2-PIX-FMT-QC08C:
|
||||||
|
|
||||||
|
- ``V4L2_PIX_FMT_QC08C``
|
||||||
|
- 'QC08C'
|
||||||
|
- Compressed Macro-tile 8-Bit YUV420 format used by Qualcomm platforms.
|
||||||
|
It is an opaque intermediate format. The used compression is lossless
|
||||||
|
and it is used by various multimedia hardware blocks like GPU, display
|
||||||
|
controllers, ISP and video accelerators.
|
||||||
|
It contains four planes for progressive video and eight planes for
|
||||||
|
interlaced video.
|
||||||
|
* .. _V4L2-PIX-FMT-QC10C:
|
||||||
|
|
||||||
|
- ``V4L2_PIX_FMT_QC10C``
|
||||||
|
- 'QC10C'
|
||||||
|
- Compressed Macro-tile 10-Bit YUV420 format used by Qualcomm platforms.
|
||||||
|
It is an opaque intermediate format. The used compression is lossless
|
||||||
|
and it is used by various multimedia hardware blocks like GPU, display
|
||||||
|
controllers, ISP and video accelerators.
|
||||||
|
It contains four planes for progressive video.
|
||||||
.. raw:: latex
|
.. raw:: latex
|
||||||
|
|
||||||
\normalsize
|
\normalsize
|
||||||
|
|
|
||||||
|
|
@ -48,6 +48,17 @@ are often referred to as greyscale formats.
|
||||||
- ...
|
- ...
|
||||||
- ...
|
- ...
|
||||||
|
|
||||||
|
* .. _V4L2-PIX-FMT-IPU3-Y10:
|
||||||
|
|
||||||
|
- ``V4L2_PIX_FMT_IPU3_Y10``
|
||||||
|
- 'ip3y'
|
||||||
|
|
||||||
|
- Y'\ :sub:`0`\ [7:0]
|
||||||
|
- Y'\ :sub:`1`\ [5:0] Y'\ :sub:`0`\ [9:8]
|
||||||
|
- Y'\ :sub:`2`\ [3:0] Y'\ :sub:`1`\ [9:6]
|
||||||
|
- Y'\ :sub:`3`\ [1:0] Y'\ :sub:`2`\ [9:4]
|
||||||
|
- Y'\ :sub:`3`\ [9:2]
|
||||||
|
|
||||||
* .. _V4L2-PIX-FMT-Y10:
|
* .. _V4L2-PIX-FMT-Y10:
|
||||||
|
|
||||||
- ``V4L2_PIX_FMT_Y10``
|
- ``V4L2_PIX_FMT_Y10``
|
||||||
|
|
@ -133,4 +144,5 @@ are often referred to as greyscale formats.
|
||||||
|
|
||||||
For the Y16 and Y16_BE formats, the actual sampling precision may be lower
|
For the Y16 and Y16_BE formats, the actual sampling precision may be lower
|
||||||
than 16 bits. For example, 10 bits per pixel uses values in the range 0 to
|
than 16 bits. For example, 10 bits per pixel uses values in the range 0 to
|
||||||
1023.
|
1023. For the IPU3_Y10 format 25 pixels are packed into 32 bytes, which
|
||||||
|
leaves the 6 most significant bits of the last byte padded with 0.
|
||||||
|
|
|
||||||
|
|
@ -43,8 +43,7 @@ the capture or output process during streaming
|
||||||
Capture hardware is disabled and no input buffers are filled (if there
|
Capture hardware is disabled and no input buffers are filled (if there
|
||||||
are any empty buffers in the incoming queue) until ``VIDIOC_STREAMON``
|
are any empty buffers in the incoming queue) until ``VIDIOC_STREAMON``
|
||||||
has been called. Output hardware is disabled and no video signal is
|
has been called. Output hardware is disabled and no video signal is
|
||||||
produced until ``VIDIOC_STREAMON`` has been called. The ioctl will
|
produced until ``VIDIOC_STREAMON`` has been called.
|
||||||
succeed when at least one output buffer is in the incoming queue.
|
|
||||||
|
|
||||||
Memory-to-memory devices will not start until ``VIDIOC_STREAMON`` has
|
Memory-to-memory devices will not start until ``VIDIOC_STREAMON`` has
|
||||||
been called for both the capture and output stream types.
|
been called for both the capture and output stream types.
|
||||||
|
|
|
||||||
12
MAINTAINERS
12
MAINTAINERS
|
|
@ -12194,7 +12194,7 @@ T: git git://linuxtv.org/media_tree.git
|
||||||
F: Documentation/admin-guide/media/imx7.rst
|
F: Documentation/admin-guide/media/imx7.rst
|
||||||
F: Documentation/devicetree/bindings/media/nxp,imx-mipi-csi2.yaml
|
F: Documentation/devicetree/bindings/media/nxp,imx-mipi-csi2.yaml
|
||||||
F: Documentation/devicetree/bindings/media/nxp,imx7-csi.yaml
|
F: Documentation/devicetree/bindings/media/nxp,imx7-csi.yaml
|
||||||
F: drivers/media/platform/imx/imx-mipi-csis.c
|
F: drivers/media/platform/nxp/imx-mipi-csis.c
|
||||||
F: drivers/staging/media/imx/imx7-media-csi.c
|
F: drivers/staging/media/imx/imx7-media-csi.c
|
||||||
|
|
||||||
MEDIA DRIVERS FOR HELENE
|
MEDIA DRIVERS FOR HELENE
|
||||||
|
|
@ -12249,7 +12249,7 @@ L: linux-media@vger.kernel.org
|
||||||
L: linux-tegra@vger.kernel.org
|
L: linux-tegra@vger.kernel.org
|
||||||
S: Maintained
|
S: Maintained
|
||||||
T: git git://linuxtv.org/media_tree.git
|
T: git git://linuxtv.org/media_tree.git
|
||||||
F: Documentation/devicetree/bindings/media/nvidia,tegra-vde.txt
|
F: Documentation/devicetree/bindings/media/nvidia,tegra-vde.yaml
|
||||||
F: drivers/media/platform/nvidia/tegra-vde/
|
F: drivers/media/platform/nvidia/tegra-vde/
|
||||||
|
|
||||||
MEDIA DRIVERS FOR RENESAS - CEU
|
MEDIA DRIVERS FOR RENESAS - CEU
|
||||||
|
|
@ -12412,10 +12412,9 @@ F: drivers/iommu/mtk_iommu*
|
||||||
F: include/dt-bindings/memory/mt*-port.h
|
F: include/dt-bindings/memory/mt*-port.h
|
||||||
|
|
||||||
MEDIATEK JPEG DRIVER
|
MEDIATEK JPEG DRIVER
|
||||||
M: Rick Chang <rick.chang@mediatek.com>
|
|
||||||
M: Bin Liu <bin.liu@mediatek.com>
|
M: Bin Liu <bin.liu@mediatek.com>
|
||||||
S: Supported
|
S: Supported
|
||||||
F: Documentation/devicetree/bindings/media/mediatek-jpeg-decoder.txt
|
F: Documentation/devicetree/bindings/media/mediatek-jpeg-*.yaml
|
||||||
F: drivers/media/platform/mediatek/jpeg/
|
F: drivers/media/platform/mediatek/jpeg/
|
||||||
|
|
||||||
MEDIATEK MDP DRIVER
|
MEDIATEK MDP DRIVER
|
||||||
|
|
@ -12431,7 +12430,7 @@ MEDIATEK MEDIA DRIVER
|
||||||
M: Tiffany Lin <tiffany.lin@mediatek.com>
|
M: Tiffany Lin <tiffany.lin@mediatek.com>
|
||||||
M: Andrew-CT Chen <andrew-ct.chen@mediatek.com>
|
M: Andrew-CT Chen <andrew-ct.chen@mediatek.com>
|
||||||
S: Supported
|
S: Supported
|
||||||
F: Documentation/devicetree/bindings/media/mediatek-vcodec.txt
|
F: Documentation/devicetree/bindings/media/mediatek,vcodec*.yaml
|
||||||
F: Documentation/devicetree/bindings/media/mediatek-vpu.txt
|
F: Documentation/devicetree/bindings/media/mediatek-vpu.txt
|
||||||
F: drivers/media/platform/mediatek/vcodec/
|
F: drivers/media/platform/mediatek/vcodec/
|
||||||
F: drivers/media/platform/mediatek/vpu/
|
F: drivers/media/platform/mediatek/vpu/
|
||||||
|
|
@ -14246,7 +14245,7 @@ R: NXP Linux Team <linux-imx@nxp.com>
|
||||||
L: linux-media@vger.kernel.org
|
L: linux-media@vger.kernel.org
|
||||||
S: Maintained
|
S: Maintained
|
||||||
F: Documentation/devicetree/bindings/media/nxp,imx8-jpeg.yaml
|
F: Documentation/devicetree/bindings/media/nxp,imx8-jpeg.yaml
|
||||||
F: drivers/media/platform/imx-jpeg
|
F: drivers/media/platform/nxp/imx-jpeg
|
||||||
|
|
||||||
NZXT-KRAKEN2 HARDWARE MONITORING DRIVER
|
NZXT-KRAKEN2 HARDWARE MONITORING DRIVER
|
||||||
M: Jonas Malaco <jonas@protocubo.io>
|
M: Jonas Malaco <jonas@protocubo.io>
|
||||||
|
|
@ -20583,7 +20582,6 @@ F: drivers/usb/host/uhci*
|
||||||
|
|
||||||
USB VIDEO CLASS
|
USB VIDEO CLASS
|
||||||
M: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
|
M: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
|
||||||
L: linux-uvc-devel@lists.sourceforge.net (subscribers-only)
|
|
||||||
L: linux-media@vger.kernel.org
|
L: linux-media@vger.kernel.org
|
||||||
S: Maintained
|
S: Maintained
|
||||||
W: http://www.ideasonboard.org/uvc/
|
W: http://www.ideasonboard.org/uvc/
|
||||||
|
|
|
||||||
|
|
@ -27,27 +27,6 @@ static void cec_fill_msg_report_features(struct cec_adapter *adap,
|
||||||
struct cec_msg *msg,
|
struct cec_msg *msg,
|
||||||
unsigned int la_idx);
|
unsigned int la_idx);
|
||||||
|
|
||||||
/*
|
|
||||||
* 400 ms is the time it takes for one 16 byte message to be
|
|
||||||
* transferred and 5 is the maximum number of retries. Add
|
|
||||||
* another 100 ms as a margin. So if the transmit doesn't
|
|
||||||
* finish before that time something is really wrong and we
|
|
||||||
* have to time out.
|
|
||||||
*
|
|
||||||
* This is a sign that something it really wrong and a warning
|
|
||||||
* will be issued.
|
|
||||||
*/
|
|
||||||
#define CEC_XFER_TIMEOUT_MS (5 * 400 + 100)
|
|
||||||
|
|
||||||
#define call_op(adap, op, arg...) \
|
|
||||||
(adap->ops->op ? adap->ops->op(adap, ## arg) : 0)
|
|
||||||
|
|
||||||
#define call_void_op(adap, op, arg...) \
|
|
||||||
do { \
|
|
||||||
if (adap->ops->op) \
|
|
||||||
adap->ops->op(adap, ## arg); \
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
static int cec_log_addr2idx(const struct cec_adapter *adap, u8 log_addr)
|
static int cec_log_addr2idx(const struct cec_adapter *adap, u8 log_addr)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
@ -366,38 +345,48 @@ static void cec_data_completed(struct cec_data *data)
|
||||||
/*
|
/*
|
||||||
* A pending CEC transmit needs to be cancelled, either because the CEC
|
* A pending CEC transmit needs to be cancelled, either because the CEC
|
||||||
* adapter is disabled or the transmit takes an impossibly long time to
|
* adapter is disabled or the transmit takes an impossibly long time to
|
||||||
* finish.
|
* finish, or the reply timed out.
|
||||||
*
|
*
|
||||||
* This function is called with adap->lock held.
|
* This function is called with adap->lock held.
|
||||||
*/
|
*/
|
||||||
static void cec_data_cancel(struct cec_data *data, u8 tx_status)
|
static void cec_data_cancel(struct cec_data *data, u8 tx_status, u8 rx_status)
|
||||||
{
|
{
|
||||||
|
struct cec_adapter *adap = data->adap;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* It's either the current transmit, or it is a pending
|
* It's either the current transmit, or it is a pending
|
||||||
* transmit. Take the appropriate action to clear it.
|
* transmit. Take the appropriate action to clear it.
|
||||||
*/
|
*/
|
||||||
if (data->adap->transmitting == data) {
|
if (adap->transmitting == data) {
|
||||||
data->adap->transmitting = NULL;
|
adap->transmitting = NULL;
|
||||||
} else {
|
} else {
|
||||||
list_del_init(&data->list);
|
list_del_init(&data->list);
|
||||||
if (!(data->msg.tx_status & CEC_TX_STATUS_OK))
|
if (!(data->msg.tx_status & CEC_TX_STATUS_OK))
|
||||||
if (!WARN_ON(!data->adap->transmit_queue_sz))
|
if (!WARN_ON(!adap->transmit_queue_sz))
|
||||||
data->adap->transmit_queue_sz--;
|
adap->transmit_queue_sz--;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (data->msg.tx_status & CEC_TX_STATUS_OK) {
|
if (data->msg.tx_status & CEC_TX_STATUS_OK) {
|
||||||
data->msg.rx_ts = ktime_get_ns();
|
data->msg.rx_ts = ktime_get_ns();
|
||||||
data->msg.rx_status = CEC_RX_STATUS_ABORTED;
|
data->msg.rx_status = rx_status;
|
||||||
|
if (!data->blocking)
|
||||||
|
data->msg.tx_status = 0;
|
||||||
} else {
|
} else {
|
||||||
data->msg.tx_ts = ktime_get_ns();
|
data->msg.tx_ts = ktime_get_ns();
|
||||||
data->msg.tx_status |= tx_status |
|
data->msg.tx_status |= tx_status |
|
||||||
CEC_TX_STATUS_MAX_RETRIES;
|
CEC_TX_STATUS_MAX_RETRIES;
|
||||||
data->msg.tx_error_cnt++;
|
data->msg.tx_error_cnt++;
|
||||||
data->attempts = 0;
|
data->attempts = 0;
|
||||||
|
if (!data->blocking)
|
||||||
|
data->msg.rx_status = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Queue transmitted message for monitoring purposes */
|
/* Queue transmitted message for monitoring purposes */
|
||||||
cec_queue_msg_monitor(data->adap, &data->msg, 1);
|
cec_queue_msg_monitor(adap, &data->msg, 1);
|
||||||
|
|
||||||
|
if (!data->blocking && data->msg.sequence)
|
||||||
|
/* Allow drivers to process the message first */
|
||||||
|
call_op(adap, received, &data->msg);
|
||||||
|
|
||||||
cec_data_completed(data);
|
cec_data_completed(data);
|
||||||
}
|
}
|
||||||
|
|
@ -418,15 +407,15 @@ static void cec_flush(struct cec_adapter *adap)
|
||||||
while (!list_empty(&adap->transmit_queue)) {
|
while (!list_empty(&adap->transmit_queue)) {
|
||||||
data = list_first_entry(&adap->transmit_queue,
|
data = list_first_entry(&adap->transmit_queue,
|
||||||
struct cec_data, list);
|
struct cec_data, list);
|
||||||
cec_data_cancel(data, CEC_TX_STATUS_ABORTED);
|
cec_data_cancel(data, CEC_TX_STATUS_ABORTED, 0);
|
||||||
}
|
}
|
||||||
if (adap->transmitting)
|
if (adap->transmitting)
|
||||||
cec_data_cancel(adap->transmitting, CEC_TX_STATUS_ABORTED);
|
adap->transmit_in_progress_aborted = true;
|
||||||
|
|
||||||
/* Cancel the pending timeout work. */
|
/* Cancel the pending timeout work. */
|
||||||
list_for_each_entry_safe(data, n, &adap->wait_queue, list) {
|
list_for_each_entry_safe(data, n, &adap->wait_queue, list) {
|
||||||
if (cancel_delayed_work(&data->work))
|
if (cancel_delayed_work(&data->work))
|
||||||
cec_data_cancel(data, CEC_TX_STATUS_OK);
|
cec_data_cancel(data, CEC_TX_STATUS_OK, CEC_RX_STATUS_ABORTED);
|
||||||
/*
|
/*
|
||||||
* If cancel_delayed_work returned false, then
|
* If cancel_delayed_work returned false, then
|
||||||
* the cec_wait_timeout function is running,
|
* the cec_wait_timeout function is running,
|
||||||
|
|
@ -482,7 +471,7 @@ int cec_thread_func(void *_adap)
|
||||||
kthread_should_stop() ||
|
kthread_should_stop() ||
|
||||||
(!adap->transmit_in_progress &&
|
(!adap->transmit_in_progress &&
|
||||||
!list_empty(&adap->transmit_queue)),
|
!list_empty(&adap->transmit_queue)),
|
||||||
msecs_to_jiffies(CEC_XFER_TIMEOUT_MS));
|
msecs_to_jiffies(adap->xfer_timeout_ms));
|
||||||
timeout = err == 0;
|
timeout = err == 0;
|
||||||
} else {
|
} else {
|
||||||
/* Otherwise we just wait for something to happen. */
|
/* Otherwise we just wait for something to happen. */
|
||||||
|
|
@ -508,7 +497,8 @@ int cec_thread_func(void *_adap)
|
||||||
* adapter driver, or the CEC bus is in some weird
|
* adapter driver, or the CEC bus is in some weird
|
||||||
* state. On rare occasions it can happen if there is
|
* state. On rare occasions it can happen if there is
|
||||||
* so much traffic on the bus that the adapter was
|
* so much traffic on the bus that the adapter was
|
||||||
* unable to transmit for CEC_XFER_TIMEOUT_MS (2.1s).
|
* unable to transmit for xfer_timeout_ms (2.1s by
|
||||||
|
* default).
|
||||||
*/
|
*/
|
||||||
if (adap->transmitting) {
|
if (adap->transmitting) {
|
||||||
pr_warn("cec-%s: message %*ph timed out\n", adap->name,
|
pr_warn("cec-%s: message %*ph timed out\n", adap->name,
|
||||||
|
|
@ -516,7 +506,7 @@ int cec_thread_func(void *_adap)
|
||||||
adap->transmitting->msg.msg);
|
adap->transmitting->msg.msg);
|
||||||
/* Just give up on this. */
|
/* Just give up on this. */
|
||||||
cec_data_cancel(adap->transmitting,
|
cec_data_cancel(adap->transmitting,
|
||||||
CEC_TX_STATUS_TIMEOUT);
|
CEC_TX_STATUS_TIMEOUT, 0);
|
||||||
} else {
|
} else {
|
||||||
pr_warn("cec-%s: transmit timed out\n", adap->name);
|
pr_warn("cec-%s: transmit timed out\n", adap->name);
|
||||||
}
|
}
|
||||||
|
|
@ -572,10 +562,11 @@ int cec_thread_func(void *_adap)
|
||||||
if (data->attempts == 0)
|
if (data->attempts == 0)
|
||||||
data->attempts = attempts;
|
data->attempts = attempts;
|
||||||
|
|
||||||
|
adap->transmit_in_progress_aborted = false;
|
||||||
/* Tell the adapter to transmit, cancel on error */
|
/* Tell the adapter to transmit, cancel on error */
|
||||||
if (adap->ops->adap_transmit(adap, data->attempts,
|
if (call_op(adap, adap_transmit, data->attempts,
|
||||||
signal_free_time, &data->msg))
|
signal_free_time, &data->msg))
|
||||||
cec_data_cancel(data, CEC_TX_STATUS_ABORTED);
|
cec_data_cancel(data, CEC_TX_STATUS_ABORTED, 0);
|
||||||
else
|
else
|
||||||
adap->transmit_in_progress = true;
|
adap->transmit_in_progress = true;
|
||||||
|
|
||||||
|
|
@ -599,6 +590,8 @@ void cec_transmit_done_ts(struct cec_adapter *adap, u8 status,
|
||||||
struct cec_msg *msg;
|
struct cec_msg *msg;
|
||||||
unsigned int attempts_made = arb_lost_cnt + nack_cnt +
|
unsigned int attempts_made = arb_lost_cnt + nack_cnt +
|
||||||
low_drive_cnt + error_cnt;
|
low_drive_cnt + error_cnt;
|
||||||
|
bool done = status & (CEC_TX_STATUS_MAX_RETRIES | CEC_TX_STATUS_OK);
|
||||||
|
bool aborted = adap->transmit_in_progress_aborted;
|
||||||
|
|
||||||
dprintk(2, "%s: status 0x%02x\n", __func__, status);
|
dprintk(2, "%s: status 0x%02x\n", __func__, status);
|
||||||
if (attempts_made < 1)
|
if (attempts_made < 1)
|
||||||
|
|
@ -619,6 +612,7 @@ void cec_transmit_done_ts(struct cec_adapter *adap, u8 status,
|
||||||
goto wake_thread;
|
goto wake_thread;
|
||||||
}
|
}
|
||||||
adap->transmit_in_progress = false;
|
adap->transmit_in_progress = false;
|
||||||
|
adap->transmit_in_progress_aborted = false;
|
||||||
|
|
||||||
msg = &data->msg;
|
msg = &data->msg;
|
||||||
|
|
||||||
|
|
@ -639,8 +633,7 @@ void cec_transmit_done_ts(struct cec_adapter *adap, u8 status,
|
||||||
* the hardware didn't signal that it retried itself (by setting
|
* the hardware didn't signal that it retried itself (by setting
|
||||||
* CEC_TX_STATUS_MAX_RETRIES), then we will retry ourselves.
|
* CEC_TX_STATUS_MAX_RETRIES), then we will retry ourselves.
|
||||||
*/
|
*/
|
||||||
if (data->attempts > attempts_made &&
|
if (!aborted && data->attempts > attempts_made && !done) {
|
||||||
!(status & (CEC_TX_STATUS_MAX_RETRIES | CEC_TX_STATUS_OK))) {
|
|
||||||
/* Retry this message */
|
/* Retry this message */
|
||||||
data->attempts -= attempts_made;
|
data->attempts -= attempts_made;
|
||||||
if (msg->timeout)
|
if (msg->timeout)
|
||||||
|
|
@ -655,6 +648,8 @@ void cec_transmit_done_ts(struct cec_adapter *adap, u8 status,
|
||||||
goto wake_thread;
|
goto wake_thread;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (aborted && !done)
|
||||||
|
status |= CEC_TX_STATUS_ABORTED;
|
||||||
data->attempts = 0;
|
data->attempts = 0;
|
||||||
|
|
||||||
/* Always set CEC_TX_STATUS_MAX_RETRIES on error */
|
/* Always set CEC_TX_STATUS_MAX_RETRIES on error */
|
||||||
|
|
@ -733,9 +728,7 @@ static void cec_wait_timeout(struct work_struct *work)
|
||||||
|
|
||||||
/* Mark the message as timed out */
|
/* Mark the message as timed out */
|
||||||
list_del_init(&data->list);
|
list_del_init(&data->list);
|
||||||
data->msg.rx_ts = ktime_get_ns();
|
cec_data_cancel(data, CEC_TX_STATUS_OK, CEC_RX_STATUS_TIMEOUT);
|
||||||
data->msg.rx_status = CEC_RX_STATUS_TIMEOUT;
|
|
||||||
cec_data_completed(data);
|
|
||||||
unlock:
|
unlock:
|
||||||
mutex_unlock(&adap->lock);
|
mutex_unlock(&adap->lock);
|
||||||
}
|
}
|
||||||
|
|
@ -921,8 +914,12 @@ int cec_transmit_msg_fh(struct cec_adapter *adap, struct cec_msg *msg,
|
||||||
mutex_lock(&adap->lock);
|
mutex_lock(&adap->lock);
|
||||||
|
|
||||||
/* Cancel the transmit if it was interrupted */
|
/* Cancel the transmit if it was interrupted */
|
||||||
if (!data->completed)
|
if (!data->completed) {
|
||||||
cec_data_cancel(data, CEC_TX_STATUS_ABORTED);
|
if (data->msg.tx_status & CEC_TX_STATUS_OK)
|
||||||
|
cec_data_cancel(data, CEC_TX_STATUS_OK, CEC_RX_STATUS_ABORTED);
|
||||||
|
else
|
||||||
|
cec_data_cancel(data, CEC_TX_STATUS_ABORTED, 0);
|
||||||
|
}
|
||||||
|
|
||||||
/* The transmit completed (possibly with an error) */
|
/* The transmit completed (possibly with an error) */
|
||||||
*msg = data->msg;
|
*msg = data->msg;
|
||||||
|
|
@ -1278,17 +1275,22 @@ static int cec_config_log_addr(struct cec_adapter *adap,
|
||||||
* While trying to poll the physical address was reset
|
* While trying to poll the physical address was reset
|
||||||
* and the adapter was unconfigured, so bail out.
|
* and the adapter was unconfigured, so bail out.
|
||||||
*/
|
*/
|
||||||
if (!adap->is_configuring)
|
if (adap->phys_addr == CEC_PHYS_ADDR_INVALID)
|
||||||
|
return -EINTR;
|
||||||
|
|
||||||
|
/* Also bail out if the PA changed while configuring. */
|
||||||
|
if (adap->must_reconfigure)
|
||||||
return -EINTR;
|
return -EINTR;
|
||||||
|
|
||||||
if (err)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The message was aborted due to a disconnect or
|
* The message was aborted or timed out due to a disconnect or
|
||||||
* unconfigure, just bail out.
|
* unconfigure, just bail out.
|
||||||
*/
|
*/
|
||||||
if (msg.tx_status & CEC_TX_STATUS_ABORTED)
|
if (msg.tx_status &
|
||||||
|
(CEC_TX_STATUS_ABORTED | CEC_TX_STATUS_TIMEOUT))
|
||||||
return -EINTR;
|
return -EINTR;
|
||||||
if (msg.tx_status & CEC_TX_STATUS_OK)
|
if (msg.tx_status & CEC_TX_STATUS_OK)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
@ -1314,7 +1316,7 @@ static int cec_config_log_addr(struct cec_adapter *adap,
|
||||||
* Message not acknowledged, so this logical
|
* Message not acknowledged, so this logical
|
||||||
* address is free to use.
|
* address is free to use.
|
||||||
*/
|
*/
|
||||||
err = adap->ops->adap_log_addr(adap, log_addr);
|
err = call_op(adap, adap_log_addr, log_addr);
|
||||||
if (err)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
|
|
@ -1331,15 +1333,14 @@ static int cec_config_log_addr(struct cec_adapter *adap,
|
||||||
*/
|
*/
|
||||||
static void cec_adap_unconfigure(struct cec_adapter *adap)
|
static void cec_adap_unconfigure(struct cec_adapter *adap)
|
||||||
{
|
{
|
||||||
if (!adap->needs_hpd ||
|
if (!adap->needs_hpd || adap->phys_addr != CEC_PHYS_ADDR_INVALID)
|
||||||
adap->phys_addr != CEC_PHYS_ADDR_INVALID)
|
WARN_ON(call_op(adap, adap_log_addr, CEC_LOG_ADDR_INVALID));
|
||||||
WARN_ON(adap->ops->adap_log_addr(adap, CEC_LOG_ADDR_INVALID));
|
|
||||||
adap->log_addrs.log_addr_mask = 0;
|
adap->log_addrs.log_addr_mask = 0;
|
||||||
adap->is_configuring = false;
|
|
||||||
adap->is_configured = false;
|
adap->is_configured = false;
|
||||||
cec_flush(adap);
|
cec_flush(adap);
|
||||||
wake_up_interruptible(&adap->kthread_waitq);
|
wake_up_interruptible(&adap->kthread_waitq);
|
||||||
cec_post_state_event(adap);
|
cec_post_state_event(adap);
|
||||||
|
call_void_op(adap, adap_configured, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
@ -1408,6 +1409,7 @@ static int cec_config_thread_func(void *arg)
|
||||||
if (las->log_addr_type[0] == CEC_LOG_ADDR_TYPE_UNREGISTERED)
|
if (las->log_addr_type[0] == CEC_LOG_ADDR_TYPE_UNREGISTERED)
|
||||||
goto configured;
|
goto configured;
|
||||||
|
|
||||||
|
reconfigure:
|
||||||
for (i = 0; i < las->num_log_addrs; i++) {
|
for (i = 0; i < las->num_log_addrs; i++) {
|
||||||
unsigned int type = las->log_addr_type[i];
|
unsigned int type = las->log_addr_type[i];
|
||||||
const u8 *la_list;
|
const u8 *la_list;
|
||||||
|
|
@ -1430,6 +1432,13 @@ static int cec_config_thread_func(void *arg)
|
||||||
last_la = la_list[0];
|
last_la = la_list[0];
|
||||||
|
|
||||||
err = cec_config_log_addr(adap, i, last_la);
|
err = cec_config_log_addr(adap, i, last_la);
|
||||||
|
|
||||||
|
if (adap->must_reconfigure) {
|
||||||
|
adap->must_reconfigure = false;
|
||||||
|
las->log_addr_mask = 0;
|
||||||
|
goto reconfigure;
|
||||||
|
}
|
||||||
|
|
||||||
if (err > 0) /* Reused last LA */
|
if (err > 0) /* Reused last LA */
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
|
@ -1475,6 +1484,7 @@ static int cec_config_thread_func(void *arg)
|
||||||
las->log_addr[i] = CEC_LOG_ADDR_INVALID;
|
las->log_addr[i] = CEC_LOG_ADDR_INVALID;
|
||||||
adap->is_configured = true;
|
adap->is_configured = true;
|
||||||
adap->is_configuring = false;
|
adap->is_configuring = false;
|
||||||
|
adap->must_reconfigure = false;
|
||||||
cec_post_state_event(adap);
|
cec_post_state_event(adap);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
@ -1521,15 +1531,18 @@ static int cec_config_thread_func(void *arg)
|
||||||
adap->kthread_config = NULL;
|
adap->kthread_config = NULL;
|
||||||
complete(&adap->config_completion);
|
complete(&adap->config_completion);
|
||||||
mutex_unlock(&adap->lock);
|
mutex_unlock(&adap->lock);
|
||||||
|
call_void_op(adap, adap_configured, true);
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
unconfigure:
|
unconfigure:
|
||||||
for (i = 0; i < las->num_log_addrs; i++)
|
for (i = 0; i < las->num_log_addrs; i++)
|
||||||
las->log_addr[i] = CEC_LOG_ADDR_INVALID;
|
las->log_addr[i] = CEC_LOG_ADDR_INVALID;
|
||||||
cec_adap_unconfigure(adap);
|
cec_adap_unconfigure(adap);
|
||||||
|
adap->is_configuring = false;
|
||||||
|
adap->must_reconfigure = false;
|
||||||
adap->kthread_config = NULL;
|
adap->kthread_config = NULL;
|
||||||
mutex_unlock(&adap->lock);
|
|
||||||
complete(&adap->config_completion);
|
complete(&adap->config_completion);
|
||||||
|
mutex_unlock(&adap->lock);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1552,6 +1565,7 @@ static void cec_claim_log_addrs(struct cec_adapter *adap, bool block)
|
||||||
"ceccfg-%s", adap->name);
|
"ceccfg-%s", adap->name);
|
||||||
if (IS_ERR(adap->kthread_config)) {
|
if (IS_ERR(adap->kthread_config)) {
|
||||||
adap->kthread_config = NULL;
|
adap->kthread_config = NULL;
|
||||||
|
adap->is_configuring = false;
|
||||||
} else if (block) {
|
} else if (block) {
|
||||||
mutex_unlock(&adap->lock);
|
mutex_unlock(&adap->lock);
|
||||||
wait_for_completion(&adap->config_completion);
|
wait_for_completion(&adap->config_completion);
|
||||||
|
|
@ -1559,63 +1573,96 @@ static void cec_claim_log_addrs(struct cec_adapter *adap, bool block)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Helper function to enable/disable the CEC adapter.
|
||||||
|
*
|
||||||
|
* This function is called with adap->lock held.
|
||||||
|
*/
|
||||||
|
static int cec_adap_enable(struct cec_adapter *adap)
|
||||||
|
{
|
||||||
|
bool enable;
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
enable = adap->monitor_all_cnt || adap->monitor_pin_cnt ||
|
||||||
|
adap->log_addrs.num_log_addrs;
|
||||||
|
if (adap->needs_hpd)
|
||||||
|
enable = enable && adap->phys_addr != CEC_PHYS_ADDR_INVALID;
|
||||||
|
|
||||||
|
if (enable == adap->is_enabled)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/* serialize adap_enable */
|
||||||
|
mutex_lock(&adap->devnode.lock);
|
||||||
|
if (enable) {
|
||||||
|
adap->last_initiator = 0xff;
|
||||||
|
adap->transmit_in_progress = false;
|
||||||
|
ret = adap->ops->adap_enable(adap, true);
|
||||||
|
if (!ret) {
|
||||||
|
/*
|
||||||
|
* Enable monitor-all/pin modes if needed. We warn, but
|
||||||
|
* continue if this fails as this is not a critical error.
|
||||||
|
*/
|
||||||
|
if (adap->monitor_all_cnt)
|
||||||
|
WARN_ON(call_op(adap, adap_monitor_all_enable, true));
|
||||||
|
if (adap->monitor_pin_cnt)
|
||||||
|
WARN_ON(call_op(adap, adap_monitor_pin_enable, true));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
/* Disable monitor-all/pin modes if needed (needs_hpd == 1) */
|
||||||
|
if (adap->monitor_all_cnt)
|
||||||
|
WARN_ON(call_op(adap, adap_monitor_all_enable, false));
|
||||||
|
if (adap->monitor_pin_cnt)
|
||||||
|
WARN_ON(call_op(adap, adap_monitor_pin_enable, false));
|
||||||
|
WARN_ON(adap->ops->adap_enable(adap, false));
|
||||||
|
adap->last_initiator = 0xff;
|
||||||
|
adap->transmit_in_progress = false;
|
||||||
|
adap->transmit_in_progress_aborted = false;
|
||||||
|
if (adap->transmitting)
|
||||||
|
cec_data_cancel(adap->transmitting, CEC_TX_STATUS_ABORTED, 0);
|
||||||
|
}
|
||||||
|
if (!ret)
|
||||||
|
adap->is_enabled = enable;
|
||||||
|
wake_up_interruptible(&adap->kthread_waitq);
|
||||||
|
mutex_unlock(&adap->devnode.lock);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
/* Set a new physical address and send an event notifying userspace of this.
|
/* Set a new physical address and send an event notifying userspace of this.
|
||||||
*
|
*
|
||||||
* This function is called with adap->lock held.
|
* This function is called with adap->lock held.
|
||||||
*/
|
*/
|
||||||
void __cec_s_phys_addr(struct cec_adapter *adap, u16 phys_addr, bool block)
|
void __cec_s_phys_addr(struct cec_adapter *adap, u16 phys_addr, bool block)
|
||||||
{
|
{
|
||||||
|
bool becomes_invalid = phys_addr == CEC_PHYS_ADDR_INVALID;
|
||||||
|
bool is_invalid = adap->phys_addr == CEC_PHYS_ADDR_INVALID;
|
||||||
|
|
||||||
if (phys_addr == adap->phys_addr)
|
if (phys_addr == adap->phys_addr)
|
||||||
return;
|
return;
|
||||||
if (phys_addr != CEC_PHYS_ADDR_INVALID && adap->devnode.unregistered)
|
if (!becomes_invalid && adap->devnode.unregistered)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
dprintk(1, "new physical address %x.%x.%x.%x\n",
|
dprintk(1, "new physical address %x.%x.%x.%x\n",
|
||||||
cec_phys_addr_exp(phys_addr));
|
cec_phys_addr_exp(phys_addr));
|
||||||
if (phys_addr == CEC_PHYS_ADDR_INVALID ||
|
if (becomes_invalid || !is_invalid) {
|
||||||
adap->phys_addr != CEC_PHYS_ADDR_INVALID) {
|
|
||||||
adap->phys_addr = CEC_PHYS_ADDR_INVALID;
|
adap->phys_addr = CEC_PHYS_ADDR_INVALID;
|
||||||
cec_post_state_event(adap);
|
cec_post_state_event(adap);
|
||||||
cec_adap_unconfigure(adap);
|
cec_adap_unconfigure(adap);
|
||||||
/* Disabling monitor all mode should always succeed */
|
if (becomes_invalid) {
|
||||||
if (adap->monitor_all_cnt)
|
cec_adap_enable(adap);
|
||||||
WARN_ON(call_op(adap, adap_monitor_all_enable, false));
|
|
||||||
/* serialize adap_enable */
|
|
||||||
mutex_lock(&adap->devnode.lock);
|
|
||||||
if (adap->needs_hpd || list_empty(&adap->devnode.fhs)) {
|
|
||||||
WARN_ON(adap->ops->adap_enable(adap, false));
|
|
||||||
adap->transmit_in_progress = false;
|
|
||||||
wake_up_interruptible(&adap->kthread_waitq);
|
|
||||||
}
|
|
||||||
mutex_unlock(&adap->devnode.lock);
|
|
||||||
if (phys_addr == CEC_PHYS_ADDR_INVALID)
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* serialize adap_enable */
|
|
||||||
mutex_lock(&adap->devnode.lock);
|
|
||||||
adap->last_initiator = 0xff;
|
|
||||||
adap->transmit_in_progress = false;
|
|
||||||
|
|
||||||
if (adap->needs_hpd || list_empty(&adap->devnode.fhs)) {
|
|
||||||
if (adap->ops->adap_enable(adap, true)) {
|
|
||||||
mutex_unlock(&adap->devnode.lock);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (adap->monitor_all_cnt &&
|
|
||||||
call_op(adap, adap_monitor_all_enable, true)) {
|
|
||||||
if (adap->needs_hpd || list_empty(&adap->devnode.fhs))
|
|
||||||
WARN_ON(adap->ops->adap_enable(adap, false));
|
|
||||||
mutex_unlock(&adap->devnode.lock);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
mutex_unlock(&adap->devnode.lock);
|
|
||||||
|
|
||||||
adap->phys_addr = phys_addr;
|
adap->phys_addr = phys_addr;
|
||||||
|
if (is_invalid)
|
||||||
|
cec_adap_enable(adap);
|
||||||
|
|
||||||
cec_post_state_event(adap);
|
cec_post_state_event(adap);
|
||||||
if (adap->log_addrs.num_log_addrs)
|
if (!adap->log_addrs.num_log_addrs)
|
||||||
|
return;
|
||||||
|
if (adap->is_configuring)
|
||||||
|
adap->must_reconfigure = true;
|
||||||
|
else
|
||||||
cec_claim_log_addrs(adap, block);
|
cec_claim_log_addrs(adap, block);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1670,19 +1717,24 @@ int __cec_s_log_addrs(struct cec_adapter *adap,
|
||||||
struct cec_log_addrs *log_addrs, bool block)
|
struct cec_log_addrs *log_addrs, bool block)
|
||||||
{
|
{
|
||||||
u16 type_mask = 0;
|
u16 type_mask = 0;
|
||||||
|
int err;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
if (adap->devnode.unregistered)
|
if (adap->devnode.unregistered)
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
|
|
||||||
if (!log_addrs || log_addrs->num_log_addrs == 0) {
|
if (!log_addrs || log_addrs->num_log_addrs == 0) {
|
||||||
cec_adap_unconfigure(adap);
|
if (!adap->log_addrs.num_log_addrs)
|
||||||
|
return 0;
|
||||||
|
if (adap->is_configuring || adap->is_configured)
|
||||||
|
cec_adap_unconfigure(adap);
|
||||||
adap->log_addrs.num_log_addrs = 0;
|
adap->log_addrs.num_log_addrs = 0;
|
||||||
for (i = 0; i < CEC_MAX_LOG_ADDRS; i++)
|
for (i = 0; i < CEC_MAX_LOG_ADDRS; i++)
|
||||||
adap->log_addrs.log_addr[i] = CEC_LOG_ADDR_INVALID;
|
adap->log_addrs.log_addr[i] = CEC_LOG_ADDR_INVALID;
|
||||||
adap->log_addrs.osd_name[0] = '\0';
|
adap->log_addrs.osd_name[0] = '\0';
|
||||||
adap->log_addrs.vendor_id = CEC_VENDOR_ID_NONE;
|
adap->log_addrs.vendor_id = CEC_VENDOR_ID_NONE;
|
||||||
adap->log_addrs.cec_version = CEC_OP_CEC_VERSION_2_0;
|
adap->log_addrs.cec_version = CEC_OP_CEC_VERSION_2_0;
|
||||||
|
cec_adap_enable(adap);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1818,9 +1870,10 @@ int __cec_s_log_addrs(struct cec_adapter *adap,
|
||||||
|
|
||||||
log_addrs->log_addr_mask = adap->log_addrs.log_addr_mask;
|
log_addrs->log_addr_mask = adap->log_addrs.log_addr_mask;
|
||||||
adap->log_addrs = *log_addrs;
|
adap->log_addrs = *log_addrs;
|
||||||
if (adap->phys_addr != CEC_PHYS_ADDR_INVALID)
|
err = cec_adap_enable(adap);
|
||||||
|
if (!err && adap->phys_addr != CEC_PHYS_ADDR_INVALID)
|
||||||
cec_claim_log_addrs(adap, block);
|
cec_claim_log_addrs(adap, block);
|
||||||
return 0;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
int cec_s_log_addrs(struct cec_adapter *adap,
|
int cec_s_log_addrs(struct cec_adapter *adap,
|
||||||
|
|
@ -1922,11 +1975,10 @@ static int cec_receive_notify(struct cec_adapter *adap, struct cec_msg *msg,
|
||||||
msg->msg[1] != CEC_MSG_CDC_MESSAGE)
|
msg->msg[1] != CEC_MSG_CDC_MESSAGE)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (adap->ops->received) {
|
/* Allow drivers to process the message first */
|
||||||
/* Allow drivers to process the message first */
|
if (adap->ops->received && !adap->devnode.unregistered &&
|
||||||
if (adap->ops->received(adap, msg) != -ENOMSG)
|
adap->ops->received(adap, msg) != -ENOMSG)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* REPORT_PHYSICAL_ADDR, CEC_MSG_USER_CONTROL_PRESSED and
|
* REPORT_PHYSICAL_ADDR, CEC_MSG_USER_CONTROL_PRESSED and
|
||||||
|
|
@ -2119,20 +2171,25 @@ static int cec_receive_notify(struct cec_adapter *adap, struct cec_msg *msg,
|
||||||
*/
|
*/
|
||||||
int cec_monitor_all_cnt_inc(struct cec_adapter *adap)
|
int cec_monitor_all_cnt_inc(struct cec_adapter *adap)
|
||||||
{
|
{
|
||||||
int ret = 0;
|
int ret;
|
||||||
|
|
||||||
if (adap->monitor_all_cnt == 0)
|
if (adap->monitor_all_cnt++)
|
||||||
ret = call_op(adap, adap_monitor_all_enable, 1);
|
return 0;
|
||||||
if (ret == 0)
|
|
||||||
adap->monitor_all_cnt++;
|
ret = cec_adap_enable(adap);
|
||||||
|
if (ret)
|
||||||
|
adap->monitor_all_cnt--;
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
void cec_monitor_all_cnt_dec(struct cec_adapter *adap)
|
void cec_monitor_all_cnt_dec(struct cec_adapter *adap)
|
||||||
{
|
{
|
||||||
adap->monitor_all_cnt--;
|
if (WARN_ON(!adap->monitor_all_cnt))
|
||||||
if (adap->monitor_all_cnt == 0)
|
return;
|
||||||
WARN_ON(call_op(adap, adap_monitor_all_enable, 0));
|
if (--adap->monitor_all_cnt)
|
||||||
|
return;
|
||||||
|
WARN_ON(call_op(adap, adap_monitor_all_enable, false));
|
||||||
|
cec_adap_enable(adap);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
@ -2142,20 +2199,25 @@ void cec_monitor_all_cnt_dec(struct cec_adapter *adap)
|
||||||
*/
|
*/
|
||||||
int cec_monitor_pin_cnt_inc(struct cec_adapter *adap)
|
int cec_monitor_pin_cnt_inc(struct cec_adapter *adap)
|
||||||
{
|
{
|
||||||
int ret = 0;
|
int ret;
|
||||||
|
|
||||||
if (adap->monitor_pin_cnt == 0)
|
if (adap->monitor_pin_cnt++)
|
||||||
ret = call_op(adap, adap_monitor_pin_enable, 1);
|
return 0;
|
||||||
if (ret == 0)
|
|
||||||
adap->monitor_pin_cnt++;
|
ret = cec_adap_enable(adap);
|
||||||
|
if (ret)
|
||||||
|
adap->monitor_pin_cnt--;
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
void cec_monitor_pin_cnt_dec(struct cec_adapter *adap)
|
void cec_monitor_pin_cnt_dec(struct cec_adapter *adap)
|
||||||
{
|
{
|
||||||
adap->monitor_pin_cnt--;
|
if (WARN_ON(!adap->monitor_pin_cnt))
|
||||||
if (adap->monitor_pin_cnt == 0)
|
return;
|
||||||
WARN_ON(call_op(adap, adap_monitor_pin_enable, 0));
|
if (--adap->monitor_pin_cnt)
|
||||||
|
return;
|
||||||
|
WARN_ON(call_op(adap, adap_monitor_pin_enable, false));
|
||||||
|
cec_adap_enable(adap);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_DEBUG_FS
|
#ifdef CONFIG_DEBUG_FS
|
||||||
|
|
@ -2169,6 +2231,7 @@ int cec_adap_status(struct seq_file *file, void *priv)
|
||||||
struct cec_data *data;
|
struct cec_data *data;
|
||||||
|
|
||||||
mutex_lock(&adap->lock);
|
mutex_lock(&adap->lock);
|
||||||
|
seq_printf(file, "enabled: %d\n", adap->is_enabled);
|
||||||
seq_printf(file, "configured: %d\n", adap->is_configured);
|
seq_printf(file, "configured: %d\n", adap->is_configured);
|
||||||
seq_printf(file, "configuring: %d\n", adap->is_configuring);
|
seq_printf(file, "configuring: %d\n", adap->is_configuring);
|
||||||
seq_printf(file, "phys_addr: %x.%x.%x.%x\n",
|
seq_printf(file, "phys_addr: %x.%x.%x.%x\n",
|
||||||
|
|
@ -2183,6 +2246,9 @@ int cec_adap_status(struct seq_file *file, void *priv)
|
||||||
if (adap->monitor_all_cnt)
|
if (adap->monitor_all_cnt)
|
||||||
seq_printf(file, "file handles in Monitor All mode: %u\n",
|
seq_printf(file, "file handles in Monitor All mode: %u\n",
|
||||||
adap->monitor_all_cnt);
|
adap->monitor_all_cnt);
|
||||||
|
if (adap->monitor_pin_cnt)
|
||||||
|
seq_printf(file, "file handles in Monitor Pin mode: %u\n",
|
||||||
|
adap->monitor_pin_cnt);
|
||||||
if (adap->tx_timeouts) {
|
if (adap->tx_timeouts) {
|
||||||
seq_printf(file, "transmit timeouts: %u\n",
|
seq_printf(file, "transmit timeouts: %u\n",
|
||||||
adap->tx_timeouts);
|
adap->tx_timeouts);
|
||||||
|
|
|
||||||
|
|
@ -586,18 +586,6 @@ static int cec_open(struct inode *inode, struct file *filp)
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* serialize adap_enable */
|
|
||||||
mutex_lock(&devnode->lock);
|
|
||||||
if (list_empty(&devnode->fhs) &&
|
|
||||||
!adap->needs_hpd &&
|
|
||||||
adap->phys_addr == CEC_PHYS_ADDR_INVALID) {
|
|
||||||
err = adap->ops->adap_enable(adap, true);
|
|
||||||
if (err) {
|
|
||||||
mutex_unlock(&devnode->lock);
|
|
||||||
kfree(fh);
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
filp->private_data = fh;
|
filp->private_data = fh;
|
||||||
|
|
||||||
/* Queue up initial state events */
|
/* Queue up initial state events */
|
||||||
|
|
@ -607,7 +595,8 @@ static int cec_open(struct inode *inode, struct file *filp)
|
||||||
adap->conn_info.type != CEC_CONNECTOR_TYPE_NO_CONNECTOR;
|
adap->conn_info.type != CEC_CONNECTOR_TYPE_NO_CONNECTOR;
|
||||||
cec_queue_event_fh(fh, &ev, 0);
|
cec_queue_event_fh(fh, &ev, 0);
|
||||||
#ifdef CONFIG_CEC_PIN
|
#ifdef CONFIG_CEC_PIN
|
||||||
if (adap->pin && adap->pin->ops->read_hpd) {
|
if (adap->pin && adap->pin->ops->read_hpd &&
|
||||||
|
!adap->devnode.unregistered) {
|
||||||
err = adap->pin->ops->read_hpd(adap);
|
err = adap->pin->ops->read_hpd(adap);
|
||||||
if (err >= 0) {
|
if (err >= 0) {
|
||||||
ev.event = err ? CEC_EVENT_PIN_HPD_HIGH :
|
ev.event = err ? CEC_EVENT_PIN_HPD_HIGH :
|
||||||
|
|
@ -615,7 +604,8 @@ static int cec_open(struct inode *inode, struct file *filp)
|
||||||
cec_queue_event_fh(fh, &ev, 0);
|
cec_queue_event_fh(fh, &ev, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (adap->pin && adap->pin->ops->read_5v) {
|
if (adap->pin && adap->pin->ops->read_5v &&
|
||||||
|
!adap->devnode.unregistered) {
|
||||||
err = adap->pin->ops->read_5v(adap);
|
err = adap->pin->ops->read_5v(adap);
|
||||||
if (err >= 0) {
|
if (err >= 0) {
|
||||||
ev.event = err ? CEC_EVENT_PIN_5V_HIGH :
|
ev.event = err ? CEC_EVENT_PIN_5V_HIGH :
|
||||||
|
|
@ -625,6 +615,7 @@ static int cec_open(struct inode *inode, struct file *filp)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
mutex_lock(&devnode->lock);
|
||||||
mutex_lock(&devnode->lock_fhs);
|
mutex_lock(&devnode->lock_fhs);
|
||||||
list_add(&fh->list, &devnode->fhs);
|
list_add(&fh->list, &devnode->fhs);
|
||||||
mutex_unlock(&devnode->lock_fhs);
|
mutex_unlock(&devnode->lock_fhs);
|
||||||
|
|
@ -656,15 +647,10 @@ static int cec_release(struct inode *inode, struct file *filp)
|
||||||
cec_monitor_all_cnt_dec(adap);
|
cec_monitor_all_cnt_dec(adap);
|
||||||
mutex_unlock(&adap->lock);
|
mutex_unlock(&adap->lock);
|
||||||
|
|
||||||
/* serialize adap_enable */
|
|
||||||
mutex_lock(&devnode->lock);
|
mutex_lock(&devnode->lock);
|
||||||
mutex_lock(&devnode->lock_fhs);
|
mutex_lock(&devnode->lock_fhs);
|
||||||
list_del(&fh->list);
|
list_del(&fh->list);
|
||||||
mutex_unlock(&devnode->lock_fhs);
|
mutex_unlock(&devnode->lock_fhs);
|
||||||
if (cec_is_registered(adap) && list_empty(&devnode->fhs) &&
|
|
||||||
!adap->needs_hpd && adap->phys_addr == CEC_PHYS_ADDR_INVALID) {
|
|
||||||
WARN_ON(adap->ops->adap_enable(adap, false));
|
|
||||||
}
|
|
||||||
mutex_unlock(&devnode->lock);
|
mutex_unlock(&devnode->lock);
|
||||||
|
|
||||||
/* Unhook pending transmits from this filehandle. */
|
/* Unhook pending transmits from this filehandle. */
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,18 @@
|
||||||
#define CEC_NUM_DEVICES 256
|
#define CEC_NUM_DEVICES 256
|
||||||
#define CEC_NAME "cec"
|
#define CEC_NAME "cec"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 400 ms is the time it takes for one 16 byte message to be
|
||||||
|
* transferred and 5 is the maximum number of retries. Add
|
||||||
|
* another 100 ms as a margin. So if the transmit doesn't
|
||||||
|
* finish before that time something is really wrong and we
|
||||||
|
* have to time out.
|
||||||
|
*
|
||||||
|
* This is a sign that something it really wrong and a warning
|
||||||
|
* will be issued.
|
||||||
|
*/
|
||||||
|
#define CEC_XFER_TIMEOUT_MS (5 * 400 + 100)
|
||||||
|
|
||||||
int cec_debug;
|
int cec_debug;
|
||||||
module_param_named(debug, cec_debug, int, 0644);
|
module_param_named(debug, cec_debug, int, 0644);
|
||||||
MODULE_PARM_DESC(debug, "debug level (0-2)");
|
MODULE_PARM_DESC(debug, "debug level (0-2)");
|
||||||
|
|
@ -204,7 +216,7 @@ static ssize_t cec_error_inj_write(struct file *file,
|
||||||
line = strsep(&p, "\n");
|
line = strsep(&p, "\n");
|
||||||
if (!*line || *line == '#')
|
if (!*line || *line == '#')
|
||||||
continue;
|
continue;
|
||||||
if (!adap->ops->error_inj_parse_line(adap, line)) {
|
if (!call_op(adap, error_inj_parse_line, line)) {
|
||||||
kfree(buf);
|
kfree(buf);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
@ -217,7 +229,7 @@ static int cec_error_inj_show(struct seq_file *sf, void *unused)
|
||||||
{
|
{
|
||||||
struct cec_adapter *adap = sf->private;
|
struct cec_adapter *adap = sf->private;
|
||||||
|
|
||||||
return adap->ops->error_inj_show(adap, sf);
|
return call_op(adap, error_inj_show, sf);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int cec_error_inj_open(struct inode *inode, struct file *file)
|
static int cec_error_inj_open(struct inode *inode, struct file *file)
|
||||||
|
|
@ -331,6 +343,8 @@ int cec_register_adapter(struct cec_adapter *adap,
|
||||||
|
|
||||||
adap->owner = parent->driver->owner;
|
adap->owner = parent->driver->owner;
|
||||||
adap->devnode.dev.parent = parent;
|
adap->devnode.dev.parent = parent;
|
||||||
|
if (!adap->xfer_timeout_ms)
|
||||||
|
adap->xfer_timeout_ms = CEC_XFER_TIMEOUT_MS;
|
||||||
|
|
||||||
#ifdef CONFIG_MEDIA_CEC_RC
|
#ifdef CONFIG_MEDIA_CEC_RC
|
||||||
if (adap->capabilities & CEC_CAP_RC) {
|
if (adap->capabilities & CEC_CAP_RC) {
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,17 @@
|
||||||
#include <linux/atomic.h>
|
#include <linux/atomic.h>
|
||||||
#include <media/cec-pin.h>
|
#include <media/cec-pin.h>
|
||||||
|
|
||||||
|
#define call_pin_op(pin, op, arg...) \
|
||||||
|
((pin && pin->ops->op && !pin->adap->devnode.unregistered) ? \
|
||||||
|
pin->ops->op(pin->adap, ## arg) : 0)
|
||||||
|
|
||||||
|
#define call_void_pin_op(pin, op, arg...) \
|
||||||
|
do { \
|
||||||
|
if (pin && pin->ops->op && \
|
||||||
|
!pin->adap->devnode.unregistered) \
|
||||||
|
pin->ops->op(pin->adap, ## arg); \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
enum cec_pin_state {
|
enum cec_pin_state {
|
||||||
/* CEC is off */
|
/* CEC is off */
|
||||||
CEC_ST_OFF,
|
CEC_ST_OFF,
|
||||||
|
|
|
||||||
|
|
@ -135,7 +135,7 @@ static void cec_pin_update(struct cec_pin *pin, bool v, bool force)
|
||||||
|
|
||||||
static bool cec_pin_read(struct cec_pin *pin)
|
static bool cec_pin_read(struct cec_pin *pin)
|
||||||
{
|
{
|
||||||
bool v = pin->ops->read(pin->adap);
|
bool v = call_pin_op(pin, read);
|
||||||
|
|
||||||
cec_pin_update(pin, v, false);
|
cec_pin_update(pin, v, false);
|
||||||
return v;
|
return v;
|
||||||
|
|
@ -143,13 +143,13 @@ static bool cec_pin_read(struct cec_pin *pin)
|
||||||
|
|
||||||
static void cec_pin_low(struct cec_pin *pin)
|
static void cec_pin_low(struct cec_pin *pin)
|
||||||
{
|
{
|
||||||
pin->ops->low(pin->adap);
|
call_void_pin_op(pin, low);
|
||||||
cec_pin_update(pin, false, false);
|
cec_pin_update(pin, false, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool cec_pin_high(struct cec_pin *pin)
|
static bool cec_pin_high(struct cec_pin *pin)
|
||||||
{
|
{
|
||||||
pin->ops->high(pin->adap);
|
call_void_pin_op(pin, high);
|
||||||
return cec_pin_read(pin);
|
return cec_pin_read(pin);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1037,11 +1037,14 @@ static int cec_pin_thread_func(void *_adap)
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
wait_event_interruptible(pin->kthread_waitq,
|
wait_event_interruptible(pin->kthread_waitq,
|
||||||
kthread_should_stop() ||
|
kthread_should_stop() ||
|
||||||
pin->work_rx_msg.len ||
|
pin->work_rx_msg.len ||
|
||||||
pin->work_tx_status ||
|
pin->work_tx_status ||
|
||||||
atomic_read(&pin->work_irq_change) ||
|
atomic_read(&pin->work_irq_change) ||
|
||||||
atomic_read(&pin->work_pin_num_events));
|
atomic_read(&pin->work_pin_num_events));
|
||||||
|
|
||||||
|
if (kthread_should_stop())
|
||||||
|
break;
|
||||||
|
|
||||||
if (pin->work_rx_msg.len) {
|
if (pin->work_rx_msg.len) {
|
||||||
struct cec_msg *msg = &pin->work_rx_msg;
|
struct cec_msg *msg = &pin->work_rx_msg;
|
||||||
|
|
@ -1086,10 +1089,12 @@ static int cec_pin_thread_func(void *_adap)
|
||||||
CEC_PIN_IRQ_UNCHANGED)) {
|
CEC_PIN_IRQ_UNCHANGED)) {
|
||||||
case CEC_PIN_IRQ_DISABLE:
|
case CEC_PIN_IRQ_DISABLE:
|
||||||
if (irq_enabled) {
|
if (irq_enabled) {
|
||||||
pin->ops->disable_irq(adap);
|
call_void_pin_op(pin, disable_irq);
|
||||||
irq_enabled = false;
|
irq_enabled = false;
|
||||||
}
|
}
|
||||||
cec_pin_high(pin);
|
cec_pin_high(pin);
|
||||||
|
if (pin->state == CEC_ST_OFF)
|
||||||
|
break;
|
||||||
cec_pin_to_idle(pin);
|
cec_pin_to_idle(pin);
|
||||||
hrtimer_start(&pin->timer, ns_to_ktime(0),
|
hrtimer_start(&pin->timer, ns_to_ktime(0),
|
||||||
HRTIMER_MODE_REL);
|
HRTIMER_MODE_REL);
|
||||||
|
|
@ -1097,7 +1102,7 @@ static int cec_pin_thread_func(void *_adap)
|
||||||
case CEC_PIN_IRQ_ENABLE:
|
case CEC_PIN_IRQ_ENABLE:
|
||||||
if (irq_enabled)
|
if (irq_enabled)
|
||||||
break;
|
break;
|
||||||
pin->enable_irq_failed = !pin->ops->enable_irq(adap);
|
pin->enable_irq_failed = !call_pin_op(pin, enable_irq);
|
||||||
if (pin->enable_irq_failed) {
|
if (pin->enable_irq_failed) {
|
||||||
cec_pin_to_idle(pin);
|
cec_pin_to_idle(pin);
|
||||||
hrtimer_start(&pin->timer, ns_to_ktime(0),
|
hrtimer_start(&pin->timer, ns_to_ktime(0),
|
||||||
|
|
@ -1109,15 +1114,7 @@ static int cec_pin_thread_func(void *_adap)
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (kthread_should_stop())
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
if (pin->ops->disable_irq && irq_enabled)
|
|
||||||
pin->ops->disable_irq(adap);
|
|
||||||
hrtimer_cancel(&pin->timer);
|
|
||||||
cec_pin_read(pin);
|
|
||||||
cec_pin_to_idle(pin);
|
|
||||||
pin->state = CEC_ST_OFF;
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1126,24 +1123,32 @@ static int cec_pin_adap_enable(struct cec_adapter *adap, bool enable)
|
||||||
struct cec_pin *pin = adap->pin;
|
struct cec_pin *pin = adap->pin;
|
||||||
|
|
||||||
if (enable) {
|
if (enable) {
|
||||||
atomic_set(&pin->work_pin_num_events, 0);
|
|
||||||
pin->work_pin_events_rd = pin->work_pin_events_wr = 0;
|
|
||||||
pin->work_pin_events_dropped = false;
|
|
||||||
cec_pin_read(pin);
|
cec_pin_read(pin);
|
||||||
cec_pin_to_idle(pin);
|
cec_pin_to_idle(pin);
|
||||||
pin->tx_msg.len = 0;
|
pin->tx_msg.len = 0;
|
||||||
pin->timer_ts = ns_to_ktime(0);
|
pin->timer_ts = ns_to_ktime(0);
|
||||||
atomic_set(&pin->work_irq_change, CEC_PIN_IRQ_UNCHANGED);
|
atomic_set(&pin->work_irq_change, CEC_PIN_IRQ_UNCHANGED);
|
||||||
pin->kthread = kthread_run(cec_pin_thread_func, adap,
|
if (!pin->kthread) {
|
||||||
"cec-pin");
|
pin->kthread = kthread_run(cec_pin_thread_func, adap,
|
||||||
if (IS_ERR(pin->kthread)) {
|
"cec-pin");
|
||||||
pr_err("cec-pin: kernel_thread() failed\n");
|
if (IS_ERR(pin->kthread)) {
|
||||||
return PTR_ERR(pin->kthread);
|
int err = PTR_ERR(pin->kthread);
|
||||||
|
|
||||||
|
pr_err("cec-pin: kernel_thread() failed\n");
|
||||||
|
pin->kthread = NULL;
|
||||||
|
return err;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
hrtimer_start(&pin->timer, ns_to_ktime(0),
|
hrtimer_start(&pin->timer, ns_to_ktime(0),
|
||||||
HRTIMER_MODE_REL);
|
HRTIMER_MODE_REL);
|
||||||
} else {
|
} else if (pin->kthread) {
|
||||||
kthread_stop(pin->kthread);
|
hrtimer_cancel(&pin->timer);
|
||||||
|
cec_pin_high(pin);
|
||||||
|
cec_pin_to_idle(pin);
|
||||||
|
pin->state = CEC_ST_OFF;
|
||||||
|
pin->work_tx_status = 0;
|
||||||
|
atomic_set(&pin->work_irq_change, CEC_PIN_IRQ_DISABLE);
|
||||||
|
wake_up_interruptible(&pin->kthread_waitq);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
@ -1207,7 +1212,7 @@ static void cec_pin_adap_status(struct cec_adapter *adap,
|
||||||
seq_printf(file, "state: %s\n", states[pin->state].name);
|
seq_printf(file, "state: %s\n", states[pin->state].name);
|
||||||
seq_printf(file, "tx_bit: %d\n", pin->tx_bit);
|
seq_printf(file, "tx_bit: %d\n", pin->tx_bit);
|
||||||
seq_printf(file, "rx_bit: %d\n", pin->rx_bit);
|
seq_printf(file, "rx_bit: %d\n", pin->rx_bit);
|
||||||
seq_printf(file, "cec pin: %d\n", pin->ops->read(adap));
|
seq_printf(file, "cec pin: %d\n", call_pin_op(pin, read));
|
||||||
seq_printf(file, "cec pin events dropped: %u\n",
|
seq_printf(file, "cec pin events dropped: %u\n",
|
||||||
pin->work_pin_events_dropped_cnt);
|
pin->work_pin_events_dropped_cnt);
|
||||||
seq_printf(file, "irq failed: %d\n", pin->enable_irq_failed);
|
seq_printf(file, "irq failed: %d\n", pin->enable_irq_failed);
|
||||||
|
|
@ -1260,8 +1265,7 @@ static void cec_pin_adap_status(struct cec_adapter *adap,
|
||||||
pin->rx_data_bit_too_long_cnt = 0;
|
pin->rx_data_bit_too_long_cnt = 0;
|
||||||
pin->rx_low_drive_cnt = 0;
|
pin->rx_low_drive_cnt = 0;
|
||||||
pin->tx_low_drive_cnt = 0;
|
pin->tx_low_drive_cnt = 0;
|
||||||
if (pin->ops->status)
|
call_void_pin_op(pin, status, file);
|
||||||
pin->ops->status(adap, file);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int cec_pin_adap_monitor_all_enable(struct cec_adapter *adap,
|
static int cec_pin_adap_monitor_all_enable(struct cec_adapter *adap,
|
||||||
|
|
@ -1277,6 +1281,9 @@ static void cec_pin_adap_free(struct cec_adapter *adap)
|
||||||
{
|
{
|
||||||
struct cec_pin *pin = adap->pin;
|
struct cec_pin *pin = adap->pin;
|
||||||
|
|
||||||
|
if (pin->kthread)
|
||||||
|
kthread_stop(pin->kthread);
|
||||||
|
pin->kthread = NULL;
|
||||||
if (pin->ops->free)
|
if (pin->ops->free)
|
||||||
pin->ops->free(adap);
|
pin->ops->free(adap);
|
||||||
adap->pin = NULL;
|
adap->pin = NULL;
|
||||||
|
|
@ -1287,7 +1294,7 @@ static int cec_pin_received(struct cec_adapter *adap, struct cec_msg *msg)
|
||||||
{
|
{
|
||||||
struct cec_pin *pin = adap->pin;
|
struct cec_pin *pin = adap->pin;
|
||||||
|
|
||||||
if (pin->ops->received)
|
if (pin->ops->received && !adap->devnode.unregistered)
|
||||||
return pin->ops->received(adap, msg);
|
return pin->ops->received(adap, msg);
|
||||||
return -ENOMSG;
|
return -ENOMSG;
|
||||||
}
|
}
|
||||||
|
|
@ -1327,6 +1334,7 @@ struct cec_adapter *cec_pin_allocate_adapter(const struct cec_pin_ops *pin_ops,
|
||||||
return ERR_PTR(-ENOMEM);
|
return ERR_PTR(-ENOMEM);
|
||||||
pin->ops = pin_ops;
|
pin->ops = pin_ops;
|
||||||
hrtimer_init(&pin->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
|
hrtimer_init(&pin->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
|
||||||
|
atomic_set(&pin->work_pin_num_events, 0);
|
||||||
pin->timer.function = cec_pin_timer;
|
pin->timer.function = cec_pin_timer;
|
||||||
init_waitqueue_head(&pin->kthread_waitq);
|
init_waitqueue_head(&pin->kthread_waitq);
|
||||||
pin->tx_custom_low_usecs = CEC_TIM_CUSTOM_DEFAULT;
|
pin->tx_custom_low_usecs = CEC_TIM_CUSTOM_DEFAULT;
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,16 @@
|
||||||
pr_info("cec-%s: " fmt, adap->name, ## arg); \
|
pr_info("cec-%s: " fmt, adap->name, ## arg); \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
|
#define call_op(adap, op, arg...) \
|
||||||
|
((adap->ops->op && !adap->devnode.unregistered) ? \
|
||||||
|
adap->ops->op(adap, ## arg) : 0)
|
||||||
|
|
||||||
|
#define call_void_op(adap, op, arg...) \
|
||||||
|
do { \
|
||||||
|
if (adap->ops->op && !adap->devnode.unregistered) \
|
||||||
|
adap->ops->op(adap, ## arg); \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
/* devnode to cec_adapter */
|
/* devnode to cec_adapter */
|
||||||
#define to_cec_adapter(node) container_of(node, struct cec_adapter, devnode)
|
#define to_cec_adapter(node) container_of(node, struct cec_adapter, devnode)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -31,29 +31,17 @@ struct secocec_data {
|
||||||
int irq;
|
int irq;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define smb_wr16(cmd, data) smb_word_op(CMD_WORD_DATA, SECOCEC_MICRO_ADDRESS, \
|
#define smb_wr16(cmd, data) smb_word_op(SECOCEC_MICRO_ADDRESS, \
|
||||||
cmd, data, SMBUS_WRITE, NULL)
|
cmd, data, SMBUS_WRITE, NULL)
|
||||||
#define smb_rd16(cmd, res) smb_word_op(CMD_WORD_DATA, SECOCEC_MICRO_ADDRESS, \
|
#define smb_rd16(cmd, res) smb_word_op(SECOCEC_MICRO_ADDRESS, \
|
||||||
cmd, 0, SMBUS_READ, res)
|
cmd, 0, SMBUS_READ, res)
|
||||||
|
|
||||||
static int smb_word_op(short data_format, u16 slave_addr, u8 cmd, u16 data,
|
static int smb_word_op(u16 slave_addr, u8 cmd, u16 data,
|
||||||
u8 operation, u16 *result)
|
u8 operation, u16 *result)
|
||||||
{
|
{
|
||||||
unsigned int count;
|
unsigned int count;
|
||||||
short _data_format;
|
|
||||||
int status = 0;
|
int status = 0;
|
||||||
|
|
||||||
switch (data_format) {
|
|
||||||
case CMD_BYTE_DATA:
|
|
||||||
_data_format = BRA_SMB_CMD_BYTE_DATA;
|
|
||||||
break;
|
|
||||||
case CMD_WORD_DATA:
|
|
||||||
_data_format = BRA_SMB_CMD_WORD_DATA;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Active wait until ready */
|
/* Active wait until ready */
|
||||||
for (count = 0; count <= SMBTIMEOUT; ++count) {
|
for (count = 0; count <= SMBTIMEOUT; ++count) {
|
||||||
if (!(inb(HSTS) & BRA_INUSE_STS))
|
if (!(inb(HSTS) & BRA_INUSE_STS))
|
||||||
|
|
@ -75,7 +63,7 @@ static int smb_word_op(short data_format, u16 slave_addr, u8 cmd, u16 data,
|
||||||
outb((u8)(data >> 8), HDAT1);
|
outb((u8)(data >> 8), HDAT1);
|
||||||
}
|
}
|
||||||
|
|
||||||
outb(BRA_START + _data_format, HCNT);
|
outb(BRA_START + BRA_SMB_CMD_WORD_DATA, HCNT);
|
||||||
|
|
||||||
for (count = 0; count <= SMBTIMEOUT; count++) {
|
for (count = 0; count <= SMBTIMEOUT; count++) {
|
||||||
if (!(inb(HSTS) & BRA_HOST_BUSY))
|
if (!(inb(HSTS) & BRA_HOST_BUSY))
|
||||||
|
|
|
||||||
|
|
@ -443,7 +443,6 @@ static int vidioc_querycap(struct file *file, void *fh, struct v4l2_capability *
|
||||||
|
|
||||||
strscpy((char *)cap->driver, "saa7146 v4l2", sizeof(cap->driver));
|
strscpy((char *)cap->driver, "saa7146 v4l2", sizeof(cap->driver));
|
||||||
strscpy((char *)cap->card, dev->ext->name, sizeof(cap->card));
|
strscpy((char *)cap->card, dev->ext->name, sizeof(cap->card));
|
||||||
sprintf((char *)cap->bus_info, "PCI:%s", pci_name(dev->pci));
|
|
||||||
cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_VIDEO_OVERLAY |
|
cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_VIDEO_OVERLAY |
|
||||||
V4L2_CAP_READWRITE | V4L2_CAP_STREAMING |
|
V4L2_CAP_READWRITE | V4L2_CAP_STREAMING |
|
||||||
V4L2_CAP_DEVICE_CAPS;
|
V4L2_CAP_DEVICE_CAPS;
|
||||||
|
|
|
||||||
|
|
@ -126,8 +126,7 @@ static void *vb2_dma_sg_alloc(struct vb2_buffer *vb, struct device *dev,
|
||||||
* there is no memory consistency guarantee, hence dma-sg ignores DMA
|
* there is no memory consistency guarantee, hence dma-sg ignores DMA
|
||||||
* attributes passed from the upper layer.
|
* attributes passed from the upper layer.
|
||||||
*/
|
*/
|
||||||
buf->pages = kvmalloc_array(buf->num_pages, sizeof(struct page *),
|
buf->pages = kvcalloc(buf->num_pages, sizeof(struct page *), GFP_KERNEL);
|
||||||
GFP_KERNEL | __GFP_ZERO);
|
|
||||||
if (!buf->pages)
|
if (!buf->pages)
|
||||||
goto fail_pages_array_alloc;
|
goto fail_pages_array_alloc;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -977,12 +977,6 @@ EXPORT_SYMBOL_GPL(vb2_poll);
|
||||||
* and so they simplify the driver code.
|
* and so they simplify the driver code.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* The queue is busy if there is a owner and you are not that owner. */
|
|
||||||
static inline bool vb2_queue_is_busy(struct video_device *vdev, struct file *file)
|
|
||||||
{
|
|
||||||
return vdev->queue->owner && vdev->queue->owner != file->private_data;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* vb2 ioctl helpers */
|
/* vb2 ioctl helpers */
|
||||||
|
|
||||||
int vb2_ioctl_reqbufs(struct file *file, void *priv,
|
int vb2_ioctl_reqbufs(struct file *file, void *priv,
|
||||||
|
|
@ -997,7 +991,7 @@ int vb2_ioctl_reqbufs(struct file *file, void *priv,
|
||||||
p->flags = flags;
|
p->flags = flags;
|
||||||
if (res)
|
if (res)
|
||||||
return res;
|
return res;
|
||||||
if (vb2_queue_is_busy(vdev, file))
|
if (vb2_queue_is_busy(vdev->queue, file))
|
||||||
return -EBUSY;
|
return -EBUSY;
|
||||||
res = vb2_core_reqbufs(vdev->queue, p->memory, p->flags, &p->count);
|
res = vb2_core_reqbufs(vdev->queue, p->memory, p->flags, &p->count);
|
||||||
/* If count == 0, then the owner has released all buffers and he
|
/* If count == 0, then the owner has released all buffers and he
|
||||||
|
|
@ -1026,7 +1020,7 @@ int vb2_ioctl_create_bufs(struct file *file, void *priv,
|
||||||
return res != -EBUSY ? res : 0;
|
return res != -EBUSY ? res : 0;
|
||||||
if (res)
|
if (res)
|
||||||
return res;
|
return res;
|
||||||
if (vb2_queue_is_busy(vdev, file))
|
if (vb2_queue_is_busy(vdev->queue, file))
|
||||||
return -EBUSY;
|
return -EBUSY;
|
||||||
|
|
||||||
res = vb2_create_bufs(vdev->queue, p);
|
res = vb2_create_bufs(vdev->queue, p);
|
||||||
|
|
@ -1041,7 +1035,7 @@ int vb2_ioctl_prepare_buf(struct file *file, void *priv,
|
||||||
{
|
{
|
||||||
struct video_device *vdev = video_devdata(file);
|
struct video_device *vdev = video_devdata(file);
|
||||||
|
|
||||||
if (vb2_queue_is_busy(vdev, file))
|
if (vb2_queue_is_busy(vdev->queue, file))
|
||||||
return -EBUSY;
|
return -EBUSY;
|
||||||
return vb2_prepare_buf(vdev->queue, vdev->v4l2_dev->mdev, p);
|
return vb2_prepare_buf(vdev->queue, vdev->v4l2_dev->mdev, p);
|
||||||
}
|
}
|
||||||
|
|
@ -1060,7 +1054,7 @@ int vb2_ioctl_qbuf(struct file *file, void *priv, struct v4l2_buffer *p)
|
||||||
{
|
{
|
||||||
struct video_device *vdev = video_devdata(file);
|
struct video_device *vdev = video_devdata(file);
|
||||||
|
|
||||||
if (vb2_queue_is_busy(vdev, file))
|
if (vb2_queue_is_busy(vdev->queue, file))
|
||||||
return -EBUSY;
|
return -EBUSY;
|
||||||
return vb2_qbuf(vdev->queue, vdev->v4l2_dev->mdev, p);
|
return vb2_qbuf(vdev->queue, vdev->v4l2_dev->mdev, p);
|
||||||
}
|
}
|
||||||
|
|
@ -1070,7 +1064,7 @@ int vb2_ioctl_dqbuf(struct file *file, void *priv, struct v4l2_buffer *p)
|
||||||
{
|
{
|
||||||
struct video_device *vdev = video_devdata(file);
|
struct video_device *vdev = video_devdata(file);
|
||||||
|
|
||||||
if (vb2_queue_is_busy(vdev, file))
|
if (vb2_queue_is_busy(vdev->queue, file))
|
||||||
return -EBUSY;
|
return -EBUSY;
|
||||||
return vb2_dqbuf(vdev->queue, p, file->f_flags & O_NONBLOCK);
|
return vb2_dqbuf(vdev->queue, p, file->f_flags & O_NONBLOCK);
|
||||||
}
|
}
|
||||||
|
|
@ -1080,7 +1074,7 @@ int vb2_ioctl_streamon(struct file *file, void *priv, enum v4l2_buf_type i)
|
||||||
{
|
{
|
||||||
struct video_device *vdev = video_devdata(file);
|
struct video_device *vdev = video_devdata(file);
|
||||||
|
|
||||||
if (vb2_queue_is_busy(vdev, file))
|
if (vb2_queue_is_busy(vdev->queue, file))
|
||||||
return -EBUSY;
|
return -EBUSY;
|
||||||
return vb2_streamon(vdev->queue, i);
|
return vb2_streamon(vdev->queue, i);
|
||||||
}
|
}
|
||||||
|
|
@ -1090,7 +1084,7 @@ int vb2_ioctl_streamoff(struct file *file, void *priv, enum v4l2_buf_type i)
|
||||||
{
|
{
|
||||||
struct video_device *vdev = video_devdata(file);
|
struct video_device *vdev = video_devdata(file);
|
||||||
|
|
||||||
if (vb2_queue_is_busy(vdev, file))
|
if (vb2_queue_is_busy(vdev->queue, file))
|
||||||
return -EBUSY;
|
return -EBUSY;
|
||||||
return vb2_streamoff(vdev->queue, i);
|
return vb2_streamoff(vdev->queue, i);
|
||||||
}
|
}
|
||||||
|
|
@ -1100,7 +1094,7 @@ int vb2_ioctl_expbuf(struct file *file, void *priv, struct v4l2_exportbuffer *p)
|
||||||
{
|
{
|
||||||
struct video_device *vdev = video_devdata(file);
|
struct video_device *vdev = video_devdata(file);
|
||||||
|
|
||||||
if (vb2_queue_is_busy(vdev, file))
|
if (vb2_queue_is_busy(vdev->queue, file))
|
||||||
return -EBUSY;
|
return -EBUSY;
|
||||||
return vb2_expbuf(vdev->queue, p);
|
return vb2_expbuf(vdev->queue, p);
|
||||||
}
|
}
|
||||||
|
|
@ -1152,7 +1146,7 @@ ssize_t vb2_fop_write(struct file *file, const char __user *buf,
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
if (lock && mutex_lock_interruptible(lock))
|
if (lock && mutex_lock_interruptible(lock))
|
||||||
return -ERESTARTSYS;
|
return -ERESTARTSYS;
|
||||||
if (vb2_queue_is_busy(vdev, file))
|
if (vb2_queue_is_busy(vdev->queue, file))
|
||||||
goto exit;
|
goto exit;
|
||||||
err = vb2_write(vdev->queue, buf, count, ppos,
|
err = vb2_write(vdev->queue, buf, count, ppos,
|
||||||
file->f_flags & O_NONBLOCK);
|
file->f_flags & O_NONBLOCK);
|
||||||
|
|
@ -1176,7 +1170,7 @@ ssize_t vb2_fop_read(struct file *file, char __user *buf,
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
if (lock && mutex_lock_interruptible(lock))
|
if (lock && mutex_lock_interruptible(lock))
|
||||||
return -ERESTARTSYS;
|
return -ERESTARTSYS;
|
||||||
if (vb2_queue_is_busy(vdev, file))
|
if (vb2_queue_is_busy(vdev->queue, file))
|
||||||
goto exit;
|
goto exit;
|
||||||
err = vb2_read(vdev->queue, buf, count, ppos,
|
err = vb2_read(vdev->queue, buf, count, ppos,
|
||||||
file->f_flags & O_NONBLOCK);
|
file->f_flags & O_NONBLOCK);
|
||||||
|
|
|
||||||
|
|
@ -372,6 +372,7 @@ config VIDEO_OV13B10
|
||||||
config VIDEO_OV2640
|
config VIDEO_OV2640
|
||||||
tristate "OmniVision OV2640 sensor support"
|
tristate "OmniVision OV2640 sensor support"
|
||||||
depends on VIDEO_DEV && I2C
|
depends on VIDEO_DEV && I2C
|
||||||
|
select V4L2_ASYNC
|
||||||
help
|
help
|
||||||
This is a Video4Linux2 sensor driver for the OmniVision
|
This is a Video4Linux2 sensor driver for the OmniVision
|
||||||
OV2640 camera.
|
OV2640 camera.
|
||||||
|
|
|
||||||
|
|
@ -66,6 +66,9 @@
|
||||||
#define ADV7180_HUE_DEF 0
|
#define ADV7180_HUE_DEF 0
|
||||||
#define ADV7180_HUE_MAX 128
|
#define ADV7180_HUE_MAX 128
|
||||||
|
|
||||||
|
#define ADV7180_REG_DEF_VALUE_Y 0x000c
|
||||||
|
#define ADV7180_DEF_VAL_EN 0x1
|
||||||
|
#define ADV7180_DEF_VAL_AUTO_EN 0x2
|
||||||
#define ADV7180_REG_CTRL 0x000e
|
#define ADV7180_REG_CTRL 0x000e
|
||||||
#define ADV7180_CTRL_IRQ_SPACE 0x20
|
#define ADV7180_CTRL_IRQ_SPACE 0x20
|
||||||
|
|
||||||
|
|
@ -549,6 +552,40 @@ static int adv7180_s_power(struct v4l2_subdev *sd, int on)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static const char * const test_pattern_menu[] = {
|
||||||
|
"Single color",
|
||||||
|
"Color bars",
|
||||||
|
"Luma ramp",
|
||||||
|
"Boundary box",
|
||||||
|
"Disable",
|
||||||
|
};
|
||||||
|
|
||||||
|
static int adv7180_test_pattern(struct adv7180_state *state, int value)
|
||||||
|
{
|
||||||
|
unsigned int reg = 0;
|
||||||
|
|
||||||
|
/* Map menu value into register value */
|
||||||
|
if (value < 3)
|
||||||
|
reg = value;
|
||||||
|
if (value == 3)
|
||||||
|
reg = 5;
|
||||||
|
|
||||||
|
adv7180_write(state, ADV7180_REG_ANALOG_CLAMP_CTL, reg);
|
||||||
|
|
||||||
|
if (value == ARRAY_SIZE(test_pattern_menu) - 1) {
|
||||||
|
reg = adv7180_read(state, ADV7180_REG_DEF_VALUE_Y);
|
||||||
|
reg &= ~ADV7180_DEF_VAL_EN;
|
||||||
|
adv7180_write(state, ADV7180_REG_DEF_VALUE_Y, reg);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
reg = adv7180_read(state, ADV7180_REG_DEF_VALUE_Y);
|
||||||
|
reg |= ADV7180_DEF_VAL_EN | ADV7180_DEF_VAL_AUTO_EN;
|
||||||
|
adv7180_write(state, ADV7180_REG_DEF_VALUE_Y, reg);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int adv7180_s_ctrl(struct v4l2_ctrl *ctrl)
|
static int adv7180_s_ctrl(struct v4l2_ctrl *ctrl)
|
||||||
{
|
{
|
||||||
struct v4l2_subdev *sd = to_adv7180_sd(ctrl);
|
struct v4l2_subdev *sd = to_adv7180_sd(ctrl);
|
||||||
|
|
@ -592,6 +629,9 @@ static int adv7180_s_ctrl(struct v4l2_ctrl *ctrl)
|
||||||
adv7180_write(state, ADV7180_REG_FLCONTROL, 0x00);
|
adv7180_write(state, ADV7180_REG_FLCONTROL, 0x00);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case V4L2_CID_TEST_PATTERN:
|
||||||
|
ret = adv7180_test_pattern(state, val);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
ret = -EINVAL;
|
ret = -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
@ -632,6 +672,12 @@ static int adv7180_init_controls(struct adv7180_state *state)
|
||||||
ADV7180_HUE_MAX, 1, ADV7180_HUE_DEF);
|
ADV7180_HUE_MAX, 1, ADV7180_HUE_DEF);
|
||||||
v4l2_ctrl_new_custom(&state->ctrl_hdl, &adv7180_ctrl_fast_switch, NULL);
|
v4l2_ctrl_new_custom(&state->ctrl_hdl, &adv7180_ctrl_fast_switch, NULL);
|
||||||
|
|
||||||
|
v4l2_ctrl_new_std_menu_items(&state->ctrl_hdl, &adv7180_ctrl_ops,
|
||||||
|
V4L2_CID_TEST_PATTERN,
|
||||||
|
ARRAY_SIZE(test_pattern_menu) - 1,
|
||||||
|
0, ARRAY_SIZE(test_pattern_menu) - 1,
|
||||||
|
test_pattern_menu);
|
||||||
|
|
||||||
state->sd.ctrl_handler = &state->ctrl_hdl;
|
state->sd.ctrl_handler = &state->ctrl_hdl;
|
||||||
if (state->ctrl_hdl.error) {
|
if (state->ctrl_hdl.error) {
|
||||||
int err = state->ctrl_hdl.error;
|
int err = state->ctrl_hdl.error;
|
||||||
|
|
|
||||||
|
|
@ -121,7 +121,7 @@ void ccs_replace_limit(struct ccs_sensor *sensor,
|
||||||
|
|
||||||
linfo = &ccs_limits[ccs_limit_offsets[limit].info];
|
linfo = &ccs_limits[ccs_limit_offsets[limit].info];
|
||||||
|
|
||||||
dev_dbg(&client->dev, "quirk: 0x%8.8x \"%s\" %u = %d, 0x%x\n",
|
dev_dbg(&client->dev, "quirk: 0x%8.8x \"%s\" %u = %u, 0x%x\n",
|
||||||
linfo->reg, linfo->name, offset, val, val);
|
linfo->reg, linfo->name, offset, val, val);
|
||||||
|
|
||||||
ccs_assign_limit(ptr, ccs_reg_width(linfo->reg), val);
|
ccs_assign_limit(ptr, ccs_reg_width(linfo->reg), val);
|
||||||
|
|
@ -288,7 +288,7 @@ static int ccs_read_frame_fmt(struct ccs_sensor *sensor)
|
||||||
CCS_FRAME_FORMAT_DESCRIPTOR_4_PIXELS_MASK;
|
CCS_FRAME_FORMAT_DESCRIPTOR_4_PIXELS_MASK;
|
||||||
} else {
|
} else {
|
||||||
dev_dbg(&client->dev,
|
dev_dbg(&client->dev,
|
||||||
"invalid frame format model type %d\n",
|
"invalid frame format model type %u\n",
|
||||||
fmt_model_type);
|
fmt_model_type);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
@ -320,7 +320,7 @@ static int ccs_read_frame_fmt(struct ccs_sensor *sensor)
|
||||||
}
|
}
|
||||||
|
|
||||||
dev_dbg(&client->dev,
|
dev_dbg(&client->dev,
|
||||||
"%s pixels: %d %s (pixelcode %u)\n",
|
"%s pixels: %u %s (pixelcode %u)\n",
|
||||||
what, pixels, which, pixelcode);
|
what, pixels, which, pixelcode);
|
||||||
|
|
||||||
if (i < ncol_desc) {
|
if (i < ncol_desc) {
|
||||||
|
|
@ -353,9 +353,9 @@ static int ccs_read_frame_fmt(struct ccs_sensor *sensor)
|
||||||
sensor->image_start = sensor->embedded_end;
|
sensor->image_start = sensor->embedded_end;
|
||||||
}
|
}
|
||||||
|
|
||||||
dev_dbg(&client->dev, "embedded data from lines %d to %d\n",
|
dev_dbg(&client->dev, "embedded data from lines %u to %u\n",
|
||||||
sensor->embedded_start, sensor->embedded_end);
|
sensor->embedded_start, sensor->embedded_end);
|
||||||
dev_dbg(&client->dev, "image data starts at line %d\n",
|
dev_dbg(&client->dev, "image data starts at line %u\n",
|
||||||
sensor->image_start);
|
sensor->image_start);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
@ -571,7 +571,7 @@ static u32 ccs_pixel_order(struct ccs_sensor *sensor)
|
||||||
|
|
||||||
flip ^= sensor->hvflip_inv_mask;
|
flip ^= sensor->hvflip_inv_mask;
|
||||||
|
|
||||||
dev_dbg(&client->dev, "flip %d\n", flip);
|
dev_dbg(&client->dev, "flip %u\n", flip);
|
||||||
return sensor->default_pixel_order ^ flip;
|
return sensor->default_pixel_order ^ flip;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1056,18 +1056,18 @@ static int ccs_get_mbus_formats(struct ccs_sensor *sensor)
|
||||||
|
|
||||||
type = CCS_LIM(sensor, DATA_FORMAT_MODEL_TYPE);
|
type = CCS_LIM(sensor, DATA_FORMAT_MODEL_TYPE);
|
||||||
|
|
||||||
dev_dbg(&client->dev, "data_format_model_type %d\n", type);
|
dev_dbg(&client->dev, "data_format_model_type %u\n", type);
|
||||||
|
|
||||||
rval = ccs_read(sensor, PIXEL_ORDER, &pixel_order);
|
rval = ccs_read(sensor, PIXEL_ORDER, &pixel_order);
|
||||||
if (rval)
|
if (rval)
|
||||||
return rval;
|
return rval;
|
||||||
|
|
||||||
if (pixel_order >= ARRAY_SIZE(pixel_order_str)) {
|
if (pixel_order >= ARRAY_SIZE(pixel_order_str)) {
|
||||||
dev_dbg(&client->dev, "bad pixel order %d\n", pixel_order);
|
dev_dbg(&client->dev, "bad pixel order %u\n", pixel_order);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
dev_dbg(&client->dev, "pixel order %d (%s)\n", pixel_order,
|
dev_dbg(&client->dev, "pixel order %u (%s)\n", pixel_order,
|
||||||
pixel_order_str[pixel_order]);
|
pixel_order_str[pixel_order]);
|
||||||
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
|
|
@ -1105,7 +1105,7 @@ static int ccs_get_mbus_formats(struct ccs_sensor *sensor)
|
||||||
(fmt & CCS_DATA_FORMAT_DESCRIPTOR_COMPRESSED_MASK))
|
(fmt & CCS_DATA_FORMAT_DESCRIPTOR_COMPRESSED_MASK))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
dev_dbg(&client->dev, "jolly good! %d\n", j);
|
dev_dbg(&client->dev, "jolly good! %u\n", j);
|
||||||
|
|
||||||
sensor->default_mbus_frame_fmts |= 1 << j;
|
sensor->default_mbus_frame_fmts |= 1 << j;
|
||||||
}
|
}
|
||||||
|
|
@ -1602,8 +1602,11 @@ static int ccs_power_on(struct device *dev)
|
||||||
usleep_range(1000, 2000);
|
usleep_range(1000, 2000);
|
||||||
} while (--retry);
|
} while (--retry);
|
||||||
|
|
||||||
if (!reset)
|
if (!reset) {
|
||||||
return -EIO;
|
dev_err(dev, "software reset failed\n");
|
||||||
|
rval = -EIO;
|
||||||
|
goto out_cci_addr_fail;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sensor->hwcfg.i2c_addr_alt) {
|
if (sensor->hwcfg.i2c_addr_alt) {
|
||||||
|
|
@ -1999,7 +2002,7 @@ static int ccs_enum_mbus_code(struct v4l2_subdev *subdev,
|
||||||
|
|
||||||
mutex_lock(&sensor->mutex);
|
mutex_lock(&sensor->mutex);
|
||||||
|
|
||||||
dev_err(&client->dev, "subdev %s, pad %d, index %d\n",
|
dev_err(&client->dev, "subdev %s, pad %u, index %u\n",
|
||||||
subdev->name, code->pad, code->index);
|
subdev->name, code->pad, code->index);
|
||||||
|
|
||||||
if (subdev != &sensor->src->sd || code->pad != CCS_PAD_SRC) {
|
if (subdev != &sensor->src->sd || code->pad != CCS_PAD_SRC) {
|
||||||
|
|
@ -2017,7 +2020,7 @@ static int ccs_enum_mbus_code(struct v4l2_subdev *subdev,
|
||||||
|
|
||||||
if (idx == code->index) {
|
if (idx == code->index) {
|
||||||
code->code = ccs_csi_data_formats[i].code;
|
code->code = ccs_csi_data_formats[i].code;
|
||||||
dev_err(&client->dev, "found index %d, i %d, code %x\n",
|
dev_err(&client->dev, "found index %u, i %u, code %x\n",
|
||||||
code->index, i, code->code);
|
code->index, i, code->code);
|
||||||
rval = 0;
|
rval = 0;
|
||||||
break;
|
break;
|
||||||
|
|
@ -2386,7 +2389,7 @@ static void ccs_set_compose_scaler(struct v4l2_subdev *subdev,
|
||||||
max_m = clamp(max_m, CCS_LIM(sensor, SCALER_M_MIN),
|
max_m = clamp(max_m, CCS_LIM(sensor, SCALER_M_MIN),
|
||||||
CCS_LIM(sensor, SCALER_M_MAX));
|
CCS_LIM(sensor, SCALER_M_MAX));
|
||||||
|
|
||||||
dev_dbg(&client->dev, "scaling: a %d b %d max_m %d\n", a, b, max_m);
|
dev_dbg(&client->dev, "scaling: a %u b %u max_m %u\n", a, b, max_m);
|
||||||
|
|
||||||
min = min(max_m, min(a, b));
|
min = min(max_m, min(a, b));
|
||||||
max = min(max_m, max(a, b));
|
max = min(max_m, max(a, b));
|
||||||
|
|
@ -2416,7 +2419,7 @@ static void ccs_set_compose_scaler(struct v4l2_subdev *subdev,
|
||||||
sel->r.height,
|
sel->r.height,
|
||||||
sel->flags);
|
sel->flags);
|
||||||
|
|
||||||
dev_dbg(&client->dev, "trying factor %d (%d)\n", try[i], i);
|
dev_dbg(&client->dev, "trying factor %u (%u)\n", try[i], i);
|
||||||
|
|
||||||
if (this > best) {
|
if (this > best) {
|
||||||
scale_m = try[i];
|
scale_m = try[i];
|
||||||
|
|
@ -3183,7 +3186,7 @@ static int ccs_get_hwconfig(struct ccs_sensor *sensor, struct device *dev)
|
||||||
struct fwnode_handle *ep;
|
struct fwnode_handle *ep;
|
||||||
struct fwnode_handle *fwnode = dev_fwnode(dev);
|
struct fwnode_handle *fwnode = dev_fwnode(dev);
|
||||||
u32 rotation;
|
u32 rotation;
|
||||||
int i;
|
unsigned int i;
|
||||||
int rval;
|
int rval;
|
||||||
|
|
||||||
ep = fwnode_graph_get_endpoint_by_id(fwnode, 0, 0,
|
ep = fwnode_graph_get_endpoint_by_id(fwnode, 0, 0,
|
||||||
|
|
@ -3221,8 +3224,6 @@ static int ccs_get_hwconfig(struct ccs_sensor *sensor, struct device *dev)
|
||||||
goto out_err;
|
goto out_err;
|
||||||
}
|
}
|
||||||
|
|
||||||
dev_dbg(dev, "lanes %u\n", hwcfg->lanes);
|
|
||||||
|
|
||||||
rval = fwnode_property_read_u32(fwnode, "rotation", &rotation);
|
rval = fwnode_property_read_u32(fwnode, "rotation", &rotation);
|
||||||
if (!rval) {
|
if (!rval) {
|
||||||
switch (rotation) {
|
switch (rotation) {
|
||||||
|
|
@ -3244,7 +3245,7 @@ static int ccs_get_hwconfig(struct ccs_sensor *sensor, struct device *dev)
|
||||||
if (rval)
|
if (rval)
|
||||||
dev_info(dev, "can't get clock-frequency\n");
|
dev_info(dev, "can't get clock-frequency\n");
|
||||||
|
|
||||||
dev_dbg(dev, "clk %d, mode %d\n", hwcfg->ext_clk,
|
dev_dbg(dev, "clk %u, mode %u\n", hwcfg->ext_clk,
|
||||||
hwcfg->csi_signalling_mode);
|
hwcfg->csi_signalling_mode);
|
||||||
|
|
||||||
if (!bus_cfg.nr_of_link_frequencies) {
|
if (!bus_cfg.nr_of_link_frequencies) {
|
||||||
|
|
@ -3263,7 +3264,7 @@ static int ccs_get_hwconfig(struct ccs_sensor *sensor, struct device *dev)
|
||||||
|
|
||||||
for (i = 0; i < bus_cfg.nr_of_link_frequencies; i++) {
|
for (i = 0; i < bus_cfg.nr_of_link_frequencies; i++) {
|
||||||
hwcfg->op_sys_clock[i] = bus_cfg.link_frequencies[i];
|
hwcfg->op_sys_clock[i] = bus_cfg.link_frequencies[i];
|
||||||
dev_dbg(dev, "freq %d: %lld\n", i, hwcfg->op_sys_clock[i]);
|
dev_dbg(dev, "freq %u: %lld\n", i, hwcfg->op_sys_clock[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
v4l2_fwnode_endpoint_free(&bus_cfg);
|
v4l2_fwnode_endpoint_free(&bus_cfg);
|
||||||
|
|
|
||||||
|
|
@ -183,6 +183,7 @@ static int dw9714_probe(struct i2c_client *client)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
err_cleanup:
|
err_cleanup:
|
||||||
|
regulator_disable(dw9714_dev->vcc);
|
||||||
v4l2_ctrl_handler_free(&dw9714_dev->ctrls_vcm);
|
v4l2_ctrl_handler_free(&dw9714_dev->ctrls_vcm);
|
||||||
media_entity_cleanup(&dw9714_dev->sd.entity);
|
media_entity_cleanup(&dw9714_dev->sd.entity);
|
||||||
|
|
||||||
|
|
@ -201,7 +202,6 @@ static int dw9714_remove(struct i2c_client *client)
|
||||||
if (ret) {
|
if (ret) {
|
||||||
dev_err(&client->dev,
|
dev_err(&client->dev,
|
||||||
"Failed to disable vcc: %d\n", ret);
|
"Failed to disable vcc: %d\n", ret);
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pm_runtime_set_suspended(&client->dev);
|
pm_runtime_set_suspended(&client->dev);
|
||||||
|
|
|
||||||
|
|
@ -469,11 +469,6 @@ static int dw9768_probe(struct i2c_client *client)
|
||||||
|
|
||||||
dw9768->sd.entity.function = MEDIA_ENT_F_LENS;
|
dw9768->sd.entity.function = MEDIA_ENT_F_LENS;
|
||||||
|
|
||||||
/*
|
|
||||||
* Device is already turned on by i2c-core with ACPI domain PM.
|
|
||||||
* Attempt to turn off the device to satisfy the privacy LED concerns.
|
|
||||||
*/
|
|
||||||
pm_runtime_set_active(dev);
|
|
||||||
pm_runtime_enable(dev);
|
pm_runtime_enable(dev);
|
||||||
if (!pm_runtime_enabled(dev)) {
|
if (!pm_runtime_enabled(dev)) {
|
||||||
ret = dw9768_runtime_resume(dev);
|
ret = dw9768_runtime_resume(dev);
|
||||||
|
|
@ -488,7 +483,6 @@ static int dw9768_probe(struct i2c_client *client)
|
||||||
dev_err(dev, "failed to register V4L2 subdev: %d", ret);
|
dev_err(dev, "failed to register V4L2 subdev: %d", ret);
|
||||||
goto err_power_off;
|
goto err_power_off;
|
||||||
}
|
}
|
||||||
pm_runtime_idle(dev);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -295,6 +295,8 @@ static int __maybe_unused dw9807_vcm_resume(struct device *dev)
|
||||||
|
|
||||||
static const struct of_device_id dw9807_of_table[] = {
|
static const struct of_device_id dw9807_of_table[] = {
|
||||||
{ .compatible = "dongwoon,dw9807-vcm" },
|
{ .compatible = "dongwoon,dw9807-vcm" },
|
||||||
|
/* Compatibility for older firmware, NEVER USE THIS IN FIRMWARE! */
|
||||||
|
{ .compatible = "dongwoon,dw9807" },
|
||||||
{ /* sentinel */ }
|
{ /* sentinel */ }
|
||||||
};
|
};
|
||||||
MODULE_DEVICE_TABLE(of, dw9807_of_table);
|
MODULE_DEVICE_TABLE(of, dw9807_of_table);
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,7 @@
|
||||||
#include <linux/i2c.h>
|
#include <linux/i2c.h>
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
#include <linux/pm_runtime.h>
|
#include <linux/pm_runtime.h>
|
||||||
|
#include <linux/regulator/consumer.h>
|
||||||
|
|
||||||
#include <media/v4l2-ctrls.h>
|
#include <media/v4l2-ctrls.h>
|
||||||
#include <media/v4l2-fwnode.h>
|
#include <media/v4l2-fwnode.h>
|
||||||
|
|
@ -101,6 +102,12 @@ struct imx412_mode {
|
||||||
struct imx412_reg_list reg_list;
|
struct imx412_reg_list reg_list;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static const char * const imx412_supply_names[] = {
|
||||||
|
"dovdd", /* Digital I/O power */
|
||||||
|
"avdd", /* Analog power */
|
||||||
|
"dvdd", /* Digital core power */
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* struct imx412 - imx412 sensor device structure
|
* struct imx412 - imx412 sensor device structure
|
||||||
* @dev: Pointer to generic device
|
* @dev: Pointer to generic device
|
||||||
|
|
@ -109,6 +116,7 @@ struct imx412_mode {
|
||||||
* @pad: Media pad. Only one pad supported
|
* @pad: Media pad. Only one pad supported
|
||||||
* @reset_gpio: Sensor reset gpio
|
* @reset_gpio: Sensor reset gpio
|
||||||
* @inclk: Sensor input clock
|
* @inclk: Sensor input clock
|
||||||
|
* @supplies: Regulator supplies
|
||||||
* @ctrl_handler: V4L2 control handler
|
* @ctrl_handler: V4L2 control handler
|
||||||
* @link_freq_ctrl: Pointer to link frequency control
|
* @link_freq_ctrl: Pointer to link frequency control
|
||||||
* @pclk_ctrl: Pointer to pixel clock control
|
* @pclk_ctrl: Pointer to pixel clock control
|
||||||
|
|
@ -128,6 +136,7 @@ struct imx412 {
|
||||||
struct media_pad pad;
|
struct media_pad pad;
|
||||||
struct gpio_desc *reset_gpio;
|
struct gpio_desc *reset_gpio;
|
||||||
struct clk *inclk;
|
struct clk *inclk;
|
||||||
|
struct regulator_bulk_data supplies[ARRAY_SIZE(imx412_supply_names)];
|
||||||
struct v4l2_ctrl_handler ctrl_handler;
|
struct v4l2_ctrl_handler ctrl_handler;
|
||||||
struct v4l2_ctrl *link_freq_ctrl;
|
struct v4l2_ctrl *link_freq_ctrl;
|
||||||
struct v4l2_ctrl *pclk_ctrl;
|
struct v4l2_ctrl *pclk_ctrl;
|
||||||
|
|
@ -946,6 +955,16 @@ static int imx412_parse_hw_config(struct imx412 *imx412)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Get optional DT defined regulators */
|
||||||
|
for (i = 0; i < ARRAY_SIZE(imx412_supply_names); i++)
|
||||||
|
imx412->supplies[i].supply = imx412_supply_names[i];
|
||||||
|
|
||||||
|
ret = devm_regulator_bulk_get(imx412->dev,
|
||||||
|
ARRAY_SIZE(imx412_supply_names),
|
||||||
|
imx412->supplies);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
ep = fwnode_graph_get_next_endpoint(fwnode, NULL);
|
ep = fwnode_graph_get_next_endpoint(fwnode, NULL);
|
||||||
if (!ep)
|
if (!ep)
|
||||||
return -ENXIO;
|
return -ENXIO;
|
||||||
|
|
@ -1011,7 +1030,14 @@ static int imx412_power_on(struct device *dev)
|
||||||
struct imx412 *imx412 = to_imx412(sd);
|
struct imx412 *imx412 = to_imx412(sd);
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
gpiod_set_value_cansleep(imx412->reset_gpio, 1);
|
ret = regulator_bulk_enable(ARRAY_SIZE(imx412_supply_names),
|
||||||
|
imx412->supplies);
|
||||||
|
if (ret < 0) {
|
||||||
|
dev_err(dev, "failed to enable regulators\n");
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
gpiod_set_value_cansleep(imx412->reset_gpio, 0);
|
||||||
|
|
||||||
ret = clk_prepare_enable(imx412->inclk);
|
ret = clk_prepare_enable(imx412->inclk);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
|
|
@ -1024,7 +1050,9 @@ static int imx412_power_on(struct device *dev)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
error_reset:
|
error_reset:
|
||||||
gpiod_set_value_cansleep(imx412->reset_gpio, 0);
|
gpiod_set_value_cansleep(imx412->reset_gpio, 1);
|
||||||
|
regulator_bulk_disable(ARRAY_SIZE(imx412_supply_names),
|
||||||
|
imx412->supplies);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
@ -1040,10 +1068,13 @@ static int imx412_power_off(struct device *dev)
|
||||||
struct v4l2_subdev *sd = dev_get_drvdata(dev);
|
struct v4l2_subdev *sd = dev_get_drvdata(dev);
|
||||||
struct imx412 *imx412 = to_imx412(sd);
|
struct imx412 *imx412 = to_imx412(sd);
|
||||||
|
|
||||||
gpiod_set_value_cansleep(imx412->reset_gpio, 0);
|
|
||||||
|
|
||||||
clk_disable_unprepare(imx412->inclk);
|
clk_disable_unprepare(imx412->inclk);
|
||||||
|
|
||||||
|
gpiod_set_value_cansleep(imx412->reset_gpio, 1);
|
||||||
|
|
||||||
|
regulator_bulk_disable(ARRAY_SIZE(imx412_supply_names),
|
||||||
|
imx412->supplies);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1147,22 +1147,18 @@ static int max9286_poc_enable(struct max9286_priv *priv, bool enable)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int max9286_init(struct device *dev)
|
static int max9286_init(struct max9286_priv *priv)
|
||||||
{
|
{
|
||||||
struct max9286_priv *priv;
|
struct i2c_client *client = priv->client;
|
||||||
struct i2c_client *client;
|
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
client = to_i2c_client(dev);
|
|
||||||
priv = i2c_get_clientdata(client);
|
|
||||||
|
|
||||||
ret = max9286_poc_enable(priv, true);
|
ret = max9286_poc_enable(priv, true);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
ret = max9286_setup(priv);
|
ret = max9286_setup(priv);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
dev_err(dev, "Unable to setup max9286\n");
|
dev_err(&client->dev, "Unable to setup max9286\n");
|
||||||
goto err_poc_disable;
|
goto err_poc_disable;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1172,13 +1168,13 @@ static int max9286_init(struct device *dev)
|
||||||
*/
|
*/
|
||||||
ret = max9286_v4l2_register(priv);
|
ret = max9286_v4l2_register(priv);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
dev_err(dev, "Failed to register with V4L2\n");
|
dev_err(&client->dev, "Failed to register with V4L2\n");
|
||||||
goto err_poc_disable;
|
goto err_poc_disable;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = max9286_i2c_mux_init(priv);
|
ret = max9286_i2c_mux_init(priv);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
dev_err(dev, "Unable to initialize I2C multiplexer\n");
|
dev_err(&client->dev, "Unable to initialize I2C multiplexer\n");
|
||||||
goto err_v4l2_register;
|
goto err_v4l2_register;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1333,7 +1329,6 @@ static int max9286_probe(struct i2c_client *client)
|
||||||
mutex_init(&priv->mutex);
|
mutex_init(&priv->mutex);
|
||||||
|
|
||||||
priv->client = client;
|
priv->client = client;
|
||||||
i2c_set_clientdata(client, priv);
|
|
||||||
|
|
||||||
priv->gpiod_pwdn = devm_gpiod_get_optional(&client->dev, "enable",
|
priv->gpiod_pwdn = devm_gpiod_get_optional(&client->dev, "enable",
|
||||||
GPIOD_OUT_HIGH);
|
GPIOD_OUT_HIGH);
|
||||||
|
|
@ -1369,7 +1364,7 @@ static int max9286_probe(struct i2c_client *client)
|
||||||
if (ret)
|
if (ret)
|
||||||
goto err_powerdown;
|
goto err_powerdown;
|
||||||
|
|
||||||
ret = max9286_init(&client->dev);
|
ret = max9286_init(priv);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
goto err_cleanup_dt;
|
goto err_cleanup_dt;
|
||||||
|
|
||||||
|
|
@ -1385,7 +1380,7 @@ static int max9286_probe(struct i2c_client *client)
|
||||||
|
|
||||||
static int max9286_remove(struct i2c_client *client)
|
static int max9286_remove(struct i2c_client *client)
|
||||||
{
|
{
|
||||||
struct max9286_priv *priv = i2c_get_clientdata(client);
|
struct max9286_priv *priv = sd_to_max9286(i2c_get_clientdata(client));
|
||||||
|
|
||||||
i2c_mux_del_adapters(priv->mux);
|
i2c_mux_del_adapters(priv->mux);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -843,7 +843,7 @@ static int ov5645_enum_mbus_code(struct v4l2_subdev *sd,
|
||||||
if (code->index > 0)
|
if (code->index > 0)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
code->code = MEDIA_BUS_FMT_UYVY8_2X8;
|
code->code = MEDIA_BUS_FMT_UYVY8_1X16;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
@ -852,7 +852,7 @@ static int ov5645_enum_frame_size(struct v4l2_subdev *subdev,
|
||||||
struct v4l2_subdev_state *sd_state,
|
struct v4l2_subdev_state *sd_state,
|
||||||
struct v4l2_subdev_frame_size_enum *fse)
|
struct v4l2_subdev_frame_size_enum *fse)
|
||||||
{
|
{
|
||||||
if (fse->code != MEDIA_BUS_FMT_UYVY8_2X8)
|
if (fse->code != MEDIA_BUS_FMT_UYVY8_1X16)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
if (fse->index >= ARRAY_SIZE(ov5645_mode_info_data))
|
if (fse->index >= ARRAY_SIZE(ov5645_mode_info_data))
|
||||||
|
|
@ -948,7 +948,7 @@ static int ov5645_set_format(struct v4l2_subdev *sd,
|
||||||
format->which);
|
format->which);
|
||||||
__format->width = __crop->width;
|
__format->width = __crop->width;
|
||||||
__format->height = __crop->height;
|
__format->height = __crop->height;
|
||||||
__format->code = MEDIA_BUS_FMT_UYVY8_2X8;
|
__format->code = MEDIA_BUS_FMT_UYVY8_1X16;
|
||||||
__format->field = V4L2_FIELD_NONE;
|
__format->field = V4L2_FIELD_NONE;
|
||||||
__format->colorspace = V4L2_COLORSPACE_SRGB;
|
__format->colorspace = V4L2_COLORSPACE_SRGB;
|
||||||
|
|
||||||
|
|
@ -1283,7 +1283,7 @@ MODULE_DEVICE_TABLE(of, ov5645_of_match);
|
||||||
|
|
||||||
static struct i2c_driver ov5645_i2c_driver = {
|
static struct i2c_driver ov5645_i2c_driver = {
|
||||||
.driver = {
|
.driver = {
|
||||||
.of_match_table = of_match_ptr(ov5645_of_match),
|
.of_match_table = ov5645_of_match,
|
||||||
.name = "ov5645",
|
.name = "ov5645",
|
||||||
},
|
},
|
||||||
.probe_new = ov5645_probe,
|
.probe_new = ov5645_probe,
|
||||||
|
|
|
||||||
|
|
@ -2498,9 +2498,9 @@ static int ov5648_probe(struct i2c_client *client)
|
||||||
|
|
||||||
/* DOVDD: digital I/O */
|
/* DOVDD: digital I/O */
|
||||||
sensor->dovdd = devm_regulator_get(dev, "dovdd");
|
sensor->dovdd = devm_regulator_get(dev, "dovdd");
|
||||||
if (IS_ERR(sensor->dvdd)) {
|
if (IS_ERR(sensor->dovdd)) {
|
||||||
dev_err(dev, "cannot get DOVDD (digital I/O) regulator\n");
|
dev_err(dev, "cannot get DOVDD (digital I/O) regulator\n");
|
||||||
ret = PTR_ERR(sensor->dvdd);
|
ret = PTR_ERR(sensor->dovdd);
|
||||||
goto error_endpoint;
|
goto error_endpoint;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1122,7 +1122,7 @@ static int ov5695_set_ctrl(struct v4l2_ctrl *ctrl)
|
||||||
|
|
||||||
switch (ctrl->id) {
|
switch (ctrl->id) {
|
||||||
case V4L2_CID_EXPOSURE:
|
case V4L2_CID_EXPOSURE:
|
||||||
/* 4 least significant bits of expsoure are fractional part */
|
/* 4 least significant bits of exposure are fractional part */
|
||||||
ret = ov5695_write_reg(ov5695->client, OV5695_REG_EXPOSURE,
|
ret = ov5695_write_reg(ov5695->client, OV5695_REG_EXPOSURE,
|
||||||
OV5695_REG_VALUE_24BIT, ctrl->val << 4);
|
OV5695_REG_VALUE_24BIT, ctrl->val << 4);
|
||||||
break;
|
break;
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load Diff
|
|
@ -13,23 +13,28 @@
|
||||||
MODULE_DESCRIPTION("OmniVision ov7640 sensor driver");
|
MODULE_DESCRIPTION("OmniVision ov7640 sensor driver");
|
||||||
MODULE_LICENSE("GPL v2");
|
MODULE_LICENSE("GPL v2");
|
||||||
|
|
||||||
static const u8 initial_registers[] = {
|
struct reg_val {
|
||||||
0x12, 0x80,
|
u8 reg;
|
||||||
0x12, 0x54,
|
u8 val;
|
||||||
0x14, 0x24,
|
|
||||||
0x15, 0x01,
|
|
||||||
0x28, 0x20,
|
|
||||||
0x75, 0x82,
|
|
||||||
0xFF, 0xFF, /* Terminator (reg 0xFF is unused) */
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static int write_regs(struct i2c_client *client, const u8 *regs)
|
static const struct reg_val regval_init[] = {
|
||||||
{
|
{0x12, 0x80},
|
||||||
int i;
|
{0x12, 0x54},
|
||||||
|
{0x14, 0x24},
|
||||||
|
{0x15, 0x01},
|
||||||
|
{0x28, 0x20},
|
||||||
|
{0x75, 0x82},
|
||||||
|
};
|
||||||
|
|
||||||
for (i = 0; regs[i] != 0xFF; i += 2)
|
static int write_regs(struct i2c_client *client,
|
||||||
if (i2c_smbus_write_byte_data(client, regs[i], regs[i + 1]) < 0)
|
const struct reg_val *rv, int len)
|
||||||
|
{
|
||||||
|
while (--len >= 0) {
|
||||||
|
if (i2c_smbus_write_byte_data(client, rv->reg, rv->val) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
rv++;
|
||||||
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -56,7 +61,7 @@ static int ov7640_probe(struct i2c_client *client,
|
||||||
v4l_info(client, "chip found @ 0x%02x (%s)\n",
|
v4l_info(client, "chip found @ 0x%02x (%s)\n",
|
||||||
client->addr << 1, client->adapter->name);
|
client->addr << 1, client->adapter->name);
|
||||||
|
|
||||||
if (write_regs(client, initial_registers) < 0) {
|
if (write_regs(client, regval_init, ARRAY_SIZE(regval_init)) < 0) {
|
||||||
v4l_err(client, "error initializing OV7640\n");
|
v4l_err(client, "error initializing OV7640\n");
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2017,7 +2017,6 @@ static int ov7670_remove(struct i2c_client *client)
|
||||||
v4l2_async_unregister_subdev(sd);
|
v4l2_async_unregister_subdev(sd);
|
||||||
v4l2_ctrl_handler_free(&info->hdl);
|
v4l2_ctrl_handler_free(&info->hdl);
|
||||||
media_entity_cleanup(&info->sd.entity);
|
media_entity_cleanup(&info->sd.entity);
|
||||||
ov7670_power_off(sd);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -63,6 +63,7 @@
|
||||||
#define OV8856_ANAL_GAIN_STEP 1
|
#define OV8856_ANAL_GAIN_STEP 1
|
||||||
|
|
||||||
/* Digital gain controls from sensor */
|
/* Digital gain controls from sensor */
|
||||||
|
#define OV8856_REG_DIGITAL_GAIN 0x350a
|
||||||
#define OV8856_REG_MWB_R_GAIN 0x5019
|
#define OV8856_REG_MWB_R_GAIN 0x5019
|
||||||
#define OV8856_REG_MWB_G_GAIN 0x501b
|
#define OV8856_REG_MWB_G_GAIN 0x501b
|
||||||
#define OV8856_REG_MWB_B_GAIN 0x501d
|
#define OV8856_REG_MWB_B_GAIN 0x501d
|
||||||
|
|
@ -351,7 +352,7 @@ static const struct ov8856_reg lane_2_mode_3280x2464[] = {
|
||||||
{0x484b, 0x05},
|
{0x484b, 0x05},
|
||||||
{0x5000, 0x57},
|
{0x5000, 0x57},
|
||||||
{0x5001, 0x0a},
|
{0x5001, 0x0a},
|
||||||
{0x5004, 0x04},
|
{0x5004, 0x06},
|
||||||
{0x502e, 0x03},
|
{0x502e, 0x03},
|
||||||
{0x5030, 0x41},
|
{0x5030, 0x41},
|
||||||
{0x5795, 0x02},
|
{0x5795, 0x02},
|
||||||
|
|
@ -543,7 +544,7 @@ static const struct ov8856_reg lane_2_mode_1640x1232[] = {
|
||||||
{0x484b, 0x05},
|
{0x484b, 0x05},
|
||||||
{0x5000, 0x57},
|
{0x5000, 0x57},
|
||||||
{0x5001, 0x0a},
|
{0x5001, 0x0a},
|
||||||
{0x5004, 0x04},
|
{0x5004, 0x06},
|
||||||
{0x502e, 0x03},
|
{0x502e, 0x03},
|
||||||
{0x5030, 0x41},
|
{0x5030, 0x41},
|
||||||
{0x5795, 0x00},
|
{0x5795, 0x00},
|
||||||
|
|
@ -734,7 +735,7 @@ static const struct ov8856_reg lane_4_mode_3280x2464[] = {
|
||||||
{0x484b, 0x05},
|
{0x484b, 0x05},
|
||||||
{0x5000, 0x57},
|
{0x5000, 0x57},
|
||||||
{0x5001, 0x0a},
|
{0x5001, 0x0a},
|
||||||
{0x5004, 0x04},
|
{0x5004, 0x06},
|
||||||
{0x502e, 0x03},
|
{0x502e, 0x03},
|
||||||
{0x5030, 0x41},
|
{0x5030, 0x41},
|
||||||
{0x5780, 0x14},
|
{0x5780, 0x14},
|
||||||
|
|
@ -925,7 +926,7 @@ static const struct ov8856_reg lane_4_mode_1640x1232[] = {
|
||||||
{0x484b, 0x05},
|
{0x484b, 0x05},
|
||||||
{0x5000, 0x57},
|
{0x5000, 0x57},
|
||||||
{0x5001, 0x0a},
|
{0x5001, 0x0a},
|
||||||
{0x5004, 0x04},
|
{0x5004, 0x06},
|
||||||
{0x502e, 0x03},
|
{0x502e, 0x03},
|
||||||
{0x5030, 0x41},
|
{0x5030, 0x41},
|
||||||
{0x5780, 0x14},
|
{0x5780, 0x14},
|
||||||
|
|
@ -1755,19 +1756,7 @@ static int ov8856_identify_module(struct ov8856 *ov8856)
|
||||||
|
|
||||||
static int ov8856_update_digital_gain(struct ov8856 *ov8856, u32 d_gain)
|
static int ov8856_update_digital_gain(struct ov8856 *ov8856, u32 d_gain)
|
||||||
{
|
{
|
||||||
int ret;
|
return ov8856_write_reg(ov8856, OV8856_REG_DIGITAL_GAIN,
|
||||||
|
|
||||||
ret = ov8856_write_reg(ov8856, OV8856_REG_MWB_R_GAIN,
|
|
||||||
OV8856_REG_VALUE_16BIT, d_gain);
|
|
||||||
if (ret)
|
|
||||||
return ret;
|
|
||||||
|
|
||||||
ret = ov8856_write_reg(ov8856, OV8856_REG_MWB_G_GAIN,
|
|
||||||
OV8856_REG_VALUE_16BIT, d_gain);
|
|
||||||
if (ret)
|
|
||||||
return ret;
|
|
||||||
|
|
||||||
return ov8856_write_reg(ov8856, OV8856_REG_MWB_B_GAIN,
|
|
||||||
OV8856_REG_VALUE_16BIT, d_gain);
|
OV8856_REG_VALUE_16BIT, d_gain);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -47,11 +47,11 @@
|
||||||
#define OV10635_VTS 933
|
#define OV10635_VTS 933
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* As the drivers supports a single MEDIA_BUS_FMT_UYVY8_2X8 format we
|
* As the drivers supports a single MEDIA_BUS_FMT_UYVY8_1X16 format we
|
||||||
* can harcode the pixel rate.
|
* can harcode the pixel rate.
|
||||||
*
|
*
|
||||||
* PCLK is fed through the system clock, programmed @88MHz.
|
* PCLK is fed through the system clock, programmed @88MHz.
|
||||||
* MEDIA_BUS_FMT_UYVY8_2X8 format = 2 samples per pixel.
|
* MEDIA_BUS_FMT_UYVY8_1X16 format = 2 samples per pixel.
|
||||||
*
|
*
|
||||||
* Pixelrate = PCLK / 2
|
* Pixelrate = PCLK / 2
|
||||||
* FPS = (OV10635_VTS * OV10635_HTS) / PixelRate
|
* FPS = (OV10635_VTS * OV10635_HTS) / PixelRate
|
||||||
|
|
@ -409,7 +409,7 @@ static int rdacm20_enum_mbus_code(struct v4l2_subdev *sd,
|
||||||
if (code->pad || code->index > 0)
|
if (code->pad || code->index > 0)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
code->code = MEDIA_BUS_FMT_UYVY8_2X8;
|
code->code = MEDIA_BUS_FMT_UYVY8_1X16;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
@ -425,7 +425,7 @@ static int rdacm20_get_fmt(struct v4l2_subdev *sd,
|
||||||
|
|
||||||
mf->width = OV10635_WIDTH;
|
mf->width = OV10635_WIDTH;
|
||||||
mf->height = OV10635_HEIGHT;
|
mf->height = OV10635_HEIGHT;
|
||||||
mf->code = MEDIA_BUS_FMT_UYVY8_2X8;
|
mf->code = MEDIA_BUS_FMT_UYVY8_1X16;
|
||||||
mf->colorspace = V4L2_COLORSPACE_RAW;
|
mf->colorspace = V4L2_COLORSPACE_RAW;
|
||||||
mf->field = V4L2_FIELD_NONE;
|
mf->field = V4L2_FIELD_NONE;
|
||||||
mf->ycbcr_enc = V4L2_YCBCR_ENC_601;
|
mf->ycbcr_enc = V4L2_YCBCR_ENC_601;
|
||||||
|
|
@ -611,7 +611,7 @@ static int rdacm20_probe(struct i2c_client *client)
|
||||||
goto error_free_ctrls;
|
goto error_free_ctrls;
|
||||||
|
|
||||||
dev->pad.flags = MEDIA_PAD_FL_SOURCE;
|
dev->pad.flags = MEDIA_PAD_FL_SOURCE;
|
||||||
dev->sd.entity.flags |= MEDIA_ENT_F_CAM_SENSOR;
|
dev->sd.entity.function = MEDIA_ENT_F_CAM_SENSOR;
|
||||||
ret = media_entity_pads_init(&dev->sd.entity, 1, &dev->pad);
|
ret = media_entity_pads_init(&dev->sd.entity, 1, &dev->pad);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
goto error_free_ctrls;
|
goto error_free_ctrls;
|
||||||
|
|
|
||||||
|
|
@ -583,7 +583,7 @@ static int rdacm21_probe(struct i2c_client *client)
|
||||||
goto error_free_ctrls;
|
goto error_free_ctrls;
|
||||||
|
|
||||||
dev->pad.flags = MEDIA_PAD_FL_SOURCE;
|
dev->pad.flags = MEDIA_PAD_FL_SOURCE;
|
||||||
dev->sd.entity.flags |= MEDIA_ENT_F_CAM_SENSOR;
|
dev->sd.entity.function = MEDIA_ENT_F_CAM_SENSOR;
|
||||||
ret = media_entity_pads_init(&dev->sd.entity, 1, &dev->pad);
|
ret = media_entity_pads_init(&dev->sd.entity, 1, &dev->pad);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
goto error_free_ctrls;
|
goto error_free_ctrls;
|
||||||
|
|
|
||||||
|
|
@ -213,7 +213,7 @@ static int __s5k6a3_power_on(struct s5k6a3 *sensor)
|
||||||
for (i++; i < S5K6A3_NUM_SUPPLIES; i++) {
|
for (i++; i < S5K6A3_NUM_SUPPLIES; i++) {
|
||||||
ret = regulator_enable(sensor->supplies[i].consumer);
|
ret = regulator_enable(sensor->supplies[i].consumer);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
goto error_reg_dis;
|
goto error_clk;
|
||||||
}
|
}
|
||||||
|
|
||||||
gpio_set_value(sensor->gpio_reset, 1);
|
gpio_set_value(sensor->gpio_reset, 1);
|
||||||
|
|
@ -226,6 +226,8 @@ static int __s5k6a3_power_on(struct s5k6a3 *sensor)
|
||||||
msleep(20);
|
msleep(20);
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
error_clk:
|
||||||
|
clk_disable_unprepare(sensor->clock);
|
||||||
error_reg_dis:
|
error_reg_dis:
|
||||||
for (--i; i >= 0; --i)
|
for (--i; i >= 0; --i)
|
||||||
regulator_disable(sensor->supplies[i].consumer);
|
regulator_disable(sensor->supplies[i].consumer);
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,7 @@
|
||||||
* - Melexis MLX90640 Thermal Cameras
|
* - Melexis MLX90640 Thermal Cameras
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <linux/bits.h>
|
||||||
#include <linux/delay.h>
|
#include <linux/delay.h>
|
||||||
#include <linux/freezer.h>
|
#include <linux/freezer.h>
|
||||||
#include <linux/hwmon.h>
|
#include <linux/hwmon.h>
|
||||||
|
|
@ -34,6 +35,37 @@
|
||||||
|
|
||||||
#define VIDEO_I2C_DRIVER "video-i2c"
|
#define VIDEO_I2C_DRIVER "video-i2c"
|
||||||
|
|
||||||
|
/* Power control register */
|
||||||
|
#define AMG88XX_REG_PCTL 0x00
|
||||||
|
#define AMG88XX_PCTL_NORMAL 0x00
|
||||||
|
#define AMG88XX_PCTL_SLEEP 0x10
|
||||||
|
|
||||||
|
/* Reset register */
|
||||||
|
#define AMG88XX_REG_RST 0x01
|
||||||
|
#define AMG88XX_RST_FLAG 0x30
|
||||||
|
#define AMG88XX_RST_INIT 0x3f
|
||||||
|
|
||||||
|
/* Frame rate register */
|
||||||
|
#define AMG88XX_REG_FPSC 0x02
|
||||||
|
#define AMG88XX_FPSC_1FPS BIT(0)
|
||||||
|
|
||||||
|
/* Thermistor register */
|
||||||
|
#define AMG88XX_REG_TTHL 0x0e
|
||||||
|
|
||||||
|
/* Temperature register */
|
||||||
|
#define AMG88XX_REG_T01L 0x80
|
||||||
|
|
||||||
|
/* RAM */
|
||||||
|
#define MLX90640_RAM_START_ADDR 0x0400
|
||||||
|
|
||||||
|
/* EEPROM */
|
||||||
|
#define MLX90640_EEPROM_START_ADDR 0x2400
|
||||||
|
|
||||||
|
/* Control register */
|
||||||
|
#define MLX90640_REG_CTL1 0x800d
|
||||||
|
#define MLX90640_REG_CTL1_MASK GENMASK(9, 7)
|
||||||
|
#define MLX90640_REG_CTL1_MASK_SHIFT 7
|
||||||
|
|
||||||
struct video_i2c_chip;
|
struct video_i2c_chip;
|
||||||
|
|
||||||
struct video_i2c_buffer {
|
struct video_i2c_buffer {
|
||||||
|
|
@ -124,7 +156,7 @@ static int mlx90640_nvram_read(void *priv, unsigned int offset, void *val,
|
||||||
{
|
{
|
||||||
struct video_i2c_data *data = priv;
|
struct video_i2c_data *data = priv;
|
||||||
|
|
||||||
return regmap_bulk_read(data->regmap, 0x2400 + offset, val, bytes);
|
return regmap_bulk_read(data->regmap, MLX90640_EEPROM_START_ADDR + offset, val, bytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct nvmem_config mlx90640_nvram_config = {
|
static struct nvmem_config mlx90640_nvram_config = {
|
||||||
|
|
@ -135,31 +167,6 @@ static struct nvmem_config mlx90640_nvram_config = {
|
||||||
.reg_read = mlx90640_nvram_read,
|
.reg_read = mlx90640_nvram_read,
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Power control register */
|
|
||||||
#define AMG88XX_REG_PCTL 0x00
|
|
||||||
#define AMG88XX_PCTL_NORMAL 0x00
|
|
||||||
#define AMG88XX_PCTL_SLEEP 0x10
|
|
||||||
|
|
||||||
/* Reset register */
|
|
||||||
#define AMG88XX_REG_RST 0x01
|
|
||||||
#define AMG88XX_RST_FLAG 0x30
|
|
||||||
#define AMG88XX_RST_INIT 0x3f
|
|
||||||
|
|
||||||
/* Frame rate register */
|
|
||||||
#define AMG88XX_REG_FPSC 0x02
|
|
||||||
#define AMG88XX_FPSC_1FPS BIT(0)
|
|
||||||
|
|
||||||
/* Thermistor register */
|
|
||||||
#define AMG88XX_REG_TTHL 0x0e
|
|
||||||
|
|
||||||
/* Temperature register */
|
|
||||||
#define AMG88XX_REG_T01L 0x80
|
|
||||||
|
|
||||||
/* Control register */
|
|
||||||
#define MLX90640_REG_CTL1 0x800d
|
|
||||||
#define MLX90640_REG_CTL1_MASK 0x0380
|
|
||||||
#define MLX90640_REG_CTL1_MASK_SHIFT 7
|
|
||||||
|
|
||||||
static int amg88xx_xfer(struct video_i2c_data *data, char *buf)
|
static int amg88xx_xfer(struct video_i2c_data *data, char *buf)
|
||||||
{
|
{
|
||||||
return regmap_bulk_read(data->regmap, AMG88XX_REG_T01L, buf,
|
return regmap_bulk_read(data->regmap, AMG88XX_REG_T01L, buf,
|
||||||
|
|
@ -168,7 +175,7 @@ static int amg88xx_xfer(struct video_i2c_data *data, char *buf)
|
||||||
|
|
||||||
static int mlx90640_xfer(struct video_i2c_data *data, char *buf)
|
static int mlx90640_xfer(struct video_i2c_data *data, char *buf)
|
||||||
{
|
{
|
||||||
return regmap_bulk_read(data->regmap, 0x400, buf,
|
return regmap_bulk_read(data->regmap, MLX90640_RAM_START_ADDR, buf,
|
||||||
data->chip->buffer_size);
|
data->chip->buffer_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -604,15 +604,8 @@ static void __media_device_unregister_entity(struct media_entity *entity)
|
||||||
media_gobj_destroy(&entity->graph_obj);
|
media_gobj_destroy(&entity->graph_obj);
|
||||||
|
|
||||||
/* invoke entity_notify callbacks to handle entity removal?? */
|
/* invoke entity_notify callbacks to handle entity removal?? */
|
||||||
|
|
||||||
entity->graph_obj.mdev = NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* media_device_register_entity - Register an entity with a media device
|
|
||||||
* @mdev: The media device
|
|
||||||
* @entity: The entity
|
|
||||||
*/
|
|
||||||
int __must_check media_device_register_entity(struct media_device *mdev,
|
int __must_check media_device_register_entity(struct media_device *mdev,
|
||||||
struct media_entity *entity)
|
struct media_entity *entity)
|
||||||
{
|
{
|
||||||
|
|
@ -691,16 +684,6 @@ void media_device_unregister_entity(struct media_entity *entity)
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(media_device_unregister_entity);
|
EXPORT_SYMBOL_GPL(media_device_unregister_entity);
|
||||||
|
|
||||||
/**
|
|
||||||
* media_device_init() - initialize a media device
|
|
||||||
* @mdev: The media device
|
|
||||||
*
|
|
||||||
* The caller is responsible for initializing the media device before
|
|
||||||
* registration. The following fields must be set:
|
|
||||||
*
|
|
||||||
* - dev must point to the parent device
|
|
||||||
* - model must be filled with the device model name
|
|
||||||
*/
|
|
||||||
void media_device_init(struct media_device *mdev)
|
void media_device_init(struct media_device *mdev)
|
||||||
{
|
{
|
||||||
INIT_LIST_HEAD(&mdev->entities);
|
INIT_LIST_HEAD(&mdev->entities);
|
||||||
|
|
@ -715,6 +698,10 @@ void media_device_init(struct media_device *mdev)
|
||||||
|
|
||||||
atomic_set(&mdev->request_id, 0);
|
atomic_set(&mdev->request_id, 0);
|
||||||
|
|
||||||
|
if (!*mdev->bus_info)
|
||||||
|
media_set_bus_info(mdev->bus_info, sizeof(mdev->bus_info),
|
||||||
|
mdev->dev);
|
||||||
|
|
||||||
dev_dbg(mdev->dev, "Media device initialized\n");
|
dev_dbg(mdev->dev, "Media device initialized\n");
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(media_device_init);
|
EXPORT_SYMBOL_GPL(media_device_init);
|
||||||
|
|
|
||||||
|
|
@ -44,6 +44,20 @@ static inline const char *intf_type(struct media_interface *intf)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static inline const char *link_type_name(struct media_link *link)
|
||||||
|
{
|
||||||
|
switch (link->flags & MEDIA_LNK_FL_LINK_TYPE) {
|
||||||
|
case MEDIA_LNK_FL_DATA_LINK:
|
||||||
|
return "data";
|
||||||
|
case MEDIA_LNK_FL_INTERFACE_LINK:
|
||||||
|
return "interface";
|
||||||
|
case MEDIA_LNK_FL_ANCILLARY_LINK:
|
||||||
|
return "ancillary";
|
||||||
|
default:
|
||||||
|
return "unknown";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
__must_check int __media_entity_enum_init(struct media_entity_enum *ent_enum,
|
__must_check int __media_entity_enum_init(struct media_entity_enum *ent_enum,
|
||||||
int idx_max)
|
int idx_max)
|
||||||
{
|
{
|
||||||
|
|
@ -89,9 +103,7 @@ static void dev_dbg_obj(const char *event_name, struct media_gobj *gobj)
|
||||||
|
|
||||||
dev_dbg(gobj->mdev->dev,
|
dev_dbg(gobj->mdev->dev,
|
||||||
"%s id %u: %s link id %u ==> id %u\n",
|
"%s id %u: %s link id %u ==> id %u\n",
|
||||||
event_name, media_id(gobj),
|
event_name, media_id(gobj), link_type_name(link),
|
||||||
media_type(link->gobj0) == MEDIA_GRAPH_PAD ?
|
|
||||||
"data" : "interface",
|
|
||||||
media_id(link->gobj0),
|
media_id(link->gobj0),
|
||||||
media_id(link->gobj1));
|
media_id(link->gobj1));
|
||||||
break;
|
break;
|
||||||
|
|
@ -295,6 +307,12 @@ static void media_graph_walk_iter(struct media_graph *graph)
|
||||||
|
|
||||||
link = list_entry(link_top(graph), typeof(*link), list);
|
link = list_entry(link_top(graph), typeof(*link), list);
|
||||||
|
|
||||||
|
/* If the link is not a data link, don't follow it */
|
||||||
|
if ((link->flags & MEDIA_LNK_FL_LINK_TYPE) != MEDIA_LNK_FL_DATA_LINK) {
|
||||||
|
link_top(graph) = link_top(graph)->next;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
/* The link is not enabled so we do not follow. */
|
/* The link is not enabled so we do not follow. */
|
||||||
if (!(link->flags & MEDIA_LNK_FL_ENABLED)) {
|
if (!(link->flags & MEDIA_LNK_FL_ENABLED)) {
|
||||||
link_top(graph) = link_top(graph)->next;
|
link_top(graph) = link_top(graph)->next;
|
||||||
|
|
@ -579,26 +597,30 @@ static void __media_entity_remove_link(struct media_entity *entity,
|
||||||
struct media_link *rlink, *tmp;
|
struct media_link *rlink, *tmp;
|
||||||
struct media_entity *remote;
|
struct media_entity *remote;
|
||||||
|
|
||||||
if (link->source->entity == entity)
|
/* Remove the reverse links for a data link. */
|
||||||
remote = link->sink->entity;
|
if ((link->flags & MEDIA_LNK_FL_LINK_TYPE) == MEDIA_LNK_FL_DATA_LINK) {
|
||||||
else
|
|
||||||
remote = link->source->entity;
|
|
||||||
|
|
||||||
list_for_each_entry_safe(rlink, tmp, &remote->links, list) {
|
|
||||||
if (rlink != link->reverse)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (link->source->entity == entity)
|
if (link->source->entity == entity)
|
||||||
remote->num_backlinks--;
|
remote = link->sink->entity;
|
||||||
|
else
|
||||||
|
remote = link->source->entity;
|
||||||
|
|
||||||
/* Remove the remote link */
|
list_for_each_entry_safe(rlink, tmp, &remote->links, list) {
|
||||||
list_del(&rlink->list);
|
if (rlink != link->reverse)
|
||||||
media_gobj_destroy(&rlink->graph_obj);
|
continue;
|
||||||
kfree(rlink);
|
|
||||||
|
|
||||||
if (--remote->num_links == 0)
|
if (link->source->entity == entity)
|
||||||
break;
|
remote->num_backlinks--;
|
||||||
|
|
||||||
|
/* Remove the remote link */
|
||||||
|
list_del(&rlink->list);
|
||||||
|
media_gobj_destroy(&rlink->graph_obj);
|
||||||
|
kfree(rlink);
|
||||||
|
|
||||||
|
if (--remote->num_links == 0)
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
list_del(&link->list);
|
list_del(&link->list);
|
||||||
media_gobj_destroy(&link->graph_obj);
|
media_gobj_destroy(&link->graph_obj);
|
||||||
kfree(link);
|
kfree(link);
|
||||||
|
|
@ -1007,3 +1029,25 @@ void media_remove_intf_links(struct media_interface *intf)
|
||||||
mutex_unlock(&mdev->graph_mutex);
|
mutex_unlock(&mdev->graph_mutex);
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(media_remove_intf_links);
|
EXPORT_SYMBOL_GPL(media_remove_intf_links);
|
||||||
|
|
||||||
|
struct media_link *media_create_ancillary_link(struct media_entity *primary,
|
||||||
|
struct media_entity *ancillary)
|
||||||
|
{
|
||||||
|
struct media_link *link;
|
||||||
|
|
||||||
|
link = media_add_link(&primary->links);
|
||||||
|
if (!link)
|
||||||
|
return ERR_PTR(-ENOMEM);
|
||||||
|
|
||||||
|
link->gobj0 = &primary->graph_obj;
|
||||||
|
link->gobj1 = &ancillary->graph_obj;
|
||||||
|
link->flags = MEDIA_LNK_FL_IMMUTABLE | MEDIA_LNK_FL_ENABLED |
|
||||||
|
MEDIA_LNK_FL_ANCILLARY_LINK;
|
||||||
|
|
||||||
|
/* Initialize graph object embedded in the new link */
|
||||||
|
media_gobj_create(primary->graph_obj.mdev, MEDIA_GRAPH_LINK,
|
||||||
|
&link->graph_obj);
|
||||||
|
|
||||||
|
return link;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(media_create_ancillary_link);
|
||||||
|
|
|
||||||
|
|
@ -2435,8 +2435,6 @@ static int bttv_querycap(struct file *file, void *priv,
|
||||||
|
|
||||||
strscpy(cap->driver, "bttv", sizeof(cap->driver));
|
strscpy(cap->driver, "bttv", sizeof(cap->driver));
|
||||||
strscpy(cap->card, btv->video_dev.name, sizeof(cap->card));
|
strscpy(cap->card, btv->video_dev.name, sizeof(cap->card));
|
||||||
snprintf(cap->bus_info, sizeof(cap->bus_info),
|
|
||||||
"PCI:%s", pci_name(btv->c.pci));
|
|
||||||
cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_READWRITE |
|
cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_READWRITE |
|
||||||
V4L2_CAP_STREAMING | V4L2_CAP_DEVICE_CAPS;
|
V4L2_CAP_STREAMING | V4L2_CAP_DEVICE_CAPS;
|
||||||
if (no_overlay <= 0)
|
if (no_overlay <= 0)
|
||||||
|
|
|
||||||
|
|
@ -389,8 +389,6 @@ static int cx18_querycap(struct file *file, void *fh,
|
||||||
|
|
||||||
strscpy(vcap->driver, CX18_DRIVER_NAME, sizeof(vcap->driver));
|
strscpy(vcap->driver, CX18_DRIVER_NAME, sizeof(vcap->driver));
|
||||||
strscpy(vcap->card, cx->card_name, sizeof(vcap->card));
|
strscpy(vcap->card, cx->card_name, sizeof(vcap->card));
|
||||||
snprintf(vcap->bus_info, sizeof(vcap->bus_info),
|
|
||||||
"PCI:%s", pci_name(cx->pci_dev));
|
|
||||||
vcap->capabilities = cx->v4l2_cap | V4L2_CAP_DEVICE_CAPS;
|
vcap->capabilities = cx->v4l2_cap | V4L2_CAP_DEVICE_CAPS;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2165,7 +2165,7 @@ static int cx23885_initdev(struct pci_dev *pci_dev,
|
||||||
err = dma_set_mask(&pci_dev->dev, 0xffffffff);
|
err = dma_set_mask(&pci_dev->dev, 0xffffffff);
|
||||||
if (err) {
|
if (err) {
|
||||||
pr_err("%s/0: Oops: no 32bit PCI DMA ???\n", dev->name);
|
pr_err("%s/0: Oops: no 32bit PCI DMA ???\n", dev->name);
|
||||||
goto fail_ctrl;
|
goto fail_dma_set_mask;
|
||||||
}
|
}
|
||||||
|
|
||||||
err = request_irq(pci_dev->irq, cx23885_irq,
|
err = request_irq(pci_dev->irq, cx23885_irq,
|
||||||
|
|
@ -2173,7 +2173,7 @@ static int cx23885_initdev(struct pci_dev *pci_dev,
|
||||||
if (err < 0) {
|
if (err < 0) {
|
||||||
pr_err("%s: can't get IRQ %d\n",
|
pr_err("%s: can't get IRQ %d\n",
|
||||||
dev->name, pci_dev->irq);
|
dev->name, pci_dev->irq);
|
||||||
goto fail_irq;
|
goto fail_dma_set_mask;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (dev->board) {
|
switch (dev->board) {
|
||||||
|
|
@ -2195,7 +2195,7 @@ static int cx23885_initdev(struct pci_dev *pci_dev,
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
fail_irq:
|
fail_dma_set_mask:
|
||||||
cx23885_dev_unregister(dev);
|
cx23885_dev_unregister(dev);
|
||||||
fail_ctrl:
|
fail_ctrl:
|
||||||
v4l2_ctrl_handler_free(hdl);
|
v4l2_ctrl_handler_free(hdl);
|
||||||
|
|
|
||||||
|
|
@ -728,8 +728,8 @@ static int cx25821_audio_initdev(struct cx25821_dev *dev)
|
||||||
|
|
||||||
chip->irq = dev->pci->irq;
|
chip->irq = dev->pci->irq;
|
||||||
|
|
||||||
err = request_irq(dev->pci->irq, cx25821_irq,
|
err = devm_request_irq(&dev->pci->dev, dev->pci->irq, cx25821_irq,
|
||||||
IRQF_SHARED, chip->dev->name, chip);
|
IRQF_SHARED, chip->dev->name, chip);
|
||||||
|
|
||||||
if (err < 0) {
|
if (err < 0) {
|
||||||
pr_err("ERROR %s: can't get IRQ %d for ALSA\n", chip->dev->name,
|
pr_err("ERROR %s: can't get IRQ %d for ALSA\n", chip->dev->name,
|
||||||
|
|
|
||||||
|
|
@ -1332,11 +1332,11 @@ static void cx25821_finidev(struct pci_dev *pci_dev)
|
||||||
struct cx25821_dev *dev = get_cx25821(v4l2_dev);
|
struct cx25821_dev *dev = get_cx25821(v4l2_dev);
|
||||||
|
|
||||||
cx25821_shutdown(dev);
|
cx25821_shutdown(dev);
|
||||||
pci_disable_device(pci_dev);
|
|
||||||
|
|
||||||
/* unregister stuff */
|
/* unregister stuff */
|
||||||
if (pci_dev->irq)
|
if (pci_dev->irq)
|
||||||
free_irq(pci_dev->irq, dev);
|
free_irq(pci_dev->irq, dev);
|
||||||
|
pci_disable_device(pci_dev);
|
||||||
|
|
||||||
cx25821_dev_unregister(dev);
|
cx25821_dev_unregister(dev);
|
||||||
v4l2_device_unregister(v4l2_dev);
|
v4l2_device_unregister(v4l2_dev);
|
||||||
|
|
|
||||||
|
|
@ -796,7 +796,6 @@ static int vidioc_querycap(struct file *file, void *priv,
|
||||||
struct cx88_core *core = dev->core;
|
struct cx88_core *core = dev->core;
|
||||||
|
|
||||||
strscpy(cap->driver, "cx88_blackbird", sizeof(cap->driver));
|
strscpy(cap->driver, "cx88_blackbird", sizeof(cap->driver));
|
||||||
sprintf(cap->bus_info, "PCI:%s", pci_name(dev->pci));
|
|
||||||
return cx88_querycap(file, core, cap);
|
return cx88_querycap(file, core, cap);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -808,7 +808,6 @@ static int vidioc_querycap(struct file *file, void *priv,
|
||||||
struct cx88_core *core = dev->core;
|
struct cx88_core *core = dev->core;
|
||||||
|
|
||||||
strscpy(cap->driver, "cx8800", sizeof(cap->driver));
|
strscpy(cap->driver, "cx8800", sizeof(cap->driver));
|
||||||
sprintf(cap->bus_info, "PCI:%s", pci_name(dev->pci));
|
|
||||||
return cx88_querycap(file, core, cap);
|
return cx88_querycap(file, core, cap);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -292,11 +292,8 @@ static const struct v4l2_file_operations dt3155_fops = {
|
||||||
static int dt3155_querycap(struct file *filp, void *p,
|
static int dt3155_querycap(struct file *filp, void *p,
|
||||||
struct v4l2_capability *cap)
|
struct v4l2_capability *cap)
|
||||||
{
|
{
|
||||||
struct dt3155_priv *pd = video_drvdata(filp);
|
|
||||||
|
|
||||||
strscpy(cap->driver, DT3155_NAME, sizeof(cap->driver));
|
strscpy(cap->driver, DT3155_NAME, sizeof(cap->driver));
|
||||||
strscpy(cap->card, DT3155_NAME " frame grabber", sizeof(cap->card));
|
strscpy(cap->card, DT3155_NAME " frame grabber", sizeof(cap->card));
|
||||||
sprintf(cap->bus_info, "PCI:%s", pci_name(pd->pdev));
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -25,6 +25,8 @@ static const struct cio2_sensor_config cio2_supported_sensors[] = {
|
||||||
CIO2_SENSOR_CONFIG("INT33BE", 1, 419200000),
|
CIO2_SENSOR_CONFIG("INT33BE", 1, 419200000),
|
||||||
/* Omnivision OV8865 */
|
/* Omnivision OV8865 */
|
||||||
CIO2_SENSOR_CONFIG("INT347A", 1, 360000000),
|
CIO2_SENSOR_CONFIG("INT347A", 1, 360000000),
|
||||||
|
/* Omnivision OV7251 */
|
||||||
|
CIO2_SENSOR_CONFIG("INT347E", 1, 319200000),
|
||||||
/* Omnivision OV2680 */
|
/* Omnivision OV2680 */
|
||||||
CIO2_SENSOR_CONFIG("OVTI2680", 0),
|
CIO2_SENSOR_CONFIG("OVTI2680", 0),
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -65,6 +65,11 @@ static const struct ipu3_cio2_fmt formats[] = {
|
||||||
.fourcc = V4L2_PIX_FMT_IPU3_SRGGB10,
|
.fourcc = V4L2_PIX_FMT_IPU3_SRGGB10,
|
||||||
.mipicode = 0x2b,
|
.mipicode = 0x2b,
|
||||||
.bpp = 10,
|
.bpp = 10,
|
||||||
|
}, {
|
||||||
|
.mbus_code = MEDIA_BUS_FMT_Y10_1X10,
|
||||||
|
.fourcc = V4L2_PIX_FMT_IPU3_Y10,
|
||||||
|
.mipicode = 0x2b,
|
||||||
|
.bpp = 10,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -1046,12 +1051,8 @@ static const struct vb2_ops cio2_vb2_ops = {
|
||||||
static int cio2_v4l2_querycap(struct file *file, void *fh,
|
static int cio2_v4l2_querycap(struct file *file, void *fh,
|
||||||
struct v4l2_capability *cap)
|
struct v4l2_capability *cap)
|
||||||
{
|
{
|
||||||
struct cio2_device *cio2 = video_drvdata(file);
|
|
||||||
|
|
||||||
strscpy(cap->driver, CIO2_NAME, sizeof(cap->driver));
|
strscpy(cap->driver, CIO2_NAME, sizeof(cap->driver));
|
||||||
strscpy(cap->card, CIO2_DEVICE_NAME, sizeof(cap->card));
|
strscpy(cap->card, CIO2_DEVICE_NAME, sizeof(cap->card));
|
||||||
snprintf(cap->bus_info, sizeof(cap->bus_info),
|
|
||||||
"PCI:%s", pci_name(cio2->pci_dev));
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
@ -1777,8 +1778,6 @@ static int cio2_pci_probe(struct pci_dev *pci_dev,
|
||||||
cio2->media_dev.dev = dev;
|
cio2->media_dev.dev = dev;
|
||||||
strscpy(cio2->media_dev.model, CIO2_DEVICE_NAME,
|
strscpy(cio2->media_dev.model, CIO2_DEVICE_NAME,
|
||||||
sizeof(cio2->media_dev.model));
|
sizeof(cio2->media_dev.model));
|
||||||
snprintf(cio2->media_dev.bus_info, sizeof(cio2->media_dev.bus_info),
|
|
||||||
"PCI:%s", pci_name(cio2->pci_dev));
|
|
||||||
cio2->media_dev.hw_revision = 0;
|
cio2->media_dev.hw_revision = 0;
|
||||||
|
|
||||||
media_device_init(&cio2->media_dev);
|
media_device_init(&cio2->media_dev);
|
||||||
|
|
|
||||||
|
|
@ -732,7 +732,6 @@ static int ivtv_querycap(struct file *file, void *fh, struct v4l2_capability *vc
|
||||||
|
|
||||||
strscpy(vcap->driver, IVTV_DRIVER_NAME, sizeof(vcap->driver));
|
strscpy(vcap->driver, IVTV_DRIVER_NAME, sizeof(vcap->driver));
|
||||||
strscpy(vcap->card, itv->card_name, sizeof(vcap->card));
|
strscpy(vcap->card, itv->card_name, sizeof(vcap->card));
|
||||||
snprintf(vcap->bus_info, sizeof(vcap->bus_info), "PCI:%s", pci_name(itv->pdev));
|
|
||||||
vcap->capabilities = itv->v4l2_cap | V4L2_CAP_DEVICE_CAPS;
|
vcap->capabilities = itv->v4l2_cap | V4L2_CAP_DEVICE_CAPS;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1012,7 +1012,6 @@ static int vidioc_querycap(struct file *file, void *fh,
|
||||||
{
|
{
|
||||||
strscpy(cap->driver, "meye", sizeof(cap->driver));
|
strscpy(cap->driver, "meye", sizeof(cap->driver));
|
||||||
strscpy(cap->card, "meye", sizeof(cap->card));
|
strscpy(cap->card, "meye", sizeof(cap->card));
|
||||||
sprintf(cap->bus_info, "PCI:%s", pci_name(meye.mchip_dev));
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1475,7 +1475,6 @@ int saa7134_querycap(struct file *file, void *priv,
|
||||||
strscpy(cap->driver, "saa7134", sizeof(cap->driver));
|
strscpy(cap->driver, "saa7134", sizeof(cap->driver));
|
||||||
strscpy(cap->card, saa7134_boards[dev->board].name,
|
strscpy(cap->card, saa7134_boards[dev->board].name,
|
||||||
sizeof(cap->card));
|
sizeof(cap->card));
|
||||||
sprintf(cap->bus_info, "PCI:%s", pci_name(dev->pci));
|
|
||||||
cap->capabilities = V4L2_CAP_READWRITE | V4L2_CAP_STREAMING |
|
cap->capabilities = V4L2_CAP_READWRITE | V4L2_CAP_STREAMING |
|
||||||
V4L2_CAP_RADIO | V4L2_CAP_VIDEO_CAPTURE |
|
V4L2_CAP_RADIO | V4L2_CAP_VIDEO_CAPTURE |
|
||||||
V4L2_CAP_VBI_CAPTURE | V4L2_CAP_DEVICE_CAPS;
|
V4L2_CAP_VBI_CAPTURE | V4L2_CAP_DEVICE_CAPS;
|
||||||
|
|
@ -1833,8 +1832,7 @@ static int saa7134_overlay(struct file *file, void *priv, unsigned int on)
|
||||||
spin_lock_irqsave(&dev->slock, flags);
|
spin_lock_irqsave(&dev->slock, flags);
|
||||||
start_preview(dev);
|
start_preview(dev);
|
||||||
spin_unlock_irqrestore(&dev->slock, flags);
|
spin_unlock_irqrestore(&dev->slock, flags);
|
||||||
}
|
} else {
|
||||||
if (!on) {
|
|
||||||
if (priv != dev->overlay_owner)
|
if (priv != dev->overlay_owner)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
spin_lock_irqsave(&dev->slock, flags);
|
spin_lock_irqsave(&dev->slock, flags);
|
||||||
|
|
|
||||||
|
|
@ -490,7 +490,6 @@ static int vidioc_querycap(struct file *file, void *priv,
|
||||||
strscpy(cap->driver, dev->name, sizeof(cap->driver));
|
strscpy(cap->driver, dev->name, sizeof(cap->driver));
|
||||||
strscpy(cap->card, saa7164_boards[dev->board].name,
|
strscpy(cap->card, saa7164_boards[dev->board].name,
|
||||||
sizeof(cap->card));
|
sizeof(cap->card));
|
||||||
sprintf(cap->bus_info, "PCI:%s", pci_name(dev->pci));
|
|
||||||
cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_READWRITE |
|
cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_READWRITE |
|
||||||
V4L2_CAP_TUNER | V4L2_CAP_VBI_CAPTURE |
|
V4L2_CAP_TUNER | V4L2_CAP_VBI_CAPTURE |
|
||||||
V4L2_CAP_DEVICE_CAPS;
|
V4L2_CAP_DEVICE_CAPS;
|
||||||
|
|
|
||||||
|
|
@ -201,7 +201,6 @@ static int vidioc_querycap(struct file *file, void *priv,
|
||||||
strscpy(cap->driver, dev->name, sizeof(cap->driver));
|
strscpy(cap->driver, dev->name, sizeof(cap->driver));
|
||||||
strscpy(cap->card, saa7164_boards[dev->board].name,
|
strscpy(cap->card, saa7164_boards[dev->board].name,
|
||||||
sizeof(cap->card));
|
sizeof(cap->card));
|
||||||
sprintf(cap->bus_info, "PCI:%s", pci_name(dev->pci));
|
|
||||||
cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_READWRITE |
|
cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_READWRITE |
|
||||||
V4L2_CAP_TUNER | V4L2_CAP_VBI_CAPTURE |
|
V4L2_CAP_TUNER | V4L2_CAP_VBI_CAPTURE |
|
||||||
V4L2_CAP_DEVICE_CAPS;
|
V4L2_CAP_DEVICE_CAPS;
|
||||||
|
|
|
||||||
|
|
@ -764,13 +764,10 @@ static int solo_enc_querycap(struct file *file, void *priv,
|
||||||
struct v4l2_capability *cap)
|
struct v4l2_capability *cap)
|
||||||
{
|
{
|
||||||
struct solo_enc_dev *solo_enc = video_drvdata(file);
|
struct solo_enc_dev *solo_enc = video_drvdata(file);
|
||||||
struct solo_dev *solo_dev = solo_enc->solo_dev;
|
|
||||||
|
|
||||||
strscpy(cap->driver, SOLO6X10_NAME, sizeof(cap->driver));
|
strscpy(cap->driver, SOLO6X10_NAME, sizeof(cap->driver));
|
||||||
snprintf(cap->card, sizeof(cap->card), "Softlogic 6x10 Enc %d",
|
snprintf(cap->card, sizeof(cap->card), "Softlogic 6x10 Enc %d",
|
||||||
solo_enc->ch);
|
solo_enc->ch);
|
||||||
snprintf(cap->bus_info, sizeof(cap->bus_info), "PCI:%s",
|
|
||||||
pci_name(solo_dev->pdev));
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -372,12 +372,8 @@ static const struct vb2_ops solo_video_qops = {
|
||||||
static int solo_querycap(struct file *file, void *priv,
|
static int solo_querycap(struct file *file, void *priv,
|
||||||
struct v4l2_capability *cap)
|
struct v4l2_capability *cap)
|
||||||
{
|
{
|
||||||
struct solo_dev *solo_dev = video_drvdata(file);
|
|
||||||
|
|
||||||
strscpy(cap->driver, SOLO6X10_NAME, sizeof(cap->driver));
|
strscpy(cap->driver, SOLO6X10_NAME, sizeof(cap->driver));
|
||||||
strscpy(cap->card, "Softlogic 6x10", sizeof(cap->card));
|
strscpy(cap->card, "Softlogic 6x10", sizeof(cap->card));
|
||||||
snprintf(cap->bus_info, sizeof(cap->bus_info), "PCI:%s",
|
|
||||||
pci_name(solo_dev->pdev));
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -401,12 +401,8 @@ static const struct v4l2_file_operations vip_fops = {
|
||||||
static int vidioc_querycap(struct file *file, void *priv,
|
static int vidioc_querycap(struct file *file, void *priv,
|
||||||
struct v4l2_capability *cap)
|
struct v4l2_capability *cap)
|
||||||
{
|
{
|
||||||
struct sta2x11_vip *vip = video_drvdata(file);
|
|
||||||
|
|
||||||
strscpy(cap->driver, KBUILD_MODNAME, sizeof(cap->driver));
|
strscpy(cap->driver, KBUILD_MODNAME, sizeof(cap->driver));
|
||||||
strscpy(cap->card, KBUILD_MODNAME, sizeof(cap->card));
|
strscpy(cap->card, KBUILD_MODNAME, sizeof(cap->card));
|
||||||
snprintf(cap->bus_info, sizeof(cap->bus_info), "PCI:%s",
|
|
||||||
pci_name(vip->pdev));
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -604,7 +604,6 @@ static int tw5864_querycap(struct file *file, void *priv,
|
||||||
strscpy(cap->driver, "tw5864", sizeof(cap->driver));
|
strscpy(cap->driver, "tw5864", sizeof(cap->driver));
|
||||||
snprintf(cap->card, sizeof(cap->card), "TW5864 Encoder %d",
|
snprintf(cap->card, sizeof(cap->card), "TW5864 Encoder %d",
|
||||||
input->nr);
|
input->nr);
|
||||||
sprintf(cap->bus_info, "PCI:%s", pci_name(input->root->pci));
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -712,12 +712,9 @@ static int tw68_s_input(struct file *file, void *priv, unsigned int i)
|
||||||
static int tw68_querycap(struct file *file, void *priv,
|
static int tw68_querycap(struct file *file, void *priv,
|
||||||
struct v4l2_capability *cap)
|
struct v4l2_capability *cap)
|
||||||
{
|
{
|
||||||
struct tw68_dev *dev = video_drvdata(file);
|
|
||||||
|
|
||||||
strscpy(cap->driver, "tw68", sizeof(cap->driver));
|
strscpy(cap->driver, "tw68", sizeof(cap->driver));
|
||||||
strscpy(cap->card, "Techwell Capture Card",
|
strscpy(cap->card, "Techwell Capture Card",
|
||||||
sizeof(cap->card));
|
sizeof(cap->card));
|
||||||
sprintf(cap->bus_info, "PCI:%s", pci_name(dev->pci));
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -762,8 +762,6 @@ static int tw686x_querycap(struct file *file, void *priv,
|
||||||
|
|
||||||
strscpy(cap->driver, "tw686x", sizeof(cap->driver));
|
strscpy(cap->driver, "tw686x", sizeof(cap->driver));
|
||||||
strscpy(cap->card, dev->name, sizeof(cap->card));
|
strscpy(cap->card, dev->name, sizeof(cap->card));
|
||||||
snprintf(cap->bus_info, sizeof(cap->bus_info),
|
|
||||||
"PCI:%s", pci_name(dev->pci_dev));
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3249,13 +3249,8 @@ static int allegro_release(struct file *file)
|
||||||
static int allegro_querycap(struct file *file, void *fh,
|
static int allegro_querycap(struct file *file, void *fh,
|
||||||
struct v4l2_capability *cap)
|
struct v4l2_capability *cap)
|
||||||
{
|
{
|
||||||
struct video_device *vdev = video_devdata(file);
|
|
||||||
struct allegro_dev *dev = video_get_drvdata(vdev);
|
|
||||||
|
|
||||||
strscpy(cap->driver, KBUILD_MODNAME, sizeof(cap->driver));
|
strscpy(cap->driver, KBUILD_MODNAME, sizeof(cap->driver));
|
||||||
strscpy(cap->card, "Allegro DVT Video Encoder", sizeof(cap->card));
|
strscpy(cap->card, "Allegro DVT Video Encoder", sizeof(cap->card));
|
||||||
snprintf(cap->bus_info, sizeof(cap->bus_info), "platform:%s",
|
|
||||||
dev_name(&dev->plat_dev->dev));
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -26,8 +26,8 @@
|
||||||
#include "vpu_cmds.h"
|
#include "vpu_cmds.h"
|
||||||
#include "vpu_rpc.h"
|
#include "vpu_rpc.h"
|
||||||
|
|
||||||
#define VDEC_FRAME_DEPTH 256
|
|
||||||
#define VDEC_MIN_BUFFER_CAP 8
|
#define VDEC_MIN_BUFFER_CAP 8
|
||||||
|
#define VDEC_MIN_BUFFER_OUT 8
|
||||||
|
|
||||||
struct vdec_fs_info {
|
struct vdec_fs_info {
|
||||||
char name[8];
|
char name[8];
|
||||||
|
|
@ -63,8 +63,6 @@ struct vdec_t {
|
||||||
bool is_source_changed;
|
bool is_source_changed;
|
||||||
u32 source_change;
|
u32 source_change;
|
||||||
u32 drain;
|
u32 drain;
|
||||||
u32 ts_pre_count;
|
|
||||||
u32 frame_depth;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct vpu_format vdec_formats[] = {
|
static const struct vpu_format vdec_formats[] = {
|
||||||
|
|
@ -164,6 +162,12 @@ static int vdec_ctrl_init(struct vpu_inst *inst)
|
||||||
if (ctrl)
|
if (ctrl)
|
||||||
ctrl->flags |= V4L2_CTRL_FLAG_VOLATILE;
|
ctrl->flags |= V4L2_CTRL_FLAG_VOLATILE;
|
||||||
|
|
||||||
|
if (inst->ctrl_handler.error) {
|
||||||
|
ret = inst->ctrl_handler.error;
|
||||||
|
v4l2_ctrl_handler_free(&inst->ctrl_handler);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
ret = v4l2_ctrl_handler_setup(&inst->ctrl_handler);
|
ret = v4l2_ctrl_handler_setup(&inst->ctrl_handler);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
dev_err(inst->dev, "[%d] setup ctrls fail, ret = %d\n", inst->id, ret);
|
dev_err(inst->dev, "[%d] setup ctrls fail, ret = %d\n", inst->id, ret);
|
||||||
|
|
@ -470,7 +474,7 @@ static int vdec_drain(struct vpu_inst *inst)
|
||||||
if (!vdec->drain)
|
if (!vdec->drain)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (v4l2_m2m_num_src_bufs_ready(inst->fh.m2m_ctx))
|
if (!vpu_is_source_empty(inst))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (!vdec->params.frame_count) {
|
if (!vdec->params.frame_count) {
|
||||||
|
|
@ -589,11 +593,8 @@ static bool vdec_check_ready(struct vpu_inst *inst, unsigned int type)
|
||||||
{
|
{
|
||||||
struct vdec_t *vdec = inst->priv;
|
struct vdec_t *vdec = inst->priv;
|
||||||
|
|
||||||
if (V4L2_TYPE_IS_OUTPUT(type)) {
|
if (V4L2_TYPE_IS_OUTPUT(type))
|
||||||
if (vdec->ts_pre_count >= vdec->frame_depth)
|
|
||||||
return false;
|
|
||||||
return true;
|
return true;
|
||||||
}
|
|
||||||
|
|
||||||
if (vdec->req_frame_count)
|
if (vdec->req_frame_count)
|
||||||
return true;
|
return true;
|
||||||
|
|
@ -601,12 +602,21 @@ static bool vdec_check_ready(struct vpu_inst *inst, unsigned int type)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static struct vb2_v4l2_buffer *vdec_get_src_buffer(struct vpu_inst *inst, u32 count)
|
||||||
|
{
|
||||||
|
if (count > 1)
|
||||||
|
vpu_skip_frame(inst, count - 1);
|
||||||
|
|
||||||
|
return vpu_next_src_buf(inst);
|
||||||
|
}
|
||||||
|
|
||||||
static int vdec_frame_decoded(struct vpu_inst *inst, void *arg)
|
static int vdec_frame_decoded(struct vpu_inst *inst, void *arg)
|
||||||
{
|
{
|
||||||
struct vdec_t *vdec = inst->priv;
|
struct vdec_t *vdec = inst->priv;
|
||||||
struct vpu_dec_pic_info *info = arg;
|
struct vpu_dec_pic_info *info = arg;
|
||||||
struct vpu_vb2_buffer *vpu_buf;
|
struct vpu_vb2_buffer *vpu_buf;
|
||||||
struct vb2_v4l2_buffer *vbuf;
|
struct vb2_v4l2_buffer *vbuf;
|
||||||
|
struct vb2_v4l2_buffer *src_buf;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
if (!info || info->id >= ARRAY_SIZE(vdec->slots))
|
if (!info || info->id >= ARRAY_SIZE(vdec->slots))
|
||||||
|
|
@ -620,14 +630,21 @@ static int vdec_frame_decoded(struct vpu_inst *inst, void *arg)
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
vbuf = &vpu_buf->m2m_buf.vb;
|
vbuf = &vpu_buf->m2m_buf.vb;
|
||||||
|
src_buf = vdec_get_src_buffer(inst, info->consumed_count);
|
||||||
|
if (src_buf) {
|
||||||
|
v4l2_m2m_buf_copy_metadata(src_buf, vbuf, true);
|
||||||
|
if (info->consumed_count) {
|
||||||
|
v4l2_m2m_src_buf_remove(inst->fh.m2m_ctx);
|
||||||
|
vpu_set_buffer_state(src_buf, VPU_BUF_STATE_IDLE);
|
||||||
|
v4l2_m2m_buf_done(src_buf, VB2_BUF_STATE_DONE);
|
||||||
|
} else {
|
||||||
|
vpu_set_buffer_state(src_buf, VPU_BUF_STATE_DECODED);
|
||||||
|
}
|
||||||
|
}
|
||||||
if (vpu_get_buffer_state(vbuf) == VPU_BUF_STATE_DECODED)
|
if (vpu_get_buffer_state(vbuf) == VPU_BUF_STATE_DECODED)
|
||||||
dev_info(inst->dev, "[%d] buf[%d] has been decoded\n", inst->id, info->id);
|
dev_info(inst->dev, "[%d] buf[%d] has been decoded\n", inst->id, info->id);
|
||||||
vpu_set_buffer_state(vbuf, VPU_BUF_STATE_DECODED);
|
vpu_set_buffer_state(vbuf, VPU_BUF_STATE_DECODED);
|
||||||
vdec->decoded_frame_count++;
|
vdec->decoded_frame_count++;
|
||||||
if (vdec->ts_pre_count >= info->consumed_count)
|
|
||||||
vdec->ts_pre_count -= info->consumed_count;
|
|
||||||
else
|
|
||||||
vdec->ts_pre_count = 0;
|
|
||||||
exit:
|
exit:
|
||||||
vpu_inst_unlock(inst);
|
vpu_inst_unlock(inst);
|
||||||
|
|
||||||
|
|
@ -683,10 +700,9 @@ static void vdec_buf_done(struct vpu_inst *inst, struct vpu_frame_info *frame)
|
||||||
vpu_set_buffer_state(vbuf, VPU_BUF_STATE_READY);
|
vpu_set_buffer_state(vbuf, VPU_BUF_STATE_READY);
|
||||||
vb2_set_plane_payload(&vbuf->vb2_buf, 0, inst->cap_format.sizeimage[0]);
|
vb2_set_plane_payload(&vbuf->vb2_buf, 0, inst->cap_format.sizeimage[0]);
|
||||||
vb2_set_plane_payload(&vbuf->vb2_buf, 1, inst->cap_format.sizeimage[1]);
|
vb2_set_plane_payload(&vbuf->vb2_buf, 1, inst->cap_format.sizeimage[1]);
|
||||||
vbuf->vb2_buf.timestamp = frame->timestamp;
|
|
||||||
vbuf->field = inst->cap_format.field;
|
vbuf->field = inst->cap_format.field;
|
||||||
vbuf->sequence = sequence;
|
vbuf->sequence = sequence;
|
||||||
dev_dbg(inst->dev, "[%d][OUTPUT TS]%32lld\n", inst->id, frame->timestamp);
|
dev_dbg(inst->dev, "[%d][OUTPUT TS]%32lld\n", inst->id, vbuf->vb2_buf.timestamp);
|
||||||
|
|
||||||
v4l2_m2m_buf_done(vbuf, VB2_BUF_STATE_DONE);
|
v4l2_m2m_buf_done(vbuf, VB2_BUF_STATE_DONE);
|
||||||
vpu_inst_lock(inst);
|
vpu_inst_lock(inst);
|
||||||
|
|
@ -708,7 +724,6 @@ static void vdec_stop_done(struct vpu_inst *inst)
|
||||||
vdec->fixed_fmt = false;
|
vdec->fixed_fmt = false;
|
||||||
vdec->params.end_flag = 0;
|
vdec->params.end_flag = 0;
|
||||||
vdec->drain = 0;
|
vdec->drain = 0;
|
||||||
vdec->ts_pre_count = 0;
|
|
||||||
vdec->params.frame_count = 0;
|
vdec->params.frame_count = 0;
|
||||||
vdec->decoded_frame_count = 0;
|
vdec->decoded_frame_count = 0;
|
||||||
vdec->display_frame_count = 0;
|
vdec->display_frame_count = 0;
|
||||||
|
|
@ -782,7 +797,7 @@ static void vdec_init_fmt(struct vpu_inst *inst)
|
||||||
if (vdec->codec_info.progressive)
|
if (vdec->codec_info.progressive)
|
||||||
inst->cap_format.field = V4L2_FIELD_NONE;
|
inst->cap_format.field = V4L2_FIELD_NONE;
|
||||||
else
|
else
|
||||||
inst->cap_format.field = V4L2_FIELD_SEQ_BT;
|
inst->cap_format.field = V4L2_FIELD_SEQ_TB;
|
||||||
if (vdec->codec_info.color_primaries == V4L2_COLORSPACE_DEFAULT)
|
if (vdec->codec_info.color_primaries == V4L2_COLORSPACE_DEFAULT)
|
||||||
vdec->codec_info.color_primaries = V4L2_COLORSPACE_REC709;
|
vdec->codec_info.color_primaries = V4L2_COLORSPACE_REC709;
|
||||||
if (vdec->codec_info.transfer_chars == V4L2_XFER_FUNC_DEFAULT)
|
if (vdec->codec_info.transfer_chars == V4L2_XFER_FUNC_DEFAULT)
|
||||||
|
|
@ -1244,18 +1259,14 @@ static int vdec_process_output(struct vpu_inst *inst, struct vb2_buffer *vb)
|
||||||
if (free_space < vb2_get_plane_payload(vb, 0) + 0x40000)
|
if (free_space < vb2_get_plane_payload(vb, 0) + 0x40000)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
|
vpu_set_buffer_state(vbuf, VPU_BUF_STATE_INUSE);
|
||||||
ret = vpu_iface_input_frame(inst, vb);
|
ret = vpu_iface_input_frame(inst, vb);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
dev_dbg(inst->dev, "[%d][INPUT TS]%32lld\n", inst->id, vb->timestamp);
|
dev_dbg(inst->dev, "[%d][INPUT TS]%32lld\n", inst->id, vb->timestamp);
|
||||||
vdec->ts_pre_count++;
|
|
||||||
vdec->params.frame_count++;
|
vdec->params.frame_count++;
|
||||||
|
|
||||||
v4l2_m2m_src_buf_remove_by_buf(inst->fh.m2m_ctx, vbuf);
|
|
||||||
vpu_set_buffer_state(vbuf, VPU_BUF_STATE_IDLE);
|
|
||||||
v4l2_m2m_buf_done(vbuf, VB2_BUF_STATE_DONE);
|
|
||||||
|
|
||||||
if (vdec->drain)
|
if (vdec->drain)
|
||||||
vdec_drain(inst);
|
vdec_drain(inst);
|
||||||
|
|
||||||
|
|
@ -1318,7 +1329,6 @@ static void vdec_abort(struct vpu_inst *inst)
|
||||||
vdec->sequence);
|
vdec->sequence);
|
||||||
vdec->params.end_flag = 0;
|
vdec->params.end_flag = 0;
|
||||||
vdec->drain = 0;
|
vdec->drain = 0;
|
||||||
vdec->ts_pre_count = 0;
|
|
||||||
vdec->params.frame_count = 0;
|
vdec->params.frame_count = 0;
|
||||||
vdec->decoded_frame_count = 0;
|
vdec->decoded_frame_count = 0;
|
||||||
vdec->display_frame_count = 0;
|
vdec->display_frame_count = 0;
|
||||||
|
|
@ -1525,10 +1535,6 @@ static int vdec_get_debug_info(struct vpu_inst *inst, char *str, u32 size, u32 i
|
||||||
vdec->drain, vdec->eos_received, vdec->source_change);
|
vdec->drain, vdec->eos_received, vdec->source_change);
|
||||||
break;
|
break;
|
||||||
case 8:
|
case 8:
|
||||||
num = scnprintf(str, size, "ts_pre_count = %d, frame_depth = %d\n",
|
|
||||||
vdec->ts_pre_count, vdec->frame_depth);
|
|
||||||
break;
|
|
||||||
case 9:
|
|
||||||
num = scnprintf(str, size, "fps = %d/%d\n",
|
num = scnprintf(str, size, "fps = %d/%d\n",
|
||||||
vdec->codec_info.frame_rate.numerator,
|
vdec->codec_info.frame_rate.numerator,
|
||||||
vdec->codec_info.frame_rate.denominator);
|
vdec->codec_info.frame_rate.denominator);
|
||||||
|
|
@ -1562,12 +1568,8 @@ static struct vpu_inst_ops vdec_inst_ops = {
|
||||||
static void vdec_init(struct file *file)
|
static void vdec_init(struct file *file)
|
||||||
{
|
{
|
||||||
struct vpu_inst *inst = to_inst(file);
|
struct vpu_inst *inst = to_inst(file);
|
||||||
struct vdec_t *vdec;
|
|
||||||
struct v4l2_format f;
|
struct v4l2_format f;
|
||||||
|
|
||||||
vdec = inst->priv;
|
|
||||||
vdec->frame_depth = VDEC_FRAME_DEPTH;
|
|
||||||
|
|
||||||
memset(&f, 0, sizeof(f));
|
memset(&f, 0, sizeof(f));
|
||||||
f.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
|
f.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
|
||||||
f.fmt.pix_mp.pixelformat = V4L2_PIX_FMT_H264;
|
f.fmt.pix_mp.pixelformat = V4L2_PIX_FMT_H264;
|
||||||
|
|
@ -1612,36 +1614,18 @@ static int vdec_open(struct file *file)
|
||||||
|
|
||||||
vdec->fixed_fmt = false;
|
vdec->fixed_fmt = false;
|
||||||
inst->min_buffer_cap = VDEC_MIN_BUFFER_CAP;
|
inst->min_buffer_cap = VDEC_MIN_BUFFER_CAP;
|
||||||
|
inst->min_buffer_out = VDEC_MIN_BUFFER_OUT;
|
||||||
vdec_init(file);
|
vdec_init(file);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static __poll_t vdec_poll(struct file *file, poll_table *wait)
|
|
||||||
{
|
|
||||||
struct vpu_inst *inst = to_inst(file);
|
|
||||||
struct vb2_queue *src_q, *dst_q;
|
|
||||||
__poll_t ret;
|
|
||||||
|
|
||||||
ret = v4l2_m2m_fop_poll(file, wait);
|
|
||||||
src_q = v4l2_m2m_get_src_vq(inst->fh.m2m_ctx);
|
|
||||||
dst_q = v4l2_m2m_get_dst_vq(inst->fh.m2m_ctx);
|
|
||||||
if (vb2_is_streaming(src_q) && !vb2_is_streaming(dst_q))
|
|
||||||
ret &= (~EPOLLERR);
|
|
||||||
if (!src_q->error && !dst_q->error &&
|
|
||||||
(vb2_is_streaming(src_q) && list_empty(&src_q->queued_list)) &&
|
|
||||||
(vb2_is_streaming(dst_q) && list_empty(&dst_q->queued_list)))
|
|
||||||
ret &= (~EPOLLERR);
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
static const struct v4l2_file_operations vdec_fops = {
|
static const struct v4l2_file_operations vdec_fops = {
|
||||||
.owner = THIS_MODULE,
|
.owner = THIS_MODULE,
|
||||||
.open = vdec_open,
|
.open = vdec_open,
|
||||||
.release = vpu_v4l2_close,
|
.release = vpu_v4l2_close,
|
||||||
.unlocked_ioctl = video_ioctl2,
|
.unlocked_ioctl = video_ioctl2,
|
||||||
.poll = vdec_poll,
|
.poll = v4l2_m2m_fop_poll,
|
||||||
.mmap = v4l2_m2m_fop_mmap,
|
.mmap = v4l2_m2m_fop_mmap,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -33,6 +33,8 @@
|
||||||
#define VENC_CAPTURE_ENABLE BIT(1)
|
#define VENC_CAPTURE_ENABLE BIT(1)
|
||||||
#define VENC_ENABLE_MASK (VENC_OUTPUT_ENABLE | VENC_CAPTURE_ENABLE)
|
#define VENC_ENABLE_MASK (VENC_OUTPUT_ENABLE | VENC_CAPTURE_ENABLE)
|
||||||
#define VENC_MAX_BUF_CNT 8
|
#define VENC_MAX_BUF_CNT 8
|
||||||
|
#define VENC_MIN_BUFFER_OUT 6
|
||||||
|
#define VENC_MIN_BUFFER_CAP 6
|
||||||
|
|
||||||
struct venc_t {
|
struct venc_t {
|
||||||
struct vpu_encode_params params;
|
struct vpu_encode_params params;
|
||||||
|
|
@ -281,6 +283,9 @@ static int venc_g_parm(struct file *file, void *fh, struct v4l2_streamparm *parm
|
||||||
if (!parm)
|
if (!parm)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
|
if (!V4L2_TYPE_IS_OUTPUT(parm->type))
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
if (!vpu_helper_check_type(inst, parm->type))
|
if (!vpu_helper_check_type(inst, parm->type))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
|
|
@ -302,6 +307,9 @@ static int venc_s_parm(struct file *file, void *fh, struct v4l2_streamparm *parm
|
||||||
if (!parm)
|
if (!parm)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
|
if (!V4L2_TYPE_IS_OUTPUT(parm->type))
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
if (!vpu_helper_check_type(inst, parm->type))
|
if (!vpu_helper_check_type(inst, parm->type))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
|
|
@ -423,7 +431,7 @@ static int venc_drain(struct vpu_inst *inst)
|
||||||
if (inst->state != VPU_CODEC_STATE_DRAIN)
|
if (inst->state != VPU_CODEC_STATE_DRAIN)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (v4l2_m2m_num_src_bufs_ready(inst->fh.m2m_ctx))
|
if (!vpu_is_source_empty(inst))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (!venc->input_ready)
|
if (!venc->input_ready)
|
||||||
|
|
@ -680,6 +688,12 @@ static int venc_ctrl_init(struct vpu_inst *inst)
|
||||||
~(1 << V4L2_MPEG_VIDEO_HEADER_MODE_JOINED_WITH_1ST_FRAME),
|
~(1 << V4L2_MPEG_VIDEO_HEADER_MODE_JOINED_WITH_1ST_FRAME),
|
||||||
V4L2_MPEG_VIDEO_HEADER_MODE_JOINED_WITH_1ST_FRAME);
|
V4L2_MPEG_VIDEO_HEADER_MODE_JOINED_WITH_1ST_FRAME);
|
||||||
|
|
||||||
|
if (inst->ctrl_handler.error) {
|
||||||
|
ret = inst->ctrl_handler.error;
|
||||||
|
v4l2_ctrl_handler_free(&inst->ctrl_handler);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
ret = v4l2_ctrl_handler_setup(&inst->ctrl_handler);
|
ret = v4l2_ctrl_handler_setup(&inst->ctrl_handler);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
dev_err(inst->dev, "[%d] setup ctrls fail, ret = %d\n", inst->id, ret);
|
dev_err(inst->dev, "[%d] setup ctrls fail, ret = %d\n", inst->id, ret);
|
||||||
|
|
@ -775,10 +789,20 @@ static int venc_get_one_encoded_frame(struct vpu_inst *inst,
|
||||||
struct vb2_v4l2_buffer *vbuf)
|
struct vb2_v4l2_buffer *vbuf)
|
||||||
{
|
{
|
||||||
struct venc_t *venc = inst->priv;
|
struct venc_t *venc = inst->priv;
|
||||||
|
struct vb2_v4l2_buffer *src_buf;
|
||||||
|
|
||||||
if (!vbuf)
|
if (!vbuf)
|
||||||
return -EAGAIN;
|
return -EAGAIN;
|
||||||
|
|
||||||
|
src_buf = vpu_find_buf_by_sequence(inst, inst->out_format.type, frame->info.frame_id);
|
||||||
|
if (src_buf) {
|
||||||
|
v4l2_m2m_buf_copy_metadata(src_buf, vbuf, true);
|
||||||
|
vpu_set_buffer_state(src_buf, VPU_BUF_STATE_IDLE);
|
||||||
|
v4l2_m2m_src_buf_remove_by_buf(inst->fh.m2m_ctx, src_buf);
|
||||||
|
v4l2_m2m_buf_done(src_buf, VB2_BUF_STATE_DONE);
|
||||||
|
} else {
|
||||||
|
vbuf->vb2_buf.timestamp = frame->info.timestamp;
|
||||||
|
}
|
||||||
if (!venc_get_enable(inst->priv, vbuf->vb2_buf.type)) {
|
if (!venc_get_enable(inst->priv, vbuf->vb2_buf.type)) {
|
||||||
v4l2_m2m_buf_done(vbuf, VB2_BUF_STATE_ERROR);
|
v4l2_m2m_buf_done(vbuf, VB2_BUF_STATE_ERROR);
|
||||||
return 0;
|
return 0;
|
||||||
|
|
@ -800,11 +824,10 @@ static int venc_get_one_encoded_frame(struct vpu_inst *inst,
|
||||||
}
|
}
|
||||||
vb2_set_plane_payload(&vbuf->vb2_buf, 0, frame->bytesused);
|
vb2_set_plane_payload(&vbuf->vb2_buf, 0, frame->bytesused);
|
||||||
vbuf->sequence = frame->info.frame_id;
|
vbuf->sequence = frame->info.frame_id;
|
||||||
vbuf->vb2_buf.timestamp = frame->info.timestamp;
|
|
||||||
vbuf->field = inst->cap_format.field;
|
vbuf->field = inst->cap_format.field;
|
||||||
vbuf->flags |= frame->info.pic_type;
|
vbuf->flags |= frame->info.pic_type;
|
||||||
vpu_set_buffer_state(vbuf, VPU_BUF_STATE_IDLE);
|
vpu_set_buffer_state(vbuf, VPU_BUF_STATE_IDLE);
|
||||||
dev_dbg(inst->dev, "[%d][OUTPUT TS]%32lld\n", inst->id, frame->info.timestamp);
|
dev_dbg(inst->dev, "[%d][OUTPUT TS]%32lld\n", inst->id, vbuf->vb2_buf.timestamp);
|
||||||
v4l2_m2m_buf_done(vbuf, VB2_BUF_STATE_DONE);
|
v4l2_m2m_buf_done(vbuf, VB2_BUF_STATE_DONE);
|
||||||
venc->ready_count++;
|
venc->ready_count++;
|
||||||
|
|
||||||
|
|
@ -860,33 +883,6 @@ static int venc_frame_encoded(struct vpu_inst *inst, void *arg)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void venc_buf_done(struct vpu_inst *inst, struct vpu_frame_info *frame)
|
|
||||||
{
|
|
||||||
struct vb2_v4l2_buffer *vbuf;
|
|
||||||
|
|
||||||
if (!inst->fh.m2m_ctx)
|
|
||||||
return;
|
|
||||||
|
|
||||||
vpu_inst_lock(inst);
|
|
||||||
if (!venc_get_enable(inst->priv, frame->type))
|
|
||||||
goto exit;
|
|
||||||
vbuf = vpu_find_buf_by_sequence(inst, frame->type, frame->sequence);
|
|
||||||
if (!vbuf) {
|
|
||||||
dev_err(inst->dev, "[%d] can't find buf: type %d, sequence %d\n",
|
|
||||||
inst->id, frame->type, frame->sequence);
|
|
||||||
goto exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
vpu_set_buffer_state(vbuf, VPU_BUF_STATE_IDLE);
|
|
||||||
if (V4L2_TYPE_IS_OUTPUT(frame->type))
|
|
||||||
v4l2_m2m_src_buf_remove_by_buf(inst->fh.m2m_ctx, vbuf);
|
|
||||||
else
|
|
||||||
v4l2_m2m_dst_buf_remove_by_buf(inst->fh.m2m_ctx, vbuf);
|
|
||||||
v4l2_m2m_buf_done(vbuf, VB2_BUF_STATE_DONE);
|
|
||||||
exit:
|
|
||||||
vpu_inst_unlock(inst);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void venc_set_last_buffer_dequeued(struct vpu_inst *inst)
|
static void venc_set_last_buffer_dequeued(struct vpu_inst *inst)
|
||||||
{
|
{
|
||||||
struct venc_t *venc = inst->priv;
|
struct venc_t *venc = inst->priv;
|
||||||
|
|
@ -1252,7 +1248,6 @@ static struct vpu_inst_ops venc_inst_ops = {
|
||||||
.check_ready = venc_check_ready,
|
.check_ready = venc_check_ready,
|
||||||
.input_done = venc_input_done,
|
.input_done = venc_input_done,
|
||||||
.get_one_frame = venc_frame_encoded,
|
.get_one_frame = venc_frame_encoded,
|
||||||
.buf_done = venc_buf_done,
|
|
||||||
.stop_done = venc_stop_done,
|
.stop_done = venc_stop_done,
|
||||||
.event_notify = venc_event_notify,
|
.event_notify = venc_event_notify,
|
||||||
.release = venc_release,
|
.release = venc_release,
|
||||||
|
|
@ -1333,6 +1328,8 @@ static int venc_open(struct file *file)
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
|
inst->min_buffer_out = VENC_MIN_BUFFER_OUT;
|
||||||
|
inst->min_buffer_cap = VENC_MIN_BUFFER_CAP;
|
||||||
venc_init(file);
|
venc_init(file);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
||||||
|
|
@ -413,10 +413,6 @@ int vpu_inst_create_dbgfs_file(struct vpu_inst *inst)
|
||||||
vpu->debugfs,
|
vpu->debugfs,
|
||||||
inst,
|
inst,
|
||||||
&vpu_dbg_inst_fops);
|
&vpu_dbg_inst_fops);
|
||||||
if (!inst->debugfs) {
|
|
||||||
dev_err(inst->dev, "vpu create debugfs %s fail\n", name);
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
@ -451,10 +447,6 @@ int vpu_core_create_dbgfs_file(struct vpu_core *core)
|
||||||
vpu->debugfs,
|
vpu->debugfs,
|
||||||
core,
|
core,
|
||||||
&vpu_dbg_core_fops);
|
&vpu_dbg_core_fops);
|
||||||
if (!core->debugfs) {
|
|
||||||
dev_err(core->dev, "vpu create debugfs %s fail\n", name);
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (!core->debugfs_fwlog) {
|
if (!core->debugfs_fwlog) {
|
||||||
scnprintf(name, sizeof(name), "fwlog.%d", core->id);
|
scnprintf(name, sizeof(name), "fwlog.%d", core->id);
|
||||||
|
|
@ -463,10 +455,6 @@ int vpu_core_create_dbgfs_file(struct vpu_core *core)
|
||||||
vpu->debugfs,
|
vpu->debugfs,
|
||||||
core,
|
core,
|
||||||
&vpu_dbg_fwlog_fops);
|
&vpu_dbg_fwlog_fops);
|
||||||
if (!core->debugfs_fwlog) {
|
|
||||||
dev_err(core->dev, "vpu create debugfs %s fail\n", name);
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
||||||
|
|
@ -69,8 +69,8 @@ enum {
|
||||||
VPU_MSG_ID_BS_ERROR,
|
VPU_MSG_ID_BS_ERROR,
|
||||||
VPU_MSG_ID_UNSUPPORTED,
|
VPU_MSG_ID_UNSUPPORTED,
|
||||||
VPU_MSG_ID_TIMESTAMP_INFO,
|
VPU_MSG_ID_TIMESTAMP_INFO,
|
||||||
|
|
||||||
VPU_MSG_ID_FIRMWARE_XCPT,
|
VPU_MSG_ID_FIRMWARE_XCPT,
|
||||||
|
VPU_MSG_ID_PIC_SKIPPED,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum VPU_ENC_MEMORY_RESOURSE {
|
enum VPU_ENC_MEMORY_RESOURSE {
|
||||||
|
|
|
||||||
|
|
@ -170,6 +170,7 @@ enum {
|
||||||
VID_API_EVENT_DEC_CHECK_RES = 0x24,
|
VID_API_EVENT_DEC_CHECK_RES = 0x24,
|
||||||
VID_API_EVENT_DEC_CFG_INFO = 0x25,
|
VID_API_EVENT_DEC_CFG_INFO = 0x25,
|
||||||
VID_API_EVENT_UNSUPPORTED_STREAM = 0x26,
|
VID_API_EVENT_UNSUPPORTED_STREAM = 0x26,
|
||||||
|
VID_API_EVENT_PIC_SKIPPED = 0x27,
|
||||||
VID_API_EVENT_STR_SUSPENDED = 0x30,
|
VID_API_EVENT_STR_SUSPENDED = 0x30,
|
||||||
VID_API_EVENT_SNAPSHOT_DONE = 0x40,
|
VID_API_EVENT_SNAPSHOT_DONE = 0x40,
|
||||||
VID_API_EVENT_FW_STATUS = 0xF0,
|
VID_API_EVENT_FW_STATUS = 0xF0,
|
||||||
|
|
@ -703,6 +704,7 @@ static struct vpu_pair malone_msgs[] = {
|
||||||
{VPU_MSG_ID_BS_ERROR, VID_API_EVENT_BS_ERROR},
|
{VPU_MSG_ID_BS_ERROR, VID_API_EVENT_BS_ERROR},
|
||||||
{VPU_MSG_ID_UNSUPPORTED, VID_API_EVENT_UNSUPPORTED_STREAM},
|
{VPU_MSG_ID_UNSUPPORTED, VID_API_EVENT_UNSUPPORTED_STREAM},
|
||||||
{VPU_MSG_ID_FIRMWARE_XCPT, VID_API_EVENT_FIRMWARE_XCPT},
|
{VPU_MSG_ID_FIRMWARE_XCPT, VID_API_EVENT_FIRMWARE_XCPT},
|
||||||
|
{VPU_MSG_ID_PIC_SKIPPED, VID_API_EVENT_PIC_SKIPPED},
|
||||||
};
|
};
|
||||||
|
|
||||||
static void vpu_malone_pack_fs_alloc(struct vpu_rpc_event *pkt,
|
static void vpu_malone_pack_fs_alloc(struct vpu_rpc_event *pkt,
|
||||||
|
|
@ -1556,7 +1558,7 @@ int vpu_malone_input_frame(struct vpu_shared_addr *shared,
|
||||||
* merge the data to next frame
|
* merge the data to next frame
|
||||||
*/
|
*/
|
||||||
vbuf = to_vb2_v4l2_buffer(vb);
|
vbuf = to_vb2_v4l2_buffer(vb);
|
||||||
if (vpu_vb_is_codecconfig(vbuf) && (s64)vb->timestamp < 0) {
|
if (vpu_vb_is_codecconfig(vbuf)) {
|
||||||
inst->extra_size += size;
|
inst->extra_size += size;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -166,6 +166,13 @@ static void vpu_session_handle_firmware_xcpt(struct vpu_inst *inst, struct vpu_r
|
||||||
vpu_v4l2_set_error(inst);
|
vpu_v4l2_set_error(inst);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void vpu_session_handle_pic_skipped(struct vpu_inst *inst, struct vpu_rpc_event *pkt)
|
||||||
|
{
|
||||||
|
vpu_inst_lock(inst);
|
||||||
|
vpu_skip_frame(inst, 1);
|
||||||
|
vpu_inst_unlock(inst);
|
||||||
|
}
|
||||||
|
|
||||||
static struct vpu_msg_handler handlers[] = {
|
static struct vpu_msg_handler handlers[] = {
|
||||||
{VPU_MSG_ID_START_DONE, vpu_session_handle_start_done},
|
{VPU_MSG_ID_START_DONE, vpu_session_handle_start_done},
|
||||||
{VPU_MSG_ID_STOP_DONE, vpu_session_handle_stop_done},
|
{VPU_MSG_ID_STOP_DONE, vpu_session_handle_stop_done},
|
||||||
|
|
@ -181,6 +188,7 @@ static struct vpu_msg_handler handlers[] = {
|
||||||
{VPU_MSG_ID_PIC_EOS, vpu_session_handle_eos},
|
{VPU_MSG_ID_PIC_EOS, vpu_session_handle_eos},
|
||||||
{VPU_MSG_ID_UNSUPPORTED, vpu_session_handle_error},
|
{VPU_MSG_ID_UNSUPPORTED, vpu_session_handle_error},
|
||||||
{VPU_MSG_ID_FIRMWARE_XCPT, vpu_session_handle_firmware_xcpt},
|
{VPU_MSG_ID_FIRMWARE_XCPT, vpu_session_handle_firmware_xcpt},
|
||||||
|
{VPU_MSG_ID_PIC_SKIPPED, vpu_session_handle_pic_skipped},
|
||||||
};
|
};
|
||||||
|
|
||||||
static int vpu_session_handle_msg(struct vpu_inst *inst, struct vpu_rpc_event *msg)
|
static int vpu_session_handle_msg(struct vpu_inst *inst, struct vpu_rpc_event *msg)
|
||||||
|
|
|
||||||
|
|
@ -73,10 +73,10 @@ void vpu_v4l2_set_error(struct vpu_inst *inst)
|
||||||
if (inst->fh.m2m_ctx) {
|
if (inst->fh.m2m_ctx) {
|
||||||
src_q = v4l2_m2m_get_src_vq(inst->fh.m2m_ctx);
|
src_q = v4l2_m2m_get_src_vq(inst->fh.m2m_ctx);
|
||||||
dst_q = v4l2_m2m_get_dst_vq(inst->fh.m2m_ctx);
|
dst_q = v4l2_m2m_get_dst_vq(inst->fh.m2m_ctx);
|
||||||
if (src_q)
|
src_q->error = 1;
|
||||||
src_q->error = 1;
|
dst_q->error = 1;
|
||||||
if (dst_q)
|
wake_up(&src_q->done_wq);
|
||||||
dst_q->error = 1;
|
wake_up(&dst_q->done_wq);
|
||||||
}
|
}
|
||||||
vpu_inst_unlock(inst);
|
vpu_inst_unlock(inst);
|
||||||
}
|
}
|
||||||
|
|
@ -127,6 +127,19 @@ int vpu_set_last_buffer_dequeued(struct vpu_inst *inst)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool vpu_is_source_empty(struct vpu_inst *inst)
|
||||||
|
{
|
||||||
|
struct v4l2_m2m_buffer *buf = NULL;
|
||||||
|
|
||||||
|
if (!inst->fh.m2m_ctx)
|
||||||
|
return true;
|
||||||
|
v4l2_m2m_for_each_src_buf(inst->fh.m2m_ctx, buf) {
|
||||||
|
if (vpu_get_buffer_state(&buf->vb) == VPU_BUF_STATE_IDLE)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
const struct vpu_format *vpu_try_fmt_common(struct vpu_inst *inst, struct v4l2_format *f)
|
const struct vpu_format *vpu_try_fmt_common(struct vpu_inst *inst, struct v4l2_format *f)
|
||||||
{
|
{
|
||||||
struct v4l2_pix_format_mplane *pixmp = &f->fmt.pix_mp;
|
struct v4l2_pix_format_mplane *pixmp = &f->fmt.pix_mp;
|
||||||
|
|
@ -234,6 +247,49 @@ int vpu_process_capture_buffer(struct vpu_inst *inst)
|
||||||
return call_vop(inst, process_capture, &vbuf->vb2_buf);
|
return call_vop(inst, process_capture, &vbuf->vb2_buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct vb2_v4l2_buffer *vpu_next_src_buf(struct vpu_inst *inst)
|
||||||
|
{
|
||||||
|
struct vb2_v4l2_buffer *src_buf = v4l2_m2m_next_src_buf(inst->fh.m2m_ctx);
|
||||||
|
|
||||||
|
if (!src_buf || vpu_get_buffer_state(src_buf) == VPU_BUF_STATE_IDLE)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
while (vpu_vb_is_codecconfig(src_buf)) {
|
||||||
|
v4l2_m2m_src_buf_remove(inst->fh.m2m_ctx);
|
||||||
|
vpu_set_buffer_state(src_buf, VPU_BUF_STATE_IDLE);
|
||||||
|
v4l2_m2m_buf_done(src_buf, VB2_BUF_STATE_DONE);
|
||||||
|
|
||||||
|
src_buf = v4l2_m2m_next_src_buf(inst->fh.m2m_ctx);
|
||||||
|
if (!src_buf || vpu_get_buffer_state(src_buf) == VPU_BUF_STATE_IDLE)
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return src_buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
void vpu_skip_frame(struct vpu_inst *inst, int count)
|
||||||
|
{
|
||||||
|
struct vb2_v4l2_buffer *src_buf;
|
||||||
|
enum vb2_buffer_state state;
|
||||||
|
int i = 0;
|
||||||
|
|
||||||
|
if (count <= 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
while (i < count) {
|
||||||
|
src_buf = v4l2_m2m_src_buf_remove(inst->fh.m2m_ctx);
|
||||||
|
if (!src_buf || vpu_get_buffer_state(src_buf) == VPU_BUF_STATE_IDLE)
|
||||||
|
return;
|
||||||
|
if (vpu_get_buffer_state(src_buf) == VPU_BUF_STATE_DECODED)
|
||||||
|
state = VB2_BUF_STATE_DONE;
|
||||||
|
else
|
||||||
|
state = VB2_BUF_STATE_ERROR;
|
||||||
|
i++;
|
||||||
|
vpu_set_buffer_state(src_buf, VPU_BUF_STATE_IDLE);
|
||||||
|
v4l2_m2m_buf_done(src_buf, state);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
struct vb2_v4l2_buffer *vpu_find_buf_by_sequence(struct vpu_inst *inst, u32 type, u32 sequence)
|
struct vb2_v4l2_buffer *vpu_find_buf_by_sequence(struct vpu_inst *inst, u32 type, u32 sequence)
|
||||||
{
|
{
|
||||||
struct v4l2_m2m_buffer *buf = NULL;
|
struct v4l2_m2m_buffer *buf = NULL;
|
||||||
|
|
@ -342,6 +398,10 @@ static int vpu_vb2_queue_setup(struct vb2_queue *vq,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (V4L2_TYPE_IS_OUTPUT(vq->type))
|
||||||
|
*buf_count = max_t(unsigned int, *buf_count, inst->min_buffer_out);
|
||||||
|
else
|
||||||
|
*buf_count = max_t(unsigned int, *buf_count, inst->min_buffer_cap);
|
||||||
*plane_count = cur_fmt->num_planes;
|
*plane_count = cur_fmt->num_planes;
|
||||||
for (i = 0; i < cur_fmt->num_planes; i++)
|
for (i = 0; i < cur_fmt->num_planes; i++)
|
||||||
psize[i] = cur_fmt->sizeimage[i];
|
psize[i] = cur_fmt->sizeimage[i];
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,8 @@ int vpu_v4l2_close(struct file *file);
|
||||||
const struct vpu_format *vpu_try_fmt_common(struct vpu_inst *inst, struct v4l2_format *f);
|
const struct vpu_format *vpu_try_fmt_common(struct vpu_inst *inst, struct v4l2_format *f);
|
||||||
int vpu_process_output_buffer(struct vpu_inst *inst);
|
int vpu_process_output_buffer(struct vpu_inst *inst);
|
||||||
int vpu_process_capture_buffer(struct vpu_inst *inst);
|
int vpu_process_capture_buffer(struct vpu_inst *inst);
|
||||||
|
struct vb2_v4l2_buffer *vpu_next_src_buf(struct vpu_inst *inst);
|
||||||
|
void vpu_skip_frame(struct vpu_inst *inst, int count);
|
||||||
struct vb2_v4l2_buffer *vpu_find_buf_by_sequence(struct vpu_inst *inst, u32 type, u32 sequence);
|
struct vb2_v4l2_buffer *vpu_find_buf_by_sequence(struct vpu_inst *inst, u32 type, u32 sequence);
|
||||||
struct vb2_v4l2_buffer *vpu_find_buf_by_idx(struct vpu_inst *inst, u32 type, u32 idx);
|
struct vb2_v4l2_buffer *vpu_find_buf_by_idx(struct vpu_inst *inst, u32 type, u32 idx);
|
||||||
void vpu_v4l2_set_error(struct vpu_inst *inst);
|
void vpu_v4l2_set_error(struct vpu_inst *inst);
|
||||||
|
|
@ -27,6 +29,7 @@ int vpu_notify_source_change(struct vpu_inst *inst);
|
||||||
int vpu_set_last_buffer_dequeued(struct vpu_inst *inst);
|
int vpu_set_last_buffer_dequeued(struct vpu_inst *inst);
|
||||||
void vpu_vb2_buffers_return(struct vpu_inst *inst, unsigned int type, enum vb2_buffer_state state);
|
void vpu_vb2_buffers_return(struct vpu_inst *inst, unsigned int type, enum vb2_buffer_state state);
|
||||||
int vpu_get_num_buffers(struct vpu_inst *inst, u32 type);
|
int vpu_get_num_buffers(struct vpu_inst *inst, u32 type);
|
||||||
|
bool vpu_is_source_empty(struct vpu_inst *inst);
|
||||||
|
|
||||||
dma_addr_t vpu_get_vb_phy_addr(struct vb2_buffer *vb, u32 plane_no);
|
dma_addr_t vpu_get_vb_phy_addr(struct vb2_buffer *vb, u32 plane_no);
|
||||||
unsigned int vpu_get_vb_length(struct vb2_buffer *vb, u32 plane_no);
|
unsigned int vpu_get_vb_length(struct vb2_buffer *vb, u32 plane_no);
|
||||||
|
|
|
||||||
|
|
@ -1993,6 +1993,7 @@ static int aspeed_video_probe(struct platform_device *pdev)
|
||||||
|
|
||||||
rc = aspeed_video_setup_video(video);
|
rc = aspeed_video_setup_video(video);
|
||||||
if (rc) {
|
if (rc) {
|
||||||
|
aspeed_video_free_buf(video, &video->jpeg);
|
||||||
clk_unprepare(video->vclk);
|
clk_unprepare(video->vclk);
|
||||||
clk_unprepare(video->eclk);
|
clk_unprepare(video->eclk);
|
||||||
return rc;
|
return rc;
|
||||||
|
|
@ -2024,8 +2025,7 @@ static int aspeed_video_remove(struct platform_device *pdev)
|
||||||
|
|
||||||
v4l2_device_unregister(v4l2_dev);
|
v4l2_device_unregister(v4l2_dev);
|
||||||
|
|
||||||
dma_free_coherent(video->dev, VE_JPEG_HEADER_SIZE, video->jpeg.virt,
|
aspeed_video_free_buf(video, &video->jpeg);
|
||||||
video->jpeg.dma);
|
|
||||||
|
|
||||||
of_reserved_mem_device_release(dev);
|
of_reserved_mem_device_release(dev);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -401,6 +401,7 @@ static void isc_stop_streaming(struct vb2_queue *vq)
|
||||||
struct isc_buffer *buf;
|
struct isc_buffer *buf;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
|
mutex_lock(&isc->awb_mutex);
|
||||||
v4l2_ctrl_activate(isc->do_wb_ctrl, false);
|
v4l2_ctrl_activate(isc->do_wb_ctrl, false);
|
||||||
|
|
||||||
isc->stop = true;
|
isc->stop = true;
|
||||||
|
|
@ -410,6 +411,8 @@ static void isc_stop_streaming(struct vb2_queue *vq)
|
||||||
v4l2_err(&isc->v4l2_dev,
|
v4l2_err(&isc->v4l2_dev,
|
||||||
"Timeout waiting for end of the capture\n");
|
"Timeout waiting for end of the capture\n");
|
||||||
|
|
||||||
|
mutex_unlock(&isc->awb_mutex);
|
||||||
|
|
||||||
/* Disable DMA interrupt */
|
/* Disable DMA interrupt */
|
||||||
regmap_write(isc->regmap, ISC_INTDIS, ISC_INT_DDONE);
|
regmap_write(isc->regmap, ISC_INTDIS, ISC_INT_DDONE);
|
||||||
|
|
||||||
|
|
@ -442,7 +445,7 @@ static void isc_buffer_queue(struct vb2_buffer *vb)
|
||||||
|
|
||||||
spin_lock_irqsave(&isc->dma_queue_lock, flags);
|
spin_lock_irqsave(&isc->dma_queue_lock, flags);
|
||||||
if (!isc->cur_frm && list_empty(&isc->dma_queue) &&
|
if (!isc->cur_frm && list_empty(&isc->dma_queue) &&
|
||||||
vb2_is_streaming(vb->vb2_queue)) {
|
vb2_start_streaming_called(vb->vb2_queue)) {
|
||||||
isc->cur_frm = buf;
|
isc->cur_frm = buf;
|
||||||
isc_start_dma(isc);
|
isc_start_dma(isc);
|
||||||
} else
|
} else
|
||||||
|
|
@ -1029,7 +1032,7 @@ static int isc_s_fmt_vid_cap(struct file *file, void *priv,
|
||||||
{
|
{
|
||||||
struct isc_device *isc = video_drvdata(file);
|
struct isc_device *isc = video_drvdata(file);
|
||||||
|
|
||||||
if (vb2_is_streaming(&isc->vb2_vidq))
|
if (vb2_is_busy(&isc->vb2_vidq))
|
||||||
return -EBUSY;
|
return -EBUSY;
|
||||||
|
|
||||||
return isc_set_fmt(isc, f);
|
return isc_set_fmt(isc, f);
|
||||||
|
|
@ -1397,10 +1400,6 @@ static void isc_awb_work(struct work_struct *w)
|
||||||
u32 min, max;
|
u32 min, max;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
/* streaming is not active anymore */
|
|
||||||
if (isc->stop)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (ctrls->hist_stat != HIST_ENABLED)
|
if (ctrls->hist_stat != HIST_ENABLED)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
|
@ -1455,7 +1454,24 @@ static void isc_awb_work(struct work_struct *w)
|
||||||
}
|
}
|
||||||
regmap_write(regmap, ISC_HIS_CFG + isc->offsets.his,
|
regmap_write(regmap, ISC_HIS_CFG + isc->offsets.his,
|
||||||
hist_id | baysel | ISC_HIS_CFG_RAR);
|
hist_id | baysel | ISC_HIS_CFG_RAR);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We have to make sure the streaming has not stopped meanwhile.
|
||||||
|
* ISC requires a frame to clock the internal profile update.
|
||||||
|
* To avoid issues, lock the sequence with a mutex
|
||||||
|
*/
|
||||||
|
mutex_lock(&isc->awb_mutex);
|
||||||
|
|
||||||
|
/* streaming is not active anymore */
|
||||||
|
if (isc->stop) {
|
||||||
|
mutex_unlock(&isc->awb_mutex);
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
|
||||||
isc_update_profile(isc);
|
isc_update_profile(isc);
|
||||||
|
|
||||||
|
mutex_unlock(&isc->awb_mutex);
|
||||||
|
|
||||||
/* if awb has been disabled, we don't need to start another histogram */
|
/* if awb has been disabled, we don't need to start another histogram */
|
||||||
if (ctrls->awb)
|
if (ctrls->awb)
|
||||||
regmap_write(regmap, ISC_CTRLEN, ISC_CTRL_HISREQ);
|
regmap_write(regmap, ISC_CTRLEN, ISC_CTRL_HISREQ);
|
||||||
|
|
@ -1534,6 +1550,7 @@ static int isc_s_awb_ctrl(struct v4l2_ctrl *ctrl)
|
||||||
|
|
||||||
isc_update_awb_ctrls(isc);
|
isc_update_awb_ctrls(isc);
|
||||||
|
|
||||||
|
mutex_lock(&isc->awb_mutex);
|
||||||
if (vb2_is_streaming(&isc->vb2_vidq)) {
|
if (vb2_is_streaming(&isc->vb2_vidq)) {
|
||||||
/*
|
/*
|
||||||
* If we are streaming, we can update profile to
|
* If we are streaming, we can update profile to
|
||||||
|
|
@ -1548,6 +1565,7 @@ static int isc_s_awb_ctrl(struct v4l2_ctrl *ctrl)
|
||||||
*/
|
*/
|
||||||
v4l2_ctrl_activate(isc->do_wb_ctrl, false);
|
v4l2_ctrl_activate(isc->do_wb_ctrl, false);
|
||||||
}
|
}
|
||||||
|
mutex_unlock(&isc->awb_mutex);
|
||||||
|
|
||||||
/* if we have autowhitebalance on, start histogram procedure */
|
/* if we have autowhitebalance on, start histogram procedure */
|
||||||
if (ctrls->awb == ISC_WB_AUTO &&
|
if (ctrls->awb == ISC_WB_AUTO &&
|
||||||
|
|
@ -1729,6 +1747,7 @@ static void isc_async_unbind(struct v4l2_async_notifier *notifier,
|
||||||
{
|
{
|
||||||
struct isc_device *isc = container_of(notifier->v4l2_dev,
|
struct isc_device *isc = container_of(notifier->v4l2_dev,
|
||||||
struct isc_device, v4l2_dev);
|
struct isc_device, v4l2_dev);
|
||||||
|
mutex_destroy(&isc->awb_mutex);
|
||||||
cancel_work_sync(&isc->awb_work);
|
cancel_work_sync(&isc->awb_work);
|
||||||
video_unregister_device(&isc->video_dev);
|
video_unregister_device(&isc->video_dev);
|
||||||
v4l2_ctrl_handler_free(&isc->ctrls.handler);
|
v4l2_ctrl_handler_free(&isc->ctrls.handler);
|
||||||
|
|
@ -1838,6 +1857,8 @@ static int isc_async_complete(struct v4l2_async_notifier *notifier)
|
||||||
isc->current_subdev = container_of(notifier,
|
isc->current_subdev = container_of(notifier,
|
||||||
struct isc_subdev_entity, notifier);
|
struct isc_subdev_entity, notifier);
|
||||||
mutex_init(&isc->lock);
|
mutex_init(&isc->lock);
|
||||||
|
mutex_init(&isc->awb_mutex);
|
||||||
|
|
||||||
init_completion(&isc->comp);
|
init_completion(&isc->comp);
|
||||||
|
|
||||||
/* Initialize videobuf2 queue */
|
/* Initialize videobuf2 queue */
|
||||||
|
|
@ -1906,6 +1927,7 @@ static int isc_async_complete(struct v4l2_async_notifier *notifier)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
isc_async_complete_err:
|
isc_async_complete_err:
|
||||||
|
mutex_destroy(&isc->awb_mutex);
|
||||||
mutex_destroy(&isc->lock);
|
mutex_destroy(&isc->lock);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -218,6 +218,7 @@ struct isc_reg_offsets {
|
||||||
*
|
*
|
||||||
* @lock: lock for serializing userspace file operations
|
* @lock: lock for serializing userspace file operations
|
||||||
* with ISC operations
|
* with ISC operations
|
||||||
|
* @awb_mutex: serialize access to streaming status from awb work queue
|
||||||
* @awb_lock: lock for serializing awb work queue operations
|
* @awb_lock: lock for serializing awb work queue operations
|
||||||
* with DMA/buffer operations
|
* with DMA/buffer operations
|
||||||
*
|
*
|
||||||
|
|
@ -272,7 +273,7 @@ struct isc_device {
|
||||||
struct video_device video_dev;
|
struct video_device video_dev;
|
||||||
|
|
||||||
struct vb2_queue vb2_vidq;
|
struct vb2_queue vb2_vidq;
|
||||||
spinlock_t dma_queue_lock; /* serialize access to dma queue */
|
spinlock_t dma_queue_lock;
|
||||||
struct list_head dma_queue;
|
struct list_head dma_queue;
|
||||||
struct isc_buffer *cur_frm;
|
struct isc_buffer *cur_frm;
|
||||||
unsigned int sequence;
|
unsigned int sequence;
|
||||||
|
|
@ -289,8 +290,9 @@ struct isc_device {
|
||||||
struct isc_ctrls ctrls;
|
struct isc_ctrls ctrls;
|
||||||
struct work_struct awb_work;
|
struct work_struct awb_work;
|
||||||
|
|
||||||
struct mutex lock; /* serialize access to file operations */
|
struct mutex lock;
|
||||||
spinlock_t awb_lock; /* serialize access to DMA buffers from awb work queue */
|
struct mutex awb_mutex;
|
||||||
|
spinlock_t awb_lock;
|
||||||
|
|
||||||
struct regmap_field *pipeline[ISC_PIPE_LINE_NODE_NUM];
|
struct regmap_field *pipeline[ISC_PIPE_LINE_NODE_NUM];
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -60,56 +60,39 @@
|
||||||
static const struct isc_format sama5d2_controller_formats[] = {
|
static const struct isc_format sama5d2_controller_formats[] = {
|
||||||
{
|
{
|
||||||
.fourcc = V4L2_PIX_FMT_ARGB444,
|
.fourcc = V4L2_PIX_FMT_ARGB444,
|
||||||
},
|
}, {
|
||||||
{
|
|
||||||
.fourcc = V4L2_PIX_FMT_ARGB555,
|
.fourcc = V4L2_PIX_FMT_ARGB555,
|
||||||
},
|
}, {
|
||||||
{
|
|
||||||
.fourcc = V4L2_PIX_FMT_RGB565,
|
.fourcc = V4L2_PIX_FMT_RGB565,
|
||||||
},
|
}, {
|
||||||
{
|
|
||||||
.fourcc = V4L2_PIX_FMT_ABGR32,
|
.fourcc = V4L2_PIX_FMT_ABGR32,
|
||||||
},
|
}, {
|
||||||
{
|
|
||||||
.fourcc = V4L2_PIX_FMT_XBGR32,
|
.fourcc = V4L2_PIX_FMT_XBGR32,
|
||||||
},
|
}, {
|
||||||
{
|
|
||||||
.fourcc = V4L2_PIX_FMT_YUV420,
|
.fourcc = V4L2_PIX_FMT_YUV420,
|
||||||
},
|
}, {
|
||||||
{
|
|
||||||
.fourcc = V4L2_PIX_FMT_YUYV,
|
.fourcc = V4L2_PIX_FMT_YUYV,
|
||||||
},
|
}, {
|
||||||
{
|
|
||||||
.fourcc = V4L2_PIX_FMT_YUV422P,
|
.fourcc = V4L2_PIX_FMT_YUV422P,
|
||||||
},
|
}, {
|
||||||
{
|
|
||||||
.fourcc = V4L2_PIX_FMT_GREY,
|
.fourcc = V4L2_PIX_FMT_GREY,
|
||||||
},
|
}, {
|
||||||
{
|
|
||||||
.fourcc = V4L2_PIX_FMT_Y10,
|
.fourcc = V4L2_PIX_FMT_Y10,
|
||||||
},
|
}, {
|
||||||
{
|
|
||||||
.fourcc = V4L2_PIX_FMT_SBGGR8,
|
.fourcc = V4L2_PIX_FMT_SBGGR8,
|
||||||
},
|
}, {
|
||||||
{
|
|
||||||
.fourcc = V4L2_PIX_FMT_SGBRG8,
|
.fourcc = V4L2_PIX_FMT_SGBRG8,
|
||||||
},
|
}, {
|
||||||
{
|
|
||||||
.fourcc = V4L2_PIX_FMT_SGRBG8,
|
.fourcc = V4L2_PIX_FMT_SGRBG8,
|
||||||
},
|
}, {
|
||||||
{
|
|
||||||
.fourcc = V4L2_PIX_FMT_SRGGB8,
|
.fourcc = V4L2_PIX_FMT_SRGGB8,
|
||||||
},
|
}, {
|
||||||
{
|
|
||||||
.fourcc = V4L2_PIX_FMT_SBGGR10,
|
.fourcc = V4L2_PIX_FMT_SBGGR10,
|
||||||
},
|
}, {
|
||||||
{
|
|
||||||
.fourcc = V4L2_PIX_FMT_SGBRG10,
|
.fourcc = V4L2_PIX_FMT_SGBRG10,
|
||||||
},
|
}, {
|
||||||
{
|
|
||||||
.fourcc = V4L2_PIX_FMT_SGRBG10,
|
.fourcc = V4L2_PIX_FMT_SGRBG10,
|
||||||
},
|
}, {
|
||||||
{
|
|
||||||
.fourcc = V4L2_PIX_FMT_SRGGB10,
|
.fourcc = V4L2_PIX_FMT_SRGGB10,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
@ -291,7 +274,7 @@ static void isc_sama5d2_config_rlp(struct isc_device *isc)
|
||||||
* Thus, if the YCYC mode is selected, replace it with the
|
* Thus, if the YCYC mode is selected, replace it with the
|
||||||
* sama5d2-compliant mode which is YYCC .
|
* sama5d2-compliant mode which is YYCC .
|
||||||
*/
|
*/
|
||||||
if ((rlp_mode & ISC_RLP_CFG_MODE_YCYC) == ISC_RLP_CFG_MODE_YCYC) {
|
if ((rlp_mode & ISC_RLP_CFG_MODE_MASK) == ISC_RLP_CFG_MODE_YCYC) {
|
||||||
rlp_mode &= ~ISC_RLP_CFG_MODE_MASK;
|
rlp_mode &= ~ISC_RLP_CFG_MODE_MASK;
|
||||||
rlp_mode |= ISC_RLP_CFG_MODE_YYCC;
|
rlp_mode |= ISC_RLP_CFG_MODE_YYCC;
|
||||||
}
|
}
|
||||||
|
|
@ -562,7 +545,7 @@ static int atmel_isc_probe(struct platform_device *pdev)
|
||||||
ret = clk_prepare_enable(isc->ispck);
|
ret = clk_prepare_enable(isc->ispck);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
dev_err(dev, "failed to enable ispck: %d\n", ret);
|
dev_err(dev, "failed to enable ispck: %d\n", ret);
|
||||||
goto cleanup_subdev;
|
goto disable_pm;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ispck should be greater or equal to hclock */
|
/* ispck should be greater or equal to hclock */
|
||||||
|
|
@ -580,6 +563,9 @@ static int atmel_isc_probe(struct platform_device *pdev)
|
||||||
unprepare_clk:
|
unprepare_clk:
|
||||||
clk_disable_unprepare(isc->ispck);
|
clk_disable_unprepare(isc->ispck);
|
||||||
|
|
||||||
|
disable_pm:
|
||||||
|
pm_runtime_disable(dev);
|
||||||
|
|
||||||
cleanup_subdev:
|
cleanup_subdev:
|
||||||
isc_subdev_cleanup(isc);
|
isc_subdev_cleanup(isc);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -63,65 +63,45 @@
|
||||||
static const struct isc_format sama7g5_controller_formats[] = {
|
static const struct isc_format sama7g5_controller_formats[] = {
|
||||||
{
|
{
|
||||||
.fourcc = V4L2_PIX_FMT_ARGB444,
|
.fourcc = V4L2_PIX_FMT_ARGB444,
|
||||||
},
|
}, {
|
||||||
{
|
|
||||||
.fourcc = V4L2_PIX_FMT_ARGB555,
|
.fourcc = V4L2_PIX_FMT_ARGB555,
|
||||||
},
|
}, {
|
||||||
{
|
|
||||||
.fourcc = V4L2_PIX_FMT_RGB565,
|
.fourcc = V4L2_PIX_FMT_RGB565,
|
||||||
},
|
}, {
|
||||||
{
|
|
||||||
.fourcc = V4L2_PIX_FMT_ABGR32,
|
.fourcc = V4L2_PIX_FMT_ABGR32,
|
||||||
},
|
}, {
|
||||||
{
|
|
||||||
.fourcc = V4L2_PIX_FMT_XBGR32,
|
.fourcc = V4L2_PIX_FMT_XBGR32,
|
||||||
},
|
}, {
|
||||||
{
|
|
||||||
.fourcc = V4L2_PIX_FMT_YUV420,
|
.fourcc = V4L2_PIX_FMT_YUV420,
|
||||||
},
|
}, {
|
||||||
{
|
|
||||||
.fourcc = V4L2_PIX_FMT_UYVY,
|
.fourcc = V4L2_PIX_FMT_UYVY,
|
||||||
},
|
}, {
|
||||||
{
|
|
||||||
.fourcc = V4L2_PIX_FMT_VYUY,
|
.fourcc = V4L2_PIX_FMT_VYUY,
|
||||||
},
|
}, {
|
||||||
{
|
|
||||||
.fourcc = V4L2_PIX_FMT_YUYV,
|
.fourcc = V4L2_PIX_FMT_YUYV,
|
||||||
},
|
}, {
|
||||||
{
|
|
||||||
.fourcc = V4L2_PIX_FMT_YUV422P,
|
.fourcc = V4L2_PIX_FMT_YUV422P,
|
||||||
},
|
}, {
|
||||||
{
|
|
||||||
.fourcc = V4L2_PIX_FMT_GREY,
|
.fourcc = V4L2_PIX_FMT_GREY,
|
||||||
},
|
}, {
|
||||||
{
|
|
||||||
.fourcc = V4L2_PIX_FMT_Y10,
|
.fourcc = V4L2_PIX_FMT_Y10,
|
||||||
},
|
}, {
|
||||||
{
|
|
||||||
.fourcc = V4L2_PIX_FMT_Y16,
|
.fourcc = V4L2_PIX_FMT_Y16,
|
||||||
},
|
}, {
|
||||||
{
|
|
||||||
.fourcc = V4L2_PIX_FMT_SBGGR8,
|
.fourcc = V4L2_PIX_FMT_SBGGR8,
|
||||||
},
|
}, {
|
||||||
{
|
|
||||||
.fourcc = V4L2_PIX_FMT_SGBRG8,
|
.fourcc = V4L2_PIX_FMT_SGBRG8,
|
||||||
},
|
}, {
|
||||||
{
|
|
||||||
.fourcc = V4L2_PIX_FMT_SGRBG8,
|
.fourcc = V4L2_PIX_FMT_SGRBG8,
|
||||||
},
|
}, {
|
||||||
{
|
|
||||||
.fourcc = V4L2_PIX_FMT_SRGGB8,
|
.fourcc = V4L2_PIX_FMT_SRGGB8,
|
||||||
},
|
}, {
|
||||||
{
|
|
||||||
.fourcc = V4L2_PIX_FMT_SBGGR10,
|
.fourcc = V4L2_PIX_FMT_SBGGR10,
|
||||||
},
|
}, {
|
||||||
{
|
|
||||||
.fourcc = V4L2_PIX_FMT_SGBRG10,
|
.fourcc = V4L2_PIX_FMT_SGBRG10,
|
||||||
},
|
}, {
|
||||||
{
|
|
||||||
.fourcc = V4L2_PIX_FMT_SGRBG10,
|
.fourcc = V4L2_PIX_FMT_SGRBG10,
|
||||||
},
|
}, {
|
||||||
{
|
|
||||||
.fourcc = V4L2_PIX_FMT_SRGGB10,
|
.fourcc = V4L2_PIX_FMT_SRGGB10,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
@ -225,7 +205,6 @@ static struct isc_format sama7g5_formats_list[] = {
|
||||||
.mbus_code = MEDIA_BUS_FMT_Y10_1X10,
|
.mbus_code = MEDIA_BUS_FMT_Y10_1X10,
|
||||||
.pfe_cfg0_bps = ISC_PFG_CFG0_BPS_TEN,
|
.pfe_cfg0_bps = ISC_PFG_CFG0_BPS_TEN,
|
||||||
},
|
},
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static void isc_sama7g5_config_csc(struct isc_device *isc)
|
static void isc_sama7g5_config_csc(struct isc_device *isc)
|
||||||
|
|
|
||||||
|
|
@ -454,6 +454,10 @@ static int csi2dc_init_cfg(struct v4l2_subdev *csi2dc_sd,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static const struct media_entity_operations csi2dc_entity_ops = {
|
||||||
|
.link_validate = v4l2_subdev_link_validate,
|
||||||
|
};
|
||||||
|
|
||||||
static const struct v4l2_subdev_pad_ops csi2dc_pad_ops = {
|
static const struct v4l2_subdev_pad_ops csi2dc_pad_ops = {
|
||||||
.enum_mbus_code = csi2dc_enum_mbus_code,
|
.enum_mbus_code = csi2dc_enum_mbus_code,
|
||||||
.set_fmt = csi2dc_set_fmt,
|
.set_fmt = csi2dc_set_fmt,
|
||||||
|
|
@ -683,6 +687,7 @@ static int csi2dc_probe(struct platform_device *pdev)
|
||||||
|
|
||||||
csi2dc->csi2dc_sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
|
csi2dc->csi2dc_sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
|
||||||
csi2dc->csi2dc_sd.entity.function = MEDIA_ENT_F_VID_IF_BRIDGE;
|
csi2dc->csi2dc_sd.entity.function = MEDIA_ENT_F_VID_IF_BRIDGE;
|
||||||
|
csi2dc->csi2dc_sd.entity.ops = &csi2dc_entity_ops;
|
||||||
|
|
||||||
platform_set_drvdata(pdev, csi2dc);
|
platform_set_drvdata(pdev, csi2dc);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,7 @@
|
||||||
#include <linux/platform_device.h>
|
#include <linux/platform_device.h>
|
||||||
#include <linux/slab.h>
|
#include <linux/slab.h>
|
||||||
|
|
||||||
|
#include <media/mipi-csi2.h>
|
||||||
#include <media/v4l2-ctrls.h>
|
#include <media/v4l2-ctrls.h>
|
||||||
#include <media/v4l2-device.h>
|
#include <media/v4l2-device.h>
|
||||||
#include <media/v4l2-fwnode.h>
|
#include <media/v4l2-fwnode.h>
|
||||||
|
|
@ -121,12 +122,12 @@ static const struct csi2tx_fmt csi2tx_formats[] = {
|
||||||
{
|
{
|
||||||
.mbus = MEDIA_BUS_FMT_UYVY8_1X16,
|
.mbus = MEDIA_BUS_FMT_UYVY8_1X16,
|
||||||
.bpp = 2,
|
.bpp = 2,
|
||||||
.dt = 0x1e,
|
.dt = MIPI_CSI2_DT_YUV422_8B,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
.mbus = MEDIA_BUS_FMT_RGB888_1X24,
|
.mbus = MEDIA_BUS_FMT_RGB888_1X24,
|
||||||
.bpp = 3,
|
.bpp = 3,
|
||||||
.dt = 0x24,
|
.dt = MIPI_CSI2_DT_RGB888,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -326,6 +326,8 @@ void coda_fill_bitstream(struct coda_ctx *ctx, struct list_head *buffer_list)
|
||||||
struct coda_buffer_meta *meta;
|
struct coda_buffer_meta *meta;
|
||||||
u32 start;
|
u32 start;
|
||||||
|
|
||||||
|
lockdep_assert_held(&ctx->bitstream_mutex);
|
||||||
|
|
||||||
if (ctx->bit_stream_param & CODA_BIT_STREAM_END_FLAG)
|
if (ctx->bit_stream_param & CODA_BIT_STREAM_END_FLAG)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
|
@ -2174,7 +2176,6 @@ static int coda_prepare_decode(struct coda_ctx *ctx)
|
||||||
(!(ctx->bit_stream_param & CODA_BIT_STREAM_END_FLAG))) {
|
(!(ctx->bit_stream_param & CODA_BIT_STREAM_END_FLAG))) {
|
||||||
coda_dbg(1, ctx, "bitstream payload: %d, skipping\n",
|
coda_dbg(1, ctx, "bitstream payload: %d, skipping\n",
|
||||||
coda_get_bitstream_payload(ctx));
|
coda_get_bitstream_payload(ctx));
|
||||||
v4l2_m2m_job_finish(ctx->dev->m2m_dev, ctx->fh.m2m_ctx);
|
|
||||||
return -EAGAIN;
|
return -EAGAIN;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2184,7 +2185,6 @@ static int coda_prepare_decode(struct coda_ctx *ctx)
|
||||||
|
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
v4l2_err(&dev->v4l2_dev, "failed to start decoding\n");
|
v4l2_err(&dev->v4l2_dev, "failed to start decoding\n");
|
||||||
v4l2_m2m_job_finish(ctx->dev->m2m_dev, ctx->fh.m2m_ctx);
|
|
||||||
return -EAGAIN;
|
return -EAGAIN;
|
||||||
} else {
|
} else {
|
||||||
ctx->initialized = 1;
|
ctx->initialized = 1;
|
||||||
|
|
|
||||||
|
|
@ -657,6 +657,8 @@ static int coda_try_fmt_vid_cap(struct file *file, void *priv,
|
||||||
const struct coda_q_data *q_data_src;
|
const struct coda_q_data *q_data_src;
|
||||||
const struct coda_codec *codec;
|
const struct coda_codec *codec;
|
||||||
struct vb2_queue *src_vq;
|
struct vb2_queue *src_vq;
|
||||||
|
int hscale = 0;
|
||||||
|
int vscale = 0;
|
||||||
int ret;
|
int ret;
|
||||||
bool use_vdoa;
|
bool use_vdoa;
|
||||||
|
|
||||||
|
|
@ -673,8 +675,13 @@ static int coda_try_fmt_vid_cap(struct file *file, void *priv,
|
||||||
*/
|
*/
|
||||||
src_vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT);
|
src_vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT);
|
||||||
if (vb2_is_streaming(src_vq)) {
|
if (vb2_is_streaming(src_vq)) {
|
||||||
f->fmt.pix.width = q_data_src->width;
|
if (q_data_src->fourcc == V4L2_PIX_FMT_JPEG &&
|
||||||
f->fmt.pix.height = q_data_src->height;
|
ctx->dev->devtype->product == CODA_960) {
|
||||||
|
hscale = coda_jpeg_scale(q_data_src->width, f->fmt.pix.width);
|
||||||
|
vscale = coda_jpeg_scale(q_data_src->height, f->fmt.pix.height);
|
||||||
|
}
|
||||||
|
f->fmt.pix.width = q_data_src->width >> hscale;
|
||||||
|
f->fmt.pix.height = q_data_src->height >> vscale;
|
||||||
|
|
||||||
if (q_data_src->fourcc == V4L2_PIX_FMT_JPEG) {
|
if (q_data_src->fourcc == V4L2_PIX_FMT_JPEG) {
|
||||||
if (ctx->params.jpeg_chroma_subsampling ==
|
if (ctx->params.jpeg_chroma_subsampling ==
|
||||||
|
|
@ -704,8 +711,8 @@ static int coda_try_fmt_vid_cap(struct file *file, void *priv,
|
||||||
|
|
||||||
/* The decoders always write complete macroblocks or MCUs */
|
/* The decoders always write complete macroblocks or MCUs */
|
||||||
if (ctx->inst_type == CODA_INST_DECODER) {
|
if (ctx->inst_type == CODA_INST_DECODER) {
|
||||||
f->fmt.pix.bytesperline = round_up(f->fmt.pix.width, 16);
|
f->fmt.pix.bytesperline = round_up(f->fmt.pix.width, 16 >> hscale);
|
||||||
f->fmt.pix.height = round_up(f->fmt.pix.height, 16);
|
f->fmt.pix.height = round_up(f->fmt.pix.height, 16 >> vscale);
|
||||||
if (codec->src_fourcc == V4L2_PIX_FMT_JPEG &&
|
if (codec->src_fourcc == V4L2_PIX_FMT_JPEG &&
|
||||||
f->fmt.pix.pixelformat == V4L2_PIX_FMT_YUV422P) {
|
f->fmt.pix.pixelformat == V4L2_PIX_FMT_YUV422P) {
|
||||||
f->fmt.pix.sizeimage = f->fmt.pix.bytesperline *
|
f->fmt.pix.sizeimage = f->fmt.pix.bytesperline *
|
||||||
|
|
@ -850,17 +857,26 @@ static int coda_s_fmt_vid_cap(struct file *file, void *priv,
|
||||||
struct coda_q_data *q_data_src;
|
struct coda_q_data *q_data_src;
|
||||||
const struct coda_codec *codec;
|
const struct coda_codec *codec;
|
||||||
struct v4l2_rect r;
|
struct v4l2_rect r;
|
||||||
|
int hscale = 0;
|
||||||
|
int vscale = 0;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
|
q_data_src = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT);
|
||||||
|
|
||||||
|
if (q_data_src->fourcc == V4L2_PIX_FMT_JPEG &&
|
||||||
|
ctx->dev->devtype->product == CODA_960) {
|
||||||
|
hscale = coda_jpeg_scale(q_data_src->width, f->fmt.pix.width);
|
||||||
|
vscale = coda_jpeg_scale(q_data_src->height, f->fmt.pix.height);
|
||||||
|
}
|
||||||
|
|
||||||
ret = coda_try_fmt_vid_cap(file, priv, f);
|
ret = coda_try_fmt_vid_cap(file, priv, f);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
q_data_src = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT);
|
|
||||||
r.left = 0;
|
r.left = 0;
|
||||||
r.top = 0;
|
r.top = 0;
|
||||||
r.width = q_data_src->width;
|
r.width = q_data_src->width >> hscale;
|
||||||
r.height = q_data_src->height;
|
r.height = q_data_src->height >> vscale;
|
||||||
|
|
||||||
ret = coda_s_fmt(ctx, f, &r);
|
ret = coda_s_fmt(ctx, f, &r);
|
||||||
if (ret)
|
if (ret)
|
||||||
|
|
@ -1091,17 +1107,6 @@ static int coda_s_selection(struct file *file, void *fh,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int coda_try_encoder_cmd(struct file *file, void *fh,
|
|
||||||
struct v4l2_encoder_cmd *ec)
|
|
||||||
{
|
|
||||||
struct coda_ctx *ctx = fh_to_ctx(fh);
|
|
||||||
|
|
||||||
if (ctx->inst_type != CODA_INST_ENCODER)
|
|
||||||
return -ENOTTY;
|
|
||||||
|
|
||||||
return v4l2_m2m_ioctl_try_encoder_cmd(file, fh, ec);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void coda_wake_up_capture_queue(struct coda_ctx *ctx)
|
static void coda_wake_up_capture_queue(struct coda_ctx *ctx)
|
||||||
{
|
{
|
||||||
struct vb2_queue *dst_vq;
|
struct vb2_queue *dst_vq;
|
||||||
|
|
@ -1120,7 +1125,7 @@ static int coda_encoder_cmd(struct file *file, void *fh,
|
||||||
struct vb2_v4l2_buffer *buf;
|
struct vb2_v4l2_buffer *buf;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
ret = coda_try_encoder_cmd(file, fh, ec);
|
ret = v4l2_m2m_ioctl_try_encoder_cmd(file, fh, ec);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
|
|
@ -1149,17 +1154,6 @@ static int coda_encoder_cmd(struct file *file, void *fh,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int coda_try_decoder_cmd(struct file *file, void *fh,
|
|
||||||
struct v4l2_decoder_cmd *dc)
|
|
||||||
{
|
|
||||||
struct coda_ctx *ctx = fh_to_ctx(fh);
|
|
||||||
|
|
||||||
if (ctx->inst_type != CODA_INST_DECODER)
|
|
||||||
return -ENOTTY;
|
|
||||||
|
|
||||||
return v4l2_m2m_ioctl_try_decoder_cmd(file, fh, dc);
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool coda_mark_last_meta(struct coda_ctx *ctx)
|
static bool coda_mark_last_meta(struct coda_ctx *ctx)
|
||||||
{
|
{
|
||||||
struct coda_buffer_meta *meta;
|
struct coda_buffer_meta *meta;
|
||||||
|
|
@ -1216,7 +1210,7 @@ static int coda_decoder_cmd(struct file *file, void *fh,
|
||||||
bool wakeup;
|
bool wakeup;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
ret = coda_try_decoder_cmd(file, fh, dc);
|
ret = v4l2_m2m_ioctl_try_decoder_cmd(file, fh, dc);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
|
|
@ -1291,9 +1285,6 @@ static int coda_enum_framesizes(struct file *file, void *fh,
|
||||||
struct coda_q_data *q_data_dst;
|
struct coda_q_data *q_data_dst;
|
||||||
const struct coda_codec *codec;
|
const struct coda_codec *codec;
|
||||||
|
|
||||||
if (ctx->inst_type != CODA_INST_ENCODER)
|
|
||||||
return -ENOTTY;
|
|
||||||
|
|
||||||
if (fsize->index)
|
if (fsize->index)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
|
|
@ -1324,7 +1315,8 @@ static int coda_enum_frameintervals(struct file *file, void *fh,
|
||||||
struct v4l2_frmivalenum *f)
|
struct v4l2_frmivalenum *f)
|
||||||
{
|
{
|
||||||
struct coda_ctx *ctx = fh_to_ctx(fh);
|
struct coda_ctx *ctx = fh_to_ctx(fh);
|
||||||
int i;
|
struct coda_q_data *q_data;
|
||||||
|
const struct coda_codec *codec;
|
||||||
|
|
||||||
if (f->index)
|
if (f->index)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
@ -1333,12 +1325,19 @@ static int coda_enum_frameintervals(struct file *file, void *fh,
|
||||||
if (!ctx->vdoa && f->pixel_format == V4L2_PIX_FMT_YUYV)
|
if (!ctx->vdoa && f->pixel_format == V4L2_PIX_FMT_YUYV)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
for (i = 0; i < CODA_MAX_FORMATS; i++) {
|
if (coda_format_normalize_yuv(f->pixel_format) == V4L2_PIX_FMT_YUV420) {
|
||||||
if (f->pixel_format == ctx->cvd->src_formats[i] ||
|
q_data = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE);
|
||||||
f->pixel_format == ctx->cvd->dst_formats[i])
|
codec = coda_find_codec(ctx->dev, f->pixel_format,
|
||||||
break;
|
q_data->fourcc);
|
||||||
|
} else {
|
||||||
|
codec = coda_find_codec(ctx->dev, V4L2_PIX_FMT_YUV420,
|
||||||
|
f->pixel_format);
|
||||||
}
|
}
|
||||||
if (i == CODA_MAX_FORMATS)
|
if (!codec)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
if (f->width < MIN_W || f->width > codec->max_w ||
|
||||||
|
f->height < MIN_H || f->height > codec->max_h)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
f->type = V4L2_FRMIVAL_TYPE_CONTINUOUS;
|
f->type = V4L2_FRMIVAL_TYPE_CONTINUOUS;
|
||||||
|
|
@ -1498,9 +1497,9 @@ static const struct v4l2_ioctl_ops coda_ioctl_ops = {
|
||||||
.vidioc_g_selection = coda_g_selection,
|
.vidioc_g_selection = coda_g_selection,
|
||||||
.vidioc_s_selection = coda_s_selection,
|
.vidioc_s_selection = coda_s_selection,
|
||||||
|
|
||||||
.vidioc_try_encoder_cmd = coda_try_encoder_cmd,
|
.vidioc_try_encoder_cmd = v4l2_m2m_ioctl_try_encoder_cmd,
|
||||||
.vidioc_encoder_cmd = coda_encoder_cmd,
|
.vidioc_encoder_cmd = coda_encoder_cmd,
|
||||||
.vidioc_try_decoder_cmd = coda_try_decoder_cmd,
|
.vidioc_try_decoder_cmd = v4l2_m2m_ioctl_try_decoder_cmd,
|
||||||
.vidioc_decoder_cmd = coda_decoder_cmd,
|
.vidioc_decoder_cmd = coda_decoder_cmd,
|
||||||
|
|
||||||
.vidioc_g_parm = coda_g_parm,
|
.vidioc_g_parm = coda_g_parm,
|
||||||
|
|
@ -1535,12 +1534,8 @@ static void coda_pic_run_work(struct work_struct *work)
|
||||||
mutex_lock(&dev->coda_mutex);
|
mutex_lock(&dev->coda_mutex);
|
||||||
|
|
||||||
ret = ctx->ops->prepare_run(ctx);
|
ret = ctx->ops->prepare_run(ctx);
|
||||||
if (ret < 0 && ctx->inst_type == CODA_INST_DECODER) {
|
if (ret < 0 && ctx->inst_type == CODA_INST_DECODER)
|
||||||
mutex_unlock(&dev->coda_mutex);
|
goto out;
|
||||||
mutex_unlock(&ctx->buffer_mutex);
|
|
||||||
/* job_finish scheduled by prepare_decode */
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!wait_for_completion_timeout(&ctx->completion,
|
if (!wait_for_completion_timeout(&ctx->completion,
|
||||||
msecs_to_jiffies(1000))) {
|
msecs_to_jiffies(1000))) {
|
||||||
|
|
@ -1562,6 +1557,7 @@ static void coda_pic_run_work(struct work_struct *work)
|
||||||
ctx->ops->seq_end_work)
|
ctx->ops->seq_end_work)
|
||||||
queue_work(dev->workqueue, &ctx->seq_end_work);
|
queue_work(dev->workqueue, &ctx->seq_end_work);
|
||||||
|
|
||||||
|
out:
|
||||||
mutex_unlock(&dev->coda_mutex);
|
mutex_unlock(&dev->coda_mutex);
|
||||||
mutex_unlock(&ctx->buffer_mutex);
|
mutex_unlock(&ctx->buffer_mutex);
|
||||||
|
|
||||||
|
|
@ -1665,13 +1661,18 @@ static void set_default_params(struct coda_ctx *ctx)
|
||||||
csize = coda_estimate_sizeimage(ctx, usize, max_w, max_h);
|
csize = coda_estimate_sizeimage(ctx, usize, max_w, max_h);
|
||||||
|
|
||||||
ctx->params.codec_mode = ctx->codec->mode;
|
ctx->params.codec_mode = ctx->codec->mode;
|
||||||
if (ctx->cvd->src_formats[0] == V4L2_PIX_FMT_JPEG)
|
if (ctx->cvd->src_formats[0] == V4L2_PIX_FMT_JPEG ||
|
||||||
ctx->colorspace = V4L2_COLORSPACE_JPEG;
|
ctx->cvd->dst_formats[0] == V4L2_PIX_FMT_JPEG) {
|
||||||
else
|
ctx->colorspace = V4L2_COLORSPACE_SRGB;
|
||||||
|
ctx->xfer_func = V4L2_XFER_FUNC_SRGB;
|
||||||
|
ctx->ycbcr_enc = V4L2_YCBCR_ENC_601;
|
||||||
|
ctx->quantization = V4L2_QUANTIZATION_FULL_RANGE;
|
||||||
|
} else {
|
||||||
ctx->colorspace = V4L2_COLORSPACE_REC709;
|
ctx->colorspace = V4L2_COLORSPACE_REC709;
|
||||||
ctx->xfer_func = V4L2_XFER_FUNC_DEFAULT;
|
ctx->xfer_func = V4L2_XFER_FUNC_DEFAULT;
|
||||||
ctx->ycbcr_enc = V4L2_YCBCR_ENC_DEFAULT;
|
ctx->ycbcr_enc = V4L2_YCBCR_ENC_DEFAULT;
|
||||||
ctx->quantization = V4L2_QUANTIZATION_DEFAULT;
|
ctx->quantization = V4L2_QUANTIZATION_DEFAULT;
|
||||||
|
}
|
||||||
ctx->params.framerate = 30;
|
ctx->params.framerate = 30;
|
||||||
|
|
||||||
/* Default formats for output and input queues */
|
/* Default formats for output and input queues */
|
||||||
|
|
@ -2011,13 +2012,13 @@ static int coda_start_streaming(struct vb2_queue *q, unsigned int count)
|
||||||
*/
|
*/
|
||||||
if (q_data_src->fourcc == V4L2_PIX_FMT_JPEG) {
|
if (q_data_src->fourcc == V4L2_PIX_FMT_JPEG) {
|
||||||
buf = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx);
|
buf = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx);
|
||||||
ret = coda_jpeg_decode_header(ctx, &buf->vb2_buf);
|
coda_jpeg_decode_header(ctx, &buf->vb2_buf);
|
||||||
if (ret < 0) {
|
/*
|
||||||
v4l2_err(v4l2_dev,
|
* We have to start streaming even if the first buffer
|
||||||
"failed to decode JPEG header: %d\n",
|
* does not contain a valid JPEG image. The error will
|
||||||
ret);
|
* be caught during device run and will be signalled
|
||||||
goto err;
|
* via the capture buffer error flag.
|
||||||
}
|
*/
|
||||||
|
|
||||||
q_data_dst = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE);
|
q_data_dst = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE);
|
||||||
q_data_dst->width = round_up(q_data_src->width, 16);
|
q_data_dst->width = round_up(q_data_src->width, 16);
|
||||||
|
|
@ -2344,8 +2345,8 @@ static void coda_encode_ctrls(struct coda_ctx *ctx)
|
||||||
V4L2_CID_MPEG_VIDEO_H264_CHROMA_QP_INDEX_OFFSET, -12, 12, 1, 0);
|
V4L2_CID_MPEG_VIDEO_H264_CHROMA_QP_INDEX_OFFSET, -12, 12, 1, 0);
|
||||||
v4l2_ctrl_new_std_menu(&ctx->ctrls, &coda_ctrl_ops,
|
v4l2_ctrl_new_std_menu(&ctx->ctrls, &coda_ctrl_ops,
|
||||||
V4L2_CID_MPEG_VIDEO_H264_PROFILE,
|
V4L2_CID_MPEG_VIDEO_H264_PROFILE,
|
||||||
V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE, 0x0,
|
V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_BASELINE, 0x0,
|
||||||
V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE);
|
V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_BASELINE);
|
||||||
if (ctx->dev->devtype->product == CODA_HX4 ||
|
if (ctx->dev->devtype->product == CODA_HX4 ||
|
||||||
ctx->dev->devtype->product == CODA_7541) {
|
ctx->dev->devtype->product == CODA_7541) {
|
||||||
v4l2_ctrl_new_std_menu(&ctx->ctrls, &coda_ctrl_ops,
|
v4l2_ctrl_new_std_menu(&ctx->ctrls, &coda_ctrl_ops,
|
||||||
|
|
@ -2359,12 +2360,15 @@ static void coda_encode_ctrls(struct coda_ctx *ctx)
|
||||||
if (ctx->dev->devtype->product == CODA_960) {
|
if (ctx->dev->devtype->product == CODA_960) {
|
||||||
v4l2_ctrl_new_std_menu(&ctx->ctrls, &coda_ctrl_ops,
|
v4l2_ctrl_new_std_menu(&ctx->ctrls, &coda_ctrl_ops,
|
||||||
V4L2_CID_MPEG_VIDEO_H264_LEVEL,
|
V4L2_CID_MPEG_VIDEO_H264_LEVEL,
|
||||||
V4L2_MPEG_VIDEO_H264_LEVEL_4_0,
|
V4L2_MPEG_VIDEO_H264_LEVEL_4_2,
|
||||||
~((1 << V4L2_MPEG_VIDEO_H264_LEVEL_2_0) |
|
~((1 << V4L2_MPEG_VIDEO_H264_LEVEL_1_0) |
|
||||||
|
(1 << V4L2_MPEG_VIDEO_H264_LEVEL_2_0) |
|
||||||
(1 << V4L2_MPEG_VIDEO_H264_LEVEL_3_0) |
|
(1 << V4L2_MPEG_VIDEO_H264_LEVEL_3_0) |
|
||||||
(1 << V4L2_MPEG_VIDEO_H264_LEVEL_3_1) |
|
(1 << V4L2_MPEG_VIDEO_H264_LEVEL_3_1) |
|
||||||
(1 << V4L2_MPEG_VIDEO_H264_LEVEL_3_2) |
|
(1 << V4L2_MPEG_VIDEO_H264_LEVEL_3_2) |
|
||||||
(1 << V4L2_MPEG_VIDEO_H264_LEVEL_4_0)),
|
(1 << V4L2_MPEG_VIDEO_H264_LEVEL_4_0) |
|
||||||
|
(1 << V4L2_MPEG_VIDEO_H264_LEVEL_4_1) |
|
||||||
|
(1 << V4L2_MPEG_VIDEO_H264_LEVEL_4_2)),
|
||||||
V4L2_MPEG_VIDEO_H264_LEVEL_4_0);
|
V4L2_MPEG_VIDEO_H264_LEVEL_4_0);
|
||||||
}
|
}
|
||||||
v4l2_ctrl_new_std(&ctx->ctrls, &coda_ctrl_ops,
|
v4l2_ctrl_new_std(&ctx->ctrls, &coda_ctrl_ops,
|
||||||
|
|
@ -2426,7 +2430,7 @@ static void coda_decode_ctrls(struct coda_ctx *ctx)
|
||||||
ctx->h264_profile_ctrl = v4l2_ctrl_new_std_menu(&ctx->ctrls,
|
ctx->h264_profile_ctrl = v4l2_ctrl_new_std_menu(&ctx->ctrls,
|
||||||
&coda_ctrl_ops, V4L2_CID_MPEG_VIDEO_H264_PROFILE,
|
&coda_ctrl_ops, V4L2_CID_MPEG_VIDEO_H264_PROFILE,
|
||||||
V4L2_MPEG_VIDEO_H264_PROFILE_HIGH,
|
V4L2_MPEG_VIDEO_H264_PROFILE_HIGH,
|
||||||
~((1 << V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE) |
|
~((1 << V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_BASELINE) |
|
||||||
(1 << V4L2_MPEG_VIDEO_H264_PROFILE_MAIN) |
|
(1 << V4L2_MPEG_VIDEO_H264_PROFILE_MAIN) |
|
||||||
(1 << V4L2_MPEG_VIDEO_H264_PROFILE_HIGH)),
|
(1 << V4L2_MPEG_VIDEO_H264_PROFILE_HIGH)),
|
||||||
V4L2_MPEG_VIDEO_H264_PROFILE_HIGH);
|
V4L2_MPEG_VIDEO_H264_PROFILE_HIGH);
|
||||||
|
|
@ -2901,6 +2905,23 @@ static int coda_register_device(struct coda_dev *dev, int i)
|
||||||
v4l2_disable_ioctl(vfd, VIDIOC_G_CROP);
|
v4l2_disable_ioctl(vfd, VIDIOC_G_CROP);
|
||||||
v4l2_disable_ioctl(vfd, VIDIOC_S_CROP);
|
v4l2_disable_ioctl(vfd, VIDIOC_S_CROP);
|
||||||
|
|
||||||
|
if (dev->devtype->vdevs[i]->type == CODA_INST_ENCODER) {
|
||||||
|
v4l2_disable_ioctl(vfd, VIDIOC_DECODER_CMD);
|
||||||
|
v4l2_disable_ioctl(vfd, VIDIOC_TRY_DECODER_CMD);
|
||||||
|
if (dev->devtype->vdevs[i]->dst_formats[0] == V4L2_PIX_FMT_JPEG) {
|
||||||
|
v4l2_disable_ioctl(vfd, VIDIOC_ENUM_FRAMEINTERVALS);
|
||||||
|
v4l2_disable_ioctl(vfd, VIDIOC_G_PARM);
|
||||||
|
v4l2_disable_ioctl(vfd, VIDIOC_S_PARM);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
v4l2_disable_ioctl(vfd, VIDIOC_ENCODER_CMD);
|
||||||
|
v4l2_disable_ioctl(vfd, VIDIOC_TRY_ENCODER_CMD);
|
||||||
|
v4l2_disable_ioctl(vfd, VIDIOC_ENUM_FRAMESIZES);
|
||||||
|
v4l2_disable_ioctl(vfd, VIDIOC_ENUM_FRAMEINTERVALS);
|
||||||
|
v4l2_disable_ioctl(vfd, VIDIOC_G_PARM);
|
||||||
|
v4l2_disable_ioctl(vfd, VIDIOC_S_PARM);
|
||||||
|
}
|
||||||
|
|
||||||
ret = video_register_device(vfd, VFL_TYPE_VIDEO, 0);
|
ret = video_register_device(vfd, VFL_TYPE_VIDEO, 0);
|
||||||
if (!ret)
|
if (!ret)
|
||||||
v4l2_info(&dev->v4l2_dev, "%s registered as %s\n",
|
v4l2_info(&dev->v4l2_dev, "%s registered as %s\n",
|
||||||
|
|
|
||||||
|
|
@ -283,7 +283,8 @@ int coda_jpeg_decode_header(struct coda_ctx *ctx, struct vb2_buffer *vb)
|
||||||
|
|
||||||
ret = v4l2_jpeg_parse_header(buf, len, &header);
|
ret = v4l2_jpeg_parse_header(buf, len, &header);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
v4l2_err(&dev->v4l2_dev, "failed to parse header\n");
|
v4l2_err(&dev->v4l2_dev, "failed to parse JPEG header: %pe\n",
|
||||||
|
ERR_PTR(ret));
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1328,6 +1329,7 @@ static int coda9_jpeg_prepare_decode(struct coda_ctx *ctx)
|
||||||
struct coda_q_data *q_data_src, *q_data_dst;
|
struct coda_q_data *q_data_src, *q_data_dst;
|
||||||
struct vb2_v4l2_buffer *src_buf, *dst_buf;
|
struct vb2_v4l2_buffer *src_buf, *dst_buf;
|
||||||
int chroma_interleave;
|
int chroma_interleave;
|
||||||
|
int scl_hor_mode, scl_ver_mode;
|
||||||
|
|
||||||
src_buf = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx);
|
src_buf = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx);
|
||||||
dst_buf = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx);
|
dst_buf = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx);
|
||||||
|
|
@ -1335,27 +1337,24 @@ static int coda9_jpeg_prepare_decode(struct coda_ctx *ctx)
|
||||||
q_data_dst = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE);
|
q_data_dst = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE);
|
||||||
dst_fourcc = q_data_dst->fourcc;
|
dst_fourcc = q_data_dst->fourcc;
|
||||||
|
|
||||||
|
scl_hor_mode = coda_jpeg_scale(q_data_src->width, q_data_dst->width);
|
||||||
|
scl_ver_mode = coda_jpeg_scale(q_data_src->height, q_data_dst->height);
|
||||||
|
|
||||||
if (vb2_get_plane_payload(&src_buf->vb2_buf, 0) == 0)
|
if (vb2_get_plane_payload(&src_buf->vb2_buf, 0) == 0)
|
||||||
vb2_set_plane_payload(&src_buf->vb2_buf, 0,
|
vb2_set_plane_payload(&src_buf->vb2_buf, 0,
|
||||||
vb2_plane_size(&src_buf->vb2_buf, 0));
|
vb2_plane_size(&src_buf->vb2_buf, 0));
|
||||||
|
|
||||||
chroma_format = coda9_jpeg_chroma_format(q_data_dst->fourcc);
|
chroma_format = coda9_jpeg_chroma_format(q_data_dst->fourcc);
|
||||||
if (chroma_format < 0) {
|
if (chroma_format < 0)
|
||||||
v4l2_m2m_job_finish(ctx->dev->m2m_dev, ctx->fh.m2m_ctx);
|
|
||||||
return chroma_format;
|
return chroma_format;
|
||||||
}
|
|
||||||
|
|
||||||
ret = coda_jpeg_decode_header(ctx, &src_buf->vb2_buf);
|
ret = coda_jpeg_decode_header(ctx, &src_buf->vb2_buf);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
v4l2_err(&dev->v4l2_dev, "failed to decode JPEG header: %d\n",
|
|
||||||
ret);
|
|
||||||
|
|
||||||
src_buf = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx);
|
src_buf = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx);
|
||||||
dst_buf = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx);
|
dst_buf = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx);
|
||||||
v4l2_m2m_buf_done(src_buf, VB2_BUF_STATE_DONE);
|
v4l2_m2m_buf_done(src_buf, VB2_BUF_STATE_DONE);
|
||||||
v4l2_m2m_buf_done(dst_buf, VB2_BUF_STATE_DONE);
|
v4l2_m2m_buf_done(dst_buf, VB2_BUF_STATE_ERROR);
|
||||||
|
|
||||||
v4l2_m2m_job_finish(ctx->dev->m2m_dev, ctx->fh.m2m_ctx);
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1386,7 +1385,11 @@ static int coda9_jpeg_prepare_decode(struct coda_ctx *ctx)
|
||||||
coda_write(dev, 0, CODA9_REG_JPEG_ROT_INFO);
|
coda_write(dev, 0, CODA9_REG_JPEG_ROT_INFO);
|
||||||
coda_write(dev, bus_req_num[chroma_format], CODA9_REG_JPEG_OP_INFO);
|
coda_write(dev, bus_req_num[chroma_format], CODA9_REG_JPEG_OP_INFO);
|
||||||
coda_write(dev, mcu_info[chroma_format], CODA9_REG_JPEG_MCU_INFO);
|
coda_write(dev, mcu_info[chroma_format], CODA9_REG_JPEG_MCU_INFO);
|
||||||
coda_write(dev, 0, CODA9_REG_JPEG_SCL_INFO);
|
if (scl_hor_mode || scl_ver_mode)
|
||||||
|
val = CODA9_JPEG_SCL_ENABLE | (scl_hor_mode << 2) | scl_ver_mode;
|
||||||
|
else
|
||||||
|
val = 0;
|
||||||
|
coda_write(dev, val, CODA9_REG_JPEG_SCL_INFO);
|
||||||
coda_write(dev, chroma_interleave, CODA9_REG_JPEG_DPB_CONFIG);
|
coda_write(dev, chroma_interleave, CODA9_REG_JPEG_DPB_CONFIG);
|
||||||
coda_write(dev, ctx->params.jpeg_restart_interval,
|
coda_write(dev, ctx->params.jpeg_restart_interval,
|
||||||
CODA9_REG_JPEG_RST_INTVAL);
|
CODA9_REG_JPEG_RST_INTVAL);
|
||||||
|
|
@ -1396,7 +1399,6 @@ static int coda9_jpeg_prepare_decode(struct coda_ctx *ctx)
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
v4l2_err(&dev->v4l2_dev,
|
v4l2_err(&dev->v4l2_dev,
|
||||||
"failed to set up Huffman tables: %d\n", ret);
|
"failed to set up Huffman tables: %d\n", ret);
|
||||||
v4l2_m2m_job_finish(ctx->dev->m2m_dev, ctx->fh.m2m_ctx);
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -380,6 +380,13 @@ u32 coda_mpeg4_parse_headers(struct coda_ctx *ctx, u8 *buf, u32 size);
|
||||||
void coda_update_profile_level_ctrls(struct coda_ctx *ctx, u8 profile_idc,
|
void coda_update_profile_level_ctrls(struct coda_ctx *ctx, u8 profile_idc,
|
||||||
u8 level_idc);
|
u8 level_idc);
|
||||||
|
|
||||||
|
static inline int coda_jpeg_scale(int src, int dst)
|
||||||
|
{
|
||||||
|
return (dst <= src / 8) ? 3 :
|
||||||
|
(dst <= src / 4) ? 2 :
|
||||||
|
(dst <= src / 2) ? 1 : 0;
|
||||||
|
}
|
||||||
|
|
||||||
bool coda_jpeg_check_buffer(struct coda_ctx *ctx, struct vb2_buffer *vb);
|
bool coda_jpeg_check_buffer(struct coda_ctx *ctx, struct vb2_buffer *vb);
|
||||||
int coda_jpeg_decode_header(struct coda_ctx *ctx, struct vb2_buffer *vb);
|
int coda_jpeg_decode_header(struct coda_ctx *ctx, struct vb2_buffer *vb);
|
||||||
int coda_jpeg_write_tables(struct coda_ctx *ctx);
|
int coda_jpeg_write_tables(struct coda_ctx *ctx);
|
||||||
|
|
|
||||||
|
|
@ -497,7 +497,6 @@ static int cafe_pci_probe(struct pci_dev *pdev,
|
||||||
mcam->plat_power_up = cafe_ctlr_power_up;
|
mcam->plat_power_up = cafe_ctlr_power_up;
|
||||||
mcam->plat_power_down = cafe_ctlr_power_down;
|
mcam->plat_power_down = cafe_ctlr_power_down;
|
||||||
mcam->dev = &pdev->dev;
|
mcam->dev = &pdev->dev;
|
||||||
snprintf(mcam->bus_info, sizeof(mcam->bus_info), "PCI:%s", pci_name(pdev));
|
|
||||||
/*
|
/*
|
||||||
* Vmalloc mode for buffers is traditional with this driver.
|
* Vmalloc mode for buffers is traditional with this driver.
|
||||||
* We *might* be able to run DMA_contig, especially on a system
|
* We *might* be able to run DMA_contig, especially on a system
|
||||||
|
|
|
||||||
|
|
@ -137,8 +137,6 @@ static int mtk_jpeg_querycap(struct file *file, void *priv,
|
||||||
|
|
||||||
strscpy(cap->driver, jpeg->variant->dev_name, sizeof(cap->driver));
|
strscpy(cap->driver, jpeg->variant->dev_name, sizeof(cap->driver));
|
||||||
strscpy(cap->card, jpeg->variant->dev_name, sizeof(cap->card));
|
strscpy(cap->card, jpeg->variant->dev_name, sizeof(cap->card));
|
||||||
snprintf(cap->bus_info, sizeof(cap->bus_info), "platform:%s",
|
|
||||||
dev_name(jpeg->dev));
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,7 @@ config VIDEO_MEDIATEK_VCODEC
|
||||||
select VIDEO_MEDIATEK_VCODEC_VPU if VIDEO_MEDIATEK_VPU
|
select VIDEO_MEDIATEK_VCODEC_VPU if VIDEO_MEDIATEK_VPU
|
||||||
select VIDEO_MEDIATEK_VCODEC_SCP if MTK_SCP
|
select VIDEO_MEDIATEK_VCODEC_SCP if MTK_SCP
|
||||||
select V4L2_H264
|
select V4L2_H264
|
||||||
|
select V4L2_VP9
|
||||||
select MEDIA_CONTROLLER
|
select MEDIA_CONTROLLER
|
||||||
select MEDIA_CONTROLLER_REQUEST_API
|
select MEDIA_CONTROLLER_REQUEST_API
|
||||||
help
|
help
|
||||||
|
|
|
||||||
|
|
@ -7,8 +7,12 @@ obj-$(CONFIG_VIDEO_MEDIATEK_VCODEC) += mtk-vcodec-dec.o \
|
||||||
|
|
||||||
mtk-vcodec-dec-y := vdec/vdec_h264_if.o \
|
mtk-vcodec-dec-y := vdec/vdec_h264_if.o \
|
||||||
vdec/vdec_vp8_if.o \
|
vdec/vdec_vp8_if.o \
|
||||||
|
vdec/vdec_vp8_req_if.o \
|
||||||
vdec/vdec_vp9_if.o \
|
vdec/vdec_vp9_if.o \
|
||||||
|
vdec/vdec_vp9_req_lat_if.o \
|
||||||
vdec/vdec_h264_req_if.o \
|
vdec/vdec_h264_req_if.o \
|
||||||
|
vdec/vdec_h264_req_common.o \
|
||||||
|
vdec/vdec_h264_req_multi_if.o \
|
||||||
mtk_vcodec_dec_drv.o \
|
mtk_vcodec_dec_drv.o \
|
||||||
vdec_drv_if.o \
|
vdec_drv_if.o \
|
||||||
vdec_vpu_if.o \
|
vdec_vpu_if.o \
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,7 @@ mtk_vdec_find_format(struct v4l2_format *f,
|
||||||
const struct mtk_video_fmt *fmt;
|
const struct mtk_video_fmt *fmt;
|
||||||
unsigned int k;
|
unsigned int k;
|
||||||
|
|
||||||
for (k = 0; k < dec_pdata->num_formats; k++) {
|
for (k = 0; k < *dec_pdata->num_formats; k++) {
|
||||||
fmt = &dec_pdata->vdec_formats[k];
|
fmt = &dec_pdata->vdec_formats[k];
|
||||||
if (fmt->fourcc == f->fmt.pix_mp.pixelformat)
|
if (fmt->fourcc == f->fmt.pix_mp.pixelformat)
|
||||||
return fmt;
|
return fmt;
|
||||||
|
|
@ -47,14 +47,7 @@ static struct mtk_q_data *mtk_vdec_get_q_data(struct mtk_vcodec_ctx *ctx,
|
||||||
static int vidioc_try_decoder_cmd(struct file *file, void *priv,
|
static int vidioc_try_decoder_cmd(struct file *file, void *priv,
|
||||||
struct v4l2_decoder_cmd *cmd)
|
struct v4l2_decoder_cmd *cmd)
|
||||||
{
|
{
|
||||||
struct mtk_vcodec_ctx *ctx = fh_to_ctx(priv);
|
return v4l2_m2m_ioctl_try_decoder_cmd(file, priv, cmd);
|
||||||
|
|
||||||
/* Use M2M stateless helper if relevant */
|
|
||||||
if (ctx->dev->vdec_pdata->uses_stateless_api)
|
|
||||||
return v4l2_m2m_ioctl_stateless_try_decoder_cmd(file, priv,
|
|
||||||
cmd);
|
|
||||||
else
|
|
||||||
return v4l2_m2m_ioctl_try_decoder_cmd(file, priv, cmd);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -69,10 +62,6 @@ static int vidioc_decoder_cmd(struct file *file, void *priv,
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
/* Use M2M stateless helper if relevant */
|
|
||||||
if (ctx->dev->vdec_pdata->uses_stateless_api)
|
|
||||||
return v4l2_m2m_ioctl_stateless_decoder_cmd(file, priv, cmd);
|
|
||||||
|
|
||||||
mtk_v4l2_debug(1, "decoder cmd=%u", cmd->cmd);
|
mtk_v4l2_debug(1, "decoder cmd=%u", cmd->cmd);
|
||||||
dst_vq = v4l2_m2m_get_vq(ctx->m2m_ctx,
|
dst_vq = v4l2_m2m_get_vq(ctx->m2m_ctx,
|
||||||
V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE);
|
V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE);
|
||||||
|
|
@ -152,13 +141,15 @@ void mtk_vcodec_dec_set_default_params(struct mtk_vcodec_ctx *ctx)
|
||||||
q_data->coded_height = DFT_CFG_HEIGHT;
|
q_data->coded_height = DFT_CFG_HEIGHT;
|
||||||
q_data->fmt = ctx->dev->vdec_pdata->default_cap_fmt;
|
q_data->fmt = ctx->dev->vdec_pdata->default_cap_fmt;
|
||||||
q_data->field = V4L2_FIELD_NONE;
|
q_data->field = V4L2_FIELD_NONE;
|
||||||
|
ctx->max_width = MTK_VDEC_MAX_W;
|
||||||
|
ctx->max_height = MTK_VDEC_MAX_H;
|
||||||
|
|
||||||
v4l_bound_align_image(&q_data->coded_width,
|
v4l_bound_align_image(&q_data->coded_width,
|
||||||
MTK_VDEC_MIN_W,
|
MTK_VDEC_MIN_W,
|
||||||
MTK_VDEC_MAX_W, 4,
|
ctx->max_width, 4,
|
||||||
&q_data->coded_height,
|
&q_data->coded_height,
|
||||||
MTK_VDEC_MIN_H,
|
MTK_VDEC_MIN_H,
|
||||||
MTK_VDEC_MAX_H, 5, 6);
|
ctx->max_height, 5, 6);
|
||||||
|
|
||||||
q_data->sizeimage[0] = q_data->coded_width * q_data->coded_height;
|
q_data->sizeimage[0] = q_data->coded_width * q_data->coded_height;
|
||||||
q_data->bytesperline[0] = q_data->coded_width;
|
q_data->bytesperline[0] = q_data->coded_width;
|
||||||
|
|
@ -217,7 +208,7 @@ static int vidioc_vdec_subscribe_evt(struct v4l2_fh *fh,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int vidioc_try_fmt(struct v4l2_format *f,
|
static int vidioc_try_fmt(struct mtk_vcodec_ctx *ctx, struct v4l2_format *f,
|
||||||
const struct mtk_video_fmt *fmt)
|
const struct mtk_video_fmt *fmt)
|
||||||
{
|
{
|
||||||
struct v4l2_pix_format_mplane *pix_fmt_mp = &f->fmt.pix_mp;
|
struct v4l2_pix_format_mplane *pix_fmt_mp = &f->fmt.pix_mp;
|
||||||
|
|
@ -225,9 +216,9 @@ static int vidioc_try_fmt(struct v4l2_format *f,
|
||||||
pix_fmt_mp->field = V4L2_FIELD_NONE;
|
pix_fmt_mp->field = V4L2_FIELD_NONE;
|
||||||
|
|
||||||
pix_fmt_mp->width =
|
pix_fmt_mp->width =
|
||||||
clamp(pix_fmt_mp->width, MTK_VDEC_MIN_W, MTK_VDEC_MAX_W);
|
clamp(pix_fmt_mp->width, MTK_VDEC_MIN_W, ctx->max_width);
|
||||||
pix_fmt_mp->height =
|
pix_fmt_mp->height =
|
||||||
clamp(pix_fmt_mp->height, MTK_VDEC_MIN_H, MTK_VDEC_MAX_H);
|
clamp(pix_fmt_mp->height, MTK_VDEC_MIN_H, ctx->max_height);
|
||||||
|
|
||||||
if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
|
if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
|
||||||
pix_fmt_mp->num_planes = 1;
|
pix_fmt_mp->num_planes = 1;
|
||||||
|
|
@ -245,16 +236,16 @@ static int vidioc_try_fmt(struct v4l2_format *f,
|
||||||
tmp_h = pix_fmt_mp->height;
|
tmp_h = pix_fmt_mp->height;
|
||||||
v4l_bound_align_image(&pix_fmt_mp->width,
|
v4l_bound_align_image(&pix_fmt_mp->width,
|
||||||
MTK_VDEC_MIN_W,
|
MTK_VDEC_MIN_W,
|
||||||
MTK_VDEC_MAX_W, 6,
|
ctx->max_width, 6,
|
||||||
&pix_fmt_mp->height,
|
&pix_fmt_mp->height,
|
||||||
MTK_VDEC_MIN_H,
|
MTK_VDEC_MIN_H,
|
||||||
MTK_VDEC_MAX_H, 6, 9);
|
ctx->max_height, 6, 9);
|
||||||
|
|
||||||
if (pix_fmt_mp->width < tmp_w &&
|
if (pix_fmt_mp->width < tmp_w &&
|
||||||
(pix_fmt_mp->width + 64) <= MTK_VDEC_MAX_W)
|
(pix_fmt_mp->width + 64) <= ctx->max_width)
|
||||||
pix_fmt_mp->width += 64;
|
pix_fmt_mp->width += 64;
|
||||||
if (pix_fmt_mp->height < tmp_h &&
|
if (pix_fmt_mp->height < tmp_h &&
|
||||||
(pix_fmt_mp->height + 64) <= MTK_VDEC_MAX_H)
|
(pix_fmt_mp->height + 64) <= ctx->max_height)
|
||||||
pix_fmt_mp->height += 64;
|
pix_fmt_mp->height += 64;
|
||||||
|
|
||||||
mtk_v4l2_debug(0,
|
mtk_v4l2_debug(0,
|
||||||
|
|
@ -294,7 +285,7 @@ static int vidioc_try_fmt_vid_cap_mplane(struct file *file, void *priv,
|
||||||
fmt = mtk_vdec_find_format(f, dec_pdata);
|
fmt = mtk_vdec_find_format(f, dec_pdata);
|
||||||
}
|
}
|
||||||
|
|
||||||
return vidioc_try_fmt(f, fmt);
|
return vidioc_try_fmt(ctx, f, fmt);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int vidioc_try_fmt_vid_out_mplane(struct file *file, void *priv,
|
static int vidioc_try_fmt_vid_out_mplane(struct file *file, void *priv,
|
||||||
|
|
@ -317,7 +308,7 @@ static int vidioc_try_fmt_vid_out_mplane(struct file *file, void *priv,
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
return vidioc_try_fmt(f, fmt);
|
return vidioc_try_fmt(ctx, f, fmt);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int vidioc_vdec_g_selection(struct file *file, void *priv,
|
static int vidioc_vdec_g_selection(struct file *file, void *priv,
|
||||||
|
|
@ -444,8 +435,15 @@ static int vidioc_vdec_s_fmt(struct file *file, void *priv,
|
||||||
if (fmt == NULL)
|
if (fmt == NULL)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
|
if (!(ctx->dev->dec_capability & VCODEC_CAPABILITY_4K_DISABLED) &&
|
||||||
|
fmt->fourcc != V4L2_PIX_FMT_VP8_FRAME) {
|
||||||
|
mtk_v4l2_debug(3, "4K is enabled");
|
||||||
|
ctx->max_width = VCODEC_DEC_4K_CODED_WIDTH;
|
||||||
|
ctx->max_height = VCODEC_DEC_4K_CODED_HEIGHT;
|
||||||
|
}
|
||||||
|
|
||||||
q_data->fmt = fmt;
|
q_data->fmt = fmt;
|
||||||
vidioc_try_fmt(f, q_data->fmt);
|
vidioc_try_fmt(ctx, f, q_data->fmt);
|
||||||
if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
|
if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
|
||||||
q_data->sizeimage[0] = pix_mp->plane_fmt[0].sizeimage;
|
q_data->sizeimage[0] = pix_mp->plane_fmt[0].sizeimage;
|
||||||
q_data->coded_width = pix_mp->width;
|
q_data->coded_width = pix_mp->width;
|
||||||
|
|
@ -466,6 +464,8 @@ static int vidioc_vdec_s_fmt(struct file *file, void *priv,
|
||||||
}
|
}
|
||||||
ctx->state = MTK_STATE_INIT;
|
ctx->state = MTK_STATE_INIT;
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
ctx->capture_fourcc = fmt->fourcc;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
@ -476,11 +476,14 @@ static int vidioc_vdec_s_fmt(struct file *file, void *priv,
|
||||||
ctx->picinfo.pic_w = pix_mp->width;
|
ctx->picinfo.pic_w = pix_mp->width;
|
||||||
ctx->picinfo.pic_h = pix_mp->height;
|
ctx->picinfo.pic_h = pix_mp->height;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If get pic info fail, need to use the default pic info params, or
|
||||||
|
* v4l2-compliance will fail
|
||||||
|
*/
|
||||||
ret = vdec_if_get_param(ctx, GET_PARAM_PIC_INFO, &ctx->picinfo);
|
ret = vdec_if_get_param(ctx, GET_PARAM_PIC_INFO, &ctx->picinfo);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
mtk_v4l2_err("[%d]Error!! Get GET_PARAM_PICTURE_INFO Fail",
|
mtk_v4l2_err("[%d]Error!! Get GET_PARAM_PICTURE_INFO Fail",
|
||||||
ctx->id);
|
ctx->id);
|
||||||
return -EINVAL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx->last_decoded_picinfo = ctx->picinfo;
|
ctx->last_decoded_picinfo = ctx->picinfo;
|
||||||
|
|
@ -523,20 +526,15 @@ static int vidioc_enum_framesizes(struct file *file, void *priv,
|
||||||
if (fsize->index != 0)
|
if (fsize->index != 0)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
for (i = 0; i < dec_pdata->num_framesizes; ++i) {
|
for (i = 0; i < *dec_pdata->num_framesizes; ++i) {
|
||||||
if (fsize->pixel_format != dec_pdata->vdec_framesizes[i].fourcc)
|
if (fsize->pixel_format != dec_pdata->vdec_framesizes[i].fourcc)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
fsize->type = V4L2_FRMSIZE_TYPE_STEPWISE;
|
fsize->type = V4L2_FRMSIZE_TYPE_STEPWISE;
|
||||||
fsize->stepwise = dec_pdata->vdec_framesizes[i].stepwise;
|
fsize->stepwise = dec_pdata->vdec_framesizes[i].stepwise;
|
||||||
if (!(ctx->dev->dec_capability &
|
|
||||||
VCODEC_CAPABILITY_4K_DISABLED)) {
|
fsize->stepwise.max_width = ctx->max_width;
|
||||||
mtk_v4l2_debug(3, "4K is enabled");
|
fsize->stepwise.max_height = ctx->max_height;
|
||||||
fsize->stepwise.max_width =
|
|
||||||
VCODEC_DEC_4K_CODED_WIDTH;
|
|
||||||
fsize->stepwise.max_height =
|
|
||||||
VCODEC_DEC_4K_CODED_HEIGHT;
|
|
||||||
}
|
|
||||||
mtk_v4l2_debug(1, "%x, %d %d %d %d %d %d",
|
mtk_v4l2_debug(1, "%x, %d %d %d %d %d %d",
|
||||||
ctx->dev->dec_capability,
|
ctx->dev->dec_capability,
|
||||||
fsize->stepwise.min_width,
|
fsize->stepwise.min_width,
|
||||||
|
|
@ -545,6 +543,7 @@ static int vidioc_enum_framesizes(struct file *file, void *priv,
|
||||||
fsize->stepwise.min_height,
|
fsize->stepwise.min_height,
|
||||||
fsize->stepwise.max_height,
|
fsize->stepwise.max_height,
|
||||||
fsize->stepwise.step_height);
|
fsize->stepwise.step_height);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -559,7 +558,7 @@ static int vidioc_enum_fmt(struct v4l2_fmtdesc *f, void *priv,
|
||||||
const struct mtk_video_fmt *fmt;
|
const struct mtk_video_fmt *fmt;
|
||||||
int i, j = 0;
|
int i, j = 0;
|
||||||
|
|
||||||
for (i = 0; i < dec_pdata->num_formats; i++) {
|
for (i = 0; i < *dec_pdata->num_formats; i++) {
|
||||||
if (output_queue &&
|
if (output_queue &&
|
||||||
dec_pdata->vdec_formats[i].type != MTK_FMT_DEC)
|
dec_pdata->vdec_formats[i].type != MTK_FMT_DEC)
|
||||||
continue;
|
continue;
|
||||||
|
|
@ -572,7 +571,7 @@ static int vidioc_enum_fmt(struct v4l2_fmtdesc *f, void *priv,
|
||||||
++j;
|
++j;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (i == dec_pdata->num_formats)
|
if (i == *dec_pdata->num_formats)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
fmt = &dec_pdata->vdec_formats[i];
|
fmt = &dec_pdata->vdec_formats[i];
|
||||||
|
|
@ -737,6 +736,8 @@ int vb2ops_vdec_buf_prepare(struct vb2_buffer *vb)
|
||||||
i, vb2_plane_size(vb, i),
|
i, vb2_plane_size(vb, i),
|
||||||
q_data->sizeimage[i]);
|
q_data->sizeimage[i]);
|
||||||
}
|
}
|
||||||
|
if (!V4L2_TYPE_IS_OUTPUT(vb->type))
|
||||||
|
vb2_set_plane_payload(vb, i, q_data->sizeimage[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user