1 | /* SPDX-License-Identifier: GPL-2.0-only */ |
2 | /* |
3 | * Copyright (C) 2012 Samsung Electronics Co., Ltd. |
4 | */ |
5 | |
6 | #ifndef FIMC_LITE_H_ |
7 | #define FIMC_LITE_H_ |
8 | |
9 | #include <linux/sizes.h> |
10 | #include <linux/io.h> |
11 | #include <linux/irqreturn.h> |
12 | #include <linux/platform_device.h> |
13 | #include <linux/sched.h> |
14 | #include <linux/spinlock.h> |
15 | #include <linux/types.h> |
16 | #include <linux/videodev2.h> |
17 | |
18 | #include <media/media-entity.h> |
19 | #include <media/videobuf2-v4l2.h> |
20 | #include <media/v4l2-ctrls.h> |
21 | #include <media/v4l2-device.h> |
22 | #include <media/v4l2-mediabus.h> |
23 | #include <media/drv-intf/exynos-fimc.h> |
24 | |
25 | #define FIMC_LITE_DRV_NAME "exynos-fimc-lite" |
26 | #define FLITE_CLK_NAME "flite" |
27 | #define FIMC_LITE_MAX_DEVS 3 |
28 | #define FLITE_REQ_BUFS_MIN 2 |
29 | #define FLITE_DEFAULT_WIDTH 640 |
30 | #define FLITE_DEFAULT_HEIGHT 480 |
31 | |
32 | /* Bit index definitions for struct fimc_lite::state */ |
33 | enum { |
34 | ST_FLITE_LPM, |
35 | ST_FLITE_PENDING, |
36 | ST_FLITE_RUN, |
37 | ST_FLITE_STREAM, |
38 | ST_FLITE_SUSPENDED, |
39 | ST_FLITE_OFF, |
40 | ST_FLITE_IN_USE, |
41 | ST_FLITE_CONFIG, |
42 | ST_SENSOR_STREAM, |
43 | }; |
44 | |
45 | #define FLITE_SD_PAD_SINK 0 |
46 | #define FLITE_SD_PAD_SOURCE_DMA 1 |
47 | #define FLITE_SD_PAD_SOURCE_ISP 2 |
48 | #define FLITE_SD_PADS_NUM 3 |
49 | |
50 | /** |
51 | * struct flite_drvdata - FIMC-LITE IP variant data structure |
52 | * @max_width: maximum camera interface input width in pixels |
53 | * @max_height: maximum camera interface input height in pixels |
54 | * @out_width_align: minimum output width alignment in pixels |
55 | * @win_hor_offs_align: minimum camera interface crop window horizontal |
56 | * offset alignment in pixels |
57 | * @out_hor_offs_align: minimum output DMA compose rectangle horizontal |
58 | * offset alignment in pixels |
59 | * @max_dma_bufs: number of output DMA buffer start address registers |
60 | * @num_instances: total number of FIMC-LITE IP instances available |
61 | */ |
62 | struct flite_drvdata { |
63 | unsigned short max_width; |
64 | unsigned short max_height; |
65 | unsigned short out_width_align; |
66 | unsigned short win_hor_offs_align; |
67 | unsigned short out_hor_offs_align; |
68 | unsigned short max_dma_bufs; |
69 | unsigned short num_instances; |
70 | }; |
71 | |
72 | struct fimc_lite_events { |
73 | unsigned int data_overflow; |
74 | }; |
75 | |
76 | #define FLITE_MAX_PLANES 1 |
77 | |
78 | /** |
79 | * struct flite_frame - source/target frame properties |
80 | * @f_width: full pixel width |
81 | * @f_height: full pixel height |
82 | * @rect: crop/composition rectangle |
83 | * @fmt: pointer to pixel format description data structure |
84 | */ |
85 | struct flite_frame { |
86 | u16 f_width; |
87 | u16 f_height; |
88 | struct v4l2_rect rect; |
89 | const struct fimc_fmt *fmt; |
90 | }; |
91 | |
92 | /** |
93 | * struct flite_buffer - video buffer structure |
94 | * @vb: vb2 buffer |
95 | * @list: list head for the buffers queue |
96 | * @addr: DMA buffer start address |
97 | * @index: DMA start address register's index |
98 | */ |
99 | struct flite_buffer { |
100 | struct vb2_v4l2_buffer vb; |
101 | struct list_head list; |
102 | dma_addr_t addr; |
103 | unsigned short index; |
104 | }; |
105 | |
106 | /** |
107 | * struct fimc_lite - fimc lite structure |
108 | * @pdev: pointer to FIMC-LITE platform device |
109 | * @dd: SoC specific driver data structure |
110 | * @ve: exynos video device entity structure |
111 | * @v4l2_dev: pointer to top the level v4l2_device |
112 | * @fh: v4l2 file handle |
113 | * @subdev: FIMC-LITE subdev |
114 | * @vd_pad: media (sink) pad for the capture video node |
115 | * @subdev_pads: the subdev media pads |
116 | * @sensor: sensor subdev attached to FIMC-LITE directly or through MIPI-CSIS |
117 | * @ctrl_handler: v4l2 control handler |
118 | * @test_pattern: test pattern controls |
119 | * @index: FIMC-LITE platform device index |
120 | * @slock: spinlock protecting this data structure and the hw registers |
121 | * @lock: mutex serializing video device and the subdev operations |
122 | * @clock: FIMC-LITE gate clock |
123 | * @regs: memory mapped io registers |
124 | * @irq_queue: interrupt handler waitqueue |
125 | * @payload: image size in bytes (w x h x bpp) |
126 | * @inp_frame: camera input frame structure |
127 | * @out_frame: DMA output frame structure |
128 | * @out_path: output data path (DMA or FIFO) |
129 | * @source_subdev_grp_id: source subdev group id |
130 | * @state: driver state flags |
131 | * @pending_buf_q: pending buffers queue head |
132 | * @active_buf_q: the queue head of buffers scheduled in hardware |
133 | * @vb_queue: vb2 buffers queue |
134 | * @buf_index: helps to keep track of the DMA start address register index |
135 | * @frame_count: the captured frames counter |
136 | * @reqbufs_count: the number of buffers requested with REQBUFS ioctl |
137 | * @events: event info |
138 | * @streaming: is streaming in progress? |
139 | */ |
140 | struct fimc_lite { |
141 | struct platform_device *pdev; |
142 | struct flite_drvdata *dd; |
143 | struct exynos_video_entity ve; |
144 | struct v4l2_device *v4l2_dev; |
145 | struct v4l2_fh fh; |
146 | struct v4l2_subdev subdev; |
147 | struct media_pad vd_pad; |
148 | struct media_pad subdev_pads[FLITE_SD_PADS_NUM]; |
149 | struct v4l2_subdev *sensor; |
150 | struct v4l2_ctrl_handler ctrl_handler; |
151 | struct v4l2_ctrl *test_pattern; |
152 | int index; |
153 | |
154 | struct mutex lock; |
155 | spinlock_t slock; |
156 | |
157 | struct clk *clock; |
158 | void __iomem *regs; |
159 | wait_queue_head_t irq_queue; |
160 | |
161 | unsigned long payload[FLITE_MAX_PLANES]; |
162 | struct flite_frame inp_frame; |
163 | struct flite_frame out_frame; |
164 | atomic_t out_path; |
165 | unsigned int source_subdev_grp_id; |
166 | |
167 | unsigned long state; |
168 | struct list_head pending_buf_q; |
169 | struct list_head active_buf_q; |
170 | struct vb2_queue vb_queue; |
171 | unsigned short buf_index; |
172 | unsigned int frame_count; |
173 | unsigned int reqbufs_count; |
174 | |
175 | struct fimc_lite_events events; |
176 | bool streaming; |
177 | }; |
178 | |
179 | static inline bool fimc_lite_active(struct fimc_lite *fimc) |
180 | { |
181 | unsigned long flags; |
182 | bool ret; |
183 | |
184 | spin_lock_irqsave(&fimc->slock, flags); |
185 | ret = fimc->state & (1 << ST_FLITE_RUN) || |
186 | fimc->state & (1 << ST_FLITE_PENDING); |
187 | spin_unlock_irqrestore(lock: &fimc->slock, flags); |
188 | return ret; |
189 | } |
190 | |
191 | static inline void fimc_lite_active_queue_add(struct fimc_lite *dev, |
192 | struct flite_buffer *buf) |
193 | { |
194 | list_add_tail(new: &buf->list, head: &dev->active_buf_q); |
195 | } |
196 | |
197 | static inline struct flite_buffer *fimc_lite_active_queue_pop( |
198 | struct fimc_lite *dev) |
199 | { |
200 | struct flite_buffer *buf = list_entry(dev->active_buf_q.next, |
201 | struct flite_buffer, list); |
202 | list_del(entry: &buf->list); |
203 | return buf; |
204 | } |
205 | |
206 | static inline void fimc_lite_pending_queue_add(struct fimc_lite *dev, |
207 | struct flite_buffer *buf) |
208 | { |
209 | list_add_tail(new: &buf->list, head: &dev->pending_buf_q); |
210 | } |
211 | |
212 | static inline struct flite_buffer *fimc_lite_pending_queue_pop( |
213 | struct fimc_lite *dev) |
214 | { |
215 | struct flite_buffer *buf = list_entry(dev->pending_buf_q.next, |
216 | struct flite_buffer, list); |
217 | list_del(entry: &buf->list); |
218 | return buf; |
219 | } |
220 | |
221 | #endif /* FIMC_LITE_H_ */ |
222 | |