18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * Copyright (C) STMicroelectronics SA 2014
48c2ecf20Sopenharmony_ci * Authors: Fabien Dessenne <fabien.dessenne@st.com> for STMicroelectronics.
58c2ecf20Sopenharmony_ci */
68c2ecf20Sopenharmony_ci
78c2ecf20Sopenharmony_ci#include <linux/clk.h>
88c2ecf20Sopenharmony_ci#include <linux/ktime.h>
98c2ecf20Sopenharmony_ci#include <linux/platform_device.h>
108c2ecf20Sopenharmony_ci#include <linux/spinlock.h>
118c2ecf20Sopenharmony_ci
128c2ecf20Sopenharmony_ci#include <media/v4l2-ctrls.h>
138c2ecf20Sopenharmony_ci#include <media/v4l2-device.h>
148c2ecf20Sopenharmony_ci#include <media/v4l2-mem2mem.h>
158c2ecf20Sopenharmony_ci
168c2ecf20Sopenharmony_ci#include <media/videobuf2-dma-contig.h>
178c2ecf20Sopenharmony_ci
188c2ecf20Sopenharmony_ci#define BDISP_NAME              "bdisp"
198c2ecf20Sopenharmony_ci
208c2ecf20Sopenharmony_ci/*
218c2ecf20Sopenharmony_ci *  Max nb of nodes in node-list:
228c2ecf20Sopenharmony_ci *   - 2 nodes to handle wide 4K pictures
238c2ecf20Sopenharmony_ci *   - 2 nodes to handle two planes (Y & CbCr) */
248c2ecf20Sopenharmony_ci#define MAX_OUTPUT_PLANES       2
258c2ecf20Sopenharmony_ci#define MAX_VERTICAL_STRIDES    2
268c2ecf20Sopenharmony_ci#define MAX_NB_NODE             (MAX_OUTPUT_PLANES * MAX_VERTICAL_STRIDES)
278c2ecf20Sopenharmony_ci
288c2ecf20Sopenharmony_ci/* struct bdisp_ctrls - bdisp control set
298c2ecf20Sopenharmony_ci * @hflip:      horizontal flip
308c2ecf20Sopenharmony_ci * @vflip:      vertical flip
318c2ecf20Sopenharmony_ci */
328c2ecf20Sopenharmony_cistruct bdisp_ctrls {
338c2ecf20Sopenharmony_ci	struct v4l2_ctrl        *hflip;
348c2ecf20Sopenharmony_ci	struct v4l2_ctrl        *vflip;
358c2ecf20Sopenharmony_ci};
368c2ecf20Sopenharmony_ci
378c2ecf20Sopenharmony_ci/**
388c2ecf20Sopenharmony_ci * struct bdisp_fmt - driver's internal color format data
398c2ecf20Sopenharmony_ci * @pixelformat:fourcc code for this format
408c2ecf20Sopenharmony_ci * @nb_planes:  number of planes  (ex: [0]=RGB/Y - [1]=Cb/Cr, ...)
418c2ecf20Sopenharmony_ci * @bpp:        bits per pixel (general)
428c2ecf20Sopenharmony_ci * @bpp_plane0: byte per pixel for the 1st plane
438c2ecf20Sopenharmony_ci * @w_align:    width alignment in pixel (multiple of)
448c2ecf20Sopenharmony_ci * @h_align:    height alignment in pixel (multiple of)
458c2ecf20Sopenharmony_ci */
468c2ecf20Sopenharmony_cistruct bdisp_fmt {
478c2ecf20Sopenharmony_ci	u32                     pixelformat;
488c2ecf20Sopenharmony_ci	u8                      nb_planes;
498c2ecf20Sopenharmony_ci	u8                      bpp;
508c2ecf20Sopenharmony_ci	u8                      bpp_plane0;
518c2ecf20Sopenharmony_ci	u8                      w_align;
528c2ecf20Sopenharmony_ci	u8                      h_align;
538c2ecf20Sopenharmony_ci};
548c2ecf20Sopenharmony_ci
558c2ecf20Sopenharmony_ci/**
568c2ecf20Sopenharmony_ci * struct bdisp_frame - frame properties
578c2ecf20Sopenharmony_ci *
588c2ecf20Sopenharmony_ci * @width:      frame width (including padding)
598c2ecf20Sopenharmony_ci * @height:     frame height (including padding)
608c2ecf20Sopenharmony_ci * @fmt:        pointer to frame format descriptor
618c2ecf20Sopenharmony_ci * @field:      frame / field type
628c2ecf20Sopenharmony_ci * @bytesperline: stride of the 1st plane
638c2ecf20Sopenharmony_ci * @sizeimage:  image size in bytes
648c2ecf20Sopenharmony_ci * @colorspace: colorspace
658c2ecf20Sopenharmony_ci * @crop:       crop area
668c2ecf20Sopenharmony_ci * @paddr:      image physical addresses per plane ([0]=RGB/Y - [1]=Cb/Cr, ...)
678c2ecf20Sopenharmony_ci */
688c2ecf20Sopenharmony_cistruct bdisp_frame {
698c2ecf20Sopenharmony_ci	u32                     width;
708c2ecf20Sopenharmony_ci	u32                     height;
718c2ecf20Sopenharmony_ci	const struct bdisp_fmt  *fmt;
728c2ecf20Sopenharmony_ci	enum v4l2_field         field;
738c2ecf20Sopenharmony_ci	u32                     bytesperline;
748c2ecf20Sopenharmony_ci	u32                     sizeimage;
758c2ecf20Sopenharmony_ci	enum v4l2_colorspace    colorspace;
768c2ecf20Sopenharmony_ci	struct v4l2_rect        crop;
778c2ecf20Sopenharmony_ci	dma_addr_t              paddr[4];
788c2ecf20Sopenharmony_ci};
798c2ecf20Sopenharmony_ci
808c2ecf20Sopenharmony_ci/**
818c2ecf20Sopenharmony_ci * struct bdisp_request - bdisp request
828c2ecf20Sopenharmony_ci *
838c2ecf20Sopenharmony_ci * @src:        source frame properties
848c2ecf20Sopenharmony_ci * @dst:        destination frame properties
858c2ecf20Sopenharmony_ci * @hflip:      horizontal flip
868c2ecf20Sopenharmony_ci * @vflip:      vertical flip
878c2ecf20Sopenharmony_ci * @nb_req:     number of run request
888c2ecf20Sopenharmony_ci */
898c2ecf20Sopenharmony_cistruct bdisp_request {
908c2ecf20Sopenharmony_ci	struct bdisp_frame      src;
918c2ecf20Sopenharmony_ci	struct bdisp_frame      dst;
928c2ecf20Sopenharmony_ci	unsigned int            hflip:1;
938c2ecf20Sopenharmony_ci	unsigned int            vflip:1;
948c2ecf20Sopenharmony_ci	int                     nb_req;
958c2ecf20Sopenharmony_ci};
968c2ecf20Sopenharmony_ci
978c2ecf20Sopenharmony_ci/**
988c2ecf20Sopenharmony_ci * struct bdisp_ctx - device context data
998c2ecf20Sopenharmony_ci *
1008c2ecf20Sopenharmony_ci * @src:        source frame properties
1018c2ecf20Sopenharmony_ci * @dst:        destination frame properties
1028c2ecf20Sopenharmony_ci * @state:      flags to keep track of user configuration
1038c2ecf20Sopenharmony_ci * @hflip:      horizontal flip
1048c2ecf20Sopenharmony_ci * @vflip:      vertical flip
1058c2ecf20Sopenharmony_ci * @bdisp_dev:  the device this context applies to
1068c2ecf20Sopenharmony_ci * @node:       node array
1078c2ecf20Sopenharmony_ci * @node_paddr: node physical address array
1088c2ecf20Sopenharmony_ci * @fh:         v4l2 file handle
1098c2ecf20Sopenharmony_ci * @ctrl_handler: v4l2 controls handler
1108c2ecf20Sopenharmony_ci * @bdisp_ctrls: bdisp control set
1118c2ecf20Sopenharmony_ci * @ctrls_rdy:  true if the control handler is initialized
1128c2ecf20Sopenharmony_ci */
1138c2ecf20Sopenharmony_cistruct bdisp_ctx {
1148c2ecf20Sopenharmony_ci	struct bdisp_frame      src;
1158c2ecf20Sopenharmony_ci	struct bdisp_frame      dst;
1168c2ecf20Sopenharmony_ci	u32                     state;
1178c2ecf20Sopenharmony_ci	unsigned int            hflip:1;
1188c2ecf20Sopenharmony_ci	unsigned int            vflip:1;
1198c2ecf20Sopenharmony_ci	struct bdisp_dev        *bdisp_dev;
1208c2ecf20Sopenharmony_ci	struct bdisp_node       *node[MAX_NB_NODE];
1218c2ecf20Sopenharmony_ci	dma_addr_t              node_paddr[MAX_NB_NODE];
1228c2ecf20Sopenharmony_ci	struct v4l2_fh          fh;
1238c2ecf20Sopenharmony_ci	struct v4l2_ctrl_handler ctrl_handler;
1248c2ecf20Sopenharmony_ci	struct bdisp_ctrls      bdisp_ctrls;
1258c2ecf20Sopenharmony_ci	bool                    ctrls_rdy;
1268c2ecf20Sopenharmony_ci};
1278c2ecf20Sopenharmony_ci
1288c2ecf20Sopenharmony_ci/**
1298c2ecf20Sopenharmony_ci * struct bdisp_m2m_device - v4l2 memory-to-memory device data
1308c2ecf20Sopenharmony_ci *
1318c2ecf20Sopenharmony_ci * @vdev:       video device node for v4l2 m2m mode
1328c2ecf20Sopenharmony_ci * @m2m_dev:    v4l2 m2m device data
1338c2ecf20Sopenharmony_ci * @ctx:        hardware context data
1348c2ecf20Sopenharmony_ci * @refcnt:     reference counter
1358c2ecf20Sopenharmony_ci */
1368c2ecf20Sopenharmony_cistruct bdisp_m2m_device {
1378c2ecf20Sopenharmony_ci	struct video_device     *vdev;
1388c2ecf20Sopenharmony_ci	struct v4l2_m2m_dev     *m2m_dev;
1398c2ecf20Sopenharmony_ci	struct bdisp_ctx        *ctx;
1408c2ecf20Sopenharmony_ci	int                     refcnt;
1418c2ecf20Sopenharmony_ci};
1428c2ecf20Sopenharmony_ci
1438c2ecf20Sopenharmony_ci/**
1448c2ecf20Sopenharmony_ci * struct bdisp_dbg - debug info
1458c2ecf20Sopenharmony_ci *
1468c2ecf20Sopenharmony_ci * @debugfs_entry: debugfs
1478c2ecf20Sopenharmony_ci * @copy_node:     array of last used nodes
1488c2ecf20Sopenharmony_ci * @copy_request:  last bdisp request
1498c2ecf20Sopenharmony_ci * @hw_start:      start time of last HW request
1508c2ecf20Sopenharmony_ci * @last_duration: last HW processing duration in microsecs
1518c2ecf20Sopenharmony_ci * @min_duration:  min HW processing duration in microsecs
1528c2ecf20Sopenharmony_ci * @max_duration:  max HW processing duration in microsecs
1538c2ecf20Sopenharmony_ci * @tot_duration:  total HW processing duration in microsecs
1548c2ecf20Sopenharmony_ci */
1558c2ecf20Sopenharmony_cistruct bdisp_dbg {
1568c2ecf20Sopenharmony_ci	struct dentry           *debugfs_entry;
1578c2ecf20Sopenharmony_ci	struct bdisp_node       *copy_node[MAX_NB_NODE];
1588c2ecf20Sopenharmony_ci	struct bdisp_request    copy_request;
1598c2ecf20Sopenharmony_ci	ktime_t                 hw_start;
1608c2ecf20Sopenharmony_ci	s64                     last_duration;
1618c2ecf20Sopenharmony_ci	s64                     min_duration;
1628c2ecf20Sopenharmony_ci	s64                     max_duration;
1638c2ecf20Sopenharmony_ci	s64                     tot_duration;
1648c2ecf20Sopenharmony_ci};
1658c2ecf20Sopenharmony_ci
1668c2ecf20Sopenharmony_ci/**
1678c2ecf20Sopenharmony_ci * struct bdisp_dev - abstraction for bdisp entity
1688c2ecf20Sopenharmony_ci *
1698c2ecf20Sopenharmony_ci * @v4l2_dev:   v4l2 device
1708c2ecf20Sopenharmony_ci * @vdev:       video device
1718c2ecf20Sopenharmony_ci * @pdev:       platform device
1728c2ecf20Sopenharmony_ci * @dev:        device
1738c2ecf20Sopenharmony_ci * @lock:       mutex protecting this data structure
1748c2ecf20Sopenharmony_ci * @slock:      spinlock protecting this data structure
1758c2ecf20Sopenharmony_ci * @id:         device index
1768c2ecf20Sopenharmony_ci * @m2m:        memory-to-memory V4L2 device information
1778c2ecf20Sopenharmony_ci * @state:      flags used to synchronize m2m and capture mode operation
1788c2ecf20Sopenharmony_ci * @clock:      IP clock
1798c2ecf20Sopenharmony_ci * @regs:       registers
1808c2ecf20Sopenharmony_ci * @irq_queue:  interrupt handler waitqueue
1818c2ecf20Sopenharmony_ci * @work_queue: workqueue to handle timeouts
1828c2ecf20Sopenharmony_ci * @timeout_work: IRQ timeout structure
1838c2ecf20Sopenharmony_ci * @dbg:        debug info
1848c2ecf20Sopenharmony_ci */
1858c2ecf20Sopenharmony_cistruct bdisp_dev {
1868c2ecf20Sopenharmony_ci	struct v4l2_device      v4l2_dev;
1878c2ecf20Sopenharmony_ci	struct video_device     vdev;
1888c2ecf20Sopenharmony_ci	struct platform_device  *pdev;
1898c2ecf20Sopenharmony_ci	struct device           *dev;
1908c2ecf20Sopenharmony_ci	spinlock_t              slock;
1918c2ecf20Sopenharmony_ci	struct mutex            lock;
1928c2ecf20Sopenharmony_ci	u16                     id;
1938c2ecf20Sopenharmony_ci	struct bdisp_m2m_device m2m;
1948c2ecf20Sopenharmony_ci	unsigned long           state;
1958c2ecf20Sopenharmony_ci	struct clk              *clock;
1968c2ecf20Sopenharmony_ci	void __iomem            *regs;
1978c2ecf20Sopenharmony_ci	wait_queue_head_t       irq_queue;
1988c2ecf20Sopenharmony_ci	struct workqueue_struct *work_queue;
1998c2ecf20Sopenharmony_ci	struct delayed_work     timeout_work;
2008c2ecf20Sopenharmony_ci	struct bdisp_dbg        dbg;
2018c2ecf20Sopenharmony_ci};
2028c2ecf20Sopenharmony_ci
2038c2ecf20Sopenharmony_civoid bdisp_hw_free_nodes(struct bdisp_ctx *ctx);
2048c2ecf20Sopenharmony_ciint bdisp_hw_alloc_nodes(struct bdisp_ctx *ctx);
2058c2ecf20Sopenharmony_civoid bdisp_hw_free_filters(struct device *dev);
2068c2ecf20Sopenharmony_ciint bdisp_hw_alloc_filters(struct device *dev);
2078c2ecf20Sopenharmony_ciint bdisp_hw_reset(struct bdisp_dev *bdisp);
2088c2ecf20Sopenharmony_ciint bdisp_hw_get_and_clear_irq(struct bdisp_dev *bdisp);
2098c2ecf20Sopenharmony_ciint bdisp_hw_update(struct bdisp_ctx *ctx);
2108c2ecf20Sopenharmony_ci
2118c2ecf20Sopenharmony_civoid bdisp_debugfs_remove(struct bdisp_dev *bdisp);
2128c2ecf20Sopenharmony_civoid bdisp_debugfs_create(struct bdisp_dev *bdisp);
2138c2ecf20Sopenharmony_civoid bdisp_dbg_perf_begin(struct bdisp_dev *bdisp);
2148c2ecf20Sopenharmony_civoid bdisp_dbg_perf_end(struct bdisp_dev *bdisp);
215