1 // SPDX-License-Identifier: GPL-2.0
2 /*
3 * camss-vfe.c
4 *
5 * Qualcomm MSM Camera Subsystem - VFE (Video Front End) Module
6 *
7 * Copyright (c) 2013-2015, The Linux Foundation. All rights reserved.
8 * Copyright (C) 2015-2018 Linaro Ltd.
9 */
10 #include <linux/clk.h>
11 #include <linux/completion.h>
12 #include <linux/interrupt.h>
13 #include <linux/iommu.h>
14 #include <linux/mutex.h>
15 #include <linux/of.h>
16 #include <linux/platform_device.h>
17 #include <linux/pm_runtime.h>
18 #include <linux/spinlock_types.h>
19 #include <linux/spinlock.h>
20 #include <media/media-entity.h>
21 #include <media/v4l2-device.h>
22 #include <media/v4l2-subdev.h>
23
24 #include "camss-vfe.h"
25 #include "camss.h"
26
27 #define MSM_VFE_NAME "msm_vfe"
28
29 /* VFE reset timeout */
30 #define VFE_RESET_TIMEOUT_MS 50
31
32 #define SCALER_RATIO_MAX 16
33
34 struct vfe_format {
35 u32 code;
36 u8 bpp;
37 };
38
39 static const struct vfe_format formats_rdi_8x16[] = {
40 { MEDIA_BUS_FMT_UYVY8_2X8, 8 },
41 { MEDIA_BUS_FMT_VYUY8_2X8, 8 },
42 { MEDIA_BUS_FMT_YUYV8_2X8, 8 },
43 { MEDIA_BUS_FMT_YVYU8_2X8, 8 },
44 { MEDIA_BUS_FMT_SBGGR8_1X8, 8 },
45 { MEDIA_BUS_FMT_SGBRG8_1X8, 8 },
46 { MEDIA_BUS_FMT_SGRBG8_1X8, 8 },
47 { MEDIA_BUS_FMT_SRGGB8_1X8, 8 },
48 { MEDIA_BUS_FMT_SBGGR10_1X10, 10 },
49 { MEDIA_BUS_FMT_SGBRG10_1X10, 10 },
50 { MEDIA_BUS_FMT_SGRBG10_1X10, 10 },
51 { MEDIA_BUS_FMT_SRGGB10_1X10, 10 },
52 { MEDIA_BUS_FMT_SBGGR12_1X12, 12 },
53 { MEDIA_BUS_FMT_SGBRG12_1X12, 12 },
54 { MEDIA_BUS_FMT_SGRBG12_1X12, 12 },
55 { MEDIA_BUS_FMT_SRGGB12_1X12, 12 },
56 { MEDIA_BUS_FMT_Y10_1X10, 10 },
57 };
58
59 static const struct vfe_format formats_pix_8x16[] = {
60 { MEDIA_BUS_FMT_UYVY8_2X8, 8 },
61 { MEDIA_BUS_FMT_VYUY8_2X8, 8 },
62 { MEDIA_BUS_FMT_YUYV8_2X8, 8 },
63 { MEDIA_BUS_FMT_YVYU8_2X8, 8 },
64 };
65
66 static const struct vfe_format formats_rdi_8x96[] = {
67 { MEDIA_BUS_FMT_UYVY8_2X8, 8 },
68 { MEDIA_BUS_FMT_VYUY8_2X8, 8 },
69 { MEDIA_BUS_FMT_YUYV8_2X8, 8 },
70 { MEDIA_BUS_FMT_YVYU8_2X8, 8 },
71 { MEDIA_BUS_FMT_SBGGR8_1X8, 8 },
72 { MEDIA_BUS_FMT_SGBRG8_1X8, 8 },
73 { MEDIA_BUS_FMT_SGRBG8_1X8, 8 },
74 { MEDIA_BUS_FMT_SRGGB8_1X8, 8 },
75 { MEDIA_BUS_FMT_SBGGR10_1X10, 10 },
76 { MEDIA_BUS_FMT_SGBRG10_1X10, 10 },
77 { MEDIA_BUS_FMT_SGRBG10_1X10, 10 },
78 { MEDIA_BUS_FMT_SRGGB10_1X10, 10 },
79 { MEDIA_BUS_FMT_SBGGR10_2X8_PADHI_LE, 16 },
80 { MEDIA_BUS_FMT_SBGGR12_1X12, 12 },
81 { MEDIA_BUS_FMT_SGBRG12_1X12, 12 },
82 { MEDIA_BUS_FMT_SGRBG12_1X12, 12 },
83 { MEDIA_BUS_FMT_SRGGB12_1X12, 12 },
84 { MEDIA_BUS_FMT_SBGGR14_1X14, 14 },
85 { MEDIA_BUS_FMT_SGBRG14_1X14, 14 },
86 { MEDIA_BUS_FMT_SGRBG14_1X14, 14 },
87 { MEDIA_BUS_FMT_SRGGB14_1X14, 14 },
88 { MEDIA_BUS_FMT_Y10_1X10, 10 },
89 { MEDIA_BUS_FMT_Y10_2X8_PADHI_LE, 16 },
90 };
91
92 static const struct vfe_format formats_pix_8x96[] = {
93 { MEDIA_BUS_FMT_UYVY8_2X8, 8 },
94 { MEDIA_BUS_FMT_VYUY8_2X8, 8 },
95 { MEDIA_BUS_FMT_YUYV8_2X8, 8 },
96 { MEDIA_BUS_FMT_YVYU8_2X8, 8 },
97 };
98
99 static const struct vfe_format formats_rdi_845[] = {
100 { MEDIA_BUS_FMT_UYVY8_2X8, 8 },
101 { MEDIA_BUS_FMT_VYUY8_2X8, 8 },
102 { MEDIA_BUS_FMT_YUYV8_2X8, 8 },
103 { MEDIA_BUS_FMT_YVYU8_2X8, 8 },
104 { MEDIA_BUS_FMT_SBGGR8_1X8, 8 },
105 { MEDIA_BUS_FMT_SGBRG8_1X8, 8 },
106 { MEDIA_BUS_FMT_SGRBG8_1X8, 8 },
107 { MEDIA_BUS_FMT_SRGGB8_1X8, 8 },
108 { MEDIA_BUS_FMT_SBGGR10_1X10, 10 },
109 { MEDIA_BUS_FMT_SGBRG10_1X10, 10 },
110 { MEDIA_BUS_FMT_SGRBG10_1X10, 10 },
111 { MEDIA_BUS_FMT_SRGGB10_1X10, 10 },
112 { MEDIA_BUS_FMT_SBGGR10_2X8_PADHI_LE, 16 },
113 { MEDIA_BUS_FMT_SBGGR12_1X12, 12 },
114 { MEDIA_BUS_FMT_SGBRG12_1X12, 12 },
115 { MEDIA_BUS_FMT_SGRBG12_1X12, 12 },
116 { MEDIA_BUS_FMT_SRGGB12_1X12, 12 },
117 { MEDIA_BUS_FMT_SBGGR14_1X14, 14 },
118 { MEDIA_BUS_FMT_SGBRG14_1X14, 14 },
119 { MEDIA_BUS_FMT_SGRBG14_1X14, 14 },
120 { MEDIA_BUS_FMT_SRGGB14_1X14, 14 },
121 { MEDIA_BUS_FMT_Y10_1X10, 10 },
122 { MEDIA_BUS_FMT_Y10_2X8_PADHI_LE, 16 },
123 };
124
125 /*
126 * vfe_get_bpp - map media bus format to bits per pixel
127 * @formats: supported media bus formats array
128 * @nformats: size of @formats array
129 * @code: media bus format code
130 *
131 * Return number of bits per pixel
132 */
vfe_get_bpp(const struct vfe_format * formats,unsigned int nformats,u32 code)133 static u8 vfe_get_bpp(const struct vfe_format *formats,
134 unsigned int nformats, u32 code)
135 {
136 unsigned int i;
137
138 for (i = 0; i < nformats; i++)
139 if (code == formats[i].code)
140 return formats[i].bpp;
141
142 WARN(1, "Unknown format\n");
143
144 return formats[0].bpp;
145 }
146
vfe_find_code(u32 * code,unsigned int n_code,unsigned int index,u32 req_code)147 static u32 vfe_find_code(u32 *code, unsigned int n_code,
148 unsigned int index, u32 req_code)
149 {
150 int i;
151
152 if (!req_code && (index >= n_code))
153 return 0;
154
155 for (i = 0; i < n_code; i++)
156 if (req_code) {
157 if (req_code == code[i])
158 return req_code;
159 } else {
160 if (i == index)
161 return code[i];
162 }
163
164 return code[0];
165 }
166
vfe_src_pad_code(struct vfe_line * line,u32 sink_code,unsigned int index,u32 src_req_code)167 static u32 vfe_src_pad_code(struct vfe_line *line, u32 sink_code,
168 unsigned int index, u32 src_req_code)
169 {
170 struct vfe_device *vfe = to_vfe(line);
171
172 if (vfe->camss->version == CAMSS_8x16)
173 switch (sink_code) {
174 case MEDIA_BUS_FMT_YUYV8_2X8:
175 {
176 u32 src_code[] = {
177 MEDIA_BUS_FMT_YUYV8_2X8,
178 MEDIA_BUS_FMT_YUYV8_1_5X8,
179 };
180
181 return vfe_find_code(src_code, ARRAY_SIZE(src_code),
182 index, src_req_code);
183 }
184 case MEDIA_BUS_FMT_YVYU8_2X8:
185 {
186 u32 src_code[] = {
187 MEDIA_BUS_FMT_YVYU8_2X8,
188 MEDIA_BUS_FMT_YVYU8_1_5X8,
189 };
190
191 return vfe_find_code(src_code, ARRAY_SIZE(src_code),
192 index, src_req_code);
193 }
194 case MEDIA_BUS_FMT_UYVY8_2X8:
195 {
196 u32 src_code[] = {
197 MEDIA_BUS_FMT_UYVY8_2X8,
198 MEDIA_BUS_FMT_UYVY8_1_5X8,
199 };
200
201 return vfe_find_code(src_code, ARRAY_SIZE(src_code),
202 index, src_req_code);
203 }
204 case MEDIA_BUS_FMT_VYUY8_2X8:
205 {
206 u32 src_code[] = {
207 MEDIA_BUS_FMT_VYUY8_2X8,
208 MEDIA_BUS_FMT_VYUY8_1_5X8,
209 };
210
211 return vfe_find_code(src_code, ARRAY_SIZE(src_code),
212 index, src_req_code);
213 }
214 default:
215 if (index > 0)
216 return 0;
217
218 return sink_code;
219 }
220 else if (vfe->camss->version == CAMSS_8x96 ||
221 vfe->camss->version == CAMSS_660 ||
222 vfe->camss->version == CAMSS_845)
223 switch (sink_code) {
224 case MEDIA_BUS_FMT_YUYV8_2X8:
225 {
226 u32 src_code[] = {
227 MEDIA_BUS_FMT_YUYV8_2X8,
228 MEDIA_BUS_FMT_YVYU8_2X8,
229 MEDIA_BUS_FMT_UYVY8_2X8,
230 MEDIA_BUS_FMT_VYUY8_2X8,
231 MEDIA_BUS_FMT_YUYV8_1_5X8,
232 };
233
234 return vfe_find_code(src_code, ARRAY_SIZE(src_code),
235 index, src_req_code);
236 }
237 case MEDIA_BUS_FMT_YVYU8_2X8:
238 {
239 u32 src_code[] = {
240 MEDIA_BUS_FMT_YVYU8_2X8,
241 MEDIA_BUS_FMT_YUYV8_2X8,
242 MEDIA_BUS_FMT_UYVY8_2X8,
243 MEDIA_BUS_FMT_VYUY8_2X8,
244 MEDIA_BUS_FMT_YVYU8_1_5X8,
245 };
246
247 return vfe_find_code(src_code, ARRAY_SIZE(src_code),
248 index, src_req_code);
249 }
250 case MEDIA_BUS_FMT_UYVY8_2X8:
251 {
252 u32 src_code[] = {
253 MEDIA_BUS_FMT_UYVY8_2X8,
254 MEDIA_BUS_FMT_YUYV8_2X8,
255 MEDIA_BUS_FMT_YVYU8_2X8,
256 MEDIA_BUS_FMT_VYUY8_2X8,
257 MEDIA_BUS_FMT_UYVY8_1_5X8,
258 };
259
260 return vfe_find_code(src_code, ARRAY_SIZE(src_code),
261 index, src_req_code);
262 }
263 case MEDIA_BUS_FMT_VYUY8_2X8:
264 {
265 u32 src_code[] = {
266 MEDIA_BUS_FMT_VYUY8_2X8,
267 MEDIA_BUS_FMT_YUYV8_2X8,
268 MEDIA_BUS_FMT_YVYU8_2X8,
269 MEDIA_BUS_FMT_UYVY8_2X8,
270 MEDIA_BUS_FMT_VYUY8_1_5X8,
271 };
272
273 return vfe_find_code(src_code, ARRAY_SIZE(src_code),
274 index, src_req_code);
275 }
276 default:
277 if (index > 0)
278 return 0;
279
280 return sink_code;
281 }
282 else
283 return 0;
284 }
285
vfe_reset(struct vfe_device * vfe)286 int vfe_reset(struct vfe_device *vfe)
287 {
288 unsigned long time;
289
290 reinit_completion(&vfe->reset_complete);
291
292 vfe->ops->global_reset(vfe);
293
294 time = wait_for_completion_timeout(&vfe->reset_complete,
295 msecs_to_jiffies(VFE_RESET_TIMEOUT_MS));
296 if (!time) {
297 dev_err(vfe->camss->dev, "VFE reset timeout\n");
298 return -EIO;
299 }
300
301 return 0;
302 }
303
vfe_init_outputs(struct vfe_device * vfe)304 static void vfe_init_outputs(struct vfe_device *vfe)
305 {
306 int i;
307
308 for (i = 0; i < vfe->line_num; i++) {
309 struct vfe_output *output = &vfe->line[i].output;
310
311 output->state = VFE_OUTPUT_OFF;
312 output->buf[0] = NULL;
313 output->buf[1] = NULL;
314 INIT_LIST_HEAD(&output->pending_bufs);
315 }
316 }
317
vfe_reset_output_maps(struct vfe_device * vfe)318 static void vfe_reset_output_maps(struct vfe_device *vfe)
319 {
320 int i;
321
322 for (i = 0; i < ARRAY_SIZE(vfe->wm_output_map); i++)
323 vfe->wm_output_map[i] = VFE_LINE_NONE;
324 }
325
vfe_reserve_wm(struct vfe_device * vfe,enum vfe_line_id line_id)326 int vfe_reserve_wm(struct vfe_device *vfe, enum vfe_line_id line_id)
327 {
328 int ret = -EBUSY;
329 int i;
330
331 for (i = 0; i < ARRAY_SIZE(vfe->wm_output_map); i++) {
332 if (vfe->wm_output_map[i] == VFE_LINE_NONE) {
333 vfe->wm_output_map[i] = line_id;
334 ret = i;
335 break;
336 }
337 }
338
339 return ret;
340 }
341
vfe_release_wm(struct vfe_device * vfe,u8 wm)342 int vfe_release_wm(struct vfe_device *vfe, u8 wm)
343 {
344 if (wm >= ARRAY_SIZE(vfe->wm_output_map))
345 return -EINVAL;
346
347 vfe->wm_output_map[wm] = VFE_LINE_NONE;
348
349 return 0;
350 }
351
vfe_buf_get_pending(struct vfe_output * output)352 struct camss_buffer *vfe_buf_get_pending(struct vfe_output *output)
353 {
354 struct camss_buffer *buffer = NULL;
355
356 if (!list_empty(&output->pending_bufs)) {
357 buffer = list_first_entry(&output->pending_bufs,
358 struct camss_buffer,
359 queue);
360 list_del(&buffer->queue);
361 }
362
363 return buffer;
364 }
365
vfe_buf_add_pending(struct vfe_output * output,struct camss_buffer * buffer)366 void vfe_buf_add_pending(struct vfe_output *output,
367 struct camss_buffer *buffer)
368 {
369 INIT_LIST_HEAD(&buffer->queue);
370 list_add_tail(&buffer->queue, &output->pending_bufs);
371 }
372
373 /*
374 * vfe_buf_flush_pending - Flush all pending buffers.
375 * @output: VFE output
376 * @state: vb2 buffer state
377 */
vfe_buf_flush_pending(struct vfe_output * output,enum vb2_buffer_state state)378 static void vfe_buf_flush_pending(struct vfe_output *output,
379 enum vb2_buffer_state state)
380 {
381 struct camss_buffer *buf;
382 struct camss_buffer *t;
383
384 list_for_each_entry_safe(buf, t, &output->pending_bufs, queue) {
385 vb2_buffer_done(&buf->vb.vb2_buf, state);
386 list_del(&buf->queue);
387 }
388 }
389
vfe_put_output(struct vfe_line * line)390 int vfe_put_output(struct vfe_line *line)
391 {
392 struct vfe_device *vfe = to_vfe(line);
393 struct vfe_output *output = &line->output;
394 unsigned long flags;
395 unsigned int i;
396
397 spin_lock_irqsave(&vfe->output_lock, flags);
398
399 for (i = 0; i < output->wm_num; i++)
400 vfe_release_wm(vfe, output->wm_idx[i]);
401
402 output->state = VFE_OUTPUT_OFF;
403
404 spin_unlock_irqrestore(&vfe->output_lock, flags);
405 return 0;
406 }
407
408 /**
409 * vfe_isr_comp_done() - Process composite image done interrupt
410 * @vfe: VFE Device
411 * @comp: Composite image id
412 */
vfe_isr_comp_done(struct vfe_device * vfe,u8 comp)413 void vfe_isr_comp_done(struct vfe_device *vfe, u8 comp)
414 {
415 unsigned int i;
416
417 for (i = 0; i < ARRAY_SIZE(vfe->wm_output_map); i++)
418 if (vfe->wm_output_map[i] == VFE_LINE_PIX) {
419 vfe->isr_ops.wm_done(vfe, i);
420 break;
421 }
422 }
423
vfe_isr_reset_ack(struct vfe_device * vfe)424 void vfe_isr_reset_ack(struct vfe_device *vfe)
425 {
426 complete(&vfe->reset_complete);
427 }
428
429 /*
430 * vfe_set_clock_rates - Calculate and set clock rates on VFE module
431 * @vfe: VFE device
432 *
433 * Return 0 on success or a negative error code otherwise
434 */
vfe_set_clock_rates(struct vfe_device * vfe)435 static int vfe_set_clock_rates(struct vfe_device *vfe)
436 {
437 struct device *dev = vfe->camss->dev;
438 u64 pixel_clock[VFE_LINE_NUM_MAX];
439 int i, j;
440 int ret;
441
442 for (i = VFE_LINE_RDI0; i < vfe->line_num; i++) {
443 ret = camss_get_pixel_clock(&vfe->line[i].subdev.entity,
444 &pixel_clock[i]);
445 if (ret)
446 pixel_clock[i] = 0;
447 }
448
449 for (i = 0; i < vfe->nclocks; i++) {
450 struct camss_clock *clock = &vfe->clock[i];
451
452 if (!strcmp(clock->name, "vfe0") ||
453 !strcmp(clock->name, "vfe1") ||
454 !strcmp(clock->name, "vfe_lite")) {
455 u64 min_rate = 0;
456 long rate;
457
458 for (j = VFE_LINE_RDI0; j < vfe->line_num; j++) {
459 u32 tmp;
460 u8 bpp;
461
462 if (j == VFE_LINE_PIX) {
463 tmp = pixel_clock[j];
464 } else {
465 struct vfe_line *l = &vfe->line[j];
466
467 bpp = vfe_get_bpp(l->formats,
468 l->nformats,
469 l->fmt[MSM_VFE_PAD_SINK].code);
470 tmp = pixel_clock[j] * bpp / 64;
471 }
472
473 if (min_rate < tmp)
474 min_rate = tmp;
475 }
476
477 camss_add_clock_margin(&min_rate);
478
479 for (j = 0; j < clock->nfreqs; j++)
480 if (min_rate < clock->freq[j])
481 break;
482
483 if (j == clock->nfreqs) {
484 dev_err(dev,
485 "Pixel clock is too high for VFE");
486 return -EINVAL;
487 }
488
489 /* if sensor pixel clock is not available */
490 /* set highest possible VFE clock rate */
491 if (min_rate == 0)
492 j = clock->nfreqs - 1;
493
494 rate = clk_round_rate(clock->clk, clock->freq[j]);
495 if (rate < 0) {
496 dev_err(dev, "clk round rate failed: %ld\n",
497 rate);
498 return -EINVAL;
499 }
500
501 ret = clk_set_rate(clock->clk, rate);
502 if (ret < 0) {
503 dev_err(dev, "clk set rate failed: %d\n", ret);
504 return ret;
505 }
506 }
507 }
508
509 return 0;
510 }
511
512 /*
513 * vfe_check_clock_rates - Check current clock rates on VFE module
514 * @vfe: VFE device
515 *
516 * Return 0 if current clock rates are suitable for a new pipeline
517 * or a negative error code otherwise
518 */
vfe_check_clock_rates(struct vfe_device * vfe)519 static int vfe_check_clock_rates(struct vfe_device *vfe)
520 {
521 u64 pixel_clock[VFE_LINE_NUM_MAX];
522 int i, j;
523 int ret;
524
525 for (i = VFE_LINE_RDI0; i < vfe->line_num; i++) {
526 ret = camss_get_pixel_clock(&vfe->line[i].subdev.entity,
527 &pixel_clock[i]);
528 if (ret)
529 pixel_clock[i] = 0;
530 }
531
532 for (i = 0; i < vfe->nclocks; i++) {
533 struct camss_clock *clock = &vfe->clock[i];
534
535 if (!strcmp(clock->name, "vfe0") ||
536 !strcmp(clock->name, "vfe1")) {
537 u64 min_rate = 0;
538 unsigned long rate;
539
540 for (j = VFE_LINE_RDI0; j < vfe->line_num; j++) {
541 u32 tmp;
542 u8 bpp;
543
544 if (j == VFE_LINE_PIX) {
545 tmp = pixel_clock[j];
546 } else {
547 struct vfe_line *l = &vfe->line[j];
548
549 bpp = vfe_get_bpp(l->formats,
550 l->nformats,
551 l->fmt[MSM_VFE_PAD_SINK].code);
552 tmp = pixel_clock[j] * bpp / 64;
553 }
554
555 if (min_rate < tmp)
556 min_rate = tmp;
557 }
558
559 camss_add_clock_margin(&min_rate);
560
561 rate = clk_get_rate(clock->clk);
562 if (rate < min_rate)
563 return -EBUSY;
564 }
565 }
566
567 return 0;
568 }
569
570 /*
571 * vfe_get - Power up and reset VFE module
572 * @vfe: VFE Device
573 *
574 * Return 0 on success or a negative error code otherwise
575 */
vfe_get(struct vfe_device * vfe)576 static int vfe_get(struct vfe_device *vfe)
577 {
578 int ret;
579
580 mutex_lock(&vfe->power_lock);
581
582 if (vfe->power_count == 0) {
583 ret = vfe->ops->pm_domain_on(vfe);
584 if (ret < 0)
585 goto error_pm_domain;
586
587 ret = pm_runtime_get_sync(vfe->camss->dev);
588 if (ret < 0)
589 goto error_pm_runtime_get;
590
591 ret = vfe_set_clock_rates(vfe);
592 if (ret < 0)
593 goto error_pm_runtime_get;
594
595 ret = camss_enable_clocks(vfe->nclocks, vfe->clock,
596 vfe->camss->dev);
597 if (ret < 0)
598 goto error_pm_runtime_get;
599
600 ret = vfe_reset(vfe);
601 if (ret < 0)
602 goto error_reset;
603
604 vfe_reset_output_maps(vfe);
605
606 vfe_init_outputs(vfe);
607 } else {
608 ret = vfe_check_clock_rates(vfe);
609 if (ret < 0)
610 goto error_pm_runtime_get;
611 }
612 vfe->power_count++;
613
614 mutex_unlock(&vfe->power_lock);
615
616 return 0;
617
618 error_reset:
619 camss_disable_clocks(vfe->nclocks, vfe->clock);
620
621 error_pm_runtime_get:
622 pm_runtime_put_sync(vfe->camss->dev);
623 vfe->ops->pm_domain_off(vfe);
624
625 error_pm_domain:
626 mutex_unlock(&vfe->power_lock);
627
628 return ret;
629 }
630
631 /*
632 * vfe_put - Power down VFE module
633 * @vfe: VFE Device
634 */
vfe_put(struct vfe_device * vfe)635 static void vfe_put(struct vfe_device *vfe)
636 {
637 mutex_lock(&vfe->power_lock);
638
639 if (vfe->power_count == 0) {
640 dev_err(vfe->camss->dev, "vfe power off on power_count == 0\n");
641 goto exit;
642 } else if (vfe->power_count == 1) {
643 if (vfe->was_streaming) {
644 vfe->was_streaming = 0;
645 vfe->ops->vfe_halt(vfe);
646 }
647 camss_disable_clocks(vfe->nclocks, vfe->clock);
648 pm_runtime_put_sync(vfe->camss->dev);
649 vfe->ops->pm_domain_off(vfe);
650 }
651
652 vfe->power_count--;
653
654 exit:
655 mutex_unlock(&vfe->power_lock);
656 }
657
658 /*
659 * vfe_flush_buffers - Return all vb2 buffers
660 * @vid: Video device structure
661 * @state: vb2 buffer state of the returned buffers
662 *
663 * Return all buffers to vb2. This includes queued pending buffers (still
664 * unused) and any buffers given to the hardware but again still not used.
665 *
666 * Return 0 on success or a negative error code otherwise
667 */
vfe_flush_buffers(struct camss_video * vid,enum vb2_buffer_state state)668 int vfe_flush_buffers(struct camss_video *vid,
669 enum vb2_buffer_state state)
670 {
671 struct vfe_line *line = container_of(vid, struct vfe_line, video_out);
672 struct vfe_device *vfe = to_vfe(line);
673 struct vfe_output *output;
674 unsigned long flags;
675
676 output = &line->output;
677
678 spin_lock_irqsave(&vfe->output_lock, flags);
679
680 vfe_buf_flush_pending(output, state);
681
682 if (output->buf[0])
683 vb2_buffer_done(&output->buf[0]->vb.vb2_buf, state);
684
685 if (output->buf[1])
686 vb2_buffer_done(&output->buf[1]->vb.vb2_buf, state);
687
688 if (output->last_buffer) {
689 vb2_buffer_done(&output->last_buffer->vb.vb2_buf, state);
690 output->last_buffer = NULL;
691 }
692
693 spin_unlock_irqrestore(&vfe->output_lock, flags);
694
695 return 0;
696 }
697
698 /*
699 * vfe_set_power - Power on/off VFE module
700 * @sd: VFE V4L2 subdevice
701 * @on: Requested power state
702 *
703 * Return 0 on success or a negative error code otherwise
704 */
vfe_set_power(struct v4l2_subdev * sd,int on)705 static int vfe_set_power(struct v4l2_subdev *sd, int on)
706 {
707 struct vfe_line *line = v4l2_get_subdevdata(sd);
708 struct vfe_device *vfe = to_vfe(line);
709 int ret;
710
711 if (on) {
712 ret = vfe_get(vfe);
713 if (ret < 0)
714 return ret;
715
716 vfe->ops->hw_version_read(vfe, vfe->camss->dev);
717 } else {
718 vfe_put(vfe);
719 }
720
721 return 0;
722 }
723
724 /*
725 * vfe_set_stream - Enable/disable streaming on VFE module
726 * @sd: VFE V4L2 subdevice
727 * @enable: Requested streaming state
728 *
729 * Main configuration of VFE module is triggered here.
730 *
731 * Return 0 on success or a negative error code otherwise
732 */
vfe_set_stream(struct v4l2_subdev * sd,int enable)733 static int vfe_set_stream(struct v4l2_subdev *sd, int enable)
734 {
735 struct vfe_line *line = v4l2_get_subdevdata(sd);
736 struct vfe_device *vfe = to_vfe(line);
737 int ret;
738
739 if (enable) {
740 ret = vfe->ops->vfe_enable(line);
741 if (ret < 0)
742 dev_err(vfe->camss->dev,
743 "Failed to enable vfe outputs\n");
744 } else {
745 ret = vfe->ops->vfe_disable(line);
746 if (ret < 0)
747 dev_err(vfe->camss->dev,
748 "Failed to disable vfe outputs\n");
749 }
750
751 return ret;
752 }
753
754 /*
755 * __vfe_get_format - Get pointer to format structure
756 * @line: VFE line
757 * @cfg: V4L2 subdev pad configuration
758 * @pad: pad from which format is requested
759 * @which: TRY or ACTIVE format
760 *
761 * Return pointer to TRY or ACTIVE format structure
762 */
763 static struct v4l2_mbus_framefmt *
__vfe_get_format(struct vfe_line * line,struct v4l2_subdev_pad_config * cfg,unsigned int pad,enum v4l2_subdev_format_whence which)764 __vfe_get_format(struct vfe_line *line,
765 struct v4l2_subdev_pad_config *cfg,
766 unsigned int pad,
767 enum v4l2_subdev_format_whence which)
768 {
769 if (which == V4L2_SUBDEV_FORMAT_TRY)
770 return v4l2_subdev_get_try_format(&line->subdev, cfg, pad);
771
772 return &line->fmt[pad];
773 }
774
775 /*
776 * __vfe_get_compose - Get pointer to compose selection structure
777 * @line: VFE line
778 * @cfg: V4L2 subdev pad configuration
779 * @which: TRY or ACTIVE format
780 *
781 * Return pointer to TRY or ACTIVE compose rectangle structure
782 */
783 static struct v4l2_rect *
__vfe_get_compose(struct vfe_line * line,struct v4l2_subdev_pad_config * cfg,enum v4l2_subdev_format_whence which)784 __vfe_get_compose(struct vfe_line *line,
785 struct v4l2_subdev_pad_config *cfg,
786 enum v4l2_subdev_format_whence which)
787 {
788 if (which == V4L2_SUBDEV_FORMAT_TRY)
789 return v4l2_subdev_get_try_compose(&line->subdev, cfg,
790 MSM_VFE_PAD_SINK);
791
792 return &line->compose;
793 }
794
795 /*
796 * __vfe_get_crop - Get pointer to crop selection structure
797 * @line: VFE line
798 * @cfg: V4L2 subdev pad configuration
799 * @which: TRY or ACTIVE format
800 *
801 * Return pointer to TRY or ACTIVE crop rectangle structure
802 */
803 static struct v4l2_rect *
__vfe_get_crop(struct vfe_line * line,struct v4l2_subdev_pad_config * cfg,enum v4l2_subdev_format_whence which)804 __vfe_get_crop(struct vfe_line *line,
805 struct v4l2_subdev_pad_config *cfg,
806 enum v4l2_subdev_format_whence which)
807 {
808 if (which == V4L2_SUBDEV_FORMAT_TRY)
809 return v4l2_subdev_get_try_crop(&line->subdev, cfg,
810 MSM_VFE_PAD_SRC);
811
812 return &line->crop;
813 }
814
815 /*
816 * vfe_try_format - Handle try format by pad subdev method
817 * @line: VFE line
818 * @cfg: V4L2 subdev pad configuration
819 * @pad: pad on which format is requested
820 * @fmt: pointer to v4l2 format structure
821 * @which: wanted subdev format
822 */
vfe_try_format(struct vfe_line * line,struct v4l2_subdev_pad_config * cfg,unsigned int pad,struct v4l2_mbus_framefmt * fmt,enum v4l2_subdev_format_whence which)823 static void vfe_try_format(struct vfe_line *line,
824 struct v4l2_subdev_pad_config *cfg,
825 unsigned int pad,
826 struct v4l2_mbus_framefmt *fmt,
827 enum v4l2_subdev_format_whence which)
828 {
829 unsigned int i;
830 u32 code;
831
832 switch (pad) {
833 case MSM_VFE_PAD_SINK:
834 /* Set format on sink pad */
835
836 for (i = 0; i < line->nformats; i++)
837 if (fmt->code == line->formats[i].code)
838 break;
839
840 /* If not found, use UYVY as default */
841 if (i >= line->nformats)
842 fmt->code = MEDIA_BUS_FMT_UYVY8_2X8;
843
844 fmt->width = clamp_t(u32, fmt->width, 1, 8191);
845 fmt->height = clamp_t(u32, fmt->height, 1, 8191);
846
847 fmt->field = V4L2_FIELD_NONE;
848 fmt->colorspace = V4L2_COLORSPACE_SRGB;
849
850 break;
851
852 case MSM_VFE_PAD_SRC:
853 /* Set and return a format same as sink pad */
854 code = fmt->code;
855
856 *fmt = *__vfe_get_format(line, cfg, MSM_VFE_PAD_SINK, which);
857
858 fmt->code = vfe_src_pad_code(line, fmt->code, 0, code);
859
860 if (line->id == VFE_LINE_PIX) {
861 struct v4l2_rect *rect;
862
863 rect = __vfe_get_crop(line, cfg, which);
864
865 fmt->width = rect->width;
866 fmt->height = rect->height;
867 }
868
869 break;
870 }
871
872 fmt->colorspace = V4L2_COLORSPACE_SRGB;
873 }
874
875 /*
876 * vfe_try_compose - Handle try compose selection by pad subdev method
877 * @line: VFE line
878 * @cfg: V4L2 subdev pad configuration
879 * @rect: pointer to v4l2 rect structure
880 * @which: wanted subdev format
881 */
vfe_try_compose(struct vfe_line * line,struct v4l2_subdev_pad_config * cfg,struct v4l2_rect * rect,enum v4l2_subdev_format_whence which)882 static void vfe_try_compose(struct vfe_line *line,
883 struct v4l2_subdev_pad_config *cfg,
884 struct v4l2_rect *rect,
885 enum v4l2_subdev_format_whence which)
886 {
887 struct v4l2_mbus_framefmt *fmt;
888
889 fmt = __vfe_get_format(line, cfg, MSM_VFE_PAD_SINK, which);
890
891 if (rect->width > fmt->width)
892 rect->width = fmt->width;
893
894 if (rect->height > fmt->height)
895 rect->height = fmt->height;
896
897 if (fmt->width > rect->width * SCALER_RATIO_MAX)
898 rect->width = (fmt->width + SCALER_RATIO_MAX - 1) /
899 SCALER_RATIO_MAX;
900
901 rect->width &= ~0x1;
902
903 if (fmt->height > rect->height * SCALER_RATIO_MAX)
904 rect->height = (fmt->height + SCALER_RATIO_MAX - 1) /
905 SCALER_RATIO_MAX;
906
907 if (rect->width < 16)
908 rect->width = 16;
909
910 if (rect->height < 4)
911 rect->height = 4;
912 }
913
914 /*
915 * vfe_try_crop - Handle try crop selection by pad subdev method
916 * @line: VFE line
917 * @cfg: V4L2 subdev pad configuration
918 * @rect: pointer to v4l2 rect structure
919 * @which: wanted subdev format
920 */
vfe_try_crop(struct vfe_line * line,struct v4l2_subdev_pad_config * cfg,struct v4l2_rect * rect,enum v4l2_subdev_format_whence which)921 static void vfe_try_crop(struct vfe_line *line,
922 struct v4l2_subdev_pad_config *cfg,
923 struct v4l2_rect *rect,
924 enum v4l2_subdev_format_whence which)
925 {
926 struct v4l2_rect *compose;
927
928 compose = __vfe_get_compose(line, cfg, which);
929
930 if (rect->width > compose->width)
931 rect->width = compose->width;
932
933 if (rect->width + rect->left > compose->width)
934 rect->left = compose->width - rect->width;
935
936 if (rect->height > compose->height)
937 rect->height = compose->height;
938
939 if (rect->height + rect->top > compose->height)
940 rect->top = compose->height - rect->height;
941
942 /* wm in line based mode writes multiple of 16 horizontally */
943 rect->left += (rect->width & 0xf) >> 1;
944 rect->width &= ~0xf;
945
946 if (rect->width < 16) {
947 rect->left = 0;
948 rect->width = 16;
949 }
950
951 if (rect->height < 4) {
952 rect->top = 0;
953 rect->height = 4;
954 }
955 }
956
957 /*
958 * vfe_enum_mbus_code - Handle pixel format enumeration
959 * @sd: VFE V4L2 subdevice
960 * @cfg: V4L2 subdev pad configuration
961 * @code: pointer to v4l2_subdev_mbus_code_enum structure
962 *
963 * return -EINVAL or zero on success
964 */
vfe_enum_mbus_code(struct v4l2_subdev * sd,struct v4l2_subdev_pad_config * cfg,struct v4l2_subdev_mbus_code_enum * code)965 static int vfe_enum_mbus_code(struct v4l2_subdev *sd,
966 struct v4l2_subdev_pad_config *cfg,
967 struct v4l2_subdev_mbus_code_enum *code)
968 {
969 struct vfe_line *line = v4l2_get_subdevdata(sd);
970
971 if (code->pad == MSM_VFE_PAD_SINK) {
972 if (code->index >= line->nformats)
973 return -EINVAL;
974
975 code->code = line->formats[code->index].code;
976 } else {
977 struct v4l2_mbus_framefmt *sink_fmt;
978
979 sink_fmt = __vfe_get_format(line, cfg, MSM_VFE_PAD_SINK,
980 code->which);
981
982 code->code = vfe_src_pad_code(line, sink_fmt->code,
983 code->index, 0);
984 if (!code->code)
985 return -EINVAL;
986 }
987
988 return 0;
989 }
990
991 /*
992 * vfe_enum_frame_size - Handle frame size enumeration
993 * @sd: VFE V4L2 subdevice
994 * @cfg: V4L2 subdev pad configuration
995 * @fse: pointer to v4l2_subdev_frame_size_enum structure
996 *
997 * Return -EINVAL or zero on success
998 */
vfe_enum_frame_size(struct v4l2_subdev * sd,struct v4l2_subdev_pad_config * cfg,struct v4l2_subdev_frame_size_enum * fse)999 static int vfe_enum_frame_size(struct v4l2_subdev *sd,
1000 struct v4l2_subdev_pad_config *cfg,
1001 struct v4l2_subdev_frame_size_enum *fse)
1002 {
1003 struct vfe_line *line = v4l2_get_subdevdata(sd);
1004 struct v4l2_mbus_framefmt format;
1005
1006 if (fse->index != 0)
1007 return -EINVAL;
1008
1009 format.code = fse->code;
1010 format.width = 1;
1011 format.height = 1;
1012 vfe_try_format(line, cfg, fse->pad, &format, fse->which);
1013 fse->min_width = format.width;
1014 fse->min_height = format.height;
1015
1016 if (format.code != fse->code)
1017 return -EINVAL;
1018
1019 format.code = fse->code;
1020 format.width = -1;
1021 format.height = -1;
1022 vfe_try_format(line, cfg, fse->pad, &format, fse->which);
1023 fse->max_width = format.width;
1024 fse->max_height = format.height;
1025
1026 return 0;
1027 }
1028
1029 /*
1030 * vfe_get_format - Handle get format by pads subdev method
1031 * @sd: VFE V4L2 subdevice
1032 * @cfg: V4L2 subdev pad configuration
1033 * @fmt: pointer to v4l2 subdev format structure
1034 *
1035 * Return -EINVAL or zero on success
1036 */
vfe_get_format(struct v4l2_subdev * sd,struct v4l2_subdev_pad_config * cfg,struct v4l2_subdev_format * fmt)1037 static int vfe_get_format(struct v4l2_subdev *sd,
1038 struct v4l2_subdev_pad_config *cfg,
1039 struct v4l2_subdev_format *fmt)
1040 {
1041 struct vfe_line *line = v4l2_get_subdevdata(sd);
1042 struct v4l2_mbus_framefmt *format;
1043
1044 format = __vfe_get_format(line, cfg, fmt->pad, fmt->which);
1045 if (format == NULL)
1046 return -EINVAL;
1047
1048 fmt->format = *format;
1049
1050 return 0;
1051 }
1052
1053 static int vfe_set_selection(struct v4l2_subdev *sd,
1054 struct v4l2_subdev_pad_config *cfg,
1055 struct v4l2_subdev_selection *sel);
1056
1057 /*
1058 * vfe_set_format - Handle set format by pads subdev method
1059 * @sd: VFE V4L2 subdevice
1060 * @cfg: V4L2 subdev pad configuration
1061 * @fmt: pointer to v4l2 subdev format structure
1062 *
1063 * Return -EINVAL or zero on success
1064 */
vfe_set_format(struct v4l2_subdev * sd,struct v4l2_subdev_pad_config * cfg,struct v4l2_subdev_format * fmt)1065 static int vfe_set_format(struct v4l2_subdev *sd,
1066 struct v4l2_subdev_pad_config *cfg,
1067 struct v4l2_subdev_format *fmt)
1068 {
1069 struct vfe_line *line = v4l2_get_subdevdata(sd);
1070 struct v4l2_mbus_framefmt *format;
1071
1072 format = __vfe_get_format(line, cfg, fmt->pad, fmt->which);
1073 if (format == NULL)
1074 return -EINVAL;
1075
1076 vfe_try_format(line, cfg, fmt->pad, &fmt->format, fmt->which);
1077 *format = fmt->format;
1078
1079 if (fmt->pad == MSM_VFE_PAD_SINK) {
1080 struct v4l2_subdev_selection sel = { 0 };
1081 int ret;
1082
1083 /* Propagate the format from sink to source */
1084 format = __vfe_get_format(line, cfg, MSM_VFE_PAD_SRC,
1085 fmt->which);
1086
1087 *format = fmt->format;
1088 vfe_try_format(line, cfg, MSM_VFE_PAD_SRC, format,
1089 fmt->which);
1090
1091 if (line->id != VFE_LINE_PIX)
1092 return 0;
1093
1094 /* Reset sink pad compose selection */
1095 sel.which = fmt->which;
1096 sel.pad = MSM_VFE_PAD_SINK;
1097 sel.target = V4L2_SEL_TGT_COMPOSE;
1098 sel.r.width = fmt->format.width;
1099 sel.r.height = fmt->format.height;
1100 ret = vfe_set_selection(sd, cfg, &sel);
1101 if (ret < 0)
1102 return ret;
1103 }
1104
1105 return 0;
1106 }
1107
1108 /*
1109 * vfe_get_selection - Handle get selection by pads subdev method
1110 * @sd: VFE V4L2 subdevice
1111 * @cfg: V4L2 subdev pad configuration
1112 * @sel: pointer to v4l2 subdev selection structure
1113 *
1114 * Return -EINVAL or zero on success
1115 */
vfe_get_selection(struct v4l2_subdev * sd,struct v4l2_subdev_pad_config * cfg,struct v4l2_subdev_selection * sel)1116 static int vfe_get_selection(struct v4l2_subdev *sd,
1117 struct v4l2_subdev_pad_config *cfg,
1118 struct v4l2_subdev_selection *sel)
1119 {
1120 struct vfe_line *line = v4l2_get_subdevdata(sd);
1121 struct v4l2_subdev_format fmt = { 0 };
1122 struct v4l2_rect *rect;
1123 int ret;
1124
1125 if (line->id != VFE_LINE_PIX)
1126 return -EINVAL;
1127
1128 if (sel->pad == MSM_VFE_PAD_SINK)
1129 switch (sel->target) {
1130 case V4L2_SEL_TGT_COMPOSE_BOUNDS:
1131 fmt.pad = sel->pad;
1132 fmt.which = sel->which;
1133 ret = vfe_get_format(sd, cfg, &fmt);
1134 if (ret < 0)
1135 return ret;
1136
1137 sel->r.left = 0;
1138 sel->r.top = 0;
1139 sel->r.width = fmt.format.width;
1140 sel->r.height = fmt.format.height;
1141 break;
1142 case V4L2_SEL_TGT_COMPOSE:
1143 rect = __vfe_get_compose(line, cfg, sel->which);
1144 if (rect == NULL)
1145 return -EINVAL;
1146
1147 sel->r = *rect;
1148 break;
1149 default:
1150 return -EINVAL;
1151 }
1152 else if (sel->pad == MSM_VFE_PAD_SRC)
1153 switch (sel->target) {
1154 case V4L2_SEL_TGT_CROP_BOUNDS:
1155 rect = __vfe_get_compose(line, cfg, sel->which);
1156 if (rect == NULL)
1157 return -EINVAL;
1158
1159 sel->r.left = rect->left;
1160 sel->r.top = rect->top;
1161 sel->r.width = rect->width;
1162 sel->r.height = rect->height;
1163 break;
1164 case V4L2_SEL_TGT_CROP:
1165 rect = __vfe_get_crop(line, cfg, sel->which);
1166 if (rect == NULL)
1167 return -EINVAL;
1168
1169 sel->r = *rect;
1170 break;
1171 default:
1172 return -EINVAL;
1173 }
1174
1175 return 0;
1176 }
1177
1178 /*
1179 * vfe_set_selection - Handle set selection by pads subdev method
1180 * @sd: VFE V4L2 subdevice
1181 * @cfg: V4L2 subdev pad configuration
1182 * @sel: pointer to v4l2 subdev selection structure
1183 *
1184 * Return -EINVAL or zero on success
1185 */
vfe_set_selection(struct v4l2_subdev * sd,struct v4l2_subdev_pad_config * cfg,struct v4l2_subdev_selection * sel)1186 static int vfe_set_selection(struct v4l2_subdev *sd,
1187 struct v4l2_subdev_pad_config *cfg,
1188 struct v4l2_subdev_selection *sel)
1189 {
1190 struct vfe_line *line = v4l2_get_subdevdata(sd);
1191 struct v4l2_rect *rect;
1192 int ret;
1193
1194 if (line->id != VFE_LINE_PIX)
1195 return -EINVAL;
1196
1197 if (sel->target == V4L2_SEL_TGT_COMPOSE &&
1198 sel->pad == MSM_VFE_PAD_SINK) {
1199 struct v4l2_subdev_selection crop = { 0 };
1200
1201 rect = __vfe_get_compose(line, cfg, sel->which);
1202 if (rect == NULL)
1203 return -EINVAL;
1204
1205 vfe_try_compose(line, cfg, &sel->r, sel->which);
1206 *rect = sel->r;
1207
1208 /* Reset source crop selection */
1209 crop.which = sel->which;
1210 crop.pad = MSM_VFE_PAD_SRC;
1211 crop.target = V4L2_SEL_TGT_CROP;
1212 crop.r = *rect;
1213 ret = vfe_set_selection(sd, cfg, &crop);
1214 } else if (sel->target == V4L2_SEL_TGT_CROP &&
1215 sel->pad == MSM_VFE_PAD_SRC) {
1216 struct v4l2_subdev_format fmt = { 0 };
1217
1218 rect = __vfe_get_crop(line, cfg, sel->which);
1219 if (rect == NULL)
1220 return -EINVAL;
1221
1222 vfe_try_crop(line, cfg, &sel->r, sel->which);
1223 *rect = sel->r;
1224
1225 /* Reset source pad format width and height */
1226 fmt.which = sel->which;
1227 fmt.pad = MSM_VFE_PAD_SRC;
1228 ret = vfe_get_format(sd, cfg, &fmt);
1229 if (ret < 0)
1230 return ret;
1231
1232 fmt.format.width = rect->width;
1233 fmt.format.height = rect->height;
1234 ret = vfe_set_format(sd, cfg, &fmt);
1235 } else {
1236 ret = -EINVAL;
1237 }
1238
1239 return ret;
1240 }
1241
1242 /*
1243 * vfe_init_formats - Initialize formats on all pads
1244 * @sd: VFE V4L2 subdevice
1245 * @fh: V4L2 subdev file handle
1246 *
1247 * Initialize all pad formats with default values.
1248 *
1249 * Return 0 on success or a negative error code otherwise
1250 */
vfe_init_formats(struct v4l2_subdev * sd,struct v4l2_subdev_fh * fh)1251 static int vfe_init_formats(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
1252 {
1253 struct v4l2_subdev_format format = {
1254 .pad = MSM_VFE_PAD_SINK,
1255 .which = fh ? V4L2_SUBDEV_FORMAT_TRY :
1256 V4L2_SUBDEV_FORMAT_ACTIVE,
1257 .format = {
1258 .code = MEDIA_BUS_FMT_UYVY8_2X8,
1259 .width = 1920,
1260 .height = 1080
1261 }
1262 };
1263
1264 return vfe_set_format(sd, fh ? fh->pad : NULL, &format);
1265 }
1266
1267 /*
1268 * msm_vfe_subdev_init - Initialize VFE device structure and resources
1269 * @vfe: VFE device
1270 * @res: VFE module resources table
1271 *
1272 * Return 0 on success or a negative error code otherwise
1273 */
msm_vfe_subdev_init(struct camss * camss,struct vfe_device * vfe,const struct resources * res,u8 id)1274 int msm_vfe_subdev_init(struct camss *camss, struct vfe_device *vfe,
1275 const struct resources *res, u8 id)
1276 {
1277 struct device *dev = camss->dev;
1278 struct platform_device *pdev = to_platform_device(dev);
1279 struct resource *r;
1280 int i, j;
1281 int ret;
1282
1283 switch (camss->version) {
1284 case CAMSS_8x16:
1285 vfe->ops = &vfe_ops_4_1;
1286 break;
1287 case CAMSS_8x96:
1288 vfe->ops = &vfe_ops_4_7;
1289 break;
1290 case CAMSS_660:
1291 vfe->ops = &vfe_ops_4_8;
1292 break;
1293
1294 case CAMSS_845:
1295 vfe->ops = &vfe_ops_170;
1296 break;
1297 default:
1298 return -EINVAL;
1299 }
1300 vfe->ops->subdev_init(dev, vfe);
1301
1302 /* Memory */
1303
1304 r = platform_get_resource_byname(pdev, IORESOURCE_MEM, res->reg[0]);
1305 vfe->base = devm_ioremap_resource(dev, r);
1306 if (IS_ERR(vfe->base)) {
1307 dev_err(dev, "could not map memory\n");
1308 return PTR_ERR(vfe->base);
1309 }
1310
1311 /* Interrupt */
1312
1313 r = platform_get_resource_byname(pdev, IORESOURCE_IRQ,
1314 res->interrupt[0]);
1315 if (!r) {
1316 dev_err(dev, "missing IRQ\n");
1317 return -EINVAL;
1318 }
1319
1320 vfe->irq = r->start;
1321 snprintf(vfe->irq_name, sizeof(vfe->irq_name), "%s_%s%d",
1322 dev_name(dev), MSM_VFE_NAME, vfe->id);
1323 ret = devm_request_irq(dev, vfe->irq, vfe->ops->isr,
1324 IRQF_TRIGGER_RISING, vfe->irq_name, vfe);
1325 if (ret < 0) {
1326 dev_err(dev, "request_irq failed: %d\n", ret);
1327 return ret;
1328 }
1329
1330 /* Clocks */
1331
1332 vfe->nclocks = 0;
1333 while (res->clock[vfe->nclocks])
1334 vfe->nclocks++;
1335
1336 vfe->clock = devm_kcalloc(dev, vfe->nclocks, sizeof(*vfe->clock),
1337 GFP_KERNEL);
1338 if (!vfe->clock)
1339 return -ENOMEM;
1340
1341 for (i = 0; i < vfe->nclocks; i++) {
1342 struct camss_clock *clock = &vfe->clock[i];
1343
1344 clock->clk = devm_clk_get(dev, res->clock[i]);
1345 if (IS_ERR(clock->clk))
1346 return PTR_ERR(clock->clk);
1347
1348 clock->name = res->clock[i];
1349
1350 clock->nfreqs = 0;
1351 while (res->clock_rate[i][clock->nfreqs])
1352 clock->nfreqs++;
1353
1354 if (!clock->nfreqs) {
1355 clock->freq = NULL;
1356 continue;
1357 }
1358
1359 clock->freq = devm_kcalloc(dev,
1360 clock->nfreqs,
1361 sizeof(*clock->freq),
1362 GFP_KERNEL);
1363 if (!clock->freq)
1364 return -ENOMEM;
1365
1366 for (j = 0; j < clock->nfreqs; j++)
1367 clock->freq[j] = res->clock_rate[i][j];
1368 }
1369
1370 mutex_init(&vfe->power_lock);
1371 vfe->power_count = 0;
1372
1373 mutex_init(&vfe->stream_lock);
1374 vfe->stream_count = 0;
1375
1376 spin_lock_init(&vfe->output_lock);
1377
1378 vfe->camss = camss;
1379 vfe->id = id;
1380 vfe->reg_update = 0;
1381
1382 for (i = VFE_LINE_RDI0; i < vfe->line_num; i++) {
1383 struct vfe_line *l = &vfe->line[i];
1384
1385 l->video_out.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
1386 l->video_out.camss = camss;
1387 l->id = i;
1388 init_completion(&l->output.sof);
1389 init_completion(&l->output.reg_update);
1390
1391 if (camss->version == CAMSS_8x16) {
1392 if (i == VFE_LINE_PIX) {
1393 l->formats = formats_pix_8x16;
1394 l->nformats = ARRAY_SIZE(formats_pix_8x16);
1395 } else {
1396 l->formats = formats_rdi_8x16;
1397 l->nformats = ARRAY_SIZE(formats_rdi_8x16);
1398 }
1399 } else if (camss->version == CAMSS_8x96 ||
1400 camss->version == CAMSS_660) {
1401 if (i == VFE_LINE_PIX) {
1402 l->formats = formats_pix_8x96;
1403 l->nformats = ARRAY_SIZE(formats_pix_8x96);
1404 } else {
1405 l->formats = formats_rdi_8x96;
1406 l->nformats = ARRAY_SIZE(formats_rdi_8x96);
1407 }
1408 } else if (camss->version == CAMSS_845) {
1409 l->formats = formats_rdi_845;
1410 l->nformats = ARRAY_SIZE(formats_rdi_845);
1411 } else {
1412 return -EINVAL;
1413 }
1414 }
1415
1416 init_completion(&vfe->reset_complete);
1417 init_completion(&vfe->halt_complete);
1418
1419 return 0;
1420 }
1421
1422 /*
1423 * msm_vfe_get_vfe_id - Get VFE HW module id
1424 * @entity: Pointer to VFE media entity structure
1425 * @id: Return CSID HW module id here
1426 */
msm_vfe_get_vfe_id(struct media_entity * entity,u8 * id)1427 void msm_vfe_get_vfe_id(struct media_entity *entity, u8 *id)
1428 {
1429 struct v4l2_subdev *sd;
1430 struct vfe_line *line;
1431 struct vfe_device *vfe;
1432
1433 sd = media_entity_to_v4l2_subdev(entity);
1434 line = v4l2_get_subdevdata(sd);
1435 vfe = to_vfe(line);
1436
1437 *id = vfe->id;
1438 }
1439
1440 /*
1441 * msm_vfe_get_vfe_line_id - Get VFE line id by media entity
1442 * @entity: Pointer to VFE media entity structure
1443 * @id: Return VFE line id here
1444 */
msm_vfe_get_vfe_line_id(struct media_entity * entity,enum vfe_line_id * id)1445 void msm_vfe_get_vfe_line_id(struct media_entity *entity, enum vfe_line_id *id)
1446 {
1447 struct v4l2_subdev *sd;
1448 struct vfe_line *line;
1449
1450 sd = media_entity_to_v4l2_subdev(entity);
1451 line = v4l2_get_subdevdata(sd);
1452
1453 *id = line->id;
1454 }
1455
1456 /*
1457 * vfe_link_setup - Setup VFE connections
1458 * @entity: Pointer to media entity structure
1459 * @local: Pointer to local pad
1460 * @remote: Pointer to remote pad
1461 * @flags: Link flags
1462 *
1463 * Return 0 on success
1464 */
vfe_link_setup(struct media_entity * entity,const struct media_pad * local,const struct media_pad * remote,u32 flags)1465 static int vfe_link_setup(struct media_entity *entity,
1466 const struct media_pad *local,
1467 const struct media_pad *remote, u32 flags)
1468 {
1469 if (flags & MEDIA_LNK_FL_ENABLED)
1470 if (media_entity_remote_pad(local))
1471 return -EBUSY;
1472
1473 return 0;
1474 }
1475
1476 static const struct v4l2_subdev_core_ops vfe_core_ops = {
1477 .s_power = vfe_set_power,
1478 };
1479
1480 static const struct v4l2_subdev_video_ops vfe_video_ops = {
1481 .s_stream = vfe_set_stream,
1482 };
1483
1484 static const struct v4l2_subdev_pad_ops vfe_pad_ops = {
1485 .enum_mbus_code = vfe_enum_mbus_code,
1486 .enum_frame_size = vfe_enum_frame_size,
1487 .get_fmt = vfe_get_format,
1488 .set_fmt = vfe_set_format,
1489 .get_selection = vfe_get_selection,
1490 .set_selection = vfe_set_selection,
1491 };
1492
1493 static const struct v4l2_subdev_ops vfe_v4l2_ops = {
1494 .core = &vfe_core_ops,
1495 .video = &vfe_video_ops,
1496 .pad = &vfe_pad_ops,
1497 };
1498
1499 static const struct v4l2_subdev_internal_ops vfe_v4l2_internal_ops = {
1500 .open = vfe_init_formats,
1501 };
1502
1503 static const struct media_entity_operations vfe_media_ops = {
1504 .link_setup = vfe_link_setup,
1505 .link_validate = v4l2_subdev_link_validate,
1506 };
1507
1508 /*
1509 * msm_vfe_register_entities - Register subdev node for VFE module
1510 * @vfe: VFE device
1511 * @v4l2_dev: V4L2 device
1512 *
1513 * Initialize and register a subdev node for the VFE module. Then
1514 * call msm_video_register() to register the video device node which
1515 * will be connected to this subdev node. Then actually create the
1516 * media link between them.
1517 *
1518 * Return 0 on success or a negative error code otherwise
1519 */
msm_vfe_register_entities(struct vfe_device * vfe,struct v4l2_device * v4l2_dev)1520 int msm_vfe_register_entities(struct vfe_device *vfe,
1521 struct v4l2_device *v4l2_dev)
1522 {
1523 struct device *dev = vfe->camss->dev;
1524 struct v4l2_subdev *sd;
1525 struct media_pad *pads;
1526 struct camss_video *video_out;
1527 int ret;
1528 int i;
1529
1530 for (i = 0; i < vfe->line_num; i++) {
1531 char name[32];
1532
1533 sd = &vfe->line[i].subdev;
1534 pads = vfe->line[i].pads;
1535 video_out = &vfe->line[i].video_out;
1536
1537 v4l2_subdev_init(sd, &vfe_v4l2_ops);
1538 sd->internal_ops = &vfe_v4l2_internal_ops;
1539 sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
1540 if (i == VFE_LINE_PIX)
1541 snprintf(sd->name, ARRAY_SIZE(sd->name), "%s%d_%s",
1542 MSM_VFE_NAME, vfe->id, "pix");
1543 else
1544 snprintf(sd->name, ARRAY_SIZE(sd->name), "%s%d_%s%d",
1545 MSM_VFE_NAME, vfe->id, "rdi", i);
1546
1547 v4l2_set_subdevdata(sd, &vfe->line[i]);
1548
1549 ret = vfe_init_formats(sd, NULL);
1550 if (ret < 0) {
1551 dev_err(dev, "Failed to init format: %d\n", ret);
1552 goto error_init;
1553 }
1554
1555 pads[MSM_VFE_PAD_SINK].flags = MEDIA_PAD_FL_SINK;
1556 pads[MSM_VFE_PAD_SRC].flags = MEDIA_PAD_FL_SOURCE;
1557
1558 sd->entity.function = MEDIA_ENT_F_PROC_VIDEO_PIXEL_FORMATTER;
1559 sd->entity.ops = &vfe_media_ops;
1560 ret = media_entity_pads_init(&sd->entity, MSM_VFE_PADS_NUM,
1561 pads);
1562 if (ret < 0) {
1563 dev_err(dev, "Failed to init media entity: %d\n", ret);
1564 goto error_init;
1565 }
1566
1567 ret = v4l2_device_register_subdev(v4l2_dev, sd);
1568 if (ret < 0) {
1569 dev_err(dev, "Failed to register subdev: %d\n", ret);
1570 goto error_reg_subdev;
1571 }
1572
1573 video_out->ops = &vfe->video_ops;
1574 video_out->bpl_alignment = 8;
1575 video_out->line_based = 0;
1576 if (i == VFE_LINE_PIX) {
1577 video_out->bpl_alignment = 16;
1578 video_out->line_based = 1;
1579 }
1580 snprintf(name, ARRAY_SIZE(name), "%s%d_%s%d",
1581 MSM_VFE_NAME, vfe->id, "video", i);
1582 ret = msm_video_register(video_out, v4l2_dev, name,
1583 i == VFE_LINE_PIX ? 1 : 0);
1584 if (ret < 0) {
1585 dev_err(dev, "Failed to register video node: %d\n",
1586 ret);
1587 goto error_reg_video;
1588 }
1589
1590 ret = media_create_pad_link(
1591 &sd->entity, MSM_VFE_PAD_SRC,
1592 &video_out->vdev.entity, 0,
1593 MEDIA_LNK_FL_IMMUTABLE | MEDIA_LNK_FL_ENABLED);
1594 if (ret < 0) {
1595 dev_err(dev, "Failed to link %s->%s entities: %d\n",
1596 sd->entity.name, video_out->vdev.entity.name,
1597 ret);
1598 goto error_link;
1599 }
1600 }
1601
1602 return 0;
1603
1604 error_link:
1605 msm_video_unregister(video_out);
1606
1607 error_reg_video:
1608 v4l2_device_unregister_subdev(sd);
1609
1610 error_reg_subdev:
1611 media_entity_cleanup(&sd->entity);
1612
1613 error_init:
1614 for (i--; i >= 0; i--) {
1615 sd = &vfe->line[i].subdev;
1616 video_out = &vfe->line[i].video_out;
1617
1618 msm_video_unregister(video_out);
1619 v4l2_device_unregister_subdev(sd);
1620 media_entity_cleanup(&sd->entity);
1621 }
1622
1623 return ret;
1624 }
1625
1626 /*
1627 * msm_vfe_unregister_entities - Unregister VFE module subdev node
1628 * @vfe: VFE device
1629 */
msm_vfe_unregister_entities(struct vfe_device * vfe)1630 void msm_vfe_unregister_entities(struct vfe_device *vfe)
1631 {
1632 int i;
1633
1634 mutex_destroy(&vfe->power_lock);
1635 mutex_destroy(&vfe->stream_lock);
1636
1637 for (i = 0; i < vfe->line_num; i++) {
1638 struct v4l2_subdev *sd = &vfe->line[i].subdev;
1639 struct camss_video *video_out = &vfe->line[i].video_out;
1640
1641 msm_video_unregister(video_out);
1642 v4l2_device_unregister_subdev(sd);
1643 media_entity_cleanup(&sd->entity);
1644 }
1645 }
1646