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