215 lines
6.5 KiB
C
215 lines
6.5 KiB
C
/* SPDX-License-Identifier: GPL-2.0 */
|
|
/*
|
|
* Copyright (C) STMicroelectronics SA 2014
|
|
* Authors: Fabien Dessenne <fabien.dessenne@st.com> for STMicroelectronics.
|
|
*/
|
|
|
|
#include <linux/clk.h>
|
|
#include <linux/ktime.h>
|
|
#include <linux/platform_device.h>
|
|
#include <linux/spinlock.h>
|
|
|
|
#include <media/v4l2-ctrls.h>
|
|
#include <media/v4l2-device.h>
|
|
#include <media/v4l2-mem2mem.h>
|
|
|
|
#include <media/videobuf2-dma-contig.h>
|
|
|
|
#define BDISP_NAME "bdisp"
|
|
|
|
/*
|
|
* Max nb of nodes in node-list:
|
|
* - 2 nodes to handle wide 4K pictures
|
|
* - 2 nodes to handle two planes (Y & CbCr) */
|
|
#define MAX_OUTPUT_PLANES 2
|
|
#define MAX_VERTICAL_STRIDES 2
|
|
#define MAX_NB_NODE (MAX_OUTPUT_PLANES * MAX_VERTICAL_STRIDES)
|
|
|
|
/* struct bdisp_ctrls - bdisp control set
|
|
* @hflip: horizontal flip
|
|
* @vflip: vertical flip
|
|
*/
|
|
struct bdisp_ctrls {
|
|
struct v4l2_ctrl *hflip;
|
|
struct v4l2_ctrl *vflip;
|
|
};
|
|
|
|
/**
|
|
* struct bdisp_fmt - driver's internal color format data
|
|
* @pixelformat:fourcc code for this format
|
|
* @nb_planes: number of planes (ex: [0]=RGB/Y - [1]=Cb/Cr, ...)
|
|
* @bpp: bits per pixel (general)
|
|
* @bpp_plane0: byte per pixel for the 1st plane
|
|
* @w_align: width alignment in pixel (multiple of)
|
|
* @h_align: height alignment in pixel (multiple of)
|
|
*/
|
|
struct bdisp_fmt {
|
|
u32 pixelformat;
|
|
u8 nb_planes;
|
|
u8 bpp;
|
|
u8 bpp_plane0;
|
|
u8 w_align;
|
|
u8 h_align;
|
|
};
|
|
|
|
/**
|
|
* struct bdisp_frame - frame properties
|
|
*
|
|
* @width: frame width (including padding)
|
|
* @height: frame height (including padding)
|
|
* @fmt: pointer to frame format descriptor
|
|
* @field: frame / field type
|
|
* @bytesperline: stride of the 1st plane
|
|
* @sizeimage: image size in bytes
|
|
* @colorspace: colorspace
|
|
* @crop: crop area
|
|
* @paddr: image physical addresses per plane ([0]=RGB/Y - [1]=Cb/Cr, ...)
|
|
*/
|
|
struct bdisp_frame {
|
|
u32 width;
|
|
u32 height;
|
|
const struct bdisp_fmt *fmt;
|
|
enum v4l2_field field;
|
|
u32 bytesperline;
|
|
u32 sizeimage;
|
|
enum v4l2_colorspace colorspace;
|
|
struct v4l2_rect crop;
|
|
dma_addr_t paddr[4];
|
|
};
|
|
|
|
/**
|
|
* struct bdisp_request - bdisp request
|
|
*
|
|
* @src: source frame properties
|
|
* @dst: destination frame properties
|
|
* @hflip: horizontal flip
|
|
* @vflip: vertical flip
|
|
* @nb_req: number of run request
|
|
*/
|
|
struct bdisp_request {
|
|
struct bdisp_frame src;
|
|
struct bdisp_frame dst;
|
|
unsigned int hflip:1;
|
|
unsigned int vflip:1;
|
|
int nb_req;
|
|
};
|
|
|
|
/**
|
|
* struct bdisp_ctx - device context data
|
|
*
|
|
* @src: source frame properties
|
|
* @dst: destination frame properties
|
|
* @state: flags to keep track of user configuration
|
|
* @hflip: horizontal flip
|
|
* @vflip: vertical flip
|
|
* @bdisp_dev: the device this context applies to
|
|
* @node: node array
|
|
* @node_paddr: node physical address array
|
|
* @fh: v4l2 file handle
|
|
* @ctrl_handler: v4l2 controls handler
|
|
* @bdisp_ctrls: bdisp control set
|
|
* @ctrls_rdy: true if the control handler is initialized
|
|
*/
|
|
struct bdisp_ctx {
|
|
struct bdisp_frame src;
|
|
struct bdisp_frame dst;
|
|
u32 state;
|
|
unsigned int hflip:1;
|
|
unsigned int vflip:1;
|
|
struct bdisp_dev *bdisp_dev;
|
|
struct bdisp_node *node[MAX_NB_NODE];
|
|
dma_addr_t node_paddr[MAX_NB_NODE];
|
|
struct v4l2_fh fh;
|
|
struct v4l2_ctrl_handler ctrl_handler;
|
|
struct bdisp_ctrls bdisp_ctrls;
|
|
bool ctrls_rdy;
|
|
};
|
|
|
|
/**
|
|
* struct bdisp_m2m_device - v4l2 memory-to-memory device data
|
|
*
|
|
* @vdev: video device node for v4l2 m2m mode
|
|
* @m2m_dev: v4l2 m2m device data
|
|
* @ctx: hardware context data
|
|
* @refcnt: reference counter
|
|
*/
|
|
struct bdisp_m2m_device {
|
|
struct video_device *vdev;
|
|
struct v4l2_m2m_dev *m2m_dev;
|
|
struct bdisp_ctx *ctx;
|
|
int refcnt;
|
|
};
|
|
|
|
/**
|
|
* struct bdisp_dbg - debug info
|
|
*
|
|
* @debugfs_entry: debugfs
|
|
* @copy_node: array of last used nodes
|
|
* @copy_request: last bdisp request
|
|
* @hw_start: start time of last HW request
|
|
* @last_duration: last HW processing duration in microsecs
|
|
* @min_duration: min HW processing duration in microsecs
|
|
* @max_duration: max HW processing duration in microsecs
|
|
* @tot_duration: total HW processing duration in microsecs
|
|
*/
|
|
struct bdisp_dbg {
|
|
struct dentry *debugfs_entry;
|
|
struct bdisp_node *copy_node[MAX_NB_NODE];
|
|
struct bdisp_request copy_request;
|
|
ktime_t hw_start;
|
|
s64 last_duration;
|
|
s64 min_duration;
|
|
s64 max_duration;
|
|
s64 tot_duration;
|
|
};
|
|
|
|
/**
|
|
* struct bdisp_dev - abstraction for bdisp entity
|
|
*
|
|
* @v4l2_dev: v4l2 device
|
|
* @vdev: video device
|
|
* @pdev: platform device
|
|
* @dev: device
|
|
* @lock: mutex protecting this data structure
|
|
* @slock: spinlock protecting this data structure
|
|
* @id: device index
|
|
* @m2m: memory-to-memory V4L2 device information
|
|
* @state: flags used to synchronize m2m and capture mode operation
|
|
* @clock: IP clock
|
|
* @regs: registers
|
|
* @irq_queue: interrupt handler waitqueue
|
|
* @work_queue: workqueue to handle timeouts
|
|
* @timeout_work: IRQ timeout structure
|
|
* @dbg: debug info
|
|
*/
|
|
struct bdisp_dev {
|
|
struct v4l2_device v4l2_dev;
|
|
struct video_device vdev;
|
|
struct platform_device *pdev;
|
|
struct device *dev;
|
|
spinlock_t slock;
|
|
struct mutex lock;
|
|
u16 id;
|
|
struct bdisp_m2m_device m2m;
|
|
unsigned long state;
|
|
struct clk *clock;
|
|
void __iomem *regs;
|
|
wait_queue_head_t irq_queue;
|
|
struct workqueue_struct *work_queue;
|
|
struct delayed_work timeout_work;
|
|
struct bdisp_dbg dbg;
|
|
};
|
|
|
|
void bdisp_hw_free_nodes(struct bdisp_ctx *ctx);
|
|
int bdisp_hw_alloc_nodes(struct bdisp_ctx *ctx);
|
|
void bdisp_hw_free_filters(struct device *dev);
|
|
int bdisp_hw_alloc_filters(struct device *dev);
|
|
int bdisp_hw_reset(struct bdisp_dev *bdisp);
|
|
int bdisp_hw_get_and_clear_irq(struct bdisp_dev *bdisp);
|
|
int bdisp_hw_update(struct bdisp_ctx *ctx);
|
|
|
|
void bdisp_debugfs_remove(struct bdisp_dev *bdisp);
|
|
void bdisp_debugfs_create(struct bdisp_dev *bdisp);
|
|
void bdisp_dbg_perf_begin(struct bdisp_dev *bdisp);
|
|
void bdisp_dbg_perf_end(struct bdisp_dev *bdisp);
|