Loading...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 | /* 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); |