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