]>
Commit | Line | Data |
---|---|---|
8d0f6e13 | 1 | // SPDX-License-Identifier: GPL-2.0 |
37404f91 HF |
2 | /* |
3 | * Driver for STM32 Digital Camera Memory Interface | |
4 | * | |
5 | * Copyright (C) STMicroelectronics SA 2017 | |
6 | * Authors: Yannick Fertre <yannick.fertre@st.com> | |
7 | * Hugues Fruchet <hugues.fruchet@st.com> | |
8 | * for STMicroelectronics. | |
37404f91 HF |
9 | * |
10 | * This driver is based on atmel_isi.c | |
11 | * | |
12 | */ | |
13 | ||
14 | #include <linux/clk.h> | |
15 | #include <linux/completion.h> | |
16 | #include <linux/delay.h> | |
17 | #include <linux/dmaengine.h> | |
18 | #include <linux/init.h> | |
19 | #include <linux/interrupt.h> | |
20 | #include <linux/kernel.h> | |
21 | #include <linux/module.h> | |
22 | #include <linux/of.h> | |
23 | #include <linux/of_device.h> | |
859969b3 | 24 | #include <linux/of_graph.h> |
152e0bf6 | 25 | #include <linux/pinctrl/consumer.h> |
37404f91 | 26 | #include <linux/platform_device.h> |
152e0bf6 | 27 | #include <linux/pm_runtime.h> |
37404f91 HF |
28 | #include <linux/reset.h> |
29 | #include <linux/videodev2.h> | |
30 | ||
31 | #include <media/v4l2-ctrls.h> | |
32 | #include <media/v4l2-dev.h> | |
33 | #include <media/v4l2-device.h> | |
34 | #include <media/v4l2-event.h> | |
859969b3 | 35 | #include <media/v4l2-fwnode.h> |
37404f91 HF |
36 | #include <media/v4l2-image-sizes.h> |
37 | #include <media/v4l2-ioctl.h> | |
d533d501 | 38 | #include <media/v4l2-rect.h> |
37404f91 HF |
39 | #include <media/videobuf2-dma-contig.h> |
40 | ||
41 | #define DRV_NAME "stm32-dcmi" | |
42 | ||
43 | /* Registers offset for DCMI */ | |
44 | #define DCMI_CR 0x00 /* Control Register */ | |
45 | #define DCMI_SR 0x04 /* Status Register */ | |
46 | #define DCMI_RIS 0x08 /* Raw Interrupt Status register */ | |
47 | #define DCMI_IER 0x0C /* Interrupt Enable Register */ | |
48 | #define DCMI_MIS 0x10 /* Masked Interrupt Status register */ | |
49 | #define DCMI_ICR 0x14 /* Interrupt Clear Register */ | |
50 | #define DCMI_ESCR 0x18 /* Embedded Synchronization Code Register */ | |
51 | #define DCMI_ESUR 0x1C /* Embedded Synchronization Unmask Register */ | |
52 | #define DCMI_CWSTRT 0x20 /* Crop Window STaRT */ | |
53 | #define DCMI_CWSIZE 0x24 /* Crop Window SIZE */ | |
54 | #define DCMI_DR 0x28 /* Data Register */ | |
55 | #define DCMI_IDR 0x2C /* IDentifier Register */ | |
56 | ||
57 | /* Bits definition for control register (DCMI_CR) */ | |
58 | #define CR_CAPTURE BIT(0) | |
59 | #define CR_CM BIT(1) | |
60 | #define CR_CROP BIT(2) | |
61 | #define CR_JPEG BIT(3) | |
62 | #define CR_ESS BIT(4) | |
63 | #define CR_PCKPOL BIT(5) | |
64 | #define CR_HSPOL BIT(6) | |
65 | #define CR_VSPOL BIT(7) | |
66 | #define CR_FCRC_0 BIT(8) | |
67 | #define CR_FCRC_1 BIT(9) | |
68 | #define CR_EDM_0 BIT(10) | |
69 | #define CR_EDM_1 BIT(11) | |
70 | #define CR_ENABLE BIT(14) | |
71 | ||
72 | /* Bits definition for status register (DCMI_SR) */ | |
73 | #define SR_HSYNC BIT(0) | |
74 | #define SR_VSYNC BIT(1) | |
75 | #define SR_FNE BIT(2) | |
76 | ||
77 | /* | |
78 | * Bits definition for interrupt registers | |
79 | * (DCMI_RIS, DCMI_IER, DCMI_MIS, DCMI_ICR) | |
80 | */ | |
81 | #define IT_FRAME BIT(0) | |
82 | #define IT_OVR BIT(1) | |
83 | #define IT_ERR BIT(2) | |
84 | #define IT_VSYNC BIT(3) | |
85 | #define IT_LINE BIT(4) | |
86 | ||
87 | enum state { | |
88 | STOPPED = 0, | |
2d494d4a | 89 | WAIT_FOR_BUFFER, |
37404f91 | 90 | RUNNING, |
37404f91 HF |
91 | }; |
92 | ||
93 | #define MIN_WIDTH 16U | |
bfe75f76 | 94 | #define MAX_WIDTH 2592U |
37404f91 | 95 | #define MIN_HEIGHT 16U |
bfe75f76 | 96 | #define MAX_HEIGHT 2592U |
3e187c81 | 97 | |
37404f91 HF |
98 | #define TIMEOUT_MS 1000 |
99 | ||
1be0a2b7 HF |
100 | #define OVERRUN_ERROR_THRESHOLD 3 |
101 | ||
37404f91 HF |
102 | struct dcmi_format { |
103 | u32 fourcc; | |
104 | u32 mbus_code; | |
105 | u8 bpp; | |
106 | }; | |
107 | ||
d533d501 HF |
108 | struct dcmi_framesize { |
109 | u32 width; | |
110 | u32 height; | |
111 | }; | |
112 | ||
37404f91 HF |
113 | struct dcmi_buf { |
114 | struct vb2_v4l2_buffer vb; | |
115 | bool prepared; | |
116 | dma_addr_t paddr; | |
117 | size_t size; | |
118 | struct list_head list; | |
119 | }; | |
120 | ||
121 | struct stm32_dcmi { | |
122 | /* Protects the access of variables shared within the interrupt */ | |
123 | spinlock_t irqlock; | |
124 | struct device *dev; | |
125 | void __iomem *regs; | |
126 | struct resource *res; | |
127 | struct reset_control *rstc; | |
128 | int sequence; | |
129 | struct list_head buffers; | |
130 | struct dcmi_buf *active; | |
131 | ||
132 | struct v4l2_device v4l2_dev; | |
133 | struct video_device *vdev; | |
134 | struct v4l2_async_notifier notifier; | |
49cff8db | 135 | struct v4l2_subdev *source; |
37404f91 | 136 | struct v4l2_format fmt; |
d533d501 HF |
137 | struct v4l2_rect crop; |
138 | bool do_crop; | |
37404f91 | 139 | |
38e423ee HF |
140 | const struct dcmi_format **sd_formats; |
141 | unsigned int num_of_sd_formats; | |
142 | const struct dcmi_format *sd_format; | |
d533d501 HF |
143 | struct dcmi_framesize *sd_framesizes; |
144 | unsigned int num_of_sd_framesizes; | |
145 | struct dcmi_framesize sd_framesize; | |
146 | struct v4l2_rect sd_bounds; | |
37404f91 HF |
147 | |
148 | /* Protect this data structure */ | |
149 | struct mutex lock; | |
150 | struct vb2_queue queue; | |
151 | ||
859969b3 | 152 | struct v4l2_fwnode_bus_parallel bus; |
3c80f6f8 | 153 | enum v4l2_mbus_type bus_type; |
37404f91 HF |
154 | struct completion complete; |
155 | struct clk *mclk; | |
156 | enum state state; | |
157 | struct dma_chan *dma_chan; | |
158 | dma_cookie_t dma_cookie; | |
159 | u32 misr; | |
160 | int errors_count; | |
a1029f55 | 161 | int overrun_count; |
37404f91 | 162 | int buffers_count; |
b3ce6f6f HF |
163 | |
164 | /* Ensure DMA operations atomicity */ | |
165 | struct mutex dma_lock; | |
34f8d704 HF |
166 | |
167 | struct media_device mdev; | |
168 | struct media_pad vid_cap_pad; | |
f4378baf | 169 | struct media_pipeline pipeline; |
37404f91 HF |
170 | }; |
171 | ||
172 | static inline struct stm32_dcmi *notifier_to_dcmi(struct v4l2_async_notifier *n) | |
173 | { | |
174 | return container_of(n, struct stm32_dcmi, notifier); | |
175 | } | |
176 | ||
177 | static inline u32 reg_read(void __iomem *base, u32 reg) | |
178 | { | |
179 | return readl_relaxed(base + reg); | |
180 | } | |
181 | ||
182 | static inline void reg_write(void __iomem *base, u32 reg, u32 val) | |
183 | { | |
184 | writel_relaxed(val, base + reg); | |
185 | } | |
186 | ||
187 | static inline void reg_set(void __iomem *base, u32 reg, u32 mask) | |
188 | { | |
189 | reg_write(base, reg, reg_read(base, reg) | mask); | |
190 | } | |
191 | ||
192 | static inline void reg_clear(void __iomem *base, u32 reg, u32 mask) | |
193 | { | |
194 | reg_write(base, reg, reg_read(base, reg) & ~mask); | |
195 | } | |
196 | ||
49bcc174 | 197 | static int dcmi_start_capture(struct stm32_dcmi *dcmi, struct dcmi_buf *buf); |
37404f91 | 198 | |
3e187c81 HF |
199 | static void dcmi_buffer_done(struct stm32_dcmi *dcmi, |
200 | struct dcmi_buf *buf, | |
201 | size_t bytesused, | |
202 | int err) | |
203 | { | |
204 | struct vb2_v4l2_buffer *vbuf; | |
205 | ||
206 | if (!buf) | |
207 | return; | |
208 | ||
49bcc174 HF |
209 | list_del_init(&buf->list); |
210 | ||
3e187c81 HF |
211 | vbuf = &buf->vb; |
212 | ||
213 | vbuf->sequence = dcmi->sequence++; | |
214 | vbuf->field = V4L2_FIELD_NONE; | |
215 | vbuf->vb2_buf.timestamp = ktime_get_ns(); | |
216 | vb2_set_plane_payload(&vbuf->vb2_buf, 0, bytesused); | |
217 | vb2_buffer_done(&vbuf->vb2_buf, | |
218 | err ? VB2_BUF_STATE_ERROR : VB2_BUF_STATE_DONE); | |
219 | dev_dbg(dcmi->dev, "buffer[%d] done seq=%d, bytesused=%zu\n", | |
220 | vbuf->vb2_buf.index, vbuf->sequence, bytesused); | |
221 | ||
222 | dcmi->buffers_count++; | |
223 | dcmi->active = NULL; | |
224 | } | |
225 | ||
226 | static int dcmi_restart_capture(struct stm32_dcmi *dcmi) | |
227 | { | |
49bcc174 HF |
228 | struct dcmi_buf *buf; |
229 | ||
3e187c81 HF |
230 | spin_lock_irq(&dcmi->irqlock); |
231 | ||
232 | if (dcmi->state != RUNNING) { | |
233 | spin_unlock_irq(&dcmi->irqlock); | |
234 | return -EINVAL; | |
235 | } | |
236 | ||
237 | /* Restart a new DMA transfer with next buffer */ | |
238 | if (list_empty(&dcmi->buffers)) { | |
b53a24fc | 239 | dev_dbg(dcmi->dev, "Capture restart is deferred to next buffer queueing\n"); |
2d494d4a | 240 | dcmi->state = WAIT_FOR_BUFFER; |
3e187c81 | 241 | spin_unlock_irq(&dcmi->irqlock); |
b53a24fc | 242 | return 0; |
3e187c81 | 243 | } |
49bcc174 HF |
244 | buf = list_entry(dcmi->buffers.next, struct dcmi_buf, list); |
245 | dcmi->active = buf; | |
3e187c81 HF |
246 | |
247 | spin_unlock_irq(&dcmi->irqlock); | |
248 | ||
49bcc174 | 249 | return dcmi_start_capture(dcmi, buf); |
3e187c81 HF |
250 | } |
251 | ||
37404f91 HF |
252 | static void dcmi_dma_callback(void *param) |
253 | { | |
254 | struct stm32_dcmi *dcmi = (struct stm32_dcmi *)param; | |
37404f91 HF |
255 | struct dma_tx_state state; |
256 | enum dma_status status; | |
3e187c81 | 257 | struct dcmi_buf *buf = dcmi->active; |
37404f91 | 258 | |
49bcc174 HF |
259 | spin_lock_irq(&dcmi->irqlock); |
260 | ||
37404f91 | 261 | /* Check DMA status */ |
4b84e750 | 262 | status = dmaengine_tx_status(dcmi->dma_chan, dcmi->dma_cookie, &state); |
37404f91 HF |
263 | |
264 | switch (status) { | |
265 | case DMA_IN_PROGRESS: | |
266 | dev_dbg(dcmi->dev, "%s: Received DMA_IN_PROGRESS\n", __func__); | |
267 | break; | |
268 | case DMA_PAUSED: | |
269 | dev_err(dcmi->dev, "%s: Received DMA_PAUSED\n", __func__); | |
270 | break; | |
271 | case DMA_ERROR: | |
272 | dev_err(dcmi->dev, "%s: Received DMA_ERROR\n", __func__); | |
a331df3c HF |
273 | |
274 | /* Return buffer to V4L2 in error state */ | |
275 | dcmi_buffer_done(dcmi, buf, 0, -EIO); | |
37404f91 HF |
276 | break; |
277 | case DMA_COMPLETE: | |
278 | dev_dbg(dcmi->dev, "%s: Received DMA_COMPLETE\n", __func__); | |
279 | ||
3e187c81 HF |
280 | /* Return buffer to V4L2 */ |
281 | dcmi_buffer_done(dcmi, buf, buf->size, 0); | |
37404f91 | 282 | |
49bcc174 HF |
283 | spin_unlock_irq(&dcmi->irqlock); |
284 | ||
3e187c81 HF |
285 | /* Restart capture */ |
286 | if (dcmi_restart_capture(dcmi)) | |
287 | dev_err(dcmi->dev, "%s: Cannot restart capture on DMA complete\n", | |
288 | __func__); | |
49bcc174 | 289 | return; |
37404f91 HF |
290 | default: |
291 | dev_err(dcmi->dev, "%s: Received unknown status\n", __func__); | |
292 | break; | |
293 | } | |
49bcc174 HF |
294 | |
295 | spin_unlock_irq(&dcmi->irqlock); | |
37404f91 HF |
296 | } |
297 | ||
298 | static int dcmi_start_dma(struct stm32_dcmi *dcmi, | |
299 | struct dcmi_buf *buf) | |
300 | { | |
301 | struct dma_async_tx_descriptor *desc = NULL; | |
302 | struct dma_slave_config config; | |
303 | int ret; | |
304 | ||
305 | memset(&config, 0, sizeof(config)); | |
306 | ||
307 | config.src_addr = (dma_addr_t)dcmi->res->start + DCMI_DR; | |
308 | config.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; | |
309 | config.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; | |
310 | config.dst_maxburst = 4; | |
311 | ||
312 | /* Configure DMA channel */ | |
313 | ret = dmaengine_slave_config(dcmi->dma_chan, &config); | |
314 | if (ret < 0) { | |
315 | dev_err(dcmi->dev, "%s: DMA channel config failed (%d)\n", | |
316 | __func__, ret); | |
317 | return ret; | |
318 | } | |
319 | ||
b3ce6f6f | 320 | /* |
ab32b2c3 | 321 | * Avoid call of dmaengine_terminate_sync() between |
b3ce6f6f HF |
322 | * dmaengine_prep_slave_single() and dmaengine_submit() |
323 | * by locking the whole DMA submission sequence | |
324 | */ | |
325 | mutex_lock(&dcmi->dma_lock); | |
326 | ||
37404f91 HF |
327 | /* Prepare a DMA transaction */ |
328 | desc = dmaengine_prep_slave_single(dcmi->dma_chan, buf->paddr, | |
329 | buf->size, | |
4b84e750 HF |
330 | DMA_DEV_TO_MEM, |
331 | DMA_PREP_INTERRUPT); | |
37404f91 | 332 | if (!desc) { |
4b84e750 HF |
333 | dev_err(dcmi->dev, "%s: DMA dmaengine_prep_slave_single failed for buffer phy=%pad size=%zu\n", |
334 | __func__, &buf->paddr, buf->size); | |
b3ce6f6f | 335 | mutex_unlock(&dcmi->dma_lock); |
37404f91 HF |
336 | return -EINVAL; |
337 | } | |
338 | ||
339 | /* Set completion callback routine for notification */ | |
340 | desc->callback = dcmi_dma_callback; | |
341 | desc->callback_param = dcmi; | |
342 | ||
343 | /* Push current DMA transaction in the pending queue */ | |
344 | dcmi->dma_cookie = dmaengine_submit(desc); | |
134e15e6 HF |
345 | if (dma_submit_error(dcmi->dma_cookie)) { |
346 | dev_err(dcmi->dev, "%s: DMA submission failed\n", __func__); | |
b3ce6f6f | 347 | mutex_unlock(&dcmi->dma_lock); |
134e15e6 HF |
348 | return -ENXIO; |
349 | } | |
37404f91 | 350 | |
b3ce6f6f HF |
351 | mutex_unlock(&dcmi->dma_lock); |
352 | ||
37404f91 HF |
353 | dma_async_issue_pending(dcmi->dma_chan); |
354 | ||
355 | return 0; | |
356 | } | |
357 | ||
49bcc174 | 358 | static int dcmi_start_capture(struct stm32_dcmi *dcmi, struct dcmi_buf *buf) |
37404f91 HF |
359 | { |
360 | int ret; | |
37404f91 HF |
361 | |
362 | if (!buf) | |
363 | return -EINVAL; | |
364 | ||
365 | ret = dcmi_start_dma(dcmi, buf); | |
366 | if (ret) { | |
367 | dcmi->errors_count++; | |
368 | return ret; | |
369 | } | |
370 | ||
371 | /* Enable capture */ | |
372 | reg_set(dcmi->regs, DCMI_CR, CR_CAPTURE); | |
373 | ||
374 | return 0; | |
375 | } | |
376 | ||
d533d501 HF |
377 | static void dcmi_set_crop(struct stm32_dcmi *dcmi) |
378 | { | |
379 | u32 size, start; | |
380 | ||
381 | /* Crop resolution */ | |
382 | size = ((dcmi->crop.height - 1) << 16) | | |
383 | ((dcmi->crop.width << 1) - 1); | |
384 | reg_write(dcmi->regs, DCMI_CWSIZE, size); | |
385 | ||
386 | /* Crop start point */ | |
387 | start = ((dcmi->crop.top) << 16) | | |
388 | ((dcmi->crop.left << 1)); | |
389 | reg_write(dcmi->regs, DCMI_CWSTRT, start); | |
390 | ||
391 | dev_dbg(dcmi->dev, "Cropping to %ux%u@%u:%u\n", | |
392 | dcmi->crop.width, dcmi->crop.height, | |
393 | dcmi->crop.left, dcmi->crop.top); | |
394 | ||
395 | /* Enable crop */ | |
396 | reg_set(dcmi->regs, DCMI_CR, CR_CROP); | |
397 | } | |
398 | ||
3e187c81 HF |
399 | static void dcmi_process_jpeg(struct stm32_dcmi *dcmi) |
400 | { | |
401 | struct dma_tx_state state; | |
402 | enum dma_status status; | |
3e187c81 HF |
403 | struct dcmi_buf *buf = dcmi->active; |
404 | ||
405 | if (!buf) | |
406 | return; | |
407 | ||
408 | /* | |
409 | * Because of variable JPEG buffer size sent by sensor, | |
4b84e750 | 410 | * DMA transfer never completes due to transfer size never reached. |
3e187c81 HF |
411 | * In order to ensure that all the JPEG data are transferred |
412 | * in active buffer memory, DMA is drained. | |
413 | * Then DMA tx status gives the amount of data transferred | |
414 | * to memory, which is then returned to V4L2 through the active | |
415 | * buffer payload. | |
416 | */ | |
417 | ||
418 | /* Drain DMA */ | |
4b84e750 | 419 | dmaengine_synchronize(dcmi->dma_chan); |
3e187c81 HF |
420 | |
421 | /* Get DMA residue to get JPEG size */ | |
4b84e750 | 422 | status = dmaengine_tx_status(dcmi->dma_chan, dcmi->dma_cookie, &state); |
3e187c81 HF |
423 | if (status != DMA_ERROR && state.residue < buf->size) { |
424 | /* Return JPEG buffer to V4L2 with received JPEG buffer size */ | |
425 | dcmi_buffer_done(dcmi, buf, buf->size - state.residue, 0); | |
426 | } else { | |
427 | dcmi->errors_count++; | |
428 | dev_err(dcmi->dev, "%s: Cannot get JPEG size from DMA\n", | |
429 | __func__); | |
430 | /* Return JPEG buffer to V4L2 in ERROR state */ | |
431 | dcmi_buffer_done(dcmi, buf, 0, -EIO); | |
432 | } | |
433 | ||
434 | /* Abort DMA operation */ | |
ab32b2c3 | 435 | dmaengine_terminate_sync(dcmi->dma_chan); |
3e187c81 HF |
436 | |
437 | /* Restart capture */ | |
438 | if (dcmi_restart_capture(dcmi)) | |
439 | dev_err(dcmi->dev, "%s: Cannot restart capture on JPEG received\n", | |
440 | __func__); | |
441 | } | |
442 | ||
37404f91 HF |
443 | static irqreturn_t dcmi_irq_thread(int irq, void *arg) |
444 | { | |
445 | struct stm32_dcmi *dcmi = arg; | |
446 | ||
f8c5363d | 447 | spin_lock_irq(&dcmi->irqlock); |
37404f91 | 448 | |
1be0a2b7 HF |
449 | if (dcmi->misr & IT_OVR) { |
450 | dcmi->overrun_count++; | |
451 | if (dcmi->overrun_count > OVERRUN_ERROR_THRESHOLD) | |
452 | dcmi->errors_count++; | |
37404f91 | 453 | } |
1be0a2b7 HF |
454 | if (dcmi->misr & IT_ERR) |
455 | dcmi->errors_count++; | |
37404f91 | 456 | |
3e187c81 HF |
457 | if (dcmi->sd_format->fourcc == V4L2_PIX_FMT_JPEG && |
458 | dcmi->misr & IT_FRAME) { | |
459 | /* JPEG received */ | |
460 | spin_unlock_irq(&dcmi->irqlock); | |
461 | dcmi_process_jpeg(dcmi); | |
462 | return IRQ_HANDLED; | |
463 | } | |
464 | ||
f8c5363d | 465 | spin_unlock_irq(&dcmi->irqlock); |
37404f91 HF |
466 | return IRQ_HANDLED; |
467 | } | |
468 | ||
469 | static irqreturn_t dcmi_irq_callback(int irq, void *arg) | |
470 | { | |
471 | struct stm32_dcmi *dcmi = arg; | |
f8c5363d | 472 | unsigned long flags; |
37404f91 | 473 | |
f8c5363d | 474 | spin_lock_irqsave(&dcmi->irqlock, flags); |
37404f91 HF |
475 | |
476 | dcmi->misr = reg_read(dcmi->regs, DCMI_MIS); | |
477 | ||
478 | /* Clear interrupt */ | |
479 | reg_set(dcmi->regs, DCMI_ICR, IT_FRAME | IT_OVR | IT_ERR); | |
480 | ||
f8c5363d | 481 | spin_unlock_irqrestore(&dcmi->irqlock, flags); |
37404f91 HF |
482 | |
483 | return IRQ_WAKE_THREAD; | |
484 | } | |
485 | ||
486 | static int dcmi_queue_setup(struct vb2_queue *vq, | |
487 | unsigned int *nbuffers, | |
488 | unsigned int *nplanes, | |
489 | unsigned int sizes[], | |
490 | struct device *alloc_devs[]) | |
491 | { | |
492 | struct stm32_dcmi *dcmi = vb2_get_drv_priv(vq); | |
493 | unsigned int size; | |
494 | ||
495 | size = dcmi->fmt.fmt.pix.sizeimage; | |
496 | ||
497 | /* Make sure the image size is large enough */ | |
498 | if (*nplanes) | |
499 | return sizes[0] < size ? -EINVAL : 0; | |
500 | ||
501 | *nplanes = 1; | |
502 | sizes[0] = size; | |
503 | ||
37404f91 HF |
504 | dev_dbg(dcmi->dev, "Setup queue, count=%d, size=%d\n", |
505 | *nbuffers, size); | |
506 | ||
507 | return 0; | |
508 | } | |
509 | ||
510 | static int dcmi_buf_init(struct vb2_buffer *vb) | |
511 | { | |
512 | struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); | |
513 | struct dcmi_buf *buf = container_of(vbuf, struct dcmi_buf, vb); | |
514 | ||
515 | INIT_LIST_HEAD(&buf->list); | |
516 | ||
517 | return 0; | |
518 | } | |
519 | ||
520 | static int dcmi_buf_prepare(struct vb2_buffer *vb) | |
521 | { | |
522 | struct stm32_dcmi *dcmi = vb2_get_drv_priv(vb->vb2_queue); | |
523 | struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); | |
524 | struct dcmi_buf *buf = container_of(vbuf, struct dcmi_buf, vb); | |
525 | unsigned long size; | |
526 | ||
527 | size = dcmi->fmt.fmt.pix.sizeimage; | |
528 | ||
529 | if (vb2_plane_size(vb, 0) < size) { | |
530 | dev_err(dcmi->dev, "%s data will not fit into plane (%lu < %lu)\n", | |
531 | __func__, vb2_plane_size(vb, 0), size); | |
532 | return -EINVAL; | |
533 | } | |
534 | ||
535 | vb2_set_plane_payload(vb, 0, size); | |
536 | ||
537 | if (!buf->prepared) { | |
538 | /* Get memory addresses */ | |
539 | buf->paddr = | |
540 | vb2_dma_contig_plane_dma_addr(&buf->vb.vb2_buf, 0); | |
541 | buf->size = vb2_plane_size(&buf->vb.vb2_buf, 0); | |
542 | buf->prepared = true; | |
543 | ||
544 | vb2_set_plane_payload(&buf->vb.vb2_buf, 0, buf->size); | |
545 | ||
2c737e9c | 546 | dev_dbg(dcmi->dev, "buffer[%d] phy=%pad size=%zu\n", |
37404f91 HF |
547 | vb->index, &buf->paddr, buf->size); |
548 | } | |
549 | ||
550 | return 0; | |
551 | } | |
552 | ||
553 | static void dcmi_buf_queue(struct vb2_buffer *vb) | |
554 | { | |
555 | struct stm32_dcmi *dcmi = vb2_get_drv_priv(vb->vb2_queue); | |
556 | struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); | |
557 | struct dcmi_buf *buf = container_of(vbuf, struct dcmi_buf, vb); | |
37404f91 | 558 | |
f8c5363d | 559 | spin_lock_irq(&dcmi->irqlock); |
37404f91 | 560 | |
49bcc174 HF |
561 | /* Enqueue to video buffers list */ |
562 | list_add_tail(&buf->list, &dcmi->buffers); | |
37404f91 | 563 | |
2d494d4a HF |
564 | if (dcmi->state == WAIT_FOR_BUFFER) { |
565 | dcmi->state = RUNNING; | |
49bcc174 | 566 | dcmi->active = buf; |
2d494d4a | 567 | |
37404f91 HF |
568 | dev_dbg(dcmi->dev, "Starting capture on buffer[%d] queued\n", |
569 | buf->vb.vb2_buf.index); | |
570 | ||
f8c5363d | 571 | spin_unlock_irq(&dcmi->irqlock); |
49bcc174 | 572 | if (dcmi_start_capture(dcmi, buf)) |
37404f91 HF |
573 | dev_err(dcmi->dev, "%s: Cannot restart capture on overflow or error\n", |
574 | __func__); | |
49bcc174 | 575 | return; |
37404f91 | 576 | } |
49bcc174 HF |
577 | |
578 | spin_unlock_irq(&dcmi->irqlock); | |
37404f91 HF |
579 | } |
580 | ||
f4378baf HF |
581 | static struct media_entity *dcmi_find_source(struct stm32_dcmi *dcmi) |
582 | { | |
583 | struct media_entity *entity = &dcmi->vdev->entity; | |
584 | struct media_pad *pad; | |
585 | ||
586 | /* Walk searching for entity having no sink */ | |
587 | while (1) { | |
588 | pad = &entity->pads[0]; | |
589 | if (!(pad->flags & MEDIA_PAD_FL_SINK)) | |
590 | break; | |
591 | ||
592 | pad = media_entity_remote_pad(pad); | |
593 | if (!pad || !is_media_entity_v4l2_subdev(pad->entity)) | |
594 | break; | |
595 | ||
596 | entity = pad->entity; | |
597 | } | |
598 | ||
599 | return entity; | |
600 | } | |
601 | ||
602 | static int dcmi_pipeline_s_fmt(struct stm32_dcmi *dcmi, | |
603 | struct v4l2_subdev_pad_config *pad_cfg, | |
604 | struct v4l2_subdev_format *format) | |
605 | { | |
49cff8db | 606 | struct media_entity *entity = &dcmi->source->entity; |
f4378baf HF |
607 | struct v4l2_subdev *subdev; |
608 | struct media_pad *sink_pad = NULL; | |
609 | struct media_pad *src_pad = NULL; | |
610 | struct media_pad *pad = NULL; | |
611 | struct v4l2_subdev_format fmt = *format; | |
612 | bool found = false; | |
613 | int ret; | |
614 | ||
615 | /* | |
616 | * Starting from sensor subdevice, walk within | |
617 | * pipeline and set format on each subdevice | |
618 | */ | |
619 | while (1) { | |
620 | unsigned int i; | |
621 | ||
622 | /* Search if current entity has a source pad */ | |
623 | for (i = 0; i < entity->num_pads; i++) { | |
624 | pad = &entity->pads[i]; | |
625 | if (pad->flags & MEDIA_PAD_FL_SOURCE) { | |
626 | src_pad = pad; | |
627 | found = true; | |
628 | break; | |
629 | } | |
630 | } | |
631 | if (!found) | |
632 | break; | |
633 | ||
634 | subdev = media_entity_to_v4l2_subdev(entity); | |
635 | ||
636 | /* Propagate format on sink pad if any, otherwise source pad */ | |
637 | if (sink_pad) | |
638 | pad = sink_pad; | |
639 | ||
640 | dev_dbg(dcmi->dev, "\"%s\":%d pad format set to 0x%x %ux%u\n", | |
641 | subdev->name, pad->index, format->format.code, | |
642 | format->format.width, format->format.height); | |
643 | ||
644 | fmt.pad = pad->index; | |
645 | ret = v4l2_subdev_call(subdev, pad, set_fmt, pad_cfg, &fmt); | |
646 | if (ret < 0) { | |
647 | dev_err(dcmi->dev, "%s: Failed to set format 0x%x %ux%u on \"%s\":%d pad (%d)\n", | |
648 | __func__, format->format.code, | |
649 | format->format.width, format->format.height, | |
650 | subdev->name, pad->index, ret); | |
651 | return ret; | |
652 | } | |
653 | ||
654 | if (fmt.format.code != format->format.code || | |
655 | fmt.format.width != format->format.width || | |
656 | fmt.format.height != format->format.height) { | |
657 | dev_dbg(dcmi->dev, "\"%s\":%d pad format has been changed to 0x%x %ux%u\n", | |
658 | subdev->name, pad->index, fmt.format.code, | |
659 | fmt.format.width, fmt.format.height); | |
660 | } | |
661 | ||
662 | /* Walk to next entity */ | |
663 | sink_pad = media_entity_remote_pad(src_pad); | |
664 | if (!sink_pad || !is_media_entity_v4l2_subdev(sink_pad->entity)) | |
665 | break; | |
666 | ||
667 | entity = sink_pad->entity; | |
668 | } | |
669 | *format = fmt; | |
670 | ||
671 | return 0; | |
672 | } | |
673 | ||
674 | static int dcmi_pipeline_s_stream(struct stm32_dcmi *dcmi, int state) | |
675 | { | |
676 | struct media_entity *entity = &dcmi->vdev->entity; | |
677 | struct v4l2_subdev *subdev; | |
678 | struct media_pad *pad; | |
679 | int ret; | |
680 | ||
681 | /* Start/stop all entities within pipeline */ | |
682 | while (1) { | |
683 | pad = &entity->pads[0]; | |
684 | if (!(pad->flags & MEDIA_PAD_FL_SINK)) | |
685 | break; | |
686 | ||
687 | pad = media_entity_remote_pad(pad); | |
688 | if (!pad || !is_media_entity_v4l2_subdev(pad->entity)) | |
689 | break; | |
690 | ||
691 | entity = pad->entity; | |
692 | subdev = media_entity_to_v4l2_subdev(entity); | |
693 | ||
694 | ret = v4l2_subdev_call(subdev, video, s_stream, state); | |
695 | if (ret < 0 && ret != -ENOIOCTLCMD) { | |
696 | dev_err(dcmi->dev, "%s: \"%s\" failed to %s streaming (%d)\n", | |
697 | __func__, subdev->name, | |
698 | state ? "start" : "stop", ret); | |
699 | return ret; | |
700 | } | |
701 | ||
702 | dev_dbg(dcmi->dev, "\"%s\" is %s\n", | |
703 | subdev->name, state ? "started" : "stopped"); | |
704 | } | |
705 | ||
706 | return 0; | |
707 | } | |
708 | ||
709 | static int dcmi_pipeline_start(struct stm32_dcmi *dcmi) | |
710 | { | |
711 | return dcmi_pipeline_s_stream(dcmi, 1); | |
712 | } | |
713 | ||
714 | static void dcmi_pipeline_stop(struct stm32_dcmi *dcmi) | |
715 | { | |
716 | dcmi_pipeline_s_stream(dcmi, 0); | |
717 | } | |
718 | ||
37404f91 HF |
719 | static int dcmi_start_streaming(struct vb2_queue *vq, unsigned int count) |
720 | { | |
721 | struct stm32_dcmi *dcmi = vb2_get_drv_priv(vq); | |
722 | struct dcmi_buf *buf, *node; | |
7b7805e5 | 723 | u32 val = 0; |
37404f91 HF |
724 | int ret; |
725 | ||
152e0bf6 | 726 | ret = pm_runtime_get_sync(dcmi->dev); |
ab41b99e HF |
727 | if (ret < 0) { |
728 | dev_err(dcmi->dev, "%s: Failed to start streaming, cannot get sync (%d)\n", | |
729 | __func__, ret); | |
88f50a05 | 730 | goto err_pm_put; |
37404f91 HF |
731 | } |
732 | ||
f4378baf HF |
733 | ret = media_pipeline_start(&dcmi->vdev->entity, &dcmi->pipeline); |
734 | if (ret < 0) { | |
735 | dev_err(dcmi->dev, "%s: Failed to start streaming, media pipeline start error (%d)\n", | |
736 | __func__, ret); | |
152e0bf6 | 737 | goto err_pm_put; |
37404f91 HF |
738 | } |
739 | ||
f4378baf HF |
740 | ret = dcmi_pipeline_start(dcmi); |
741 | if (ret) | |
742 | goto err_media_pipeline_stop; | |
743 | ||
37404f91 HF |
744 | spin_lock_irq(&dcmi->irqlock); |
745 | ||
37404f91 HF |
746 | /* Set bus width */ |
747 | switch (dcmi->bus.bus_width) { | |
748 | case 14: | |
7b7805e5 | 749 | val |= CR_EDM_0 | CR_EDM_1; |
37404f91 HF |
750 | break; |
751 | case 12: | |
7b7805e5 | 752 | val |= CR_EDM_1; |
37404f91 HF |
753 | break; |
754 | case 10: | |
7b7805e5 | 755 | val |= CR_EDM_0; |
37404f91 HF |
756 | break; |
757 | default: | |
758 | /* Set bus width to 8 bits by default */ | |
759 | break; | |
760 | } | |
761 | ||
762 | /* Set vertical synchronization polarity */ | |
763 | if (dcmi->bus.flags & V4L2_MBUS_VSYNC_ACTIVE_HIGH) | |
764 | val |= CR_VSPOL; | |
765 | ||
766 | /* Set horizontal synchronization polarity */ | |
767 | if (dcmi->bus.flags & V4L2_MBUS_HSYNC_ACTIVE_HIGH) | |
768 | val |= CR_HSPOL; | |
769 | ||
770 | /* Set pixel clock polarity */ | |
771 | if (dcmi->bus.flags & V4L2_MBUS_PCLK_SAMPLE_RISING) | |
772 | val |= CR_PCKPOL; | |
773 | ||
3c80f6f8 HF |
774 | /* |
775 | * BT656 embedded synchronisation bus mode. | |
776 | * | |
777 | * Default SAV/EAV mode is supported here with default codes | |
778 | * SAV=0xff000080 & EAV=0xff00009d. | |
779 | * With DCMI this means LSC=SAV=0x80 & LEC=EAV=0x9d. | |
780 | */ | |
781 | if (dcmi->bus_type == V4L2_MBUS_BT656) { | |
782 | val |= CR_ESS; | |
783 | ||
784 | /* Unmask all codes */ | |
785 | reg_write(dcmi->regs, DCMI_ESUR, 0xffffffff);/* FEC:LEC:LSC:FSC */ | |
786 | ||
787 | /* Trig on LSC=0x80 & LEC=0x9d codes, ignore FSC and FEC */ | |
788 | reg_write(dcmi->regs, DCMI_ESCR, 0xff9d80ff);/* FEC:LEC:LSC:FSC */ | |
789 | } | |
790 | ||
37404f91 HF |
791 | reg_write(dcmi->regs, DCMI_CR, val); |
792 | ||
d533d501 HF |
793 | /* Set crop */ |
794 | if (dcmi->do_crop) | |
795 | dcmi_set_crop(dcmi); | |
796 | ||
3e187c81 HF |
797 | /* Enable jpeg capture */ |
798 | if (dcmi->sd_format->fourcc == V4L2_PIX_FMT_JPEG) | |
799 | reg_set(dcmi->regs, DCMI_CR, CR_CM);/* Snapshot mode */ | |
800 | ||
37404f91 HF |
801 | /* Enable dcmi */ |
802 | reg_set(dcmi->regs, DCMI_CR, CR_ENABLE); | |
803 | ||
37404f91 HF |
804 | dcmi->sequence = 0; |
805 | dcmi->errors_count = 0; | |
a1029f55 | 806 | dcmi->overrun_count = 0; |
37404f91 | 807 | dcmi->buffers_count = 0; |
37404f91 HF |
808 | |
809 | /* | |
810 | * Start transfer if at least one buffer has been queued, | |
811 | * otherwise transfer is deferred at buffer queueing | |
812 | */ | |
813 | if (list_empty(&dcmi->buffers)) { | |
814 | dev_dbg(dcmi->dev, "Start streaming is deferred to next buffer queueing\n"); | |
2d494d4a | 815 | dcmi->state = WAIT_FOR_BUFFER; |
37404f91 HF |
816 | spin_unlock_irq(&dcmi->irqlock); |
817 | return 0; | |
818 | } | |
819 | ||
49bcc174 HF |
820 | buf = list_entry(dcmi->buffers.next, struct dcmi_buf, list); |
821 | dcmi->active = buf; | |
37404f91 | 822 | |
2d494d4a HF |
823 | dcmi->state = RUNNING; |
824 | ||
49bcc174 HF |
825 | dev_dbg(dcmi->dev, "Start streaming, starting capture\n"); |
826 | ||
f8c5363d | 827 | spin_unlock_irq(&dcmi->irqlock); |
49bcc174 | 828 | ret = dcmi_start_capture(dcmi, buf); |
37404f91 | 829 | if (ret) { |
2c737e9c | 830 | dev_err(dcmi->dev, "%s: Start streaming failed, cannot start capture\n", |
37404f91 | 831 | __func__); |
f4378baf | 832 | goto err_pipeline_stop; |
37404f91 HF |
833 | } |
834 | ||
835 | /* Enable interruptions */ | |
b88ff59e HF |
836 | if (dcmi->sd_format->fourcc == V4L2_PIX_FMT_JPEG) |
837 | reg_set(dcmi->regs, DCMI_IER, IT_FRAME | IT_OVR | IT_ERR); | |
838 | else | |
839 | reg_set(dcmi->regs, DCMI_IER, IT_OVR | IT_ERR); | |
37404f91 | 840 | |
37404f91 HF |
841 | return 0; |
842 | ||
f4378baf HF |
843 | err_pipeline_stop: |
844 | dcmi_pipeline_stop(dcmi); | |
845 | ||
846 | err_media_pipeline_stop: | |
847 | media_pipeline_stop(&dcmi->vdev->entity); | |
37404f91 | 848 | |
152e0bf6 HF |
849 | err_pm_put: |
850 | pm_runtime_put(dcmi->dev); | |
37404f91 HF |
851 | spin_lock_irq(&dcmi->irqlock); |
852 | /* | |
853 | * Return all buffers to vb2 in QUEUED state. | |
854 | * This will give ownership back to userspace | |
855 | */ | |
37404f91 HF |
856 | list_for_each_entry_safe(buf, node, &dcmi->buffers, list) { |
857 | list_del_init(&buf->list); | |
858 | vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_QUEUED); | |
859 | } | |
49bcc174 | 860 | dcmi->active = NULL; |
37404f91 HF |
861 | spin_unlock_irq(&dcmi->irqlock); |
862 | ||
863 | return ret; | |
864 | } | |
865 | ||
866 | static void dcmi_stop_streaming(struct vb2_queue *vq) | |
867 | { | |
868 | struct stm32_dcmi *dcmi = vb2_get_drv_priv(vq); | |
869 | struct dcmi_buf *buf, *node; | |
37404f91 | 870 | |
f4378baf HF |
871 | dcmi_pipeline_stop(dcmi); |
872 | ||
873 | media_pipeline_stop(&dcmi->vdev->entity); | |
37404f91 | 874 | |
37404f91 HF |
875 | spin_lock_irq(&dcmi->irqlock); |
876 | ||
877 | /* Disable interruptions */ | |
878 | reg_clear(dcmi->regs, DCMI_IER, IT_FRAME | IT_OVR | IT_ERR); | |
879 | ||
880 | /* Disable DCMI */ | |
881 | reg_clear(dcmi->regs, DCMI_CR, CR_ENABLE); | |
882 | ||
37404f91 | 883 | /* Return all queued buffers to vb2 in ERROR state */ |
37404f91 HF |
884 | list_for_each_entry_safe(buf, node, &dcmi->buffers, list) { |
885 | list_del_init(&buf->list); | |
886 | vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR); | |
887 | } | |
888 | ||
49bcc174 | 889 | dcmi->active = NULL; |
fdaf5958 | 890 | dcmi->state = STOPPED; |
49bcc174 | 891 | |
37404f91 HF |
892 | spin_unlock_irq(&dcmi->irqlock); |
893 | ||
894 | /* Stop all pending DMA operations */ | |
b3ce6f6f | 895 | mutex_lock(&dcmi->dma_lock); |
ab32b2c3 | 896 | dmaengine_terminate_sync(dcmi->dma_chan); |
b3ce6f6f | 897 | mutex_unlock(&dcmi->dma_lock); |
37404f91 | 898 | |
152e0bf6 | 899 | pm_runtime_put(dcmi->dev); |
37404f91 | 900 | |
a1029f55 HF |
901 | if (dcmi->errors_count) |
902 | dev_warn(dcmi->dev, "Some errors found while streaming: errors=%d (overrun=%d), buffers=%d\n", | |
903 | dcmi->errors_count, dcmi->overrun_count, | |
904 | dcmi->buffers_count); | |
905 | dev_dbg(dcmi->dev, "Stop streaming, errors=%d (overrun=%d), buffers=%d\n", | |
906 | dcmi->errors_count, dcmi->overrun_count, | |
907 | dcmi->buffers_count); | |
37404f91 HF |
908 | } |
909 | ||
f3ab729c | 910 | static const struct vb2_ops dcmi_video_qops = { |
37404f91 HF |
911 | .queue_setup = dcmi_queue_setup, |
912 | .buf_init = dcmi_buf_init, | |
913 | .buf_prepare = dcmi_buf_prepare, | |
914 | .buf_queue = dcmi_buf_queue, | |
915 | .start_streaming = dcmi_start_streaming, | |
916 | .stop_streaming = dcmi_stop_streaming, | |
917 | .wait_prepare = vb2_ops_wait_prepare, | |
918 | .wait_finish = vb2_ops_wait_finish, | |
919 | }; | |
920 | ||
921 | static int dcmi_g_fmt_vid_cap(struct file *file, void *priv, | |
922 | struct v4l2_format *fmt) | |
923 | { | |
924 | struct stm32_dcmi *dcmi = video_drvdata(file); | |
925 | ||
926 | *fmt = dcmi->fmt; | |
927 | ||
928 | return 0; | |
929 | } | |
930 | ||
931 | static const struct dcmi_format *find_format_by_fourcc(struct stm32_dcmi *dcmi, | |
932 | unsigned int fourcc) | |
933 | { | |
38e423ee | 934 | unsigned int num_formats = dcmi->num_of_sd_formats; |
37404f91 HF |
935 | const struct dcmi_format *fmt; |
936 | unsigned int i; | |
937 | ||
938 | for (i = 0; i < num_formats; i++) { | |
38e423ee | 939 | fmt = dcmi->sd_formats[i]; |
37404f91 HF |
940 | if (fmt->fourcc == fourcc) |
941 | return fmt; | |
942 | } | |
943 | ||
944 | return NULL; | |
945 | } | |
946 | ||
d533d501 HF |
947 | static void __find_outer_frame_size(struct stm32_dcmi *dcmi, |
948 | struct v4l2_pix_format *pix, | |
949 | struct dcmi_framesize *framesize) | |
950 | { | |
951 | struct dcmi_framesize *match = NULL; | |
952 | unsigned int i; | |
953 | unsigned int min_err = UINT_MAX; | |
954 | ||
955 | for (i = 0; i < dcmi->num_of_sd_framesizes; i++) { | |
956 | struct dcmi_framesize *fsize = &dcmi->sd_framesizes[i]; | |
957 | int w_err = (fsize->width - pix->width); | |
958 | int h_err = (fsize->height - pix->height); | |
959 | int err = w_err + h_err; | |
960 | ||
b4ee3194 | 961 | if (w_err >= 0 && h_err >= 0 && err < min_err) { |
d533d501 HF |
962 | min_err = err; |
963 | match = fsize; | |
964 | } | |
965 | } | |
966 | if (!match) | |
967 | match = &dcmi->sd_framesizes[0]; | |
968 | ||
969 | *framesize = *match; | |
970 | } | |
971 | ||
37404f91 | 972 | static int dcmi_try_fmt(struct stm32_dcmi *dcmi, struct v4l2_format *f, |
d533d501 HF |
973 | const struct dcmi_format **sd_format, |
974 | struct dcmi_framesize *sd_framesize) | |
37404f91 | 975 | { |
38e423ee | 976 | const struct dcmi_format *sd_fmt; |
d533d501 | 977 | struct dcmi_framesize sd_fsize; |
38e423ee | 978 | struct v4l2_pix_format *pix = &f->fmt.pix; |
37404f91 HF |
979 | struct v4l2_subdev_pad_config pad_cfg; |
980 | struct v4l2_subdev_format format = { | |
981 | .which = V4L2_SUBDEV_FORMAT_TRY, | |
982 | }; | |
3e187c81 | 983 | bool do_crop; |
37404f91 HF |
984 | int ret; |
985 | ||
38e423ee HF |
986 | sd_fmt = find_format_by_fourcc(dcmi, pix->pixelformat); |
987 | if (!sd_fmt) { | |
33dfeb62 HF |
988 | if (!dcmi->num_of_sd_formats) |
989 | return -ENODATA; | |
990 | ||
38e423ee HF |
991 | sd_fmt = dcmi->sd_formats[dcmi->num_of_sd_formats - 1]; |
992 | pix->pixelformat = sd_fmt->fourcc; | |
37404f91 HF |
993 | } |
994 | ||
995 | /* Limit to hardware capabilities */ | |
bfe75f76 HF |
996 | pix->width = clamp(pix->width, MIN_WIDTH, MAX_WIDTH); |
997 | pix->height = clamp(pix->height, MIN_HEIGHT, MAX_HEIGHT); | |
3e187c81 HF |
998 | |
999 | /* No crop if JPEG is requested */ | |
1000 | do_crop = dcmi->do_crop && (pix->pixelformat != V4L2_PIX_FMT_JPEG); | |
37404f91 | 1001 | |
3e187c81 | 1002 | if (do_crop && dcmi->num_of_sd_framesizes) { |
d533d501 HF |
1003 | struct dcmi_framesize outer_sd_fsize; |
1004 | /* | |
1005 | * If crop is requested and sensor have discrete frame sizes, | |
1006 | * select the frame size that is just larger than request | |
1007 | */ | |
1008 | __find_outer_frame_size(dcmi, pix, &outer_sd_fsize); | |
1009 | pix->width = outer_sd_fsize.width; | |
1010 | pix->height = outer_sd_fsize.height; | |
1011 | } | |
1012 | ||
38e423ee | 1013 | v4l2_fill_mbus_format(&format.format, pix, sd_fmt->mbus_code); |
49cff8db | 1014 | ret = v4l2_subdev_call(dcmi->source, pad, set_fmt, |
37404f91 HF |
1015 | &pad_cfg, &format); |
1016 | if (ret < 0) | |
1017 | return ret; | |
1018 | ||
38e423ee HF |
1019 | /* Update pix regarding to what sensor can do */ |
1020 | v4l2_fill_pix_format(pix, &format.format); | |
37404f91 | 1021 | |
d533d501 HF |
1022 | /* Save resolution that sensor can actually do */ |
1023 | sd_fsize.width = pix->width; | |
1024 | sd_fsize.height = pix->height; | |
1025 | ||
3e187c81 | 1026 | if (do_crop) { |
d533d501 HF |
1027 | struct v4l2_rect c = dcmi->crop; |
1028 | struct v4l2_rect max_rect; | |
1029 | ||
1030 | /* | |
1031 | * Adjust crop by making the intersection between | |
1032 | * format resolution request and crop request | |
1033 | */ | |
1034 | max_rect.top = 0; | |
1035 | max_rect.left = 0; | |
1036 | max_rect.width = pix->width; | |
1037 | max_rect.height = pix->height; | |
1038 | v4l2_rect_map_inside(&c, &max_rect); | |
1039 | c.top = clamp_t(s32, c.top, 0, pix->height - c.height); | |
1040 | c.left = clamp_t(s32, c.left, 0, pix->width - c.width); | |
1041 | dcmi->crop = c; | |
1042 | ||
1043 | /* Adjust format resolution request to crop */ | |
1044 | pix->width = dcmi->crop.width; | |
1045 | pix->height = dcmi->crop.height; | |
1046 | } | |
37404f91 | 1047 | |
38e423ee HF |
1048 | pix->field = V4L2_FIELD_NONE; |
1049 | pix->bytesperline = pix->width * sd_fmt->bpp; | |
1050 | pix->sizeimage = pix->bytesperline * pix->height; | |
1051 | ||
1052 | if (sd_format) | |
1053 | *sd_format = sd_fmt; | |
d533d501 HF |
1054 | if (sd_framesize) |
1055 | *sd_framesize = sd_fsize; | |
37404f91 HF |
1056 | |
1057 | return 0; | |
1058 | } | |
1059 | ||
1060 | static int dcmi_set_fmt(struct stm32_dcmi *dcmi, struct v4l2_format *f) | |
1061 | { | |
1062 | struct v4l2_subdev_format format = { | |
1063 | .which = V4L2_SUBDEV_FORMAT_ACTIVE, | |
1064 | }; | |
38e423ee | 1065 | const struct dcmi_format *sd_format; |
d533d501 | 1066 | struct dcmi_framesize sd_framesize; |
38e423ee HF |
1067 | struct v4l2_mbus_framefmt *mf = &format.format; |
1068 | struct v4l2_pix_format *pix = &f->fmt.pix; | |
37404f91 HF |
1069 | int ret; |
1070 | ||
d533d501 HF |
1071 | /* |
1072 | * Try format, fmt.width/height could have been changed | |
1073 | * to match sensor capability or crop request | |
1074 | * sd_format & sd_framesize will contain what subdev | |
1075 | * can do for this request. | |
1076 | */ | |
1077 | ret = dcmi_try_fmt(dcmi, f, &sd_format, &sd_framesize); | |
37404f91 HF |
1078 | if (ret) |
1079 | return ret; | |
1080 | ||
3c80f6f8 HF |
1081 | /* Disable crop if JPEG is requested or BT656 bus is selected */ |
1082 | if (pix->pixelformat == V4L2_PIX_FMT_JPEG && | |
1083 | dcmi->bus_type != V4L2_MBUS_BT656) | |
3e187c81 HF |
1084 | dcmi->do_crop = false; |
1085 | ||
38e423ee HF |
1086 | /* pix to mbus format */ |
1087 | v4l2_fill_mbus_format(mf, pix, | |
1088 | sd_format->mbus_code); | |
d533d501 HF |
1089 | mf->width = sd_framesize.width; |
1090 | mf->height = sd_framesize.height; | |
1091 | ||
f4378baf | 1092 | ret = dcmi_pipeline_s_fmt(dcmi, NULL, &format); |
37404f91 HF |
1093 | if (ret < 0) |
1094 | return ret; | |
1095 | ||
d533d501 HF |
1096 | dev_dbg(dcmi->dev, "Sensor format set to 0x%x %ux%u\n", |
1097 | mf->code, mf->width, mf->height); | |
1098 | dev_dbg(dcmi->dev, "Buffer format set to %4.4s %ux%u\n", | |
1099 | (char *)&pix->pixelformat, | |
1100 | pix->width, pix->height); | |
1101 | ||
37404f91 | 1102 | dcmi->fmt = *f; |
38e423ee | 1103 | dcmi->sd_format = sd_format; |
d533d501 | 1104 | dcmi->sd_framesize = sd_framesize; |
37404f91 HF |
1105 | |
1106 | return 0; | |
1107 | } | |
1108 | ||
1109 | static int dcmi_s_fmt_vid_cap(struct file *file, void *priv, | |
1110 | struct v4l2_format *f) | |
1111 | { | |
1112 | struct stm32_dcmi *dcmi = video_drvdata(file); | |
1113 | ||
1114 | if (vb2_is_streaming(&dcmi->queue)) | |
1115 | return -EBUSY; | |
1116 | ||
1117 | return dcmi_set_fmt(dcmi, f); | |
1118 | } | |
1119 | ||
1120 | static int dcmi_try_fmt_vid_cap(struct file *file, void *priv, | |
1121 | struct v4l2_format *f) | |
1122 | { | |
1123 | struct stm32_dcmi *dcmi = video_drvdata(file); | |
1124 | ||
d533d501 | 1125 | return dcmi_try_fmt(dcmi, f, NULL, NULL); |
37404f91 HF |
1126 | } |
1127 | ||
1128 | static int dcmi_enum_fmt_vid_cap(struct file *file, void *priv, | |
1129 | struct v4l2_fmtdesc *f) | |
1130 | { | |
1131 | struct stm32_dcmi *dcmi = video_drvdata(file); | |
1132 | ||
38e423ee | 1133 | if (f->index >= dcmi->num_of_sd_formats) |
37404f91 HF |
1134 | return -EINVAL; |
1135 | ||
38e423ee | 1136 | f->pixelformat = dcmi->sd_formats[f->index]->fourcc; |
37404f91 HF |
1137 | return 0; |
1138 | } | |
1139 | ||
d533d501 HF |
1140 | static int dcmi_get_sensor_format(struct stm32_dcmi *dcmi, |
1141 | struct v4l2_pix_format *pix) | |
1142 | { | |
1143 | struct v4l2_subdev_format fmt = { | |
1144 | .which = V4L2_SUBDEV_FORMAT_ACTIVE, | |
1145 | }; | |
1146 | int ret; | |
1147 | ||
49cff8db | 1148 | ret = v4l2_subdev_call(dcmi->source, pad, get_fmt, NULL, &fmt); |
d533d501 HF |
1149 | if (ret) |
1150 | return ret; | |
1151 | ||
1152 | v4l2_fill_pix_format(pix, &fmt.format); | |
1153 | ||
1154 | return 0; | |
1155 | } | |
1156 | ||
1157 | static int dcmi_set_sensor_format(struct stm32_dcmi *dcmi, | |
1158 | struct v4l2_pix_format *pix) | |
1159 | { | |
1160 | const struct dcmi_format *sd_fmt; | |
1161 | struct v4l2_subdev_format format = { | |
1162 | .which = V4L2_SUBDEV_FORMAT_TRY, | |
1163 | }; | |
1164 | struct v4l2_subdev_pad_config pad_cfg; | |
1165 | int ret; | |
1166 | ||
1167 | sd_fmt = find_format_by_fourcc(dcmi, pix->pixelformat); | |
1168 | if (!sd_fmt) { | |
33dfeb62 HF |
1169 | if (!dcmi->num_of_sd_formats) |
1170 | return -ENODATA; | |
1171 | ||
d533d501 HF |
1172 | sd_fmt = dcmi->sd_formats[dcmi->num_of_sd_formats - 1]; |
1173 | pix->pixelformat = sd_fmt->fourcc; | |
1174 | } | |
1175 | ||
1176 | v4l2_fill_mbus_format(&format.format, pix, sd_fmt->mbus_code); | |
49cff8db | 1177 | ret = v4l2_subdev_call(dcmi->source, pad, set_fmt, |
d533d501 HF |
1178 | &pad_cfg, &format); |
1179 | if (ret < 0) | |
1180 | return ret; | |
1181 | ||
1182 | return 0; | |
1183 | } | |
1184 | ||
1185 | static int dcmi_get_sensor_bounds(struct stm32_dcmi *dcmi, | |
1186 | struct v4l2_rect *r) | |
1187 | { | |
1188 | struct v4l2_subdev_selection bounds = { | |
1189 | .which = V4L2_SUBDEV_FORMAT_ACTIVE, | |
1190 | .target = V4L2_SEL_TGT_CROP_BOUNDS, | |
1191 | }; | |
1192 | unsigned int max_width, max_height, max_pixsize; | |
1193 | struct v4l2_pix_format pix; | |
1194 | unsigned int i; | |
1195 | int ret; | |
1196 | ||
1197 | /* | |
1198 | * Get sensor bounds first | |
1199 | */ | |
49cff8db | 1200 | ret = v4l2_subdev_call(dcmi->source, pad, get_selection, |
d533d501 HF |
1201 | NULL, &bounds); |
1202 | if (!ret) | |
1203 | *r = bounds.r; | |
1204 | if (ret != -ENOIOCTLCMD) | |
1205 | return ret; | |
1206 | ||
1207 | /* | |
1208 | * If selection is not implemented, | |
1209 | * fallback by enumerating sensor frame sizes | |
1210 | * and take the largest one | |
1211 | */ | |
1212 | max_width = 0; | |
1213 | max_height = 0; | |
1214 | max_pixsize = 0; | |
1215 | for (i = 0; i < dcmi->num_of_sd_framesizes; i++) { | |
1216 | struct dcmi_framesize *fsize = &dcmi->sd_framesizes[i]; | |
1217 | unsigned int pixsize = fsize->width * fsize->height; | |
1218 | ||
1219 | if (pixsize > max_pixsize) { | |
1220 | max_pixsize = pixsize; | |
1221 | max_width = fsize->width; | |
1222 | max_height = fsize->height; | |
1223 | } | |
1224 | } | |
1225 | if (max_pixsize > 0) { | |
1226 | r->top = 0; | |
1227 | r->left = 0; | |
1228 | r->width = max_width; | |
1229 | r->height = max_height; | |
1230 | return 0; | |
1231 | } | |
1232 | ||
1233 | /* | |
1234 | * If frame sizes enumeration is not implemented, | |
1235 | * fallback by getting current sensor frame size | |
1236 | */ | |
1237 | ret = dcmi_get_sensor_format(dcmi, &pix); | |
1238 | if (ret) | |
1239 | return ret; | |
1240 | ||
1241 | r->top = 0; | |
1242 | r->left = 0; | |
1243 | r->width = pix.width; | |
1244 | r->height = pix.height; | |
1245 | ||
1246 | return 0; | |
1247 | } | |
1248 | ||
1249 | static int dcmi_g_selection(struct file *file, void *fh, | |
1250 | struct v4l2_selection *s) | |
1251 | { | |
1252 | struct stm32_dcmi *dcmi = video_drvdata(file); | |
1253 | ||
1254 | if (s->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) | |
1255 | return -EINVAL; | |
1256 | ||
1257 | switch (s->target) { | |
1258 | case V4L2_SEL_TGT_CROP_DEFAULT: | |
1259 | case V4L2_SEL_TGT_CROP_BOUNDS: | |
1260 | s->r = dcmi->sd_bounds; | |
1261 | return 0; | |
1262 | case V4L2_SEL_TGT_CROP: | |
1263 | if (dcmi->do_crop) { | |
1264 | s->r = dcmi->crop; | |
1265 | } else { | |
1266 | s->r.top = 0; | |
1267 | s->r.left = 0; | |
1268 | s->r.width = dcmi->fmt.fmt.pix.width; | |
1269 | s->r.height = dcmi->fmt.fmt.pix.height; | |
1270 | } | |
1271 | break; | |
1272 | default: | |
1273 | return -EINVAL; | |
1274 | } | |
1275 | ||
1276 | return 0; | |
1277 | } | |
1278 | ||
1279 | static int dcmi_s_selection(struct file *file, void *priv, | |
1280 | struct v4l2_selection *s) | |
1281 | { | |
1282 | struct stm32_dcmi *dcmi = video_drvdata(file); | |
1283 | struct v4l2_rect r = s->r; | |
1284 | struct v4l2_rect max_rect; | |
1285 | struct v4l2_pix_format pix; | |
1286 | ||
1287 | if (s->type != V4L2_BUF_TYPE_VIDEO_CAPTURE || | |
1288 | s->target != V4L2_SEL_TGT_CROP) | |
1289 | return -EINVAL; | |
1290 | ||
1291 | /* Reset sensor resolution to max resolution */ | |
1292 | pix.pixelformat = dcmi->fmt.fmt.pix.pixelformat; | |
1293 | pix.width = dcmi->sd_bounds.width; | |
1294 | pix.height = dcmi->sd_bounds.height; | |
1295 | dcmi_set_sensor_format(dcmi, &pix); | |
1296 | ||
1297 | /* | |
1298 | * Make the intersection between | |
1299 | * sensor resolution | |
1300 | * and crop request | |
1301 | */ | |
1302 | max_rect.top = 0; | |
1303 | max_rect.left = 0; | |
1304 | max_rect.width = pix.width; | |
1305 | max_rect.height = pix.height; | |
1306 | v4l2_rect_map_inside(&r, &max_rect); | |
1307 | r.top = clamp_t(s32, r.top, 0, pix.height - r.height); | |
1308 | r.left = clamp_t(s32, r.left, 0, pix.width - r.width); | |
1309 | ||
b4ee3194 HF |
1310 | if (!(r.top == dcmi->sd_bounds.top && |
1311 | r.left == dcmi->sd_bounds.left && | |
1312 | r.width == dcmi->sd_bounds.width && | |
1313 | r.height == dcmi->sd_bounds.height)) { | |
d533d501 HF |
1314 | /* Crop if request is different than sensor resolution */ |
1315 | dcmi->do_crop = true; | |
1316 | dcmi->crop = r; | |
1317 | dev_dbg(dcmi->dev, "s_selection: crop %ux%u@(%u,%u) from %ux%u\n", | |
1318 | r.width, r.height, r.left, r.top, | |
1319 | pix.width, pix.height); | |
1320 | } else { | |
1321 | /* Disable crop */ | |
1322 | dcmi->do_crop = false; | |
1323 | dev_dbg(dcmi->dev, "s_selection: crop is disabled\n"); | |
1324 | } | |
1325 | ||
1326 | s->r = r; | |
1327 | return 0; | |
1328 | } | |
1329 | ||
37404f91 HF |
1330 | static int dcmi_querycap(struct file *file, void *priv, |
1331 | struct v4l2_capability *cap) | |
1332 | { | |
c0decac1 MCC |
1333 | strscpy(cap->driver, DRV_NAME, sizeof(cap->driver)); |
1334 | strscpy(cap->card, "STM32 Camera Memory Interface", | |
37404f91 | 1335 | sizeof(cap->card)); |
c0decac1 | 1336 | strscpy(cap->bus_info, "platform:dcmi", sizeof(cap->bus_info)); |
37404f91 HF |
1337 | return 0; |
1338 | } | |
1339 | ||
1340 | static int dcmi_enum_input(struct file *file, void *priv, | |
1341 | struct v4l2_input *i) | |
1342 | { | |
1343 | if (i->index != 0) | |
1344 | return -EINVAL; | |
1345 | ||
1346 | i->type = V4L2_INPUT_TYPE_CAMERA; | |
c0decac1 | 1347 | strscpy(i->name, "Camera", sizeof(i->name)); |
37404f91 HF |
1348 | return 0; |
1349 | } | |
1350 | ||
1351 | static int dcmi_g_input(struct file *file, void *priv, unsigned int *i) | |
1352 | { | |
1353 | *i = 0; | |
1354 | return 0; | |
1355 | } | |
1356 | ||
1357 | static int dcmi_s_input(struct file *file, void *priv, unsigned int i) | |
1358 | { | |
1359 | if (i > 0) | |
1360 | return -EINVAL; | |
1361 | return 0; | |
1362 | } | |
1363 | ||
1364 | static int dcmi_enum_framesizes(struct file *file, void *fh, | |
1365 | struct v4l2_frmsizeenum *fsize) | |
1366 | { | |
1367 | struct stm32_dcmi *dcmi = video_drvdata(file); | |
38e423ee | 1368 | const struct dcmi_format *sd_fmt; |
37404f91 HF |
1369 | struct v4l2_subdev_frame_size_enum fse = { |
1370 | .index = fsize->index, | |
1371 | .which = V4L2_SUBDEV_FORMAT_ACTIVE, | |
1372 | }; | |
1373 | int ret; | |
1374 | ||
38e423ee HF |
1375 | sd_fmt = find_format_by_fourcc(dcmi, fsize->pixel_format); |
1376 | if (!sd_fmt) | |
37404f91 HF |
1377 | return -EINVAL; |
1378 | ||
38e423ee | 1379 | fse.code = sd_fmt->mbus_code; |
37404f91 | 1380 | |
49cff8db | 1381 | ret = v4l2_subdev_call(dcmi->source, pad, enum_frame_size, |
37404f91 HF |
1382 | NULL, &fse); |
1383 | if (ret) | |
1384 | return ret; | |
1385 | ||
1386 | fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE; | |
1387 | fsize->discrete.width = fse.max_width; | |
1388 | fsize->discrete.height = fse.max_height; | |
1389 | ||
1390 | return 0; | |
1391 | } | |
1392 | ||
aebd90aa HF |
1393 | static int dcmi_g_parm(struct file *file, void *priv, |
1394 | struct v4l2_streamparm *p) | |
1395 | { | |
1396 | struct stm32_dcmi *dcmi = video_drvdata(file); | |
1397 | ||
49cff8db | 1398 | return v4l2_g_parm_cap(video_devdata(file), dcmi->source, p); |
aebd90aa HF |
1399 | } |
1400 | ||
1401 | static int dcmi_s_parm(struct file *file, void *priv, | |
1402 | struct v4l2_streamparm *p) | |
1403 | { | |
1404 | struct stm32_dcmi *dcmi = video_drvdata(file); | |
1405 | ||
49cff8db | 1406 | return v4l2_s_parm_cap(video_devdata(file), dcmi->source, p); |
aebd90aa HF |
1407 | } |
1408 | ||
37404f91 HF |
1409 | static int dcmi_enum_frameintervals(struct file *file, void *fh, |
1410 | struct v4l2_frmivalenum *fival) | |
1411 | { | |
1412 | struct stm32_dcmi *dcmi = video_drvdata(file); | |
38e423ee | 1413 | const struct dcmi_format *sd_fmt; |
37404f91 HF |
1414 | struct v4l2_subdev_frame_interval_enum fie = { |
1415 | .index = fival->index, | |
1416 | .width = fival->width, | |
1417 | .height = fival->height, | |
1418 | .which = V4L2_SUBDEV_FORMAT_ACTIVE, | |
1419 | }; | |
1420 | int ret; | |
1421 | ||
38e423ee HF |
1422 | sd_fmt = find_format_by_fourcc(dcmi, fival->pixel_format); |
1423 | if (!sd_fmt) | |
37404f91 HF |
1424 | return -EINVAL; |
1425 | ||
38e423ee | 1426 | fie.code = sd_fmt->mbus_code; |
37404f91 | 1427 | |
49cff8db | 1428 | ret = v4l2_subdev_call(dcmi->source, pad, |
37404f91 HF |
1429 | enum_frame_interval, NULL, &fie); |
1430 | if (ret) | |
1431 | return ret; | |
1432 | ||
1433 | fival->type = V4L2_FRMIVAL_TYPE_DISCRETE; | |
1434 | fival->discrete = fie.interval; | |
1435 | ||
1436 | return 0; | |
1437 | } | |
1438 | ||
1439 | static const struct of_device_id stm32_dcmi_of_match[] = { | |
1440 | { .compatible = "st,stm32-dcmi"}, | |
1441 | { /* end node */ }, | |
1442 | }; | |
1443 | MODULE_DEVICE_TABLE(of, stm32_dcmi_of_match); | |
1444 | ||
1445 | static int dcmi_open(struct file *file) | |
1446 | { | |
1447 | struct stm32_dcmi *dcmi = video_drvdata(file); | |
49cff8db | 1448 | struct v4l2_subdev *sd = dcmi->source; |
37404f91 HF |
1449 | int ret; |
1450 | ||
1451 | if (mutex_lock_interruptible(&dcmi->lock)) | |
1452 | return -ERESTARTSYS; | |
1453 | ||
1454 | ret = v4l2_fh_open(file); | |
1455 | if (ret < 0) | |
1456 | goto unlock; | |
1457 | ||
1458 | if (!v4l2_fh_is_singular_file(file)) | |
1459 | goto fh_rel; | |
1460 | ||
1461 | ret = v4l2_subdev_call(sd, core, s_power, 1); | |
1462 | if (ret < 0 && ret != -ENOIOCTLCMD) | |
1463 | goto fh_rel; | |
1464 | ||
1465 | ret = dcmi_set_fmt(dcmi, &dcmi->fmt); | |
1466 | if (ret) | |
1467 | v4l2_subdev_call(sd, core, s_power, 0); | |
1468 | fh_rel: | |
1469 | if (ret) | |
1470 | v4l2_fh_release(file); | |
1471 | unlock: | |
1472 | mutex_unlock(&dcmi->lock); | |
1473 | return ret; | |
1474 | } | |
1475 | ||
1476 | static int dcmi_release(struct file *file) | |
1477 | { | |
1478 | struct stm32_dcmi *dcmi = video_drvdata(file); | |
49cff8db | 1479 | struct v4l2_subdev *sd = dcmi->source; |
37404f91 HF |
1480 | bool fh_singular; |
1481 | int ret; | |
1482 | ||
1483 | mutex_lock(&dcmi->lock); | |
1484 | ||
1485 | fh_singular = v4l2_fh_is_singular_file(file); | |
1486 | ||
1487 | ret = _vb2_fop_release(file, NULL); | |
1488 | ||
1489 | if (fh_singular) | |
1490 | v4l2_subdev_call(sd, core, s_power, 0); | |
1491 | ||
1492 | mutex_unlock(&dcmi->lock); | |
1493 | ||
1494 | return ret; | |
1495 | } | |
1496 | ||
1497 | static const struct v4l2_ioctl_ops dcmi_ioctl_ops = { | |
1498 | .vidioc_querycap = dcmi_querycap, | |
1499 | ||
1500 | .vidioc_try_fmt_vid_cap = dcmi_try_fmt_vid_cap, | |
1501 | .vidioc_g_fmt_vid_cap = dcmi_g_fmt_vid_cap, | |
1502 | .vidioc_s_fmt_vid_cap = dcmi_s_fmt_vid_cap, | |
1503 | .vidioc_enum_fmt_vid_cap = dcmi_enum_fmt_vid_cap, | |
d533d501 HF |
1504 | .vidioc_g_selection = dcmi_g_selection, |
1505 | .vidioc_s_selection = dcmi_s_selection, | |
37404f91 HF |
1506 | |
1507 | .vidioc_enum_input = dcmi_enum_input, | |
1508 | .vidioc_g_input = dcmi_g_input, | |
1509 | .vidioc_s_input = dcmi_s_input, | |
1510 | ||
aebd90aa HF |
1511 | .vidioc_g_parm = dcmi_g_parm, |
1512 | .vidioc_s_parm = dcmi_s_parm, | |
1513 | ||
37404f91 HF |
1514 | .vidioc_enum_framesizes = dcmi_enum_framesizes, |
1515 | .vidioc_enum_frameintervals = dcmi_enum_frameintervals, | |
1516 | ||
1517 | .vidioc_reqbufs = vb2_ioctl_reqbufs, | |
1518 | .vidioc_create_bufs = vb2_ioctl_create_bufs, | |
1519 | .vidioc_querybuf = vb2_ioctl_querybuf, | |
1520 | .vidioc_qbuf = vb2_ioctl_qbuf, | |
1521 | .vidioc_dqbuf = vb2_ioctl_dqbuf, | |
1522 | .vidioc_expbuf = vb2_ioctl_expbuf, | |
1523 | .vidioc_prepare_buf = vb2_ioctl_prepare_buf, | |
1524 | .vidioc_streamon = vb2_ioctl_streamon, | |
1525 | .vidioc_streamoff = vb2_ioctl_streamoff, | |
1526 | ||
1527 | .vidioc_log_status = v4l2_ctrl_log_status, | |
1528 | .vidioc_subscribe_event = v4l2_ctrl_subscribe_event, | |
1529 | .vidioc_unsubscribe_event = v4l2_event_unsubscribe, | |
1530 | }; | |
1531 | ||
1532 | static const struct v4l2_file_operations dcmi_fops = { | |
1533 | .owner = THIS_MODULE, | |
1534 | .unlocked_ioctl = video_ioctl2, | |
1535 | .open = dcmi_open, | |
1536 | .release = dcmi_release, | |
1537 | .poll = vb2_fop_poll, | |
1538 | .mmap = vb2_fop_mmap, | |
1539 | #ifndef CONFIG_MMU | |
1540 | .get_unmapped_area = vb2_fop_get_unmapped_area, | |
1541 | #endif | |
1542 | .read = vb2_fop_read, | |
1543 | }; | |
1544 | ||
1545 | static int dcmi_set_default_fmt(struct stm32_dcmi *dcmi) | |
1546 | { | |
1547 | struct v4l2_format f = { | |
1548 | .type = V4L2_BUF_TYPE_VIDEO_CAPTURE, | |
1549 | .fmt.pix = { | |
1550 | .width = CIF_WIDTH, | |
1551 | .height = CIF_HEIGHT, | |
1552 | .field = V4L2_FIELD_NONE, | |
38e423ee | 1553 | .pixelformat = dcmi->sd_formats[0]->fourcc, |
37404f91 HF |
1554 | }, |
1555 | }; | |
1556 | int ret; | |
1557 | ||
d533d501 | 1558 | ret = dcmi_try_fmt(dcmi, &f, NULL, NULL); |
37404f91 HF |
1559 | if (ret) |
1560 | return ret; | |
38e423ee | 1561 | dcmi->sd_format = dcmi->sd_formats[0]; |
37404f91 HF |
1562 | dcmi->fmt = f; |
1563 | return 0; | |
1564 | } | |
1565 | ||
f4378baf HF |
1566 | /* |
1567 | * FIXME: For the time being we only support subdevices | |
1568 | * which expose RGB & YUV "parallel form" mbus code (_2X8). | |
1569 | * Nevertheless, this allows to support serial source subdevices | |
1570 | * and serial to parallel bridges which conform to this. | |
1571 | */ | |
37404f91 HF |
1572 | static const struct dcmi_format dcmi_formats[] = { |
1573 | { | |
1574 | .fourcc = V4L2_PIX_FMT_RGB565, | |
1575 | .mbus_code = MEDIA_BUS_FMT_RGB565_2X8_LE, | |
1576 | .bpp = 2, | |
1577 | }, { | |
1578 | .fourcc = V4L2_PIX_FMT_YUYV, | |
1579 | .mbus_code = MEDIA_BUS_FMT_YUYV8_2X8, | |
1580 | .bpp = 2, | |
1581 | }, { | |
1582 | .fourcc = V4L2_PIX_FMT_UYVY, | |
1583 | .mbus_code = MEDIA_BUS_FMT_UYVY8_2X8, | |
1584 | .bpp = 2, | |
3e187c81 HF |
1585 | }, { |
1586 | .fourcc = V4L2_PIX_FMT_JPEG, | |
1587 | .mbus_code = MEDIA_BUS_FMT_JPEG_1X8, | |
1588 | .bpp = 1, | |
734f0b01 AV |
1589 | }, { |
1590 | .fourcc = V4L2_PIX_FMT_SBGGR8, | |
1591 | .mbus_code = MEDIA_BUS_FMT_SBGGR8_1X8, | |
1592 | .bpp = 1, | |
1593 | }, { | |
1594 | .fourcc = V4L2_PIX_FMT_SGBRG8, | |
1595 | .mbus_code = MEDIA_BUS_FMT_SGBRG8_1X8, | |
1596 | .bpp = 1, | |
1597 | }, { | |
1598 | .fourcc = V4L2_PIX_FMT_SGRBG8, | |
1599 | .mbus_code = MEDIA_BUS_FMT_SGRBG8_1X8, | |
1600 | .bpp = 1, | |
1601 | }, { | |
1602 | .fourcc = V4L2_PIX_FMT_SRGGB8, | |
1603 | .mbus_code = MEDIA_BUS_FMT_SRGGB8_1X8, | |
1604 | .bpp = 1, | |
37404f91 HF |
1605 | }, |
1606 | }; | |
1607 | ||
1608 | static int dcmi_formats_init(struct stm32_dcmi *dcmi) | |
1609 | { | |
38e423ee | 1610 | const struct dcmi_format *sd_fmts[ARRAY_SIZE(dcmi_formats)]; |
37404f91 | 1611 | unsigned int num_fmts = 0, i, j; |
49cff8db | 1612 | struct v4l2_subdev *subdev = dcmi->source; |
37404f91 HF |
1613 | struct v4l2_subdev_mbus_code_enum mbus_code = { |
1614 | .which = V4L2_SUBDEV_FORMAT_ACTIVE, | |
1615 | }; | |
1616 | ||
1617 | while (!v4l2_subdev_call(subdev, pad, enum_mbus_code, | |
1618 | NULL, &mbus_code)) { | |
1619 | for (i = 0; i < ARRAY_SIZE(dcmi_formats); i++) { | |
1620 | if (dcmi_formats[i].mbus_code != mbus_code.code) | |
1621 | continue; | |
1622 | ||
3c80f6f8 HF |
1623 | /* Exclude JPEG if BT656 bus is selected */ |
1624 | if (dcmi_formats[i].fourcc == V4L2_PIX_FMT_JPEG && | |
1625 | dcmi->bus_type == V4L2_MBUS_BT656) | |
1626 | continue; | |
1627 | ||
37404f91 HF |
1628 | /* Code supported, have we got this fourcc yet? */ |
1629 | for (j = 0; j < num_fmts; j++) | |
38e423ee | 1630 | if (sd_fmts[j]->fourcc == |
585b18ed | 1631 | dcmi_formats[i].fourcc) { |
37404f91 | 1632 | /* Already available */ |
585b18ed HF |
1633 | dev_dbg(dcmi->dev, "Skipping fourcc/code: %4.4s/0x%x\n", |
1634 | (char *)&sd_fmts[j]->fourcc, | |
1635 | mbus_code.code); | |
37404f91 | 1636 | break; |
585b18ed HF |
1637 | } |
1638 | if (j == num_fmts) { | |
37404f91 | 1639 | /* New */ |
38e423ee | 1640 | sd_fmts[num_fmts++] = dcmi_formats + i; |
585b18ed HF |
1641 | dev_dbg(dcmi->dev, "Supported fourcc/code: %4.4s/0x%x\n", |
1642 | (char *)&sd_fmts[num_fmts - 1]->fourcc, | |
1643 | sd_fmts[num_fmts - 1]->mbus_code); | |
1644 | } | |
37404f91 HF |
1645 | } |
1646 | mbus_code.index++; | |
1647 | } | |
1648 | ||
1649 | if (!num_fmts) | |
1650 | return -ENXIO; | |
1651 | ||
38e423ee HF |
1652 | dcmi->num_of_sd_formats = num_fmts; |
1653 | dcmi->sd_formats = devm_kcalloc(dcmi->dev, | |
1654 | num_fmts, sizeof(struct dcmi_format *), | |
1655 | GFP_KERNEL); | |
1656 | if (!dcmi->sd_formats) { | |
1657 | dev_err(dcmi->dev, "Could not allocate memory\n"); | |
37404f91 HF |
1658 | return -ENOMEM; |
1659 | } | |
1660 | ||
38e423ee | 1661 | memcpy(dcmi->sd_formats, sd_fmts, |
37404f91 | 1662 | num_fmts * sizeof(struct dcmi_format *)); |
38e423ee | 1663 | dcmi->sd_format = dcmi->sd_formats[0]; |
37404f91 HF |
1664 | |
1665 | return 0; | |
1666 | } | |
1667 | ||
d533d501 HF |
1668 | static int dcmi_framesizes_init(struct stm32_dcmi *dcmi) |
1669 | { | |
1670 | unsigned int num_fsize = 0; | |
49cff8db | 1671 | struct v4l2_subdev *subdev = dcmi->source; |
d533d501 HF |
1672 | struct v4l2_subdev_frame_size_enum fse = { |
1673 | .which = V4L2_SUBDEV_FORMAT_ACTIVE, | |
1674 | .code = dcmi->sd_format->mbus_code, | |
1675 | }; | |
1676 | unsigned int ret; | |
1677 | unsigned int i; | |
1678 | ||
1679 | /* Allocate discrete framesizes array */ | |
1680 | while (!v4l2_subdev_call(subdev, pad, enum_frame_size, | |
1681 | NULL, &fse)) | |
1682 | fse.index++; | |
1683 | ||
1684 | num_fsize = fse.index; | |
1685 | if (!num_fsize) | |
1686 | return 0; | |
1687 | ||
1688 | dcmi->num_of_sd_framesizes = num_fsize; | |
1689 | dcmi->sd_framesizes = devm_kcalloc(dcmi->dev, num_fsize, | |
1690 | sizeof(struct dcmi_framesize), | |
1691 | GFP_KERNEL); | |
1692 | if (!dcmi->sd_framesizes) { | |
1693 | dev_err(dcmi->dev, "Could not allocate memory\n"); | |
1694 | return -ENOMEM; | |
1695 | } | |
1696 | ||
1697 | /* Fill array with sensor supported framesizes */ | |
1698 | dev_dbg(dcmi->dev, "Sensor supports %u frame sizes:\n", num_fsize); | |
1699 | for (i = 0; i < dcmi->num_of_sd_framesizes; i++) { | |
1700 | fse.index = i; | |
1701 | ret = v4l2_subdev_call(subdev, pad, enum_frame_size, | |
1702 | NULL, &fse); | |
1703 | if (ret) | |
1704 | return ret; | |
1705 | dcmi->sd_framesizes[fse.index].width = fse.max_width; | |
1706 | dcmi->sd_framesizes[fse.index].height = fse.max_height; | |
1707 | dev_dbg(dcmi->dev, "%ux%u\n", fse.max_width, fse.max_height); | |
1708 | } | |
1709 | ||
1710 | return 0; | |
1711 | } | |
1712 | ||
37404f91 HF |
1713 | static int dcmi_graph_notify_complete(struct v4l2_async_notifier *notifier) |
1714 | { | |
1715 | struct stm32_dcmi *dcmi = notifier_to_dcmi(notifier); | |
1716 | int ret; | |
1717 | ||
f4378baf HF |
1718 | /* |
1719 | * Now that the graph is complete, | |
1720 | * we search for the source subdevice | |
1721 | * in order to expose it through V4L2 interface | |
1722 | */ | |
49cff8db EG |
1723 | dcmi->source = media_entity_to_v4l2_subdev(dcmi_find_source(dcmi)); |
1724 | if (!dcmi->source) { | |
f4378baf HF |
1725 | dev_err(dcmi->dev, "Source subdevice not found\n"); |
1726 | return -ENODEV; | |
1727 | } | |
1728 | ||
49cff8db | 1729 | dcmi->vdev->ctrl_handler = dcmi->source->ctrl_handler; |
f4378baf | 1730 | |
37404f91 HF |
1731 | ret = dcmi_formats_init(dcmi); |
1732 | if (ret) { | |
1733 | dev_err(dcmi->dev, "No supported mediabus format found\n"); | |
1734 | return ret; | |
1735 | } | |
1736 | ||
d533d501 HF |
1737 | ret = dcmi_framesizes_init(dcmi); |
1738 | if (ret) { | |
1739 | dev_err(dcmi->dev, "Could not initialize framesizes\n"); | |
1740 | return ret; | |
1741 | } | |
1742 | ||
1743 | ret = dcmi_get_sensor_bounds(dcmi, &dcmi->sd_bounds); | |
1744 | if (ret) { | |
1745 | dev_err(dcmi->dev, "Could not get sensor bounds\n"); | |
1746 | return ret; | |
1747 | } | |
1748 | ||
37404f91 HF |
1749 | ret = dcmi_set_default_fmt(dcmi); |
1750 | if (ret) { | |
1751 | dev_err(dcmi->dev, "Could not set default format\n"); | |
1752 | return ret; | |
1753 | } | |
1754 | ||
37404f91 HF |
1755 | return 0; |
1756 | } | |
1757 | ||
1758 | static void dcmi_graph_notify_unbind(struct v4l2_async_notifier *notifier, | |
1759 | struct v4l2_subdev *sd, | |
1760 | struct v4l2_async_subdev *asd) | |
1761 | { | |
1762 | struct stm32_dcmi *dcmi = notifier_to_dcmi(notifier); | |
1763 | ||
1764 | dev_dbg(dcmi->dev, "Removing %s\n", video_device_node_name(dcmi->vdev)); | |
1765 | ||
8b72c18d | 1766 | /* Checks internally if vdev has been init or not */ |
37404f91 HF |
1767 | video_unregister_device(dcmi->vdev); |
1768 | } | |
1769 | ||
1770 | static int dcmi_graph_notify_bound(struct v4l2_async_notifier *notifier, | |
1771 | struct v4l2_subdev *subdev, | |
1772 | struct v4l2_async_subdev *asd) | |
1773 | { | |
1774 | struct stm32_dcmi *dcmi = notifier_to_dcmi(notifier); | |
f4378baf HF |
1775 | unsigned int ret; |
1776 | int src_pad; | |
37404f91 | 1777 | |
f4378baf | 1778 | dev_dbg(dcmi->dev, "Subdev \"%s\" bound\n", subdev->name); |
37404f91 | 1779 | |
f4378baf HF |
1780 | /* |
1781 | * Link this sub-device to DCMI, it could be | |
1782 | * a parallel camera sensor or a bridge | |
1783 | */ | |
1784 | src_pad = media_entity_get_fwnode_pad(&subdev->entity, | |
1785 | subdev->fwnode, | |
1786 | MEDIA_PAD_FL_SOURCE); | |
1787 | ||
1788 | ret = media_create_pad_link(&subdev->entity, src_pad, | |
1789 | &dcmi->vdev->entity, 0, | |
1790 | MEDIA_LNK_FL_IMMUTABLE | | |
1791 | MEDIA_LNK_FL_ENABLED); | |
1792 | if (ret) | |
1793 | dev_err(dcmi->dev, "Failed to create media pad link with subdev \"%s\"\n", | |
1794 | subdev->name); | |
1795 | else | |
1796 | dev_dbg(dcmi->dev, "DCMI is now linked to \"%s\"\n", | |
1797 | subdev->name); | |
37404f91 | 1798 | |
f4378baf | 1799 | return ret; |
37404f91 HF |
1800 | } |
1801 | ||
b6ee3f0d LP |
1802 | static const struct v4l2_async_notifier_operations dcmi_graph_notify_ops = { |
1803 | .bound = dcmi_graph_notify_bound, | |
1804 | .unbind = dcmi_graph_notify_unbind, | |
1805 | .complete = dcmi_graph_notify_complete, | |
1806 | }; | |
1807 | ||
37404f91 HF |
1808 | static int dcmi_graph_init(struct stm32_dcmi *dcmi) |
1809 | { | |
49cff8db EG |
1810 | struct v4l2_async_subdev *asd; |
1811 | struct device_node *ep; | |
37404f91 HF |
1812 | int ret; |
1813 | ||
49cff8db EG |
1814 | ep = of_graph_get_next_endpoint(dcmi->dev->of_node, NULL); |
1815 | if (!ep) { | |
1816 | dev_err(dcmi->dev, "Failed to get next endpoint\n"); | |
1817 | return -EINVAL; | |
37404f91 HF |
1818 | } |
1819 | ||
d079f94c SL |
1820 | v4l2_async_notifier_init(&dcmi->notifier); |
1821 | ||
49cff8db | 1822 | asd = v4l2_async_notifier_add_fwnode_remote_subdev( |
b01edcbd LP |
1823 | &dcmi->notifier, of_fwnode_handle(ep), |
1824 | struct v4l2_async_subdev); | |
49cff8db EG |
1825 | |
1826 | of_node_put(ep); | |
1827 | ||
1828 | if (IS_ERR(asd)) { | |
d8986600 | 1829 | dev_err(dcmi->dev, "Failed to add subdev notifier\n"); |
49cff8db | 1830 | return PTR_ERR(asd); |
37404f91 HF |
1831 | } |
1832 | ||
b6ee3f0d | 1833 | dcmi->notifier.ops = &dcmi_graph_notify_ops; |
37404f91 HF |
1834 | |
1835 | ret = v4l2_async_notifier_register(&dcmi->v4l2_dev, &dcmi->notifier); | |
1836 | if (ret < 0) { | |
d8986600 | 1837 | dev_err(dcmi->dev, "Failed to register notifier\n"); |
d079f94c | 1838 | v4l2_async_notifier_cleanup(&dcmi->notifier); |
37404f91 HF |
1839 | return ret; |
1840 | } | |
1841 | ||
1842 | return 0; | |
1843 | } | |
1844 | ||
1845 | static int dcmi_probe(struct platform_device *pdev) | |
1846 | { | |
1847 | struct device_node *np = pdev->dev.of_node; | |
1848 | const struct of_device_id *match = NULL; | |
60359a28 | 1849 | struct v4l2_fwnode_endpoint ep = { .bus_type = 0 }; |
37404f91 HF |
1850 | struct stm32_dcmi *dcmi; |
1851 | struct vb2_queue *q; | |
1852 | struct dma_chan *chan; | |
1853 | struct clk *mclk; | |
1854 | int irq; | |
1855 | int ret = 0; | |
1856 | ||
1857 | match = of_match_device(of_match_ptr(stm32_dcmi_of_match), &pdev->dev); | |
1858 | if (!match) { | |
1859 | dev_err(&pdev->dev, "Could not find a match in devicetree\n"); | |
1860 | return -ENODEV; | |
1861 | } | |
1862 | ||
1863 | dcmi = devm_kzalloc(&pdev->dev, sizeof(struct stm32_dcmi), GFP_KERNEL); | |
1864 | if (!dcmi) | |
1865 | return -ENOMEM; | |
1866 | ||
1a48e102 | 1867 | dcmi->rstc = devm_reset_control_get_exclusive(&pdev->dev, NULL); |
37404f91 | 1868 | if (IS_ERR(dcmi->rstc)) { |
b9b32762 EC |
1869 | if (PTR_ERR(dcmi->rstc) != -EPROBE_DEFER) |
1870 | dev_err(&pdev->dev, "Could not get reset control\n"); | |
1871 | ||
b5b5a27b | 1872 | return PTR_ERR(dcmi->rstc); |
37404f91 HF |
1873 | } |
1874 | ||
1875 | /* Get bus characteristics from devicetree */ | |
1876 | np = of_graph_get_next_endpoint(np, NULL); | |
1877 | if (!np) { | |
1878 | dev_err(&pdev->dev, "Could not find the endpoint\n"); | |
37404f91 HF |
1879 | return -ENODEV; |
1880 | } | |
1881 | ||
859969b3 | 1882 | ret = v4l2_fwnode_endpoint_parse(of_fwnode_handle(np), &ep); |
f11552d0 | 1883 | of_node_put(np); |
37404f91 HF |
1884 | if (ret) { |
1885 | dev_err(&pdev->dev, "Could not parse the endpoint\n"); | |
b5b5a27b | 1886 | return ret; |
37404f91 HF |
1887 | } |
1888 | ||
2d95e7ed | 1889 | if (ep.bus_type == V4L2_MBUS_CSI2_DPHY) { |
37404f91 | 1890 | dev_err(&pdev->dev, "CSI bus not supported\n"); |
37404f91 HF |
1891 | return -ENODEV; |
1892 | } | |
3c80f6f8 HF |
1893 | |
1894 | if (ep.bus_type == V4L2_MBUS_BT656 && | |
1895 | ep.bus.parallel.bus_width != 8) { | |
1896 | dev_err(&pdev->dev, "BT656 bus conflicts with %u bits bus width (8 bits required)\n", | |
1897 | ep.bus.parallel.bus_width); | |
1898 | return -ENODEV; | |
1899 | } | |
1900 | ||
37404f91 HF |
1901 | dcmi->bus.flags = ep.bus.parallel.flags; |
1902 | dcmi->bus.bus_width = ep.bus.parallel.bus_width; | |
1903 | dcmi->bus.data_shift = ep.bus.parallel.data_shift; | |
3c80f6f8 | 1904 | dcmi->bus_type = ep.bus_type; |
37404f91 | 1905 | |
37404f91 | 1906 | irq = platform_get_irq(pdev, 0); |
97299a30 | 1907 | if (irq <= 0) |
dbb9fcc8 | 1908 | return irq ? irq : -ENXIO; |
37404f91 HF |
1909 | |
1910 | dcmi->res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | |
1911 | if (!dcmi->res) { | |
1912 | dev_err(&pdev->dev, "Could not get resource\n"); | |
1913 | return -ENODEV; | |
1914 | } | |
1915 | ||
1916 | dcmi->regs = devm_ioremap_resource(&pdev->dev, dcmi->res); | |
1917 | if (IS_ERR(dcmi->regs)) { | |
1918 | dev_err(&pdev->dev, "Could not map registers\n"); | |
1919 | return PTR_ERR(dcmi->regs); | |
1920 | } | |
1921 | ||
1922 | ret = devm_request_threaded_irq(&pdev->dev, irq, dcmi_irq_callback, | |
1923 | dcmi_irq_thread, IRQF_ONESHOT, | |
1924 | dev_name(&pdev->dev), dcmi); | |
1925 | if (ret) { | |
1926 | dev_err(&pdev->dev, "Unable to request irq %d\n", irq); | |
b5b5a27b | 1927 | return ret; |
37404f91 HF |
1928 | } |
1929 | ||
1930 | mclk = devm_clk_get(&pdev->dev, "mclk"); | |
1931 | if (IS_ERR(mclk)) { | |
b5b5a27b FD |
1932 | if (PTR_ERR(mclk) != -EPROBE_DEFER) |
1933 | dev_err(&pdev->dev, "Unable to get mclk\n"); | |
37404f91 HF |
1934 | return PTR_ERR(mclk); |
1935 | } | |
1936 | ||
05e2ebfa PU |
1937 | chan = dma_request_chan(&pdev->dev, "tx"); |
1938 | if (IS_ERR(chan)) { | |
1939 | ret = PTR_ERR(chan); | |
1940 | if (ret != -EPROBE_DEFER) | |
1941 | dev_err(&pdev->dev, | |
1942 | "Failed to request DMA channel: %d\n", ret); | |
1943 | return ret; | |
37404f91 HF |
1944 | } |
1945 | ||
37404f91 HF |
1946 | spin_lock_init(&dcmi->irqlock); |
1947 | mutex_init(&dcmi->lock); | |
b3ce6f6f | 1948 | mutex_init(&dcmi->dma_lock); |
37404f91 HF |
1949 | init_completion(&dcmi->complete); |
1950 | INIT_LIST_HEAD(&dcmi->buffers); | |
1951 | ||
1952 | dcmi->dev = &pdev->dev; | |
1953 | dcmi->mclk = mclk; | |
1954 | dcmi->state = STOPPED; | |
1955 | dcmi->dma_chan = chan; | |
1956 | ||
1957 | q = &dcmi->queue; | |
1958 | ||
34f8d704 HF |
1959 | dcmi->v4l2_dev.mdev = &dcmi->mdev; |
1960 | ||
1961 | /* Initialize media device */ | |
1962 | strscpy(dcmi->mdev.model, DRV_NAME, sizeof(dcmi->mdev.model)); | |
1963 | snprintf(dcmi->mdev.bus_info, sizeof(dcmi->mdev.bus_info), | |
1964 | "platform:%s", DRV_NAME); | |
1965 | dcmi->mdev.dev = &pdev->dev; | |
1966 | media_device_init(&dcmi->mdev); | |
1967 | ||
37404f91 HF |
1968 | /* Initialize the top-level structure */ |
1969 | ret = v4l2_device_register(&pdev->dev, &dcmi->v4l2_dev); | |
1970 | if (ret) | |
34f8d704 | 1971 | goto err_media_device_cleanup; |
37404f91 HF |
1972 | |
1973 | dcmi->vdev = video_device_alloc(); | |
1974 | if (!dcmi->vdev) { | |
1975 | ret = -ENOMEM; | |
1976 | goto err_device_unregister; | |
1977 | } | |
1978 | ||
1979 | /* Video node */ | |
1980 | dcmi->vdev->fops = &dcmi_fops; | |
1981 | dcmi->vdev->v4l2_dev = &dcmi->v4l2_dev; | |
1982 | dcmi->vdev->queue = &dcmi->queue; | |
c0decac1 | 1983 | strscpy(dcmi->vdev->name, KBUILD_MODNAME, sizeof(dcmi->vdev->name)); |
37404f91 HF |
1984 | dcmi->vdev->release = video_device_release; |
1985 | dcmi->vdev->ioctl_ops = &dcmi_ioctl_ops; | |
1986 | dcmi->vdev->lock = &dcmi->lock; | |
1987 | dcmi->vdev->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING | | |
1988 | V4L2_CAP_READWRITE; | |
1989 | video_set_drvdata(dcmi->vdev, dcmi); | |
1990 | ||
34f8d704 HF |
1991 | /* Media entity pads */ |
1992 | dcmi->vid_cap_pad.flags = MEDIA_PAD_FL_SINK; | |
1993 | ret = media_entity_pads_init(&dcmi->vdev->entity, | |
1994 | 1, &dcmi->vid_cap_pad); | |
1995 | if (ret) { | |
1996 | dev_err(dcmi->dev, "Failed to init media entity pad\n"); | |
1997 | goto err_device_release; | |
1998 | } | |
1999 | dcmi->vdev->entity.flags |= MEDIA_ENT_FL_DEFAULT; | |
2000 | ||
70cad449 | 2001 | ret = video_register_device(dcmi->vdev, VFL_TYPE_VIDEO, -1); |
34f8d704 HF |
2002 | if (ret) { |
2003 | dev_err(dcmi->dev, "Failed to register video device\n"); | |
2004 | goto err_media_entity_cleanup; | |
2005 | } | |
2006 | ||
2007 | dev_dbg(dcmi->dev, "Device registered as %s\n", | |
2008 | video_device_node_name(dcmi->vdev)); | |
2009 | ||
37404f91 HF |
2010 | /* Buffer queue */ |
2011 | q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | |
2012 | q->io_modes = VB2_MMAP | VB2_READ | VB2_DMABUF; | |
2013 | q->lock = &dcmi->lock; | |
2014 | q->drv_priv = dcmi; | |
2015 | q->buf_struct_size = sizeof(struct dcmi_buf); | |
2016 | q->ops = &dcmi_video_qops; | |
2017 | q->mem_ops = &vb2_dma_contig_memops; | |
2018 | q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC; | |
2019 | q->min_buffers_needed = 2; | |
2020 | q->dev = &pdev->dev; | |
2021 | ||
2022 | ret = vb2_queue_init(q); | |
2023 | if (ret < 0) { | |
2024 | dev_err(&pdev->dev, "Failed to initialize vb2 queue\n"); | |
34f8d704 | 2025 | goto err_media_entity_cleanup; |
37404f91 HF |
2026 | } |
2027 | ||
2028 | ret = dcmi_graph_init(dcmi); | |
2029 | if (ret < 0) | |
34f8d704 | 2030 | goto err_media_entity_cleanup; |
37404f91 HF |
2031 | |
2032 | /* Reset device */ | |
2033 | ret = reset_control_assert(dcmi->rstc); | |
2034 | if (ret) { | |
2035 | dev_err(&pdev->dev, "Failed to assert the reset line\n"); | |
d079f94c | 2036 | goto err_cleanup; |
37404f91 HF |
2037 | } |
2038 | ||
2039 | usleep_range(3000, 5000); | |
2040 | ||
2041 | ret = reset_control_deassert(dcmi->rstc); | |
2042 | if (ret) { | |
2043 | dev_err(&pdev->dev, "Failed to deassert the reset line\n"); | |
d079f94c | 2044 | goto err_cleanup; |
37404f91 HF |
2045 | } |
2046 | ||
2047 | dev_info(&pdev->dev, "Probe done\n"); | |
2048 | ||
2049 | platform_set_drvdata(pdev, dcmi); | |
152e0bf6 HF |
2050 | |
2051 | pm_runtime_enable(&pdev->dev); | |
2052 | ||
37404f91 HF |
2053 | return 0; |
2054 | ||
d079f94c SL |
2055 | err_cleanup: |
2056 | v4l2_async_notifier_cleanup(&dcmi->notifier); | |
34f8d704 HF |
2057 | err_media_entity_cleanup: |
2058 | media_entity_cleanup(&dcmi->vdev->entity); | |
37404f91 HF |
2059 | err_device_release: |
2060 | video_device_release(dcmi->vdev); | |
2061 | err_device_unregister: | |
2062 | v4l2_device_unregister(&dcmi->v4l2_dev); | |
34f8d704 HF |
2063 | err_media_device_cleanup: |
2064 | media_device_cleanup(&dcmi->mdev); | |
37404f91 HF |
2065 | dma_release_channel(dcmi->dma_chan); |
2066 | ||
2067 | return ret; | |
2068 | } | |
2069 | ||
2070 | static int dcmi_remove(struct platform_device *pdev) | |
2071 | { | |
2072 | struct stm32_dcmi *dcmi = platform_get_drvdata(pdev); | |
2073 | ||
152e0bf6 HF |
2074 | pm_runtime_disable(&pdev->dev); |
2075 | ||
37404f91 | 2076 | v4l2_async_notifier_unregister(&dcmi->notifier); |
d079f94c | 2077 | v4l2_async_notifier_cleanup(&dcmi->notifier); |
34f8d704 | 2078 | media_entity_cleanup(&dcmi->vdev->entity); |
37404f91 | 2079 | v4l2_device_unregister(&dcmi->v4l2_dev); |
34f8d704 | 2080 | media_device_cleanup(&dcmi->mdev); |
152e0bf6 | 2081 | |
37404f91 HF |
2082 | dma_release_channel(dcmi->dma_chan); |
2083 | ||
2084 | return 0; | |
2085 | } | |
2086 | ||
152e0bf6 HF |
2087 | static __maybe_unused int dcmi_runtime_suspend(struct device *dev) |
2088 | { | |
2089 | struct stm32_dcmi *dcmi = dev_get_drvdata(dev); | |
2090 | ||
2091 | clk_disable_unprepare(dcmi->mclk); | |
2092 | ||
2093 | return 0; | |
2094 | } | |
2095 | ||
2096 | static __maybe_unused int dcmi_runtime_resume(struct device *dev) | |
2097 | { | |
2098 | struct stm32_dcmi *dcmi = dev_get_drvdata(dev); | |
2099 | int ret; | |
2100 | ||
2101 | ret = clk_prepare_enable(dcmi->mclk); | |
2102 | if (ret) | |
2103 | dev_err(dev, "%s: Failed to prepare_enable clock\n", __func__); | |
2104 | ||
2105 | return ret; | |
2106 | } | |
2107 | ||
2108 | static __maybe_unused int dcmi_suspend(struct device *dev) | |
2109 | { | |
2110 | /* disable clock */ | |
2111 | pm_runtime_force_suspend(dev); | |
2112 | ||
2113 | /* change pinctrl state */ | |
2114 | pinctrl_pm_select_sleep_state(dev); | |
2115 | ||
2116 | return 0; | |
2117 | } | |
2118 | ||
2119 | static __maybe_unused int dcmi_resume(struct device *dev) | |
2120 | { | |
2121 | /* restore pinctl default state */ | |
2122 | pinctrl_pm_select_default_state(dev); | |
2123 | ||
2124 | /* clock enable */ | |
2125 | pm_runtime_force_resume(dev); | |
2126 | ||
2127 | return 0; | |
2128 | } | |
2129 | ||
2130 | static const struct dev_pm_ops dcmi_pm_ops = { | |
2131 | SET_SYSTEM_SLEEP_PM_OPS(dcmi_suspend, dcmi_resume) | |
2132 | SET_RUNTIME_PM_OPS(dcmi_runtime_suspend, | |
2133 | dcmi_runtime_resume, NULL) | |
2134 | }; | |
2135 | ||
37404f91 HF |
2136 | static struct platform_driver stm32_dcmi_driver = { |
2137 | .probe = dcmi_probe, | |
2138 | .remove = dcmi_remove, | |
2139 | .driver = { | |
2140 | .name = DRV_NAME, | |
2141 | .of_match_table = of_match_ptr(stm32_dcmi_of_match), | |
152e0bf6 | 2142 | .pm = &dcmi_pm_ops, |
37404f91 HF |
2143 | }, |
2144 | }; | |
2145 | ||
2146 | module_platform_driver(stm32_dcmi_driver); | |
2147 | ||
2148 | MODULE_AUTHOR("Yannick Fertre <yannick.fertre@st.com>"); | |
2149 | MODULE_AUTHOR("Hugues Fruchet <hugues.fruchet@st.com>"); | |
2150 | MODULE_DESCRIPTION("STMicroelectronics STM32 Digital Camera Memory Interface driver"); | |
2151 | MODULE_LICENSE("GPL"); |