1*4882a593Smuzhiyun /* SPDX-License-Identifier: GPL-2.0 */ 2*4882a593Smuzhiyun /* 3*4882a593Smuzhiyun * Copyright (C) STMicroelectronics SA 2014 4*4882a593Smuzhiyun * Authors: Fabien Dessenne <fabien.dessenne@st.com> for STMicroelectronics. 5*4882a593Smuzhiyun */ 6*4882a593Smuzhiyun 7*4882a593Smuzhiyun #include <linux/clk.h> 8*4882a593Smuzhiyun #include <linux/ktime.h> 9*4882a593Smuzhiyun #include <linux/platform_device.h> 10*4882a593Smuzhiyun #include <linux/spinlock.h> 11*4882a593Smuzhiyun 12*4882a593Smuzhiyun #include <media/v4l2-ctrls.h> 13*4882a593Smuzhiyun #include <media/v4l2-device.h> 14*4882a593Smuzhiyun #include <media/v4l2-mem2mem.h> 15*4882a593Smuzhiyun 16*4882a593Smuzhiyun #include <media/videobuf2-dma-contig.h> 17*4882a593Smuzhiyun 18*4882a593Smuzhiyun #define BDISP_NAME "bdisp" 19*4882a593Smuzhiyun 20*4882a593Smuzhiyun /* 21*4882a593Smuzhiyun * Max nb of nodes in node-list: 22*4882a593Smuzhiyun * - 2 nodes to handle wide 4K pictures 23*4882a593Smuzhiyun * - 2 nodes to handle two planes (Y & CbCr) */ 24*4882a593Smuzhiyun #define MAX_OUTPUT_PLANES 2 25*4882a593Smuzhiyun #define MAX_VERTICAL_STRIDES 2 26*4882a593Smuzhiyun #define MAX_NB_NODE (MAX_OUTPUT_PLANES * MAX_VERTICAL_STRIDES) 27*4882a593Smuzhiyun 28*4882a593Smuzhiyun /* struct bdisp_ctrls - bdisp control set 29*4882a593Smuzhiyun * @hflip: horizontal flip 30*4882a593Smuzhiyun * @vflip: vertical flip 31*4882a593Smuzhiyun */ 32*4882a593Smuzhiyun struct bdisp_ctrls { 33*4882a593Smuzhiyun struct v4l2_ctrl *hflip; 34*4882a593Smuzhiyun struct v4l2_ctrl *vflip; 35*4882a593Smuzhiyun }; 36*4882a593Smuzhiyun 37*4882a593Smuzhiyun /** 38*4882a593Smuzhiyun * struct bdisp_fmt - driver's internal color format data 39*4882a593Smuzhiyun * @pixelformat:fourcc code for this format 40*4882a593Smuzhiyun * @nb_planes: number of planes (ex: [0]=RGB/Y - [1]=Cb/Cr, ...) 41*4882a593Smuzhiyun * @bpp: bits per pixel (general) 42*4882a593Smuzhiyun * @bpp_plane0: byte per pixel for the 1st plane 43*4882a593Smuzhiyun * @w_align: width alignment in pixel (multiple of) 44*4882a593Smuzhiyun * @h_align: height alignment in pixel (multiple of) 45*4882a593Smuzhiyun */ 46*4882a593Smuzhiyun struct bdisp_fmt { 47*4882a593Smuzhiyun u32 pixelformat; 48*4882a593Smuzhiyun u8 nb_planes; 49*4882a593Smuzhiyun u8 bpp; 50*4882a593Smuzhiyun u8 bpp_plane0; 51*4882a593Smuzhiyun u8 w_align; 52*4882a593Smuzhiyun u8 h_align; 53*4882a593Smuzhiyun }; 54*4882a593Smuzhiyun 55*4882a593Smuzhiyun /** 56*4882a593Smuzhiyun * struct bdisp_frame - frame properties 57*4882a593Smuzhiyun * 58*4882a593Smuzhiyun * @width: frame width (including padding) 59*4882a593Smuzhiyun * @height: frame height (including padding) 60*4882a593Smuzhiyun * @fmt: pointer to frame format descriptor 61*4882a593Smuzhiyun * @field: frame / field type 62*4882a593Smuzhiyun * @bytesperline: stride of the 1st plane 63*4882a593Smuzhiyun * @sizeimage: image size in bytes 64*4882a593Smuzhiyun * @colorspace: colorspace 65*4882a593Smuzhiyun * @crop: crop area 66*4882a593Smuzhiyun * @paddr: image physical addresses per plane ([0]=RGB/Y - [1]=Cb/Cr, ...) 67*4882a593Smuzhiyun */ 68*4882a593Smuzhiyun struct bdisp_frame { 69*4882a593Smuzhiyun u32 width; 70*4882a593Smuzhiyun u32 height; 71*4882a593Smuzhiyun const struct bdisp_fmt *fmt; 72*4882a593Smuzhiyun enum v4l2_field field; 73*4882a593Smuzhiyun u32 bytesperline; 74*4882a593Smuzhiyun u32 sizeimage; 75*4882a593Smuzhiyun enum v4l2_colorspace colorspace; 76*4882a593Smuzhiyun struct v4l2_rect crop; 77*4882a593Smuzhiyun dma_addr_t paddr[4]; 78*4882a593Smuzhiyun }; 79*4882a593Smuzhiyun 80*4882a593Smuzhiyun /** 81*4882a593Smuzhiyun * struct bdisp_request - bdisp request 82*4882a593Smuzhiyun * 83*4882a593Smuzhiyun * @src: source frame properties 84*4882a593Smuzhiyun * @dst: destination frame properties 85*4882a593Smuzhiyun * @hflip: horizontal flip 86*4882a593Smuzhiyun * @vflip: vertical flip 87*4882a593Smuzhiyun * @nb_req: number of run request 88*4882a593Smuzhiyun */ 89*4882a593Smuzhiyun struct bdisp_request { 90*4882a593Smuzhiyun struct bdisp_frame src; 91*4882a593Smuzhiyun struct bdisp_frame dst; 92*4882a593Smuzhiyun unsigned int hflip:1; 93*4882a593Smuzhiyun unsigned int vflip:1; 94*4882a593Smuzhiyun int nb_req; 95*4882a593Smuzhiyun }; 96*4882a593Smuzhiyun 97*4882a593Smuzhiyun /** 98*4882a593Smuzhiyun * struct bdisp_ctx - device context data 99*4882a593Smuzhiyun * 100*4882a593Smuzhiyun * @src: source frame properties 101*4882a593Smuzhiyun * @dst: destination frame properties 102*4882a593Smuzhiyun * @state: flags to keep track of user configuration 103*4882a593Smuzhiyun * @hflip: horizontal flip 104*4882a593Smuzhiyun * @vflip: vertical flip 105*4882a593Smuzhiyun * @bdisp_dev: the device this context applies to 106*4882a593Smuzhiyun * @node: node array 107*4882a593Smuzhiyun * @node_paddr: node physical address array 108*4882a593Smuzhiyun * @fh: v4l2 file handle 109*4882a593Smuzhiyun * @ctrl_handler: v4l2 controls handler 110*4882a593Smuzhiyun * @bdisp_ctrls: bdisp control set 111*4882a593Smuzhiyun * @ctrls_rdy: true if the control handler is initialized 112*4882a593Smuzhiyun */ 113*4882a593Smuzhiyun struct bdisp_ctx { 114*4882a593Smuzhiyun struct bdisp_frame src; 115*4882a593Smuzhiyun struct bdisp_frame dst; 116*4882a593Smuzhiyun u32 state; 117*4882a593Smuzhiyun unsigned int hflip:1; 118*4882a593Smuzhiyun unsigned int vflip:1; 119*4882a593Smuzhiyun struct bdisp_dev *bdisp_dev; 120*4882a593Smuzhiyun struct bdisp_node *node[MAX_NB_NODE]; 121*4882a593Smuzhiyun dma_addr_t node_paddr[MAX_NB_NODE]; 122*4882a593Smuzhiyun struct v4l2_fh fh; 123*4882a593Smuzhiyun struct v4l2_ctrl_handler ctrl_handler; 124*4882a593Smuzhiyun struct bdisp_ctrls bdisp_ctrls; 125*4882a593Smuzhiyun bool ctrls_rdy; 126*4882a593Smuzhiyun }; 127*4882a593Smuzhiyun 128*4882a593Smuzhiyun /** 129*4882a593Smuzhiyun * struct bdisp_m2m_device - v4l2 memory-to-memory device data 130*4882a593Smuzhiyun * 131*4882a593Smuzhiyun * @vdev: video device node for v4l2 m2m mode 132*4882a593Smuzhiyun * @m2m_dev: v4l2 m2m device data 133*4882a593Smuzhiyun * @ctx: hardware context data 134*4882a593Smuzhiyun * @refcnt: reference counter 135*4882a593Smuzhiyun */ 136*4882a593Smuzhiyun struct bdisp_m2m_device { 137*4882a593Smuzhiyun struct video_device *vdev; 138*4882a593Smuzhiyun struct v4l2_m2m_dev *m2m_dev; 139*4882a593Smuzhiyun struct bdisp_ctx *ctx; 140*4882a593Smuzhiyun int refcnt; 141*4882a593Smuzhiyun }; 142*4882a593Smuzhiyun 143*4882a593Smuzhiyun /** 144*4882a593Smuzhiyun * struct bdisp_dbg - debug info 145*4882a593Smuzhiyun * 146*4882a593Smuzhiyun * @debugfs_entry: debugfs 147*4882a593Smuzhiyun * @copy_node: array of last used nodes 148*4882a593Smuzhiyun * @copy_request: last bdisp request 149*4882a593Smuzhiyun * @hw_start: start time of last HW request 150*4882a593Smuzhiyun * @last_duration: last HW processing duration in microsecs 151*4882a593Smuzhiyun * @min_duration: min HW processing duration in microsecs 152*4882a593Smuzhiyun * @max_duration: max HW processing duration in microsecs 153*4882a593Smuzhiyun * @tot_duration: total HW processing duration in microsecs 154*4882a593Smuzhiyun */ 155*4882a593Smuzhiyun struct bdisp_dbg { 156*4882a593Smuzhiyun struct dentry *debugfs_entry; 157*4882a593Smuzhiyun struct bdisp_node *copy_node[MAX_NB_NODE]; 158*4882a593Smuzhiyun struct bdisp_request copy_request; 159*4882a593Smuzhiyun ktime_t hw_start; 160*4882a593Smuzhiyun s64 last_duration; 161*4882a593Smuzhiyun s64 min_duration; 162*4882a593Smuzhiyun s64 max_duration; 163*4882a593Smuzhiyun s64 tot_duration; 164*4882a593Smuzhiyun }; 165*4882a593Smuzhiyun 166*4882a593Smuzhiyun /** 167*4882a593Smuzhiyun * struct bdisp_dev - abstraction for bdisp entity 168*4882a593Smuzhiyun * 169*4882a593Smuzhiyun * @v4l2_dev: v4l2 device 170*4882a593Smuzhiyun * @vdev: video device 171*4882a593Smuzhiyun * @pdev: platform device 172*4882a593Smuzhiyun * @dev: device 173*4882a593Smuzhiyun * @lock: mutex protecting this data structure 174*4882a593Smuzhiyun * @slock: spinlock protecting this data structure 175*4882a593Smuzhiyun * @id: device index 176*4882a593Smuzhiyun * @m2m: memory-to-memory V4L2 device information 177*4882a593Smuzhiyun * @state: flags used to synchronize m2m and capture mode operation 178*4882a593Smuzhiyun * @clock: IP clock 179*4882a593Smuzhiyun * @regs: registers 180*4882a593Smuzhiyun * @irq_queue: interrupt handler waitqueue 181*4882a593Smuzhiyun * @work_queue: workqueue to handle timeouts 182*4882a593Smuzhiyun * @timeout_work: IRQ timeout structure 183*4882a593Smuzhiyun * @dbg: debug info 184*4882a593Smuzhiyun */ 185*4882a593Smuzhiyun struct bdisp_dev { 186*4882a593Smuzhiyun struct v4l2_device v4l2_dev; 187*4882a593Smuzhiyun struct video_device vdev; 188*4882a593Smuzhiyun struct platform_device *pdev; 189*4882a593Smuzhiyun struct device *dev; 190*4882a593Smuzhiyun spinlock_t slock; 191*4882a593Smuzhiyun struct mutex lock; 192*4882a593Smuzhiyun u16 id; 193*4882a593Smuzhiyun struct bdisp_m2m_device m2m; 194*4882a593Smuzhiyun unsigned long state; 195*4882a593Smuzhiyun struct clk *clock; 196*4882a593Smuzhiyun void __iomem *regs; 197*4882a593Smuzhiyun wait_queue_head_t irq_queue; 198*4882a593Smuzhiyun struct workqueue_struct *work_queue; 199*4882a593Smuzhiyun struct delayed_work timeout_work; 200*4882a593Smuzhiyun struct bdisp_dbg dbg; 201*4882a593Smuzhiyun }; 202*4882a593Smuzhiyun 203*4882a593Smuzhiyun void bdisp_hw_free_nodes(struct bdisp_ctx *ctx); 204*4882a593Smuzhiyun int bdisp_hw_alloc_nodes(struct bdisp_ctx *ctx); 205*4882a593Smuzhiyun void bdisp_hw_free_filters(struct device *dev); 206*4882a593Smuzhiyun int bdisp_hw_alloc_filters(struct device *dev); 207*4882a593Smuzhiyun int bdisp_hw_reset(struct bdisp_dev *bdisp); 208*4882a593Smuzhiyun int bdisp_hw_get_and_clear_irq(struct bdisp_dev *bdisp); 209*4882a593Smuzhiyun int bdisp_hw_update(struct bdisp_ctx *ctx); 210*4882a593Smuzhiyun 211*4882a593Smuzhiyun void bdisp_debugfs_remove(struct bdisp_dev *bdisp); 212*4882a593Smuzhiyun void bdisp_debugfs_create(struct bdisp_dev *bdisp); 213*4882a593Smuzhiyun void bdisp_dbg_perf_begin(struct bdisp_dev *bdisp); 214*4882a593Smuzhiyun void bdisp_dbg_perf_end(struct bdisp_dev *bdisp); 215