| /* 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); |
| int 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); |