blob: 21494b59afdea094f5ff07fc3cf4fe3cf4738365 [file] [log] [blame]
Harsh Shaha1af8822017-05-11 22:06:36 -07001/* Copyright (c) 2017, The Linux Foundation. All rights reserved.
2 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 and
5 * only version 2 as published by the Free Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 */
12
13#define pr_fmt(fmt) "%s:%d " fmt, __func__, __LINE__
14
15#include <linux/ratelimit.h>
16#include <linux/slab.h>
17#include "cam_io_util.h"
18#include "cam_cdm_util.h"
19#include "cam_hw_intf.h"
20#include "cam_vfe_hw_intf.h"
21#include "cam_irq_controller.h"
22#include "cam_vfe_bus.h"
23#include "cam_vfe_bus_ver2.h"
24#include "cam_vfe_core.h"
25
26#undef CDBG
27#define CDBG(fmt, args...) pr_debug(fmt, ##args)
28
Harsh Shah23557ae2017-05-13 18:14:34 -070029#define FRAME_BASED_EN 0
30
Harsh Shaha1af8822017-05-11 22:06:36 -070031static uint32_t irq_reg_offset[CAM_IFE_BUS_IRQ_REGISTERS_MAX] = {
32 0x0000205C,
33 0x00002060,
34 0x00002064,
35 0x0000206C,
36 0x00002070,
37 0x00002074,
38 0x00002078,
39};
40
41enum cam_vfe_bus_packer_format {
42 PACKER_FMT_PLAIN_128 = 0x0,
43 PACKER_FMT_PLAIN_8 = 0x1,
44 PACKER_FMT_PLAIN_16_10BPP = 0x2,
45 PACKER_FMT_PLAIN_16_12BPP = 0x3,
46 PACKER_FMT_PLAIN_16_14BPP = 0x4,
47 PACKER_FMT_PLAIN_16_16BPP = 0x5,
48 PACKER_FMT_ARGB_10 = 0x6,
49 PACKER_FMT_ARGB_12 = 0x7,
50 PACKER_FMT_ARGB_14 = 0x8,
51 PACKER_FMT_PLAIN_32_20BPP = 0x9,
52 PACKER_FMT_PLAIN_64 = 0xA,
53 PACKER_FMT_TP_10 = 0xB,
54 PACKER_FMT_PLAIN_32_32BPP = 0xC,
55 PACKER_FMT_PLAIN_8_ODD_EVEN = 0xD,
56 PACKER_FMT_PLAIN_8_LSB_MSB_10 = 0xE,
57 PACKER_FMT_PLAIN_8_LSB_MSB_10_ODD_EVEN = 0xF,
58 PACKER_FMT_MAX = 0xF,
59};
60
61struct cam_vfe_bus_ver2_common_data {
62 void __iomem *mem_base;
63 struct cam_hw_intf *hw_intf;
64 void *bus_irq_controller;
65 void *vfe_irq_controller;
66 struct cam_vfe_bus_ver2_reg_offset_common *common_reg;
67};
68
69struct cam_vfe_bus_ver2_wm_resource_data {
70 uint32_t index;
71 struct cam_vfe_bus_ver2_common_data *common_data;
72 struct cam_vfe_bus_ver2_reg_offset_bus_client *hw_regs;
73
74 uint32_t irq_enabled;
75
76 uint32_t offset;
77 uint32_t width;
78 uint32_t height;
79 uint32_t stride;
80 uint32_t format;
81 enum cam_vfe_bus_packer_format pack_fmt;
82
83 uint32_t burst_len;
84 uint32_t frame_based;
85
86 uint32_t irq_subsample_period;
87 uint32_t irq_subsample_pattern;
88 uint32_t framedrop_period;
89 uint32_t framedrop_pattern;
90};
91
92struct cam_vfe_bus_ver2_comp_grp_data {
93 enum cam_vfe_bus_ver2_comp_grp_type comp_grp_type;
94 struct cam_vfe_bus_ver2_common_data *common_data;
95 struct cam_vfe_bus_ver2_reg_offset_comp_grp *hw_regs;
96
97 uint32_t irq_enabled;
98 uint32_t comp_grp_local_idx;
99 uint32_t unique_id;
100
101 uint32_t is_master;
102 uint32_t dual_slave_core;
103 uint32_t intra_client_mask;
104 uint32_t composite_mask;
105};
106
107struct cam_vfe_bus_ver2_vfe_out_data {
108 uint32_t out_type;
109 struct cam_vfe_bus_ver2_common_data *common_data;
110
111 uint32_t num_wm;
112 struct cam_isp_resource_node *wm_res[PLANE_MAX];
113
114 struct cam_isp_resource_node *comp_grp;
115 enum cam_isp_hw_sync_mode dual_comp_sync_mode;
116 uint32_t dual_hw_alternate_vfe_id;
117 struct list_head vfe_out_list;
118
119 uint32_t format;
120 uint32_t max_width;
121 uint32_t max_height;
122 struct cam_cdm_utils_ops *cdm_util_ops;
123};
124
125
126struct cam_vfe_bus_ver2_priv {
127 struct cam_vfe_bus_ver2_common_data common_data;
128
129 struct cam_isp_resource_node bus_client[CAM_VFE_BUS_VER2_MAX_CLIENTS];
130 struct cam_isp_resource_node comp_grp[CAM_VFE_BUS_VER2_COMP_GRP_MAX];
131 struct cam_isp_resource_node vfe_out[CAM_VFE_BUS_VER2_VFE_OUT_MAX];
132
133 struct list_head free_comp_grp;
134 struct list_head free_dual_comp_grp;
135 struct list_head used_comp_grp;
136
137 struct cam_vfe_bus_irq_evt_payload evt_payload[128];
138 struct list_head free_payload_list;
139};
140
141static int cam_vfe_bus_put_evt_payload(void *core_info,
142 struct cam_vfe_bus_irq_evt_payload **evt_payload);
143
144static int cam_vfe_bus_ver2_get_intra_client_mask(
145 enum cam_vfe_bus_ver2_vfe_core_id dual_slave_core,
146 enum cam_vfe_bus_ver2_vfe_core_id current_core,
147 uint32_t *intra_client_mask)
148{
149 int rc = 0;
150
151 *intra_client_mask = 0;
152
153 if (dual_slave_core == current_core) {
154 pr_err("Invalid params. Same core as Master and Slave\n");
155 return -EINVAL;
156 }
157
158 switch (current_core) {
159 case CAM_VFE_BUS_VER2_VFE_CORE_0:
160 switch (dual_slave_core) {
161 case CAM_VFE_BUS_VER2_VFE_CORE_1:
162 *intra_client_mask = 0x1;
163 break;
164 case CAM_VFE_BUS_VER2_VFE_CORE_2:
165 *intra_client_mask = 0x2;
166 break;
167 default:
168 pr_err("Invalid value for slave core %u\n",
169 dual_slave_core);
170 rc = -EINVAL;
171 break;
172 }
173 break;
174 case CAM_VFE_BUS_VER2_VFE_CORE_1:
175 switch (dual_slave_core) {
176 case CAM_VFE_BUS_VER2_VFE_CORE_0:
177 *intra_client_mask = 0x1;
178 break;
179 case CAM_VFE_BUS_VER2_VFE_CORE_2:
180 *intra_client_mask = 0x2;
181 break;
182 default:
183 pr_err("Invalid value for slave core %u\n",
184 dual_slave_core);
185 rc = -EINVAL;
186 break;
187 }
188 break;
189 case CAM_VFE_BUS_VER2_VFE_CORE_2:
190 switch (dual_slave_core) {
191 case CAM_VFE_BUS_VER2_VFE_CORE_0:
192 *intra_client_mask = 0x1;
193 break;
194 case CAM_VFE_BUS_VER2_VFE_CORE_1:
195 *intra_client_mask = 0x2;
196 break;
197 default:
198 pr_err("Invalid value for slave core %u\n",
199 dual_slave_core);
200 rc = -EINVAL;
201 break;
202 }
203 break;
204 default:
205 pr_err("Invalid value for master core %u\n", current_core);
206 rc = -EINVAL;
207 break;
208 }
209
210 return rc;
211}
212
213static enum cam_vfe_bus_ver2_vfe_out_type
214 cam_vfe_bus_get_out_res_id(uint32_t res_type)
215{
216 switch (res_type) {
217 case CAM_ISP_IFE_OUT_RES_FULL:
218 return CAM_VFE_BUS_VER2_VFE_OUT_FULL;
219 case CAM_ISP_IFE_OUT_RES_DS4:
220 return CAM_VFE_BUS_VER2_VFE_OUT_DS4;
221 case CAM_ISP_IFE_OUT_RES_DS16:
222 return CAM_VFE_BUS_VER2_VFE_OUT_DS16;
223 case CAM_ISP_IFE_OUT_RES_FD:
224 return CAM_VFE_BUS_VER2_VFE_OUT_FD;
225 case CAM_ISP_IFE_OUT_RES_RAW_DUMP:
226 return CAM_VFE_BUS_VER2_VFE_OUT_RAW_DUMP;
227 case CAM_ISP_IFE_OUT_RES_PDAF:
228 return CAM_VFE_BUS_VER2_VFE_OUT_PDAF;
229 case CAM_ISP_IFE_OUT_RES_RDI_0:
230 return CAM_VFE_BUS_VER2_VFE_OUT_RDI0;
231 case CAM_ISP_IFE_OUT_RES_RDI_1:
232 return CAM_VFE_BUS_VER2_VFE_OUT_RDI1;
233 case CAM_ISP_IFE_OUT_RES_RDI_2:
234 return CAM_VFE_BUS_VER2_VFE_OUT_RDI2;
235 case CAM_ISP_IFE_OUT_RES_STATS_HDR_BE:
236 return CAM_VFE_BUS_VER2_VFE_OUT_STATS_HDR_BE;
237 case CAM_ISP_IFE_OUT_RES_STATS_HDR_BHIST:
238 return CAM_VFE_BUS_VER2_VFE_OUT_STATS_HDR_BHIST;
239 case CAM_ISP_IFE_OUT_RES_STATS_TL_BG:
240 return CAM_VFE_BUS_VER2_VFE_OUT_STATS_TL_BG;
241 case CAM_ISP_IFE_OUT_RES_STATS_BF:
242 return CAM_VFE_BUS_VER2_VFE_OUT_STATS_BF;
243 case CAM_ISP_IFE_OUT_RES_STATS_AWB_BG:
244 return CAM_VFE_BUS_VER2_VFE_OUT_STATS_AWB_BG;
245 case CAM_ISP_IFE_OUT_RES_STATS_BHIST:
246 return CAM_VFE_BUS_VER2_VFE_OUT_STATS_BHIST;
247 case CAM_ISP_IFE_OUT_RES_STATS_RS:
248 return CAM_VFE_BUS_VER2_VFE_OUT_STATS_RS;
249 case CAM_ISP_IFE_OUT_RES_STATS_CS:
250 return CAM_VFE_BUS_VER2_VFE_OUT_STATS_CS;
251 case CAM_ISP_IFE_OUT_RES_STATS_IHIST:
252 return CAM_VFE_BUS_VER2_VFE_OUT_STATS_IHIST;
253 default:
254 return CAM_VFE_BUS_VER2_VFE_OUT_MAX;
255 }
256}
257
258static int cam_vfe_bus_get_num_wm(
259 enum cam_vfe_bus_ver2_vfe_out_type res_type,
260 uint32_t format)
261{
262 switch (res_type) {
263 case CAM_VFE_BUS_VER2_VFE_OUT_RDI0:
264 case CAM_VFE_BUS_VER2_VFE_OUT_RDI1:
265 case CAM_VFE_BUS_VER2_VFE_OUT_RDI2:
266 switch (format) {
267 case CAM_FORMAT_MIPI_RAW_8:
268 case CAM_FORMAT_MIPI_RAW_10:
269 case CAM_FORMAT_MIPI_RAW_12:
270 case CAM_FORMAT_MIPI_RAW_14:
271 case CAM_FORMAT_MIPI_RAW_16:
272 case CAM_FORMAT_MIPI_RAW_20:
273 case CAM_FORMAT_PLAIN128:
274 return 1;
275 default:
276 break;
277 }
278 break;
279 case CAM_VFE_BUS_VER2_VFE_OUT_FULL:
280 switch (format) {
281 case CAM_FORMAT_NV21:
282 case CAM_FORMAT_NV12:
283 case CAM_FORMAT_MIPI_RAW_8:
284 case CAM_FORMAT_PLAIN8:
285 case CAM_FORMAT_TP10:
286 case CAM_FORMAT_UBWC_NV12:
287 case CAM_FORMAT_UBWC_NV12_4R:
288 case CAM_FORMAT_UBWC_TP10:
289 case CAM_FORMAT_UBWC_P010:
290 return 2;
291 default:
292 break;
293 }
294 break;
295 case CAM_VFE_BUS_VER2_VFE_OUT_FD:
296 switch (format) {
297 case CAM_FORMAT_NV21:
298 case CAM_FORMAT_NV12:
299 case CAM_FORMAT_PLAIN8:
300 case CAM_FORMAT_TP10:
301 case CAM_FORMAT_PLAIN16_10:
302 return 2;
303 default:
304 break;
305 }
306 break;
307 case CAM_VFE_BUS_VER2_VFE_OUT_DS4:
308 case CAM_VFE_BUS_VER2_VFE_OUT_DS16:
309 switch (format) {
310 case CAM_FORMAT_PD8:
311 case CAM_FORMAT_PD10:
312 return 1;
313 default:
314 break;
315 }
316 break;
317 case CAM_VFE_BUS_VER2_VFE_OUT_RAW_DUMP:
318 switch (format) {
319 case CAM_FORMAT_ARGB_14:
320 case CAM_FORMAT_PLAIN8:
321 case CAM_FORMAT_PLAIN16_10:
322 case CAM_FORMAT_PLAIN16_12:
323 case CAM_FORMAT_PLAIN16_14:
324 return 1;
325 default:
326 break;
327 }
328 break;
329 case CAM_VFE_BUS_VER2_VFE_OUT_PDAF:
330 switch (format) {
331 case CAM_FORMAT_PLAIN8:
332 case CAM_FORMAT_PLAIN16_10:
333 case CAM_FORMAT_PLAIN16_12:
334 case CAM_FORMAT_PLAIN16_14:
335 return 1;
336 default:
337 break;
338 }
339 break;
340 case CAM_VFE_BUS_VER2_VFE_OUT_STATS_HDR_BE:
341 case CAM_VFE_BUS_VER2_VFE_OUT_STATS_HDR_BHIST:
342 case CAM_VFE_BUS_VER2_VFE_OUT_STATS_TL_BG:
343 case CAM_VFE_BUS_VER2_VFE_OUT_STATS_BF:
344 case CAM_VFE_BUS_VER2_VFE_OUT_STATS_AWB_BG:
345 case CAM_VFE_BUS_VER2_VFE_OUT_STATS_BHIST:
346 case CAM_VFE_BUS_VER2_VFE_OUT_STATS_CS:
347 switch (format) {
348 case CAM_FORMAT_PLAIN64:
349 return 1;
350 default:
351 break;
352 }
353 break;
354 case CAM_VFE_BUS_VER2_VFE_OUT_STATS_RS:
355 case CAM_VFE_BUS_VER2_VFE_OUT_STATS_IHIST:
356 switch (format) {
357 case CAM_FORMAT_PLAIN16_16:
358 return 1;
359 default:
360 break;
361 }
362 break;
363 default:
364 break;
365 }
366
367 pr_err("Unsupported format %u for resource_type %u", format, res_type);
368
369 return -EINVAL;
370}
371
372static int cam_vfe_bus_get_wm_idx(
373 enum cam_vfe_bus_ver2_vfe_out_type vfe_out_res_id,
374 enum cam_vfe_bus_plane_type plane)
375{
376 int wm_idx = -1;
377
378 switch (vfe_out_res_id) {
379 case CAM_VFE_BUS_VER2_VFE_OUT_FULL:
380 switch (plane) {
381 case PLANE_Y:
382 wm_idx = 3;
383 break;
384 case PLANE_C:
385 wm_idx = 4;
386 break;
387 default:
388 break;
389 }
390 break;
391 case CAM_VFE_BUS_VER2_VFE_OUT_DS4:
392 switch (plane) {
393 case PLANE_Y:
394 wm_idx = 5;
395 break;
396 default:
397 break;
398 }
399 break;
400 case CAM_VFE_BUS_VER2_VFE_OUT_DS16:
401 switch (plane) {
402 case PLANE_Y:
403 wm_idx = 6;
404 break;
405 default:
406 break;
407 }
408 break;
409 case CAM_VFE_BUS_VER2_VFE_OUT_FD:
410 switch (plane) {
411 case PLANE_Y:
412 wm_idx = 7;
413 break;
414 case PLANE_C:
415 wm_idx = 8;
416 break;
417 default:
418 break;
419 }
420 break;
421 case CAM_VFE_BUS_VER2_VFE_OUT_RAW_DUMP:
422 switch (plane) {
423 case PLANE_Y:
424 wm_idx = 9;
425 break;
426 default:
427 break;
428 }
429 break;
430 case CAM_VFE_BUS_VER2_VFE_OUT_PDAF:
431 switch (plane) {
432 case PLANE_Y:
433 wm_idx = 10;
434 break;
435 default:
436 break;
437 }
438 break;
439 case CAM_VFE_BUS_VER2_VFE_OUT_RDI0:
440 switch (plane) {
441 case PLANE_Y:
442 wm_idx = 0;
443 break;
444 default:
445 break;
446 }
447 break;
448 case CAM_VFE_BUS_VER2_VFE_OUT_RDI1:
449 switch (plane) {
450 case PLANE_Y:
451 wm_idx = 1;
452 break;
453 default:
454 break;
455 }
456 break;
457 case CAM_VFE_BUS_VER2_VFE_OUT_RDI2:
458 switch (plane) {
459 case PLANE_Y:
460 wm_idx = 2;
461 break;
462 default:
463 break;
464 }
465 break;
466 case CAM_VFE_BUS_VER2_VFE_OUT_STATS_HDR_BE:
467 switch (plane) {
468 case PLANE_Y:
469 wm_idx = 11;
470 break;
471 default:
472 break;
473 }
474 break;
475 case CAM_VFE_BUS_VER2_VFE_OUT_STATS_HDR_BHIST:
476 switch (plane) {
477 case PLANE_Y:
478 wm_idx = 12;
479 break;
480 default:
481 break;
482 }
483 break;
484 case CAM_VFE_BUS_VER2_VFE_OUT_STATS_TL_BG:
485 switch (plane) {
486 case PLANE_Y:
487 wm_idx = 13;
488 break;
489 default:
490 break;
491 }
492 break;
493 case CAM_VFE_BUS_VER2_VFE_OUT_STATS_BF:
494 switch (plane) {
495 case PLANE_Y:
496 wm_idx = 14;
497 break;
498 default:
499 break;
500 }
501 break;
502 case CAM_VFE_BUS_VER2_VFE_OUT_STATS_AWB_BG:
503 switch (plane) {
504 case PLANE_Y:
505 wm_idx = 15;
506 break;
507 default:
508 break;
509 }
510 break;
511 case CAM_VFE_BUS_VER2_VFE_OUT_STATS_BHIST:
512 switch (plane) {
513 case PLANE_Y:
514 wm_idx = 16;
515 break;
516 default:
517 break;
518 }
519 break;
520 case CAM_VFE_BUS_VER2_VFE_OUT_STATS_RS:
521 switch (plane) {
522 case PLANE_Y:
523 wm_idx = 17;
524 break;
525 default:
526 break;
527 }
528 break;
529 case CAM_VFE_BUS_VER2_VFE_OUT_STATS_CS:
530 switch (plane) {
531 case PLANE_Y:
532 wm_idx = 18;
533 break;
534 default:
535 break;
536 }
537 break;
538 case CAM_VFE_BUS_VER2_VFE_OUT_STATS_IHIST:
539 switch (plane) {
540 case PLANE_Y:
541 wm_idx = 19;
542 break;
543 default:
544 break;
545 }
546 break;
547 default:
548 break;
549 }
550
551 return wm_idx;
552}
553
554static enum cam_vfe_bus_packer_format
555 cam_vfe_bus_get_packer_fmt(uint32_t out_fmt)
556{
557 switch (out_fmt) {
558 case CAM_FORMAT_NV21:
559 case CAM_FORMAT_NV12:
560 return PACKER_FMT_PLAIN_8;
561 default:
562 return PACKER_FMT_MAX;
563 }
564}
565
566static int cam_vfe_bus_acquire_wm(
567 struct cam_vfe_bus_ver2_priv *ver2_bus_priv,
568 struct cam_isp_out_port_info *out_port_info,
569 enum cam_vfe_bus_ver2_vfe_out_type vfe_out_res_id,
570 enum cam_vfe_bus_plane_type plane,
571 enum cam_isp_hw_split_id split_id,
572 uint32_t subscribe_irq,
573 struct cam_isp_resource_node **wm_res,
574 uint32_t *client_done_mask)
575{
576 uint32_t wm_idx = 0;
577 struct cam_isp_resource_node *wm_res_local = NULL;
578 struct cam_vfe_bus_ver2_wm_resource_data *rsrc_data = NULL;
579
580 *wm_res = NULL;
581 *client_done_mask = 0;
582
583 /* No need to allocate for BUS VER2. VFE OUT to WM is fixed. */
584 wm_idx = cam_vfe_bus_get_wm_idx(vfe_out_res_id, plane);
585 if (wm_idx < 0 || wm_idx >= CAM_VFE_BUS_VER2_MAX_CLIENTS) {
586 pr_err("Unsupported VFE out %d plane %d\n",
587 vfe_out_res_id, plane);
588 return -EINVAL;
589 }
590
591 wm_res_local = &ver2_bus_priv->bus_client[wm_idx];
592 wm_res_local->res_state = CAM_ISP_RESOURCE_STATE_RESERVED;
593
594 rsrc_data = wm_res_local->res_priv;
595 rsrc_data->irq_enabled = subscribe_irq;
596 rsrc_data->format = out_port_info->format;
597 rsrc_data->pack_fmt = cam_vfe_bus_get_packer_fmt(rsrc_data->format);
598
599 rsrc_data->width = out_port_info->width;
600 rsrc_data->height = out_port_info->height;
601 if (plane == PLANE_C) {
602 switch (rsrc_data->format) {
603 case CAM_FORMAT_NV21:
604 case CAM_FORMAT_NV12:
605 rsrc_data->height /= 2;
606 break;
607 default:
608 break;
609 }
610 }
611
612 if (vfe_out_res_id >= CAM_ISP_IFE_OUT_RES_RDI_0 &&
613 vfe_out_res_id <= CAM_ISP_IFE_OUT_RES_RDI_3)
614 rsrc_data->frame_based = 1;
615
616 *client_done_mask = (1 << wm_idx);
617 *wm_res = wm_res_local;
618
619 return 0;
620}
621
622static int cam_vfe_bus_release_wm(void *bus_priv,
623 struct cam_isp_resource_node *wm_res)
624{
625 struct cam_vfe_bus_ver2_wm_resource_data *rsrc_data =
626 wm_res->res_priv;
627
628 rsrc_data->irq_enabled = 0;
629 rsrc_data->offset = 0;
630 rsrc_data->width = 0;
631 rsrc_data->height = 0;
632 rsrc_data->stride = 0;
633 rsrc_data->format = 0;
634 rsrc_data->pack_fmt = 0;
635 rsrc_data->burst_len = 0;
636 rsrc_data->frame_based = 0;
637 rsrc_data->irq_subsample_period = 0;
638 rsrc_data->irq_subsample_pattern = 0;
639 rsrc_data->framedrop_period = 0;
640 rsrc_data->framedrop_pattern = 0;
641
642 wm_res->res_state = CAM_ISP_RESOURCE_STATE_AVAILABLE;
643
644 return 0;
645}
646
647static int cam_vfe_bus_start_wm(struct cam_isp_resource_node *wm_res)
648{
649 int rc = 0;
650 struct cam_vfe_bus_ver2_wm_resource_data *rsrc_data =
651 wm_res->res_priv;
652 struct cam_vfe_bus_ver2_common_data *common_data =
653 rsrc_data->common_data;
Harsh Shah23557ae2017-05-13 18:14:34 -0700654 uint32_t width;
655 uint32_t height;
656 uint32_t pack_fmt;
657 uint32_t stride;
658 uint32_t en_cfg;
Harsh Shaha1af8822017-05-11 22:06:36 -0700659
660 CDBG("WM res %d width = %d, height = %d\n", rsrc_data->index,
661 rsrc_data->width, rsrc_data->height);
662 CDBG("WM res %d pk_fmt = %d\n", rsrc_data->index,
663 rsrc_data->pack_fmt & PACKER_FMT_MAX);
664 CDBG("WM res %d stride = %d, burst len = %d\n",
665 rsrc_data->index, rsrc_data->width, 0xf);
666
Harsh Shah23557ae2017-05-13 18:14:34 -0700667 cam_io_w_mb(0, common_data->mem_base + rsrc_data->hw_regs->header_addr);
668 cam_io_w_mb(0, common_data->mem_base + rsrc_data->hw_regs->header_cfg);
669 cam_io_w_mb(0, common_data->mem_base + rsrc_data->hw_regs->frame_inc);
670 cam_io_w(0xf, common_data->mem_base + rsrc_data->hw_regs->burst_limit);
671
672 if (rsrc_data->index < 3) {
673 width = rsrc_data->width * 5/4;
674 height = 1;
675 pack_fmt = 0x0;
676 stride = rsrc_data->width * 5/4;
677 en_cfg = 0x3;
678 } else if (rsrc_data->index < 5) {
679 width = rsrc_data->width;
680 height = rsrc_data->height;
681 pack_fmt = 0xE;
682 stride = rsrc_data->width;
683 en_cfg = 0x1;
684 } else {
685 width = rsrc_data->width * 4;
686 height = rsrc_data->height / 2;
687 pack_fmt = 0x0;
688 stride = rsrc_data->width * 4;
689 en_cfg = 0x1;
690 }
691
692 cam_io_w_mb(width,
Harsh Shaha1af8822017-05-11 22:06:36 -0700693 common_data->mem_base + rsrc_data->hw_regs->buffer_width_cfg);
Harsh Shah23557ae2017-05-13 18:14:34 -0700694 cam_io_w(height,
Harsh Shaha1af8822017-05-11 22:06:36 -0700695 common_data->mem_base + rsrc_data->hw_regs->buffer_height_cfg);
Harsh Shah23557ae2017-05-13 18:14:34 -0700696 cam_io_w(pack_fmt,
Harsh Shaha1af8822017-05-11 22:06:36 -0700697 common_data->mem_base + rsrc_data->hw_regs->packer_cfg);
Harsh Shah23557ae2017-05-13 18:14:34 -0700698 cam_io_w(stride,
Harsh Shaha1af8822017-05-11 22:06:36 -0700699 common_data->mem_base + rsrc_data->hw_regs->stride);
Harsh Shaha1af8822017-05-11 22:06:36 -0700700
701 cam_io_w(0xFFFFFFFF, common_data->mem_base +
702 rsrc_data->hw_regs->irq_subsample_pattern);
703 cam_io_w(0x0, common_data->mem_base +
704 rsrc_data->hw_regs->irq_subsample_period);
705
706 cam_io_w(0xFFFFFFFF,
Harsh Shah23557ae2017-05-13 18:14:34 -0700707 common_data->mem_base + rsrc_data->hw_regs->framedrop_pattern);
Harsh Shaha1af8822017-05-11 22:06:36 -0700708 cam_io_w(0x0,
Harsh Shah23557ae2017-05-13 18:14:34 -0700709 common_data->mem_base + rsrc_data->hw_regs->framedrop_period);
Harsh Shaha1af8822017-05-11 22:06:36 -0700710
711 /* UBWC registers */
712 switch (rsrc_data->format) {
713 case CAM_FORMAT_UBWC_NV12:
714 /* Program UBWC registers */
715 break;
716 default:
717 break;
718 }
719
720 /* Subscribe IRQ */
721 if (rsrc_data->irq_enabled) {
722 /*
723 * Currently all WM IRQ are subscribed in one place. Need to
724 * make it dynamic later.
725 */
726 }
727
728 /* Enable WM */
Harsh Shah23557ae2017-05-13 18:14:34 -0700729 cam_io_w_mb(en_cfg, common_data->mem_base + rsrc_data->hw_regs->cfg);
730
731 CDBG("WM res %d width = %d, height = %d\n", rsrc_data->index,
732 width, height);
733 CDBG("WM res %d pk_fmt = %d\n", rsrc_data->index,
734 pack_fmt & PACKER_FMT_MAX);
735 CDBG("WM res %d stride = %d, burst len = %d\n",
736 rsrc_data->index, stride, 0xf);
737 CDBG("enable WM res %d offset 0x%x val 0x%x\n", rsrc_data->index,
738 (uint32_t) rsrc_data->hw_regs->cfg, en_cfg);
Harsh Shaha1af8822017-05-11 22:06:36 -0700739
740 wm_res->res_state = CAM_ISP_RESOURCE_STATE_STREAMING;
741
742 return rc;
743}
744
745static int cam_vfe_bus_stop_wm(struct cam_isp_resource_node *wm_res)
746{
747 int rc = 0;
748 struct cam_vfe_bus_ver2_wm_resource_data *rsrc_data =
749 wm_res->res_priv;
750 struct cam_vfe_bus_ver2_common_data *common_data =
751 rsrc_data->common_data;
752
753 /* Disble WM */
754 cam_io_w_mb(0x0,
755 common_data->mem_base + rsrc_data->hw_regs->cfg);
756
757 CDBG("irq_enabled %d", rsrc_data->irq_enabled);
758 /* Unsubscribe IRQ */
759 if (rsrc_data->irq_enabled) {
760 /*
761 * Currently all WM IRQ are unsubscribed in one place. Need to
762 * make it dynamic.
763 */
764 }
765
766 /* Halt & Reset WM */
767 cam_io_w_mb(BIT(rsrc_data->index),
768 common_data->mem_base + common_data->common_reg->sw_reset);
769
770 wm_res->res_state = CAM_ISP_RESOURCE_STATE_RESERVED;
771
772 return rc;
773}
774
775static int cam_vfe_bus_handle_wm_done_top_half(uint32_t evt_id,
776 struct cam_irq_th_payload *th_payload)
777{
778 return -EPERM;
779}
780
781static int cam_vfe_bus_handle_wm_done_bottom_half(void *wm_node,
782 void *evt_payload_priv)
783{
784 int rc = CAM_VFE_IRQ_STATUS_ERR;
785 struct cam_isp_resource_node *wm_res = wm_node;
786 struct cam_vfe_bus_irq_evt_payload *evt_payload = evt_payload_priv;
Harsh Shah23557ae2017-05-13 18:14:34 -0700787 struct cam_vfe_bus_ver2_wm_resource_data *rsrc_data =
788 (wm_res == NULL) ? NULL : wm_res->res_priv;
789 uint32_t *cam_ife_irq_regs;
Harsh Shaha1af8822017-05-11 22:06:36 -0700790 uint32_t status_reg;
791
Harsh Shah23557ae2017-05-13 18:14:34 -0700792 if (!evt_payload || !rsrc_data)
793 return rc;
Harsh Shaha1af8822017-05-11 22:06:36 -0700794
Harsh Shah23557ae2017-05-13 18:14:34 -0700795 cam_ife_irq_regs = evt_payload->irq_reg_val;
796 status_reg = cam_ife_irq_regs[CAM_IFE_IRQ_BUS_REG_STATUS1];
797
798 if (status_reg & BIT(rsrc_data->index)) {
799 cam_ife_irq_regs[CAM_IFE_IRQ_BUS_REG_STATUS1] &=
800 ~BIT(rsrc_data->index);
Harsh Shaha1af8822017-05-11 22:06:36 -0700801 rc = CAM_VFE_IRQ_STATUS_SUCCESS;
Harsh Shah23557ae2017-05-13 18:14:34 -0700802 }
Harsh Shaha1af8822017-05-11 22:06:36 -0700803
804 if (rc == CAM_VFE_IRQ_STATUS_SUCCESS)
805 cam_vfe_bus_put_evt_payload(evt_payload->core_info,
806 &evt_payload);
807
808 return rc;
809}
810
811static int cam_vfe_bus_init_wm_resource(uint32_t index,
812 struct cam_vfe_bus_ver2_priv *ver2_bus_priv,
813 struct cam_vfe_bus_ver2_hw_info *ver2_hw_info,
814 struct cam_isp_resource_node *wm_res)
815{
816 int rc = 0;
817 struct cam_vfe_bus_ver2_wm_resource_data *rsrc_data;
818
819 rsrc_data = kzalloc(sizeof(struct cam_vfe_bus_ver2_wm_resource_data),
820 GFP_KERNEL);
821 if (!rsrc_data) {
822 CDBG("Failed to alloc for wm res priv\n");
823 rc = -ENOMEM;
824 return rc;
825 }
826 wm_res->res_priv = rsrc_data;
827
828 rsrc_data->index = index;
829 rsrc_data->hw_regs = &ver2_hw_info->bus_client_reg[index];
830 rsrc_data->common_data = &ver2_bus_priv->common_data;
831
832 wm_res->res_state = CAM_ISP_RESOURCE_STATE_AVAILABLE;
833 INIT_LIST_HEAD(&wm_res->list);
834
835 wm_res->start = cam_vfe_bus_start_wm;
836 wm_res->stop = cam_vfe_bus_stop_wm;
837 wm_res->top_half_handler = cam_vfe_bus_handle_wm_done_top_half;
838 wm_res->bottom_half_handler = cam_vfe_bus_handle_wm_done_bottom_half;
839 wm_res->hw_intf = ver2_bus_priv->common_data.hw_intf;
840
841 return rc;
842}
843
844static void cam_vfe_bus_add_wm_to_comp_grp(
845 struct cam_isp_resource_node *comp_grp,
846 uint32_t composite_mask)
847{
848 struct cam_vfe_bus_ver2_comp_grp_data *rsrc_data = comp_grp->res_priv;
849
850 rsrc_data->composite_mask |= composite_mask;
851}
852
853static void cam_vfe_bus_match_comp_grp(
854 struct cam_vfe_bus_ver2_priv *ver2_bus_priv,
855 struct cam_isp_resource_node **comp_grp,
856 uint32_t comp_grp_local_idx,
857 uint32_t unique_id)
858{
859 struct cam_vfe_bus_ver2_comp_grp_data *rsrc_data = NULL;
860 struct cam_isp_resource_node *comp_grp_local = NULL;
861
862 list_for_each_entry(comp_grp_local,
863 &ver2_bus_priv->used_comp_grp, list) {
864 rsrc_data = comp_grp_local->res_priv;
865 if (rsrc_data->comp_grp_local_idx == comp_grp_local_idx &&
866 rsrc_data->unique_id == unique_id) {
867 /* Match found */
868 *comp_grp = comp_grp_local;
869 return;
870 }
871 }
872
873 *comp_grp = NULL;
874}
875
876static int cam_vfe_bus_acquire_comp_grp(
877 struct cam_vfe_bus_ver2_priv *ver2_bus_priv,
878 struct cam_isp_out_port_info *out_port_info,
879 uint32_t unique_id,
880 uint32_t is_dual,
881 uint32_t is_master,
882 enum cam_vfe_bus_ver2_vfe_core_id dual_slave_core,
883 struct cam_isp_resource_node **comp_grp)
884{
885 int rc = 0;
886 struct cam_isp_resource_node *comp_grp_local = NULL;
887 struct cam_vfe_bus_ver2_comp_grp_data *rsrc_data = NULL;
888
889 /* Check if matching comp_grp already acquired */
890 cam_vfe_bus_match_comp_grp(ver2_bus_priv, &comp_grp_local,
891 out_port_info->comp_grp_id, unique_id);
892
893 if (!comp_grp_local) {
894 /* First find a free group */
895 if (is_dual) {
896 if (list_empty(&ver2_bus_priv->free_dual_comp_grp)) {
897 pr_err("No Free Composite Group\n");
898 return -ENODEV;
899 }
900 comp_grp_local = list_first_entry(
901 &ver2_bus_priv->free_dual_comp_grp,
902 struct cam_isp_resource_node, list);
903 rsrc_data = comp_grp_local->res_priv;
904 rc = cam_vfe_bus_ver2_get_intra_client_mask(
905 dual_slave_core,
906 comp_grp_local->hw_intf->hw_idx,
907 &rsrc_data->intra_client_mask);
908 } else {
909 if (list_empty(&ver2_bus_priv->free_comp_grp)) {
910 pr_err("No Free Composite Group\n");
911 return -ENODEV;
912 }
913 comp_grp_local = list_first_entry(
914 &ver2_bus_priv->free_comp_grp,
915 struct cam_isp_resource_node, list);
916 rsrc_data = comp_grp_local->res_priv;
917 }
918
919 list_del(&comp_grp_local->list);
920 comp_grp_local->res_state = CAM_ISP_RESOURCE_STATE_RESERVED;
921
922 rsrc_data->is_master = is_master;
923 rsrc_data->composite_mask = 0;
924 rsrc_data->unique_id = unique_id;
925 rsrc_data->comp_grp_local_idx = out_port_info->comp_grp_id;
926
927 list_add_tail(&comp_grp_local->list,
928 &ver2_bus_priv->used_comp_grp);
929
930 } else {
931 rsrc_data = comp_grp_local->res_priv;
932 /* Do not support runtime change in composite mask */
933 if (comp_grp_local->res_state ==
934 CAM_ISP_RESOURCE_STATE_STREAMING) {
935 pr_err("Invalid State %d Comp Grp %u\n",
936 comp_grp_local->res_state,
937 rsrc_data->comp_grp_type);
938 return -EBUSY;
939 }
940 }
941
942 *comp_grp = comp_grp_local;
943
944 return rc;
945}
946
947static int cam_vfe_bus_release_comp_grp(
948 struct cam_vfe_bus_ver2_priv *ver2_bus_priv,
949 struct cam_isp_resource_node *in_comp_grp)
950{
951 struct cam_isp_resource_node *comp_grp = NULL;
952 struct cam_vfe_bus_ver2_comp_grp_data *in_rsrc_data = NULL;
953 int match_found = 0;
954
955 if (!in_comp_grp) {
956 pr_err("Invalid Params Comp Grp %pK\n", in_rsrc_data);
957 return -EINVAL;
958 }
959
960 if (in_comp_grp->res_state == CAM_ISP_RESOURCE_STATE_AVAILABLE) {
961 /* Already Released. Do Nothing */
962 return 0;
963 }
964
965 in_rsrc_data = in_comp_grp->res_priv;
966
967 list_for_each_entry(comp_grp, &ver2_bus_priv->used_comp_grp, list) {
968 if (comp_grp == in_comp_grp) {
969 match_found = 1;
970 break;
971 }
972 }
973
974 if (!match_found) {
975 pr_err("Could not find matching Comp Grp type %u\n",
976 in_rsrc_data->comp_grp_type);
977 return -ENODEV;
978 }
979
980
981 list_del(&comp_grp->list);
982 if (in_rsrc_data->comp_grp_type >= CAM_VFE_BUS_VER2_COMP_GRP_DUAL_0 &&
983 in_rsrc_data->comp_grp_type <= CAM_VFE_BUS_VER2_COMP_GRP_DUAL_5)
984 list_add_tail(&comp_grp->list,
985 &ver2_bus_priv->free_dual_comp_grp);
986 else if (in_rsrc_data->comp_grp_type >= CAM_VFE_BUS_VER2_COMP_GRP_DUAL_0
987 && in_rsrc_data->comp_grp_type <=
988 CAM_VFE_BUS_VER2_COMP_GRP_DUAL_5)
989 list_add_tail(&comp_grp->list, &ver2_bus_priv->free_comp_grp);
990
991 list_add_tail(&comp_grp->list,
992 &ver2_bus_priv->free_comp_grp);
993 in_rsrc_data->unique_id = 0;
994 in_rsrc_data->comp_grp_local_idx = 0;
995 in_rsrc_data->composite_mask = 0;
996 in_rsrc_data->dual_slave_core = CAM_VFE_BUS_VER2_VFE_CORE_MAX;
997
998 comp_grp->res_state = CAM_ISP_RESOURCE_STATE_AVAILABLE;
999
1000 return -ENODEV;
1001}
1002
1003static int cam_vfe_bus_start_comp_grp(struct cam_isp_resource_node *comp_grp)
1004{
1005 int rc = 0;
1006 struct cam_vfe_bus_ver2_comp_grp_data *rsrc_data =
1007 comp_grp->res_priv;
1008 struct cam_vfe_bus_ver2_common_data *common_data =
1009 rsrc_data->common_data;
1010
1011 /*
1012 * Individual Comp_Grp Subscribe IRQ can be done here once
1013 * dynamic IRQ enable support is added.
1014 */
Harsh Shaha1af8822017-05-11 22:06:36 -07001015
1016 cam_io_w_mb(rsrc_data->composite_mask, common_data->mem_base +
1017 rsrc_data->hw_regs->comp_mask);
1018
1019 CDBG("composite_mask is 0x%x\n", rsrc_data->composite_mask);
1020 CDBG("composite_mask addr 0x%x\n", rsrc_data->hw_regs->comp_mask);
1021
1022 if (rsrc_data->comp_grp_type >= CAM_VFE_BUS_VER2_COMP_GRP_DUAL_0 &&
1023 rsrc_data->comp_grp_type <= CAM_VFE_BUS_VER2_COMP_GRP_DUAL_5 &&
1024 rsrc_data->is_master) {
1025 int dual_comp_grp = (rsrc_data->comp_grp_type -
1026 CAM_VFE_BUS_VER2_COMP_GRP_DUAL_0);
1027 int intra_client_en = cam_io_r_mb(common_data->mem_base +
1028 common_data->common_reg->dual_master_comp_cfg);
1029
1030 /* 2 Bits per comp_grp. Hence left shift by comp_grp * 2 */
1031 intra_client_en |=
1032 (rsrc_data->intra_client_mask << dual_comp_grp * 2);
1033
1034 cam_io_w_mb(intra_client_en, common_data->mem_base +
1035 common_data->common_reg->dual_master_comp_cfg);
1036 }
1037
1038 comp_grp->res_state = CAM_ISP_RESOURCE_STATE_STREAMING;
1039 return rc;
1040}
1041
1042static int cam_vfe_bus_stop_comp_grp(struct cam_isp_resource_node *comp_grp)
1043{
1044 int rc = 0;
1045 struct cam_vfe_bus_ver2_comp_grp_data *rsrc_data =
1046 comp_grp->res_priv;
1047 struct cam_vfe_bus_ver2_common_data *common_data =
1048 rsrc_data->common_data;
1049
1050 /* Unsubscribe IRQ */
1051
1052 cam_io_w_mb(rsrc_data->composite_mask, common_data->mem_base +
1053 rsrc_data->hw_regs->comp_mask);
1054 if (rsrc_data->comp_grp_type >= CAM_VFE_BUS_VER2_COMP_GRP_DUAL_0 &&
1055 rsrc_data->comp_grp_type <= CAM_VFE_BUS_VER2_COMP_GRP_DUAL_5 &&
1056 rsrc_data->is_master) {
1057 int dual_comp_grp = (rsrc_data->comp_grp_type -
1058 CAM_VFE_BUS_VER2_COMP_GRP_DUAL_0);
1059 int intra_client_en = cam_io_r_mb(common_data->mem_base +
1060 common_data->common_reg->dual_master_comp_cfg);
1061
1062 /* 2 Bits per comp_grp. Hence left shift by comp_grp * 2 */
1063 intra_client_en &=
1064 ~(rsrc_data->intra_client_mask << dual_comp_grp * 2);
1065
1066 cam_io_w_mb(intra_client_en, common_data->mem_base +
1067 common_data->common_reg->dual_master_comp_cfg);
1068 }
1069
1070 comp_grp->res_state = CAM_ISP_RESOURCE_STATE_RESERVED;
1071
1072 return rc;
1073}
1074
1075static int cam_vfe_bus_handle_comp_done_top_half(uint32_t evt_id,
1076 struct cam_irq_th_payload *th_payload)
1077{
1078 return -EPERM;
1079}
1080
1081static int cam_vfe_bus_handle_comp_done_bottom_half(
1082 void *handler_priv,
1083 void *evt_payload_priv)
1084{
1085 int rc = CAM_VFE_IRQ_STATUS_ERR;
1086 struct cam_isp_resource_node *comp_grp = handler_priv;
1087 struct cam_vfe_bus_irq_evt_payload *evt_payload = evt_payload_priv;
1088 struct cam_vfe_bus_ver2_comp_grp_data *rsrc_data = comp_grp->res_priv;
Harsh Shah23557ae2017-05-13 18:14:34 -07001089 uint32_t *cam_ife_irq_regs;
1090 uint32_t status_reg;
1091 uint32_t comp_err_reg;
1092 uint32_t comp_grp_id;
1093
1094 if (!evt_payload)
1095 return rc;
1096
1097 cam_ife_irq_regs = evt_payload->irq_reg_val;
Harsh Shaha1af8822017-05-11 22:06:36 -07001098
1099 CDBG("comp grp type %d\n", rsrc_data->comp_grp_type);
1100 switch (rsrc_data->comp_grp_type) {
1101 case CAM_VFE_BUS_VER2_COMP_GRP_0:
1102 case CAM_VFE_BUS_VER2_COMP_GRP_1:
1103 case CAM_VFE_BUS_VER2_COMP_GRP_2:
1104 case CAM_VFE_BUS_VER2_COMP_GRP_3:
1105 case CAM_VFE_BUS_VER2_COMP_GRP_4:
1106 case CAM_VFE_BUS_VER2_COMP_GRP_5:
Harsh Shah23557ae2017-05-13 18:14:34 -07001107 comp_grp_id = (rsrc_data->comp_grp_type -
Harsh Shaha1af8822017-05-11 22:06:36 -07001108 CAM_VFE_BUS_VER2_COMP_GRP_0);
1109
1110 /* Check for Regular composite error */
1111 status_reg = cam_ife_irq_regs[CAM_IFE_IRQ_BUS_REG_STATUS0];
1112
1113 comp_err_reg = cam_ife_irq_regs[CAM_IFE_IRQ_BUS_REG_COMP_ERR];
1114 if ((status_reg & BIT(11)) &&
1115 (comp_err_reg & rsrc_data->composite_mask)) {
1116 /* Check for Regular composite error */
1117 rc = CAM_VFE_IRQ_STATUS_ERR_COMP;
1118 break;
1119 }
1120
1121 comp_err_reg = cam_ife_irq_regs[CAM_IFE_IRQ_BUS_REG_COMP_OWRT];
1122 /* Check for Regular composite Overwrite */
1123 if ((status_reg & BIT(12)) &&
1124 (comp_err_reg & rsrc_data->composite_mask)) {
1125 rc = CAM_VFE_IRQ_STATUS_COMP_OWRT;
1126 break;
1127 }
1128
Harsh Shah23557ae2017-05-13 18:14:34 -07001129 /* Regular Composite SUCCESS */
1130 if (status_reg & BIT(comp_grp_id + 5)) {
1131 cam_ife_irq_regs[CAM_IFE_IRQ_BUS_REG_STATUS0] &=
1132 ~BIT(comp_grp_id + 5);
Harsh Shaha1af8822017-05-11 22:06:36 -07001133 rc = CAM_VFE_IRQ_STATUS_SUCCESS;
Harsh Shah23557ae2017-05-13 18:14:34 -07001134 }
Harsh Shaha1af8822017-05-11 22:06:36 -07001135
1136 CDBG("status reg = 0x%x, bit index = %d\n",
Harsh Shah23557ae2017-05-13 18:14:34 -07001137 status_reg, (comp_grp_id + 5));
Harsh Shaha1af8822017-05-11 22:06:36 -07001138 break;
1139
1140 case CAM_VFE_BUS_VER2_COMP_GRP_DUAL_0:
1141 case CAM_VFE_BUS_VER2_COMP_GRP_DUAL_1:
1142 case CAM_VFE_BUS_VER2_COMP_GRP_DUAL_2:
1143 case CAM_VFE_BUS_VER2_COMP_GRP_DUAL_3:
1144 case CAM_VFE_BUS_VER2_COMP_GRP_DUAL_4:
1145 case CAM_VFE_BUS_VER2_COMP_GRP_DUAL_5:
Harsh Shah23557ae2017-05-13 18:14:34 -07001146 comp_grp_id = (rsrc_data->comp_grp_type -
Harsh Shaha1af8822017-05-11 22:06:36 -07001147 CAM_VFE_BUS_VER2_COMP_GRP_DUAL_0);
1148
1149 /* Check for DUAL composite error */
1150 status_reg = cam_ife_irq_regs[CAM_IFE_IRQ_BUS_REG_STATUS2];
1151
1152 comp_err_reg = cam_ife_irq_regs[CAM_IFE_IRQ_BUS_DUAL_COMP_ERR];
1153 if ((status_reg & BIT(6)) &&
1154 (comp_err_reg & rsrc_data->composite_mask)) {
1155 /* Check for DUAL composite error */
1156 rc = CAM_VFE_IRQ_STATUS_ERR_COMP;
1157 break;
1158 }
1159
1160 /* Check for Dual composite Overwrite */
1161 comp_err_reg = cam_ife_irq_regs[CAM_IFE_IRQ_BUS_DUAL_COMP_OWRT];
1162 if ((status_reg & BIT(7)) &&
1163 (comp_err_reg & rsrc_data->composite_mask)) {
1164 rc = CAM_VFE_IRQ_STATUS_COMP_OWRT;
1165 break;
1166 }
1167
Harsh Shah23557ae2017-05-13 18:14:34 -07001168 /* DUAL Composite SUCCESS */
1169 if (status_reg & BIT(comp_grp_id)) {
1170 cam_ife_irq_regs[CAM_IFE_IRQ_BUS_REG_STATUS2] &=
1171 ~BIT(comp_grp_id + 5);
Harsh Shaha1af8822017-05-11 22:06:36 -07001172 rc = CAM_VFE_IRQ_STATUS_SUCCESS;
Harsh Shah23557ae2017-05-13 18:14:34 -07001173 }
Harsh Shaha1af8822017-05-11 22:06:36 -07001174
1175 break;
Harsh Shaha1af8822017-05-11 22:06:36 -07001176 default:
1177 rc = CAM_VFE_IRQ_STATUS_ERR;
1178 break;
1179 }
1180
1181 if (rc == CAM_VFE_IRQ_STATUS_SUCCESS)
1182 cam_vfe_bus_put_evt_payload(evt_payload->core_info,
1183 &evt_payload);
1184
1185 return rc;
1186}
1187
1188static int cam_vfe_bus_init_comp_grp(uint32_t index,
1189 struct cam_vfe_bus_ver2_priv *ver2_bus_priv,
1190 struct cam_vfe_bus_ver2_hw_info *ver2_hw_info,
1191 struct cam_isp_resource_node *comp_grp)
1192{
1193 struct cam_vfe_bus_ver2_comp_grp_data *rsrc_data =
1194 comp_grp->res_priv;
1195
1196 rsrc_data = kzalloc(sizeof(struct cam_vfe_bus_ver2_comp_grp_data),
1197 GFP_KERNEL);
1198 if (!rsrc_data) {
1199 CDBG("Failed to alloc for comp_grp_priv\n");
1200 return -ENOMEM;
1201 }
1202 comp_grp->res_priv = rsrc_data;
1203
1204 comp_grp->res_state = CAM_ISP_RESOURCE_STATE_AVAILABLE;
1205 INIT_LIST_HEAD(&comp_grp->list);
1206
1207 rsrc_data->comp_grp_type = index;
1208 rsrc_data->common_data = &ver2_bus_priv->common_data;
1209 rsrc_data->hw_regs = &ver2_hw_info->comp_grp_reg[index];
1210 rsrc_data->dual_slave_core = CAM_VFE_BUS_VER2_VFE_CORE_MAX;
1211
1212
1213 if (rsrc_data->comp_grp_type >= CAM_VFE_BUS_VER2_COMP_GRP_DUAL_0 &&
1214 rsrc_data->comp_grp_type <= CAM_VFE_BUS_VER2_COMP_GRP_DUAL_5)
1215 list_add_tail(&comp_grp->list,
1216 &ver2_bus_priv->free_dual_comp_grp);
1217 else if (rsrc_data->comp_grp_type >= CAM_VFE_BUS_VER2_COMP_GRP_0
1218 && rsrc_data->comp_grp_type <= CAM_VFE_BUS_VER2_COMP_GRP_5)
1219 list_add_tail(&comp_grp->list, &ver2_bus_priv->free_comp_grp);
1220
1221 comp_grp->start = cam_vfe_bus_start_comp_grp;
1222 comp_grp->stop = cam_vfe_bus_stop_comp_grp;
1223 comp_grp->top_half_handler = cam_vfe_bus_handle_comp_done_top_half;
1224 comp_grp->bottom_half_handler =
1225 cam_vfe_bus_handle_comp_done_bottom_half;
1226 comp_grp->hw_intf = ver2_bus_priv->common_data.hw_intf;
1227
1228 return 0;
1229}
1230
1231static int cam_vfe_bus_acquire_vfe_out(void *bus_priv, void *acquire_args)
1232{
1233 int rc = -ENODEV;
1234 int i;
1235 enum cam_vfe_bus_ver2_vfe_out_type vfe_out_res_id;
1236 uint32_t format;
1237 uint32_t num_wm;
1238 uint32_t subscribe_irq;
1239 uint32_t client_done_mask;
1240 struct cam_vfe_bus_ver2_priv *ver2_bus_priv = bus_priv;
1241 struct cam_vfe_acquire_args *acq_args = acquire_args;
1242 struct cam_vfe_hw_vfe_out_acquire_args *out_acquire_args;
1243 struct cam_isp_resource_node *rsrc_node = NULL;
1244 struct cam_vfe_bus_ver2_vfe_out_data *rsrc_data = NULL;
1245
1246 if (!bus_priv || !acquire_args) {
1247 pr_err("Invalid Param");
1248 return -EINVAL;
1249 }
1250
1251 out_acquire_args = &acq_args->vfe_out;
1252 format = out_acquire_args->out_port_info->format;
1253
1254 CDBG("Acquiring resource type 0x%x\n",
1255 out_acquire_args->out_port_info->res_type);
1256
1257 vfe_out_res_id = cam_vfe_bus_get_out_res_id(
1258 out_acquire_args->out_port_info->res_type);
1259 if (vfe_out_res_id == CAM_VFE_BUS_VER2_VFE_OUT_MAX)
1260 return -ENODEV;
1261
1262 num_wm = cam_vfe_bus_get_num_wm(vfe_out_res_id, format);
1263 if (num_wm < 1)
1264 return -EINVAL;
1265
1266 rsrc_node = &ver2_bus_priv->vfe_out[vfe_out_res_id];
1267 if (rsrc_node->res_state != CAM_ISP_RESOURCE_STATE_AVAILABLE) {
1268 pr_err("Resource not available: Res_id %d state:%d\n",
1269 vfe_out_res_id, rsrc_node->res_state);
1270 return -EBUSY;
1271 }
1272
1273 rsrc_data = rsrc_node->res_priv;
1274 rsrc_data->num_wm = num_wm;
1275 rsrc_node->res_id = out_acquire_args->out_port_info->res_type;
1276 rsrc_node->tasklet_info = acq_args->tasklet;
1277 rsrc_node->cdm_ops = out_acquire_args->cdm_ops;
1278 rsrc_data->cdm_util_ops = out_acquire_args->cdm_ops;
1279
1280 /* Reserve Composite Group */
1281 if (num_wm > 1 || (out_acquire_args->out_port_info->comp_grp_id >
1282 CAM_ISP_RES_COMP_GROUP_NONE &&
1283 out_acquire_args->out_port_info->comp_grp_id <
1284 CAM_ISP_RES_COMP_GROUP_ID_MAX)) {
1285 rc = cam_vfe_bus_acquire_comp_grp(ver2_bus_priv,
1286 out_acquire_args->out_port_info,
1287 out_acquire_args->unique_id,
1288 out_acquire_args->is_dual,
1289 out_acquire_args->is_master,
1290 out_acquire_args->dual_slave_core,
1291 &rsrc_data->comp_grp);
1292 if (rc < 0)
1293 return rc;
1294
1295 subscribe_irq = 0;
1296 } else
1297 subscribe_irq = 1;
1298
1299 /* Reserve WM */
1300 for (i = 0; i < num_wm; i++) {
1301 rc = cam_vfe_bus_acquire_wm(ver2_bus_priv,
1302 out_acquire_args->out_port_info,
1303 vfe_out_res_id,
1304 i,
1305 out_acquire_args->split_id,
1306 subscribe_irq,
1307 &rsrc_data->wm_res[i],
1308 &client_done_mask);
1309 if (rc < 0)
1310 goto release_wm;
1311
1312 if (rsrc_data->comp_grp)
1313 cam_vfe_bus_add_wm_to_comp_grp(rsrc_data->comp_grp,
1314 client_done_mask);
1315 }
1316
1317 rsrc_node->res_state = CAM_ISP_RESOURCE_STATE_RESERVED;
1318 out_acquire_args->rsrc_node = rsrc_node;
1319
1320 CDBG("Acquire successful\n");
1321 return rc;
1322
1323release_wm:
1324 for (i--; i >= 0; i--)
1325 cam_vfe_bus_release_wm(ver2_bus_priv, rsrc_data->wm_res[i]);
1326
1327 cam_vfe_bus_release_comp_grp(ver2_bus_priv,
1328 rsrc_data->comp_grp);
1329
1330 return rc;
1331}
1332
1333static int cam_vfe_bus_release_vfe_out(void *bus_priv,
1334 struct cam_isp_resource_node *vfe_out)
1335{
1336 if (vfe_out->res_state != CAM_ISP_RESOURCE_STATE_RESERVED) {
1337 pr_err("Error! Invalid resource state:%d\n",
1338 vfe_out->res_state);
1339 }
1340
1341 if (vfe_out->res_state == CAM_ISP_RESOURCE_STATE_RESERVED)
1342 vfe_out->res_state = CAM_ISP_RESOURCE_STATE_AVAILABLE;
1343
1344 return 0;
1345}
1346
1347static int cam_vfe_bus_start_vfe_out(struct cam_isp_resource_node *vfe_out)
1348{
1349 int rc = 0, i;
Harsh Shah23557ae2017-05-13 18:14:34 -07001350 struct cam_vfe_bus_ver2_vfe_out_data *rsrc_data = vfe_out->res_priv;
1351 struct cam_vfe_bus_ver2_common_data *common_data =
1352 rsrc_data->common_data;
Harsh Shaha1af8822017-05-11 22:06:36 -07001353
1354 CDBG("Start resource index %d\n", rsrc_data->out_type);
1355
1356 if (vfe_out->res_state != CAM_ISP_RESOURCE_STATE_RESERVED) {
1357 pr_err("Error! Invalid resource state:%d\n",
1358 vfe_out->res_state);
1359 return -EACCES;
1360 }
1361
Harsh Shah23557ae2017-05-13 18:14:34 -07001362 /* Enable IRQ Mask */
1363 cam_io_w_mb(0x00001F70, common_data->mem_base + 0x2044);
1364 cam_io_w_mb(0x000FFFE7, common_data->mem_base + 0x2048);
1365 cam_io_w_mb(0x000000FF, common_data->mem_base + 0x204c);
1366
Harsh Shaha1af8822017-05-11 22:06:36 -07001367 for (i = 0; i < rsrc_data->num_wm; i++)
1368 rc = cam_vfe_bus_start_wm(rsrc_data->wm_res[i]);
1369
1370 if (rsrc_data->comp_grp)
1371 rc = cam_vfe_bus_start_comp_grp(rsrc_data->comp_grp);
1372
1373 /* VFE_MODULE_BUS_CGC_OVERRIDE */
1374 cam_io_w_mb(0xFFFFFFFF, rsrc_data->common_data->mem_base + 0x0000003C);
1375 /* VFE_MODULE_COLOR_CGC_OVERRIDE */
1376 cam_io_w_mb(0xFFFFFFFF, rsrc_data->common_data->mem_base + 0x00000034);
1377 /* VFE_MODULE_ZOOM_CGC_OVERRIDE */
1378 cam_io_w_mb(0xFFFFFFFF, rsrc_data->common_data->mem_base + 0x38);
1379 /* VFE_MODULE_LENS_CGC_OVERRIDE */
1380 cam_io_w_mb(0xFFFFFFFF, rsrc_data->common_data->mem_base + 0x0000002C);
1381 /* VFE_MODULE_STATS_CGC_OVERRIDE */
1382 cam_io_w_mb(0xFFFFFFFF, rsrc_data->common_data->mem_base + 0x00000030);
1383
1384 /* BUS_WR_INPUT_IF_ADDR_SYNC_CFG */
1385 cam_io_w_mb(0x0, rsrc_data->common_data->mem_base + 0x0000207C);
1386 /* BUS_WR_INPUT_IF_ADDR_SYNC_FRAME_HEADER */
1387 cam_io_w_mb(0x0, rsrc_data->common_data->mem_base + 0x00002080);
1388 /* BUS_WR_INPUT_IF_ADDR_SYNC_NO_SYNC */
1389 cam_io_w_mb(0xFFFFF, rsrc_data->common_data->mem_base + 0x00002084);
Harsh Shaha1af8822017-05-11 22:06:36 -07001390 /* BUS_WR_INPUT_IF_ADDR_SYNC_0 */
1391 cam_io_w_mb(0x0, rsrc_data->common_data->mem_base + 0x00002088);
1392 cam_io_w_mb(0x0, rsrc_data->common_data->mem_base + 0x0000208c);
1393 cam_io_w_mb(0x0, rsrc_data->common_data->mem_base + 0x00002090);
1394 cam_io_w_mb(0x0, rsrc_data->common_data->mem_base + 0x00002094);
1395 cam_io_w_mb(0x0, rsrc_data->common_data->mem_base + 0x00002098);
1396 cam_io_w_mb(0x0, rsrc_data->common_data->mem_base + 0x0000209c);
1397 cam_io_w_mb(0x0, rsrc_data->common_data->mem_base + 0x000020a0);
1398 cam_io_w_mb(0x0, rsrc_data->common_data->mem_base + 0x000020a4);
1399
Harsh Shah23557ae2017-05-13 18:14:34 -07001400 /* no clock gating at bus input */
1401 cam_io_w_mb(0xFFFFF, rsrc_data->common_data->mem_base + 0x0000200C);
1402
1403 /* BUS_WR_TEST_BUS_CTRL */
1404 cam_io_w_mb(0x0, rsrc_data->common_data->mem_base + 0x0000211C);
1405
Harsh Shaha1af8822017-05-11 22:06:36 -07001406 return rc;
1407}
1408
1409static int cam_vfe_bus_stop_vfe_out(struct cam_isp_resource_node *vfe_out)
1410{
1411 int rc = 0, i;
1412 struct cam_vfe_bus_ver2_vfe_out_data *rsrc_data = vfe_out->res_priv;
1413
1414 if (vfe_out->res_state == CAM_ISP_RESOURCE_STATE_AVAILABLE ||
1415 vfe_out->res_state == CAM_ISP_RESOURCE_STATE_RESERVED) {
1416 return rc;
1417 }
1418
1419 if (rsrc_data->comp_grp)
1420 rc = cam_vfe_bus_stop_comp_grp(rsrc_data->comp_grp);
1421
1422 for (i = 0; i < rsrc_data->num_wm; i++)
1423 rc = cam_vfe_bus_stop_wm(rsrc_data->wm_res[i]);
1424
1425 vfe_out->res_state = CAM_ISP_RESOURCE_STATE_STREAMING;
1426
1427 vfe_out->res_state = CAM_ISP_RESOURCE_STATE_RESERVED;
1428 return rc;
1429}
1430
1431static int cam_vfe_bus_handle_vfe_out_done_top_half(uint32_t evt_id,
1432 struct cam_irq_th_payload *th_payload)
1433{
1434 return -EPERM;
1435}
1436
1437static int cam_vfe_bus_handle_vfe_out_done_bottom_half(
1438 void *handler_priv,
1439 void *evt_payload_priv)
1440{
1441 int rc = -EINVAL;
1442 struct cam_isp_resource_node *vfe_out = handler_priv;
1443 struct cam_vfe_bus_ver2_vfe_out_data *rsrc_data = vfe_out->res_priv;
1444
1445 /*
1446 * If this resource has Composite Group then we only handle
1447 * Composite done. We acquire Composite if number of WM > 1.
1448 * So Else case is only one individual buf_done = WM[0].
1449 */
1450 if (rsrc_data->comp_grp) {
1451 rc = rsrc_data->comp_grp->bottom_half_handler(
1452 rsrc_data->comp_grp, evt_payload_priv);
1453 } else {
1454 rc = rsrc_data->wm_res[0]->bottom_half_handler(
Harsh Shah23557ae2017-05-13 18:14:34 -07001455 rsrc_data->wm_res[0], evt_payload_priv);
Harsh Shaha1af8822017-05-11 22:06:36 -07001456 }
1457
1458 return rc;
1459}
1460
1461static int cam_vfe_bus_init_vfe_out_resource(uint32_t index,
1462 struct cam_vfe_bus_ver2_priv *ver2_bus_priv,
1463 struct cam_vfe_bus_ver2_hw_info *ver2_hw_info,
1464 struct cam_isp_resource_node *vfe_out)
1465{
1466 struct cam_vfe_bus_ver2_vfe_out_data *rsrc_data = NULL;
1467 int rc = 0;
1468
1469 rsrc_data = kzalloc(sizeof(struct cam_vfe_bus_ver2_vfe_out_data),
1470 GFP_KERNEL);
1471 if (!rsrc_data) {
1472 CDBG("Error! Failed to alloc for vfe out priv\n");
1473 rc = -ENOMEM;
1474 return rc;
1475 }
1476 vfe_out->res_priv = rsrc_data;
1477
1478 vfe_out->res_type = CAM_ISP_RESOURCE_VFE_OUT;
1479 vfe_out->res_state = CAM_ISP_RESOURCE_STATE_AVAILABLE;
1480 INIT_LIST_HEAD(&vfe_out->list);
1481
1482 rsrc_data->out_type = index;
1483 rsrc_data->common_data = &ver2_bus_priv->common_data;
1484 rsrc_data->max_width =
1485 ver2_hw_info->vfe_out_hw_info[index].max_width;
1486 rsrc_data->max_height =
1487 ver2_hw_info->vfe_out_hw_info[index].max_height;
1488
1489 vfe_out->start = cam_vfe_bus_start_vfe_out;
1490 vfe_out->stop = cam_vfe_bus_stop_vfe_out;
1491 vfe_out->top_half_handler = cam_vfe_bus_handle_vfe_out_done_top_half;
1492 vfe_out->bottom_half_handler =
1493 cam_vfe_bus_handle_vfe_out_done_bottom_half;
1494 vfe_out->hw_intf = ver2_bus_priv->common_data.hw_intf;
1495
1496 return 0;
1497}
1498
1499static int cam_vfe_bus_get_evt_payload(
1500 struct cam_vfe_bus_ver2_priv *bus_priv,
1501 struct cam_vfe_bus_irq_evt_payload **evt_payload)
1502{
1503 if (list_empty(&bus_priv->free_payload_list)) {
Harsh Shah23557ae2017-05-13 18:14:34 -07001504 *evt_payload = NULL;
Harsh Shaha1af8822017-05-11 22:06:36 -07001505 pr_err("No free payload\n");
1506 return -ENODEV;
1507 }
1508
1509 *evt_payload = list_first_entry(&bus_priv->free_payload_list,
1510 struct cam_vfe_bus_irq_evt_payload, list);
1511 list_del_init(&(*evt_payload)->list);
1512 return 0;
1513}
1514
1515static int cam_vfe_bus_put_evt_payload(void *core_info,
1516 struct cam_vfe_bus_irq_evt_payload **evt_payload)
1517{
1518 struct cam_vfe_bus_ver2_priv *bus_priv = NULL;
Harsh Shah23557ae2017-05-13 18:14:34 -07001519 uint32_t *cam_ife_irq_regs = (*evt_payload)->irq_reg_val;
1520 uint32_t status_reg0, status_reg1;
1521
1522 status_reg0 = cam_ife_irq_regs[CAM_IFE_IRQ_BUS_REG_STATUS0];
1523 status_reg1 = cam_ife_irq_regs[CAM_IFE_IRQ_BUS_REG_STATUS1];
1524
1525 if (status_reg0 || status_reg1) {
1526 CDBG("status0 0x%x status1 0x%x\n", status_reg0, status_reg1);
1527 return 0;
1528 }
Harsh Shaha1af8822017-05-11 22:06:36 -07001529
1530 if (!core_info) {
1531 pr_err("Invalid param core_info NULL");
1532 return -EINVAL;
1533 }
1534 if (*evt_payload == NULL) {
1535 pr_err("No payload to put\n");
1536 return -EINVAL;
1537 }
1538 bus_priv = (*evt_payload)->bus_priv;
1539 list_add_tail(&(*evt_payload)->list, &bus_priv->free_payload_list);
1540 *evt_payload = NULL;
1541 return 0;
1542}
1543
1544static int cam_vfe_bus_ver2_handle_irq(uint32_t evt_id,
1545 struct cam_irq_th_payload *th_payload)
1546{
1547 int32_t rc;
1548 int i;
1549 struct cam_vfe_irq_handler_priv *handler_priv;
1550 struct cam_vfe_hw_core_info *core_info;
1551 struct cam_vfe_bus_irq_evt_payload *evt_payload;
1552 struct cam_vfe_bus *bus_info;
1553 struct cam_vfe_bus_ver2_priv *bus_priv;
1554 struct cam_irq_controller_reg_info *reg_info;
Harsh Shah23557ae2017-05-13 18:14:34 -07001555 uint32_t irq_mask;
Harsh Shaha1af8822017-05-11 22:06:36 -07001556
1557 handler_priv = th_payload->handler_priv;
1558 core_info = handler_priv->core_info;
1559 bus_info = core_info->vfe_bus;
1560 bus_priv = bus_info->bus_priv;
1561 reg_info = &bus_priv->common_data.common_reg->irq_reg_info;
1562
1563 /*
1564 * add reset ack handling here once supported.
1565 * Just clear all the bus irq status registers and ignore the reset.
1566 */
1567
1568 CDBG("Enter\n");
1569 rc = cam_vfe_bus_get_evt_payload(bus_priv, &evt_payload);
1570 if (rc) {
1571 pr_err("No tasklet_cmd is free in queue\n");
1572 return rc;
1573 }
1574
1575 cam_isp_hw_get_timestamp(&evt_payload->ts);
1576
1577 evt_payload->core_index = handler_priv->core_index;
1578 evt_payload->core_info = handler_priv->core_info;
1579 evt_payload->bus_priv = bus_priv;
1580 CDBG("core_idx %d, core_info %llx\n", handler_priv->core_index,
1581 (uint64_t)handler_priv->core_info);
1582
1583 for (i = 0; i < CAM_IFE_BUS_IRQ_REGISTERS_MAX; i++) {
Harsh Shah23557ae2017-05-13 18:14:34 -07001584 irq_mask = cam_io_r(handler_priv->mem_base +
1585 irq_reg_offset[i] - (0xC * 2));
1586 evt_payload->irq_reg_val[i] = irq_mask &
1587 cam_io_r(handler_priv->mem_base + irq_reg_offset[i]);
Harsh Shaha1af8822017-05-11 22:06:36 -07001588 CDBG("irq_status%d = 0x%x\n", i, evt_payload->irq_reg_val[i]);
1589 }
1590 for (i = 0; i <= CAM_IFE_IRQ_BUS_REG_STATUS2; i++) {
1591 cam_io_w(evt_payload->irq_reg_val[i], handler_priv->mem_base +
1592 reg_info->irq_reg_set[i].clear_reg_offset);
1593 CDBG("Clear irq_status%d = 0x%x offset 0x%x\n", i,
1594 evt_payload->irq_reg_val[i],
1595 reg_info->irq_reg_set[i].clear_reg_offset);
1596 }
1597 cam_io_w(reg_info->global_clear_bitmask, handler_priv->mem_base +
1598 reg_info->global_clear_offset);
1599 CDBG("Global clear bitmask = 0x%x offset 0x%x\n",
1600 reg_info->global_clear_bitmask,
1601 reg_info->global_clear_offset);
1602
1603 th_payload->evt_payload_priv = evt_payload;
1604
1605 return rc;
1606}
1607
1608static int cam_vfe_bus_update_buf(void *priv, void *cmd_args,
1609 uint32_t arg_size)
1610{
1611 struct cam_vfe_bus_ver2_priv *bus_priv;
1612 struct cam_isp_hw_get_buf_update *update_buf;
1613 struct cam_vfe_bus_ver2_vfe_out_data *vfe_out_data = NULL;
1614 struct cam_vfe_bus_ver2_wm_resource_data *wm_data = NULL;
Harsh Shah23557ae2017-05-13 18:14:34 -07001615 uint32_t reg_val_pair[8];
Harsh Shaha1af8822017-05-11 22:06:36 -07001616 uint32_t i, size = 0;
1617
1618 /*
1619 * Need the entire buf io config so we can get the stride info
1620 * for the wm.
1621 */
1622
1623 bus_priv = (struct cam_vfe_bus_ver2_priv *) priv;
1624 update_buf = (struct cam_isp_hw_get_buf_update *) cmd_args;
1625
1626 vfe_out_data = (struct cam_vfe_bus_ver2_vfe_out_data *)
1627 update_buf->cdm.res->res_priv;
1628
1629 if (!vfe_out_data || !vfe_out_data->cdm_util_ops) {
1630 pr_err("Failed! Invalid data\n");
1631 return -EINVAL;
1632 }
1633
1634 if (update_buf->num_buf < vfe_out_data->num_wm) {
1635 pr_err("Failed! Invalid number buffers:%d required:%d\n",
1636 update_buf->num_buf, vfe_out_data->num_wm);
1637 return -ENOMEM;
1638 }
1639
1640 size = vfe_out_data->cdm_util_ops->cdm_required_size_reg_random(
1641 vfe_out_data->num_wm);
1642
1643 /* cdm util returns dwords, need to convert to bytes */
1644 if ((size * 4) > update_buf->cdm.size) {
1645 pr_err("Failed! Buf size:%d insufficient, expected size:%d\n",
1646 update_buf->cdm.size, size);
1647 return -ENOMEM;
1648 }
1649
1650 for (i = 0 ; i < vfe_out_data->num_wm; i++) {
1651 wm_data = vfe_out_data->wm_res[i]->res_priv;
1652 reg_val_pair[2 * i] = wm_data->hw_regs->image_addr;
1653 reg_val_pair[2 * i + 1] = update_buf->image_buf[i];
1654 CDBG("offset 0x%x, value 0x%llx\n",
1655 wm_data->hw_regs->image_addr,
1656 (uint64_t) update_buf->image_buf[i]);
1657 }
1658
1659 vfe_out_data->cdm_util_ops->cdm_write_regrandom(
1660 update_buf->cdm.cmd_buf_addr,
1661 vfe_out_data->num_wm, reg_val_pair);
1662 /* cdm util returns dwords, need to convert to bytes */
1663 update_buf->cdm.used_bytes = size * 4;
1664
1665 return 0;
1666}
1667
1668static int cam_vfe_bus_process_cmd(void *priv,
1669 uint32_t cmd_type, void *cmd_args, uint32_t arg_size)
1670{
1671 int rc = -EINVAL;
1672
1673 if (!priv || !cmd_args) {
1674 pr_err_ratelimited("Error! Invalid input arguments\n");
1675 return -EINVAL;
1676 }
1677
1678 switch (cmd_type) {
1679 case CAM_VFE_HW_CMD_GET_BUF_UPDATE:
1680 rc = cam_vfe_bus_update_buf(priv, cmd_args, arg_size);
1681 break;
1682 default:
1683 pr_err_ratelimited("Error! Invalid camif process command:%d\n",
1684 cmd_type);
1685 break;
1686 }
1687
1688 return rc;
1689}
1690
1691int cam_vfe_bus_ver2_init(
1692 void __iomem *mem_base,
1693 struct cam_hw_intf *hw_intf,
1694 void *bus_hw_info,
1695 void *vfe_irq_controller,
1696 struct cam_vfe_bus **vfe_bus)
1697{
1698 int i, rc = 0;
1699 struct cam_vfe_bus_ver2_priv *bus_priv = NULL;
1700 struct cam_vfe_bus *vfe_bus_local;
1701 struct cam_vfe_bus_ver2_hw_info *ver2_hw_info = bus_hw_info;
1702
1703 CDBG("Enter\n");
1704
1705 vfe_bus_local = kzalloc(sizeof(struct cam_vfe_bus), GFP_KERNEL);
1706 if (!vfe_bus_local) {
1707 CDBG("Failed to alloc for vfe_bus\n");
1708 rc = -ENOMEM;
1709 goto err_alloc_bus;
1710 }
1711
1712 bus_priv = kzalloc(sizeof(struct cam_vfe_bus_ver2_priv),
1713 GFP_KERNEL);
1714 if (!bus_priv) {
1715 CDBG("Failed to alloc for vfe_bus_priv\n");
1716 rc = -ENOMEM;
1717 goto err_alloc_priv;
1718 }
1719 vfe_bus_local->bus_priv = bus_priv;
1720
1721 bus_priv->common_data.mem_base = mem_base;
1722 bus_priv->common_data.hw_intf = hw_intf;
1723 bus_priv->common_data.vfe_irq_controller = vfe_irq_controller;
1724 bus_priv->common_data.common_reg = &ver2_hw_info->common_reg;
1725
1726 INIT_LIST_HEAD(&bus_priv->free_comp_grp);
1727 INIT_LIST_HEAD(&bus_priv->free_dual_comp_grp);
1728 INIT_LIST_HEAD(&bus_priv->used_comp_grp);
1729
1730 for (i = 0; i < CAM_VFE_BUS_VER2_MAX_CLIENTS; i++) {
1731 rc = cam_vfe_bus_init_wm_resource(i, bus_priv, bus_hw_info,
1732 &bus_priv->bus_client[i]);
1733 if (rc < 0) {
1734 pr_err("Error! Init WM failed\n");
1735 goto err_init_wm;
1736 }
1737 }
1738
1739 for (i = 0; i < CAM_VFE_BUS_VER2_COMP_GRP_MAX; i++) {
1740 rc = cam_vfe_bus_init_comp_grp(i, bus_priv, bus_hw_info,
1741 &bus_priv->comp_grp[i]);
1742 if (rc < 0) {
1743 pr_err("Error! Init Comp Grp failed\n");
1744 goto err_init_comp_grp;
1745 }
1746 }
1747
1748 for (i = 0; i < CAM_VFE_BUS_VER2_VFE_OUT_MAX; i++) {
1749 rc = cam_vfe_bus_init_vfe_out_resource(i, bus_priv, bus_hw_info,
1750 &bus_priv->vfe_out[i]);
1751 if (rc < 0) {
1752 pr_err("Error! Init VFE Out failed\n");
1753 goto err_init_vfe_out;
1754 }
1755 }
1756
1757 INIT_LIST_HEAD(&bus_priv->free_payload_list);
1758 for (i = 0; i < 128; i++) {
1759 INIT_LIST_HEAD(&bus_priv->evt_payload[i].list);
1760 list_add_tail(&bus_priv->evt_payload[i].list,
1761 &bus_priv->free_payload_list);
1762 }
1763
1764 vfe_bus_local->acquire_resource = cam_vfe_bus_acquire_vfe_out;
1765 vfe_bus_local->release_resource = cam_vfe_bus_release_vfe_out;
1766 vfe_bus_local->start_resource = cam_vfe_bus_start_vfe_out;
1767 vfe_bus_local->stop_resource = cam_vfe_bus_stop_vfe_out;
1768 vfe_bus_local->top_half_handler = cam_vfe_bus_ver2_handle_irq;
1769 vfe_bus_local->bottom_half_handler = NULL;
1770 vfe_bus_local->process_cmd = cam_vfe_bus_process_cmd;
1771
1772 *vfe_bus = vfe_bus_local;
1773
1774 return rc;
1775
1776err_init_vfe_out:
1777err_init_comp_grp:
1778err_init_wm:
1779 kfree(vfe_bus_local->bus_priv);
1780err_alloc_priv:
1781 kfree(vfe_bus_local);
1782err_alloc_bus:
1783 return rc;
1784}