linux/drivers/media/platform/rcar-vin/rcar-vin.h
Niklas Söderlund bea2b6a4e1 media: rcar-vin: Add support for suspend and resume
Add support for suspend and resume by stopping and starting the video
pipeline while still retaining all buffers given to the driver by
user-space and internally allocated ones, this gives the application a
seamless experience.

Buffers are never returned to user-space unprocessed so user-space don't
notice when suspending. When resuming the driver restarts the capture
session using the internal scratch buffer, this happens before
user-space is unfrozen, this leads to speedy response times once the
application resumes its execution.

As the entire pipeline is stopped on suspend all subdevices in use are
also stopped, and if they enter a shutdown state when not streaming
(such as the R-Car CSI-2 driver) they too will be suspended and resumed
in sync with the VIN driver.

To be able to do keep track of which VINs should be resumed a new
internal state SUSPENDED is added to recode this.

Signed-off-by: Niklas Söderlund <niklas.soderlund+renesas@ragnatech.se>
Reviewed-by: Jacopo Mondi <jacopo+renesas@jmondi.org>
Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl>
Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
2020-11-16 10:31:10 +01:00

308 lines
7.9 KiB
C

/* SPDX-License-Identifier: GPL-2.0+ */
/*
* Driver for Renesas R-Car VIN
*
* Copyright (C) 2016 Renesas Electronics Corp.
* Copyright (C) 2011-2013 Renesas Solutions Corp.
* Copyright (C) 2013 Cogent Embedded, Inc., <source@cogentembedded.com>
* Copyright (C) 2008 Magnus Damm
*
* Based on the soc-camera rcar_vin driver
*/
#ifndef __RCAR_VIN__
#define __RCAR_VIN__
#include <linux/kref.h>
#include <media/v4l2-async.h>
#include <media/v4l2-ctrls.h>
#include <media/v4l2-dev.h>
#include <media/v4l2-device.h>
#include <media/v4l2-fwnode.h>
#include <media/videobuf2-v4l2.h>
/* Number of HW buffers */
#define HW_BUFFER_NUM 3
/* Address alignment mask for HW buffers */
#define HW_BUFFER_MASK 0x7f
/* Max number on VIN instances that can be in a system */
#define RCAR_VIN_NUM 8
struct rvin_group;
enum model_id {
RCAR_H1,
RCAR_M1,
RCAR_GEN2,
RCAR_GEN3,
};
enum rvin_csi_id {
RVIN_CSI20,
RVIN_CSI21,
RVIN_CSI40,
RVIN_CSI41,
RVIN_CSI_MAX,
};
/**
* STOPPED - No operation in progress
* STARTING - Capture starting up
* RUNNING - Operation in progress have buffers
* STOPPING - Stopping operation
* SUSPENDED - Capture is suspended
*/
enum rvin_dma_state {
STOPPED = 0,
STARTING,
RUNNING,
STOPPING,
SUSPENDED,
};
/**
* enum rvin_buffer_type
*
* Describes how a buffer is given to the hardware. To be able
* to capture SEQ_TB/BT it's needed to capture to the same vb2
* buffer twice so the type of buffer needs to be kept.
*
* FULL - One capture fills the whole vb2 buffer
* HALF_TOP - One capture fills the top half of the vb2 buffer
* HALF_BOTTOM - One capture fills the bottom half of the vb2 buffer
*/
enum rvin_buffer_type {
FULL,
HALF_TOP,
HALF_BOTTOM,
};
/**
* struct rvin_video_format - Data format stored in memory
* @fourcc: Pixelformat
* @bpp: Bytes per pixel
*/
struct rvin_video_format {
u32 fourcc;
u8 bpp;
};
/**
* struct rvin_parallel_entity - Parallel video input endpoint descriptor
* @asd: sub-device descriptor for async framework
* @subdev: subdevice matched using async framework
* @mbus_type: media bus type
* @bus: media bus parallel configuration
* @source_pad: source pad of remote subdevice
* @sink_pad: sink pad of remote subdevice
*
*/
struct rvin_parallel_entity {
struct v4l2_async_subdev asd;
struct v4l2_subdev *subdev;
enum v4l2_mbus_type mbus_type;
struct v4l2_fwnode_bus_parallel bus;
unsigned int source_pad;
unsigned int sink_pad;
};
/**
* struct rvin_group_route - describes a route from a channel of a
* CSI-2 receiver to a VIN
*
* @csi: CSI-2 receiver ID.
* @channel: Output channel of the CSI-2 receiver.
* @vin: VIN ID.
* @mask: Bitmask of the different CHSEL register values that
* allow for a route from @csi + @chan to @vin.
*
* .. note::
* Each R-Car CSI-2 receiver has four output channels facing the VIN
* devices, each channel can carry one CSI-2 Virtual Channel (VC).
* There is no correlation between channel number and CSI-2 VC. It's
* up to the CSI-2 receiver driver to configure which VC is output
* on which channel, the VIN devices only care about output channels.
*
* There are in some cases multiple CHSEL register settings which would
* allow for the same route from @csi + @channel to @vin. For example
* on R-Car H3 both the CHSEL values 0 and 3 allow for a route from
* CSI40/VC0 to VIN0. All possible CHSEL values for a route need to be
* recorded as a bitmask in @mask, in this example bit 0 and 3 should
* be set.
*/
struct rvin_group_route {
enum rvin_csi_id csi;
unsigned int channel;
unsigned int vin;
unsigned int mask;
};
/**
* struct rvin_info - Information about the particular VIN implementation
* @model: VIN model
* @use_mc: use media controller instead of controlling subdevice
* @nv12: support outputing NV12 pixel format
* @max_width: max input width the VIN supports
* @max_height: max input height the VIN supports
* @routes: list of possible routes from the CSI-2 recivers to
* all VINs. The list mush be NULL terminated.
*/
struct rvin_info {
enum model_id model;
bool use_mc;
bool nv12;
unsigned int max_width;
unsigned int max_height;
const struct rvin_group_route *routes;
};
/**
* struct rvin_dev - Renesas VIN device structure
* @dev: (OF) device
* @base: device I/O register space remapped to virtual memory
* @info: info about VIN instance
*
* @vdev: V4L2 video device associated with VIN
* @v4l2_dev: V4L2 device
* @ctrl_handler: V4L2 control handler
* @notifier: V4L2 asynchronous subdevs notifier
*
* @parallel: parallel input subdevice descriptor
*
* @group: Gen3 CSI group
* @id: Gen3 group id for this VIN
* @pad: media pad for the video device entity
*
* @lock: protects @queue
* @queue: vb2 buffers queue
* @scratch: cpu address for scratch buffer
* @scratch_phys: physical address of the scratch buffer
*
* @qlock: protects @buf_hw, @buf_list, @sequence and @state
* @buf_hw: Keeps track of buffers given to HW slot
* @buf_list: list of queued buffers
* @sequence: V4L2 buffers sequence number
* @state: keeps track of operation state
*
* @is_csi: flag to mark the VIN as using a CSI-2 subdevice
* @chsel Cached value of the current CSI-2 channel selection
*
* @mbus_code: media bus format code
* @format: active V4L2 pixel format
*
* @crop: active cropping
* @compose: active composing
* @src_rect: active size of the video source
* @std: active video standard of the video source
*
* @alpha: Alpha component to fill in for supported pixel formats
*/
struct rvin_dev {
struct device *dev;
void __iomem *base;
const struct rvin_info *info;
struct video_device vdev;
struct v4l2_device v4l2_dev;
struct v4l2_ctrl_handler ctrl_handler;
struct v4l2_async_notifier notifier;
struct rvin_parallel_entity *parallel;
struct rvin_group *group;
unsigned int id;
struct media_pad pad;
struct mutex lock;
struct vb2_queue queue;
void *scratch;
dma_addr_t scratch_phys;
spinlock_t qlock;
struct {
struct vb2_v4l2_buffer *buffer;
enum rvin_buffer_type type;
dma_addr_t phys;
} buf_hw[HW_BUFFER_NUM];
struct list_head buf_list;
unsigned int sequence;
enum rvin_dma_state state;
bool is_csi;
unsigned int chsel;
u32 mbus_code;
struct v4l2_pix_format format;
struct v4l2_rect crop;
struct v4l2_rect compose;
struct v4l2_rect src_rect;
v4l2_std_id std;
unsigned int alpha;
};
#define vin_to_source(vin) ((vin)->parallel->subdev)
/* Debug */
#define vin_dbg(d, fmt, arg...) dev_dbg(d->dev, fmt, ##arg)
#define vin_info(d, fmt, arg...) dev_info(d->dev, fmt, ##arg)
#define vin_warn(d, fmt, arg...) dev_warn(d->dev, fmt, ##arg)
#define vin_err(d, fmt, arg...) dev_err(d->dev, fmt, ##arg)
/**
* struct rvin_group - VIN CSI2 group information
* @refcount: number of VIN instances using the group
*
* @mdev: media device which represents the group
*
* @lock: protects the count, notifier, vin and csi members
* @count: number of enabled VIN instances found in DT
* @notifier: group notifier for CSI-2 async subdevices
* @vin: VIN instances which are part of the group
* @csi: array of pairs of fwnode and subdev pointers
* to all CSI-2 subdevices.
*/
struct rvin_group {
struct kref refcount;
struct media_device mdev;
struct mutex lock;
unsigned int count;
struct v4l2_async_notifier notifier;
struct rvin_dev *vin[RCAR_VIN_NUM];
struct {
struct fwnode_handle *fwnode;
struct v4l2_subdev *subdev;
} csi[RVIN_CSI_MAX];
};
int rvin_dma_register(struct rvin_dev *vin, int irq);
void rvin_dma_unregister(struct rvin_dev *vin);
int rvin_v4l2_register(struct rvin_dev *vin);
void rvin_v4l2_unregister(struct rvin_dev *vin);
const struct rvin_video_format *rvin_format_from_pixel(struct rvin_dev *vin,
u32 pixelformat);
/* Cropping, composing and scaling */
void rvin_crop_scale_comp(struct rvin_dev *vin);
int rvin_set_channel_routing(struct rvin_dev *vin, u8 chsel);
void rvin_set_alpha(struct rvin_dev *vin, unsigned int alpha);
int rvin_start_streaming(struct rvin_dev *vin);
void rvin_stop_streaming(struct rvin_dev *vin);
#endif