blob: 9203ee6ed1d90f8aae2f8b73a7c3387c05e8b8e4 [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
Junzhe Zou193d78c2017-05-16 15:10:54 -070031#define MAX_BUF_UPDATE_REG_NUM \
32 (sizeof(struct cam_vfe_bus_ver2_reg_offset_bus_client)/4)
Jing Zhoua4e9fbe2017-05-15 14:37:21 -070033#define MAX_REG_VAL_PAIR_SIZE \
34 (MAX_BUF_UPDATE_REG_NUM * 2 * CAM_PACKET_MAX_PLANES)
35
36#define CAM_VFE_ADD_REG_VAL_PAIR(buf_array, index, offset, val) \
37 do { \
38 buf_array[index++] = offset; \
39 buf_array[index++] = val; \
40 } while (0)
41
Harsh Shaha1af8822017-05-11 22:06:36 -070042static uint32_t irq_reg_offset[CAM_IFE_BUS_IRQ_REGISTERS_MAX] = {
43 0x0000205C,
44 0x00002060,
45 0x00002064,
46 0x0000206C,
47 0x00002070,
48 0x00002074,
49 0x00002078,
50};
51
52enum cam_vfe_bus_packer_format {
53 PACKER_FMT_PLAIN_128 = 0x0,
54 PACKER_FMT_PLAIN_8 = 0x1,
55 PACKER_FMT_PLAIN_16_10BPP = 0x2,
56 PACKER_FMT_PLAIN_16_12BPP = 0x3,
57 PACKER_FMT_PLAIN_16_14BPP = 0x4,
58 PACKER_FMT_PLAIN_16_16BPP = 0x5,
59 PACKER_FMT_ARGB_10 = 0x6,
60 PACKER_FMT_ARGB_12 = 0x7,
61 PACKER_FMT_ARGB_14 = 0x8,
62 PACKER_FMT_PLAIN_32_20BPP = 0x9,
63 PACKER_FMT_PLAIN_64 = 0xA,
64 PACKER_FMT_TP_10 = 0xB,
65 PACKER_FMT_PLAIN_32_32BPP = 0xC,
66 PACKER_FMT_PLAIN_8_ODD_EVEN = 0xD,
67 PACKER_FMT_PLAIN_8_LSB_MSB_10 = 0xE,
68 PACKER_FMT_PLAIN_8_LSB_MSB_10_ODD_EVEN = 0xF,
69 PACKER_FMT_MAX = 0xF,
70};
71
72struct cam_vfe_bus_ver2_common_data {
73 void __iomem *mem_base;
74 struct cam_hw_intf *hw_intf;
75 void *bus_irq_controller;
76 void *vfe_irq_controller;
77 struct cam_vfe_bus_ver2_reg_offset_common *common_reg;
Jing Zhoua4e9fbe2017-05-15 14:37:21 -070078 uint32_t io_buf_update[
79 MAX_REG_VAL_PAIR_SIZE];
Harsh Shaha1af8822017-05-11 22:06:36 -070080};
81
82struct cam_vfe_bus_ver2_wm_resource_data {
83 uint32_t index;
84 struct cam_vfe_bus_ver2_common_data *common_data;
85 struct cam_vfe_bus_ver2_reg_offset_bus_client *hw_regs;
86
87 uint32_t irq_enabled;
88
Jing Zhoua4e9fbe2017-05-15 14:37:21 -070089 uint32_t init_cfg_done;
Harsh Shaha1af8822017-05-11 22:06:36 -070090 uint32_t offset;
91 uint32_t width;
92 uint32_t height;
93 uint32_t stride;
94 uint32_t format;
95 enum cam_vfe_bus_packer_format pack_fmt;
96
97 uint32_t burst_len;
98 uint32_t frame_based;
99
Jing Zhoua4e9fbe2017-05-15 14:37:21 -0700100 uint32_t en_ubwc;
101 uint32_t packer_cfg;
102 uint32_t tile_cfg;
103 uint32_t h_init;
104 uint32_t v_init;
105 uint32_t ubwc_meta_stride;
106 uint32_t ubwc_mode_cfg;
107 uint32_t ubwc_meta_offset;
108
Harsh Shaha1af8822017-05-11 22:06:36 -0700109 uint32_t irq_subsample_period;
110 uint32_t irq_subsample_pattern;
111 uint32_t framedrop_period;
112 uint32_t framedrop_pattern;
Jing Zhoua4e9fbe2017-05-15 14:37:21 -0700113
114 uint32_t en_cfg;
Harsh Shaha1af8822017-05-11 22:06:36 -0700115};
116
117struct cam_vfe_bus_ver2_comp_grp_data {
118 enum cam_vfe_bus_ver2_comp_grp_type comp_grp_type;
119 struct cam_vfe_bus_ver2_common_data *common_data;
120 struct cam_vfe_bus_ver2_reg_offset_comp_grp *hw_regs;
121
122 uint32_t irq_enabled;
123 uint32_t comp_grp_local_idx;
124 uint32_t unique_id;
125
126 uint32_t is_master;
127 uint32_t dual_slave_core;
128 uint32_t intra_client_mask;
129 uint32_t composite_mask;
130};
131
132struct cam_vfe_bus_ver2_vfe_out_data {
133 uint32_t out_type;
134 struct cam_vfe_bus_ver2_common_data *common_data;
135
136 uint32_t num_wm;
137 struct cam_isp_resource_node *wm_res[PLANE_MAX];
138
139 struct cam_isp_resource_node *comp_grp;
140 enum cam_isp_hw_sync_mode dual_comp_sync_mode;
141 uint32_t dual_hw_alternate_vfe_id;
142 struct list_head vfe_out_list;
143
144 uint32_t format;
145 uint32_t max_width;
146 uint32_t max_height;
147 struct cam_cdm_utils_ops *cdm_util_ops;
148};
149
150
151struct cam_vfe_bus_ver2_priv {
152 struct cam_vfe_bus_ver2_common_data common_data;
153
154 struct cam_isp_resource_node bus_client[CAM_VFE_BUS_VER2_MAX_CLIENTS];
155 struct cam_isp_resource_node comp_grp[CAM_VFE_BUS_VER2_COMP_GRP_MAX];
156 struct cam_isp_resource_node vfe_out[CAM_VFE_BUS_VER2_VFE_OUT_MAX];
157
158 struct list_head free_comp_grp;
159 struct list_head free_dual_comp_grp;
160 struct list_head used_comp_grp;
161
162 struct cam_vfe_bus_irq_evt_payload evt_payload[128];
163 struct list_head free_payload_list;
164};
165
166static int cam_vfe_bus_put_evt_payload(void *core_info,
167 struct cam_vfe_bus_irq_evt_payload **evt_payload);
168
169static int cam_vfe_bus_ver2_get_intra_client_mask(
170 enum cam_vfe_bus_ver2_vfe_core_id dual_slave_core,
171 enum cam_vfe_bus_ver2_vfe_core_id current_core,
172 uint32_t *intra_client_mask)
173{
174 int rc = 0;
175
176 *intra_client_mask = 0;
177
178 if (dual_slave_core == current_core) {
179 pr_err("Invalid params. Same core as Master and Slave\n");
180 return -EINVAL;
181 }
182
183 switch (current_core) {
184 case CAM_VFE_BUS_VER2_VFE_CORE_0:
185 switch (dual_slave_core) {
186 case CAM_VFE_BUS_VER2_VFE_CORE_1:
187 *intra_client_mask = 0x1;
188 break;
189 case CAM_VFE_BUS_VER2_VFE_CORE_2:
190 *intra_client_mask = 0x2;
191 break;
192 default:
193 pr_err("Invalid value for slave core %u\n",
194 dual_slave_core);
195 rc = -EINVAL;
196 break;
197 }
198 break;
199 case CAM_VFE_BUS_VER2_VFE_CORE_1:
200 switch (dual_slave_core) {
201 case CAM_VFE_BUS_VER2_VFE_CORE_0:
202 *intra_client_mask = 0x1;
203 break;
204 case CAM_VFE_BUS_VER2_VFE_CORE_2:
205 *intra_client_mask = 0x2;
206 break;
207 default:
208 pr_err("Invalid value for slave core %u\n",
209 dual_slave_core);
210 rc = -EINVAL;
211 break;
212 }
213 break;
214 case CAM_VFE_BUS_VER2_VFE_CORE_2:
215 switch (dual_slave_core) {
216 case CAM_VFE_BUS_VER2_VFE_CORE_0:
217 *intra_client_mask = 0x1;
218 break;
219 case CAM_VFE_BUS_VER2_VFE_CORE_1:
220 *intra_client_mask = 0x2;
221 break;
222 default:
223 pr_err("Invalid value for slave core %u\n",
224 dual_slave_core);
225 rc = -EINVAL;
226 break;
227 }
228 break;
229 default:
230 pr_err("Invalid value for master core %u\n", current_core);
231 rc = -EINVAL;
232 break;
233 }
234
235 return rc;
236}
237
238static enum cam_vfe_bus_ver2_vfe_out_type
239 cam_vfe_bus_get_out_res_id(uint32_t res_type)
240{
241 switch (res_type) {
242 case CAM_ISP_IFE_OUT_RES_FULL:
243 return CAM_VFE_BUS_VER2_VFE_OUT_FULL;
244 case CAM_ISP_IFE_OUT_RES_DS4:
245 return CAM_VFE_BUS_VER2_VFE_OUT_DS4;
246 case CAM_ISP_IFE_OUT_RES_DS16:
247 return CAM_VFE_BUS_VER2_VFE_OUT_DS16;
248 case CAM_ISP_IFE_OUT_RES_FD:
249 return CAM_VFE_BUS_VER2_VFE_OUT_FD;
250 case CAM_ISP_IFE_OUT_RES_RAW_DUMP:
251 return CAM_VFE_BUS_VER2_VFE_OUT_RAW_DUMP;
252 case CAM_ISP_IFE_OUT_RES_PDAF:
253 return CAM_VFE_BUS_VER2_VFE_OUT_PDAF;
254 case CAM_ISP_IFE_OUT_RES_RDI_0:
255 return CAM_VFE_BUS_VER2_VFE_OUT_RDI0;
256 case CAM_ISP_IFE_OUT_RES_RDI_1:
257 return CAM_VFE_BUS_VER2_VFE_OUT_RDI1;
258 case CAM_ISP_IFE_OUT_RES_RDI_2:
259 return CAM_VFE_BUS_VER2_VFE_OUT_RDI2;
260 case CAM_ISP_IFE_OUT_RES_STATS_HDR_BE:
261 return CAM_VFE_BUS_VER2_VFE_OUT_STATS_HDR_BE;
262 case CAM_ISP_IFE_OUT_RES_STATS_HDR_BHIST:
263 return CAM_VFE_BUS_VER2_VFE_OUT_STATS_HDR_BHIST;
264 case CAM_ISP_IFE_OUT_RES_STATS_TL_BG:
265 return CAM_VFE_BUS_VER2_VFE_OUT_STATS_TL_BG;
266 case CAM_ISP_IFE_OUT_RES_STATS_BF:
267 return CAM_VFE_BUS_VER2_VFE_OUT_STATS_BF;
268 case CAM_ISP_IFE_OUT_RES_STATS_AWB_BG:
269 return CAM_VFE_BUS_VER2_VFE_OUT_STATS_AWB_BG;
270 case CAM_ISP_IFE_OUT_RES_STATS_BHIST:
271 return CAM_VFE_BUS_VER2_VFE_OUT_STATS_BHIST;
272 case CAM_ISP_IFE_OUT_RES_STATS_RS:
273 return CAM_VFE_BUS_VER2_VFE_OUT_STATS_RS;
274 case CAM_ISP_IFE_OUT_RES_STATS_CS:
275 return CAM_VFE_BUS_VER2_VFE_OUT_STATS_CS;
276 case CAM_ISP_IFE_OUT_RES_STATS_IHIST:
277 return CAM_VFE_BUS_VER2_VFE_OUT_STATS_IHIST;
278 default:
279 return CAM_VFE_BUS_VER2_VFE_OUT_MAX;
280 }
281}
282
283static int cam_vfe_bus_get_num_wm(
284 enum cam_vfe_bus_ver2_vfe_out_type res_type,
285 uint32_t format)
286{
287 switch (res_type) {
288 case CAM_VFE_BUS_VER2_VFE_OUT_RDI0:
289 case CAM_VFE_BUS_VER2_VFE_OUT_RDI1:
290 case CAM_VFE_BUS_VER2_VFE_OUT_RDI2:
291 switch (format) {
292 case CAM_FORMAT_MIPI_RAW_8:
293 case CAM_FORMAT_MIPI_RAW_10:
294 case CAM_FORMAT_MIPI_RAW_12:
295 case CAM_FORMAT_MIPI_RAW_14:
296 case CAM_FORMAT_MIPI_RAW_16:
297 case CAM_FORMAT_MIPI_RAW_20:
298 case CAM_FORMAT_PLAIN128:
299 return 1;
300 default:
301 break;
302 }
303 break;
304 case CAM_VFE_BUS_VER2_VFE_OUT_FULL:
305 switch (format) {
306 case CAM_FORMAT_NV21:
307 case CAM_FORMAT_NV12:
308 case CAM_FORMAT_MIPI_RAW_8:
309 case CAM_FORMAT_PLAIN8:
310 case CAM_FORMAT_TP10:
311 case CAM_FORMAT_UBWC_NV12:
312 case CAM_FORMAT_UBWC_NV12_4R:
313 case CAM_FORMAT_UBWC_TP10:
314 case CAM_FORMAT_UBWC_P010:
315 return 2;
316 default:
317 break;
318 }
319 break;
320 case CAM_VFE_BUS_VER2_VFE_OUT_FD:
321 switch (format) {
322 case CAM_FORMAT_NV21:
323 case CAM_FORMAT_NV12:
324 case CAM_FORMAT_PLAIN8:
325 case CAM_FORMAT_TP10:
326 case CAM_FORMAT_PLAIN16_10:
327 return 2;
328 default:
329 break;
330 }
331 break;
332 case CAM_VFE_BUS_VER2_VFE_OUT_DS4:
333 case CAM_VFE_BUS_VER2_VFE_OUT_DS16:
334 switch (format) {
335 case CAM_FORMAT_PD8:
336 case CAM_FORMAT_PD10:
337 return 1;
338 default:
339 break;
340 }
341 break;
342 case CAM_VFE_BUS_VER2_VFE_OUT_RAW_DUMP:
343 switch (format) {
344 case CAM_FORMAT_ARGB_14:
345 case CAM_FORMAT_PLAIN8:
346 case CAM_FORMAT_PLAIN16_10:
347 case CAM_FORMAT_PLAIN16_12:
348 case CAM_FORMAT_PLAIN16_14:
349 return 1;
350 default:
351 break;
352 }
353 break;
354 case CAM_VFE_BUS_VER2_VFE_OUT_PDAF:
355 switch (format) {
356 case CAM_FORMAT_PLAIN8:
357 case CAM_FORMAT_PLAIN16_10:
358 case CAM_FORMAT_PLAIN16_12:
359 case CAM_FORMAT_PLAIN16_14:
360 return 1;
361 default:
362 break;
363 }
364 break;
365 case CAM_VFE_BUS_VER2_VFE_OUT_STATS_HDR_BE:
366 case CAM_VFE_BUS_VER2_VFE_OUT_STATS_HDR_BHIST:
367 case CAM_VFE_BUS_VER2_VFE_OUT_STATS_TL_BG:
368 case CAM_VFE_BUS_VER2_VFE_OUT_STATS_BF:
369 case CAM_VFE_BUS_VER2_VFE_OUT_STATS_AWB_BG:
370 case CAM_VFE_BUS_VER2_VFE_OUT_STATS_BHIST:
371 case CAM_VFE_BUS_VER2_VFE_OUT_STATS_CS:
372 switch (format) {
373 case CAM_FORMAT_PLAIN64:
Abhishek Kondaveetib31b46c2017-06-23 04:56:24 +0530374 case CAM_FORMAT_PLAIN128:
Harsh Shaha1af8822017-05-11 22:06:36 -0700375 return 1;
376 default:
377 break;
378 }
379 break;
380 case CAM_VFE_BUS_VER2_VFE_OUT_STATS_RS:
381 case CAM_VFE_BUS_VER2_VFE_OUT_STATS_IHIST:
382 switch (format) {
383 case CAM_FORMAT_PLAIN16_16:
384 return 1;
385 default:
386 break;
387 }
388 break;
389 default:
390 break;
391 }
392
393 pr_err("Unsupported format %u for resource_type %u", format, res_type);
394
395 return -EINVAL;
396}
397
398static int cam_vfe_bus_get_wm_idx(
399 enum cam_vfe_bus_ver2_vfe_out_type vfe_out_res_id,
400 enum cam_vfe_bus_plane_type plane)
401{
402 int wm_idx = -1;
403
404 switch (vfe_out_res_id) {
405 case CAM_VFE_BUS_VER2_VFE_OUT_FULL:
406 switch (plane) {
407 case PLANE_Y:
408 wm_idx = 3;
409 break;
410 case PLANE_C:
411 wm_idx = 4;
412 break;
413 default:
414 break;
415 }
416 break;
417 case CAM_VFE_BUS_VER2_VFE_OUT_DS4:
418 switch (plane) {
419 case PLANE_Y:
420 wm_idx = 5;
421 break;
422 default:
423 break;
424 }
425 break;
426 case CAM_VFE_BUS_VER2_VFE_OUT_DS16:
427 switch (plane) {
428 case PLANE_Y:
429 wm_idx = 6;
430 break;
431 default:
432 break;
433 }
434 break;
435 case CAM_VFE_BUS_VER2_VFE_OUT_FD:
436 switch (plane) {
437 case PLANE_Y:
438 wm_idx = 7;
439 break;
440 case PLANE_C:
441 wm_idx = 8;
442 break;
443 default:
444 break;
445 }
446 break;
447 case CAM_VFE_BUS_VER2_VFE_OUT_RAW_DUMP:
448 switch (plane) {
449 case PLANE_Y:
450 wm_idx = 9;
451 break;
452 default:
453 break;
454 }
455 break;
456 case CAM_VFE_BUS_VER2_VFE_OUT_PDAF:
457 switch (plane) {
458 case PLANE_Y:
459 wm_idx = 10;
460 break;
461 default:
462 break;
463 }
464 break;
465 case CAM_VFE_BUS_VER2_VFE_OUT_RDI0:
466 switch (plane) {
467 case PLANE_Y:
468 wm_idx = 0;
469 break;
470 default:
471 break;
472 }
473 break;
474 case CAM_VFE_BUS_VER2_VFE_OUT_RDI1:
475 switch (plane) {
476 case PLANE_Y:
477 wm_idx = 1;
478 break;
479 default:
480 break;
481 }
482 break;
483 case CAM_VFE_BUS_VER2_VFE_OUT_RDI2:
484 switch (plane) {
485 case PLANE_Y:
486 wm_idx = 2;
487 break;
488 default:
489 break;
490 }
491 break;
492 case CAM_VFE_BUS_VER2_VFE_OUT_STATS_HDR_BE:
493 switch (plane) {
494 case PLANE_Y:
495 wm_idx = 11;
496 break;
497 default:
498 break;
499 }
500 break;
501 case CAM_VFE_BUS_VER2_VFE_OUT_STATS_HDR_BHIST:
502 switch (plane) {
503 case PLANE_Y:
504 wm_idx = 12;
505 break;
506 default:
507 break;
508 }
509 break;
510 case CAM_VFE_BUS_VER2_VFE_OUT_STATS_TL_BG:
511 switch (plane) {
512 case PLANE_Y:
513 wm_idx = 13;
514 break;
515 default:
516 break;
517 }
518 break;
519 case CAM_VFE_BUS_VER2_VFE_OUT_STATS_BF:
520 switch (plane) {
521 case PLANE_Y:
522 wm_idx = 14;
523 break;
524 default:
525 break;
526 }
527 break;
528 case CAM_VFE_BUS_VER2_VFE_OUT_STATS_AWB_BG:
529 switch (plane) {
530 case PLANE_Y:
531 wm_idx = 15;
532 break;
533 default:
534 break;
535 }
536 break;
537 case CAM_VFE_BUS_VER2_VFE_OUT_STATS_BHIST:
538 switch (plane) {
539 case PLANE_Y:
540 wm_idx = 16;
541 break;
542 default:
543 break;
544 }
545 break;
546 case CAM_VFE_BUS_VER2_VFE_OUT_STATS_RS:
547 switch (plane) {
548 case PLANE_Y:
549 wm_idx = 17;
550 break;
551 default:
552 break;
553 }
554 break;
555 case CAM_VFE_BUS_VER2_VFE_OUT_STATS_CS:
556 switch (plane) {
557 case PLANE_Y:
558 wm_idx = 18;
559 break;
560 default:
561 break;
562 }
563 break;
564 case CAM_VFE_BUS_VER2_VFE_OUT_STATS_IHIST:
565 switch (plane) {
566 case PLANE_Y:
567 wm_idx = 19;
568 break;
569 default:
570 break;
571 }
572 break;
573 default:
574 break;
575 }
576
577 return wm_idx;
578}
579
580static enum cam_vfe_bus_packer_format
581 cam_vfe_bus_get_packer_fmt(uint32_t out_fmt)
582{
583 switch (out_fmt) {
584 case CAM_FORMAT_NV21:
585 case CAM_FORMAT_NV12:
586 return PACKER_FMT_PLAIN_8;
587 default:
588 return PACKER_FMT_MAX;
589 }
590}
591
592static int cam_vfe_bus_acquire_wm(
593 struct cam_vfe_bus_ver2_priv *ver2_bus_priv,
594 struct cam_isp_out_port_info *out_port_info,
595 enum cam_vfe_bus_ver2_vfe_out_type vfe_out_res_id,
596 enum cam_vfe_bus_plane_type plane,
597 enum cam_isp_hw_split_id split_id,
598 uint32_t subscribe_irq,
599 struct cam_isp_resource_node **wm_res,
600 uint32_t *client_done_mask)
601{
602 uint32_t wm_idx = 0;
603 struct cam_isp_resource_node *wm_res_local = NULL;
604 struct cam_vfe_bus_ver2_wm_resource_data *rsrc_data = NULL;
605
606 *wm_res = NULL;
607 *client_done_mask = 0;
608
609 /* No need to allocate for BUS VER2. VFE OUT to WM is fixed. */
610 wm_idx = cam_vfe_bus_get_wm_idx(vfe_out_res_id, plane);
611 if (wm_idx < 0 || wm_idx >= CAM_VFE_BUS_VER2_MAX_CLIENTS) {
612 pr_err("Unsupported VFE out %d plane %d\n",
613 vfe_out_res_id, plane);
614 return -EINVAL;
615 }
616
617 wm_res_local = &ver2_bus_priv->bus_client[wm_idx];
618 wm_res_local->res_state = CAM_ISP_RESOURCE_STATE_RESERVED;
619
620 rsrc_data = wm_res_local->res_priv;
621 rsrc_data->irq_enabled = subscribe_irq;
622 rsrc_data->format = out_port_info->format;
623 rsrc_data->pack_fmt = cam_vfe_bus_get_packer_fmt(rsrc_data->format);
624
625 rsrc_data->width = out_port_info->width;
626 rsrc_data->height = out_port_info->height;
Jing Zhoua4e9fbe2017-05-15 14:37:21 -0700627
628 if (rsrc_data->index < 3) {
629 rsrc_data->width = rsrc_data->width * 5/4 * rsrc_data->height;
630 rsrc_data->height = 1;
631 rsrc_data->pack_fmt = 0x0;
632 rsrc_data->en_cfg = 0x3;
Abhishek Kondaveetib31b46c2017-06-23 04:56:24 +0530633 } else if (rsrc_data->index < 5 ||
634 rsrc_data->index == 7 || rsrc_data->index == 8) {
Jing Zhoua4e9fbe2017-05-15 14:37:21 -0700635 switch (plane) {
636 case PLANE_Y:
637 switch (rsrc_data->format) {
638 case CAM_FORMAT_UBWC_NV12:
639 case CAM_FORMAT_UBWC_NV12_4R:
640 case CAM_FORMAT_UBWC_TP10:
641 rsrc_data->en_ubwc = 1;
642 break;
643 default:
644 break;
645 }
646 break;
647 case PLANE_C:
648 switch (rsrc_data->format) {
649 case CAM_FORMAT_NV21:
650 case CAM_FORMAT_NV12:
651 rsrc_data->height /= 2;
652 break;
653 case CAM_FORMAT_UBWC_NV12:
654 case CAM_FORMAT_UBWC_NV12_4R:
655 case CAM_FORMAT_UBWC_TP10:
656 rsrc_data->height /= 2;
657 rsrc_data->en_ubwc = 1;
658 break;
659 default:
660 break;
661 }
Harsh Shaha1af8822017-05-11 22:06:36 -0700662 break;
663 default:
Jing Zhoua4e9fbe2017-05-15 14:37:21 -0700664 pr_err("Invalid plane type %d\n", plane);
665 return -EINVAL;
Harsh Shaha1af8822017-05-11 22:06:36 -0700666 }
Jing Zhoua4e9fbe2017-05-15 14:37:21 -0700667 rsrc_data->pack_fmt = 0xE;
668 rsrc_data->en_cfg = 0x1;
Abhishek Kondaveetib31b46c2017-06-23 04:56:24 +0530669 } else if (rsrc_data->index >= 11) {
670 rsrc_data->width = 0;
671 rsrc_data->height = 0;
672 rsrc_data->pack_fmt = 0x0;
673 rsrc_data->stride = 1;
674 rsrc_data->en_cfg = 0x3;
Jing Zhoua4e9fbe2017-05-15 14:37:21 -0700675 } else {
676 rsrc_data->width = rsrc_data->width * 4;
677 rsrc_data->height = rsrc_data->height / 2;
678 rsrc_data->pack_fmt = 0x0;
679 rsrc_data->en_cfg = 0x1;
Harsh Shaha1af8822017-05-11 22:06:36 -0700680 }
681
682 if (vfe_out_res_id >= CAM_ISP_IFE_OUT_RES_RDI_0 &&
683 vfe_out_res_id <= CAM_ISP_IFE_OUT_RES_RDI_3)
684 rsrc_data->frame_based = 1;
685
686 *client_done_mask = (1 << wm_idx);
687 *wm_res = wm_res_local;
688
689 return 0;
690}
691
692static int cam_vfe_bus_release_wm(void *bus_priv,
693 struct cam_isp_resource_node *wm_res)
694{
695 struct cam_vfe_bus_ver2_wm_resource_data *rsrc_data =
696 wm_res->res_priv;
697
698 rsrc_data->irq_enabled = 0;
699 rsrc_data->offset = 0;
700 rsrc_data->width = 0;
701 rsrc_data->height = 0;
702 rsrc_data->stride = 0;
703 rsrc_data->format = 0;
704 rsrc_data->pack_fmt = 0;
705 rsrc_data->burst_len = 0;
706 rsrc_data->frame_based = 0;
707 rsrc_data->irq_subsample_period = 0;
708 rsrc_data->irq_subsample_pattern = 0;
709 rsrc_data->framedrop_period = 0;
710 rsrc_data->framedrop_pattern = 0;
Jing Zhoua4e9fbe2017-05-15 14:37:21 -0700711 rsrc_data->packer_cfg = 0;
712 rsrc_data->en_ubwc = 0;
713 rsrc_data->tile_cfg = 0;
714 rsrc_data->h_init = 0;
715 rsrc_data->v_init = 0;
716 rsrc_data->ubwc_meta_stride = 0;
717 rsrc_data->ubwc_mode_cfg = 0;
718 rsrc_data->ubwc_meta_offset = 0;
719 rsrc_data->init_cfg_done = 0;
720 rsrc_data->en_cfg = 0;
Harsh Shaha1af8822017-05-11 22:06:36 -0700721 wm_res->res_state = CAM_ISP_RESOURCE_STATE_AVAILABLE;
722
723 return 0;
724}
725
726static int cam_vfe_bus_start_wm(struct cam_isp_resource_node *wm_res)
727{
728 int rc = 0;
729 struct cam_vfe_bus_ver2_wm_resource_data *rsrc_data =
730 wm_res->res_priv;
731 struct cam_vfe_bus_ver2_common_data *common_data =
732 rsrc_data->common_data;
Harsh Shaha1af8822017-05-11 22:06:36 -0700733
Harsh Shah23557ae2017-05-13 18:14:34 -0700734 cam_io_w_mb(0, common_data->mem_base + rsrc_data->hw_regs->header_addr);
735 cam_io_w_mb(0, common_data->mem_base + rsrc_data->hw_regs->header_cfg);
736 cam_io_w_mb(0, common_data->mem_base + rsrc_data->hw_regs->frame_inc);
737 cam_io_w(0xf, common_data->mem_base + rsrc_data->hw_regs->burst_limit);
738
Jing Zhoua4e9fbe2017-05-15 14:37:21 -0700739 cam_io_w_mb(rsrc_data->width,
Harsh Shaha1af8822017-05-11 22:06:36 -0700740 common_data->mem_base + rsrc_data->hw_regs->buffer_width_cfg);
Jing Zhoua4e9fbe2017-05-15 14:37:21 -0700741 cam_io_w(rsrc_data->height,
Harsh Shaha1af8822017-05-11 22:06:36 -0700742 common_data->mem_base + rsrc_data->hw_regs->buffer_height_cfg);
Jing Zhoua4e9fbe2017-05-15 14:37:21 -0700743 cam_io_w(rsrc_data->pack_fmt,
Harsh Shaha1af8822017-05-11 22:06:36 -0700744 common_data->mem_base + rsrc_data->hw_regs->packer_cfg);
Harsh Shaha1af8822017-05-11 22:06:36 -0700745
746 cam_io_w(0xFFFFFFFF, common_data->mem_base +
747 rsrc_data->hw_regs->irq_subsample_pattern);
748 cam_io_w(0x0, common_data->mem_base +
749 rsrc_data->hw_regs->irq_subsample_period);
750
751 cam_io_w(0xFFFFFFFF,
Harsh Shah23557ae2017-05-13 18:14:34 -0700752 common_data->mem_base + rsrc_data->hw_regs->framedrop_pattern);
Harsh Shaha1af8822017-05-11 22:06:36 -0700753 cam_io_w(0x0,
Harsh Shah23557ae2017-05-13 18:14:34 -0700754 common_data->mem_base + rsrc_data->hw_regs->framedrop_period);
Harsh Shaha1af8822017-05-11 22:06:36 -0700755
Harsh Shah23557ae2017-05-13 18:14:34 -0700756 CDBG("WM res %d width = %d, height = %d\n", rsrc_data->index,
Jing Zhoua4e9fbe2017-05-15 14:37:21 -0700757 rsrc_data->width, rsrc_data->height);
Harsh Shah23557ae2017-05-13 18:14:34 -0700758 CDBG("WM res %d pk_fmt = %d\n", rsrc_data->index,
Jing Zhoua4e9fbe2017-05-15 14:37:21 -0700759 rsrc_data->pack_fmt & PACKER_FMT_MAX);
Harsh Shah23557ae2017-05-13 18:14:34 -0700760 CDBG("WM res %d stride = %d, burst len = %d\n",
Jing Zhoua4e9fbe2017-05-15 14:37:21 -0700761 rsrc_data->index, rsrc_data->stride, 0xf);
Harsh Shah23557ae2017-05-13 18:14:34 -0700762 CDBG("enable WM res %d offset 0x%x val 0x%x\n", rsrc_data->index,
Jing Zhoua4e9fbe2017-05-15 14:37:21 -0700763 (uint32_t) rsrc_data->hw_regs->cfg, rsrc_data->en_cfg);
Harsh Shaha1af8822017-05-11 22:06:36 -0700764
765 wm_res->res_state = CAM_ISP_RESOURCE_STATE_STREAMING;
766
767 return rc;
768}
769
770static int cam_vfe_bus_stop_wm(struct cam_isp_resource_node *wm_res)
771{
772 int rc = 0;
773 struct cam_vfe_bus_ver2_wm_resource_data *rsrc_data =
774 wm_res->res_priv;
775 struct cam_vfe_bus_ver2_common_data *common_data =
776 rsrc_data->common_data;
777
778 /* Disble WM */
779 cam_io_w_mb(0x0,
780 common_data->mem_base + rsrc_data->hw_regs->cfg);
781
782 CDBG("irq_enabled %d", rsrc_data->irq_enabled);
783 /* Unsubscribe IRQ */
784 if (rsrc_data->irq_enabled) {
785 /*
786 * Currently all WM IRQ are unsubscribed in one place. Need to
787 * make it dynamic.
788 */
789 }
790
791 /* Halt & Reset WM */
792 cam_io_w_mb(BIT(rsrc_data->index),
793 common_data->mem_base + common_data->common_reg->sw_reset);
794
795 wm_res->res_state = CAM_ISP_RESOURCE_STATE_RESERVED;
796
797 return rc;
798}
799
800static int cam_vfe_bus_handle_wm_done_top_half(uint32_t evt_id,
801 struct cam_irq_th_payload *th_payload)
802{
803 return -EPERM;
804}
805
806static int cam_vfe_bus_handle_wm_done_bottom_half(void *wm_node,
807 void *evt_payload_priv)
808{
809 int rc = CAM_VFE_IRQ_STATUS_ERR;
810 struct cam_isp_resource_node *wm_res = wm_node;
811 struct cam_vfe_bus_irq_evt_payload *evt_payload = evt_payload_priv;
Harsh Shah23557ae2017-05-13 18:14:34 -0700812 struct cam_vfe_bus_ver2_wm_resource_data *rsrc_data =
813 (wm_res == NULL) ? NULL : wm_res->res_priv;
814 uint32_t *cam_ife_irq_regs;
Harsh Shaha1af8822017-05-11 22:06:36 -0700815 uint32_t status_reg;
816
Harsh Shah23557ae2017-05-13 18:14:34 -0700817 if (!evt_payload || !rsrc_data)
818 return rc;
Harsh Shaha1af8822017-05-11 22:06:36 -0700819
Harsh Shah23557ae2017-05-13 18:14:34 -0700820 cam_ife_irq_regs = evt_payload->irq_reg_val;
821 status_reg = cam_ife_irq_regs[CAM_IFE_IRQ_BUS_REG_STATUS1];
822
823 if (status_reg & BIT(rsrc_data->index)) {
824 cam_ife_irq_regs[CAM_IFE_IRQ_BUS_REG_STATUS1] &=
825 ~BIT(rsrc_data->index);
Harsh Shaha1af8822017-05-11 22:06:36 -0700826 rc = CAM_VFE_IRQ_STATUS_SUCCESS;
Harsh Shah23557ae2017-05-13 18:14:34 -0700827 }
Harsh Shaha1af8822017-05-11 22:06:36 -0700828
829 if (rc == CAM_VFE_IRQ_STATUS_SUCCESS)
830 cam_vfe_bus_put_evt_payload(evt_payload->core_info,
831 &evt_payload);
832
833 return rc;
834}
835
836static int cam_vfe_bus_init_wm_resource(uint32_t index,
837 struct cam_vfe_bus_ver2_priv *ver2_bus_priv,
838 struct cam_vfe_bus_ver2_hw_info *ver2_hw_info,
839 struct cam_isp_resource_node *wm_res)
840{
Harsh Shaha1af8822017-05-11 22:06:36 -0700841 struct cam_vfe_bus_ver2_wm_resource_data *rsrc_data;
842
843 rsrc_data = kzalloc(sizeof(struct cam_vfe_bus_ver2_wm_resource_data),
844 GFP_KERNEL);
845 if (!rsrc_data) {
Harsh Shah545df9a2017-06-16 16:43:17 -0700846 CDBG("Failed to alloc for WM res priv\n");
847 return -ENOMEM;
Harsh Shaha1af8822017-05-11 22:06:36 -0700848 }
849 wm_res->res_priv = rsrc_data;
850
851 rsrc_data->index = index;
852 rsrc_data->hw_regs = &ver2_hw_info->bus_client_reg[index];
853 rsrc_data->common_data = &ver2_bus_priv->common_data;
854
855 wm_res->res_state = CAM_ISP_RESOURCE_STATE_AVAILABLE;
856 INIT_LIST_HEAD(&wm_res->list);
857
858 wm_res->start = cam_vfe_bus_start_wm;
859 wm_res->stop = cam_vfe_bus_stop_wm;
860 wm_res->top_half_handler = cam_vfe_bus_handle_wm_done_top_half;
861 wm_res->bottom_half_handler = cam_vfe_bus_handle_wm_done_bottom_half;
862 wm_res->hw_intf = ver2_bus_priv->common_data.hw_intf;
863
Harsh Shah545df9a2017-06-16 16:43:17 -0700864 return 0;
865}
866
867static int cam_vfe_bus_deinit_wm_resource(
868 struct cam_isp_resource_node *wm_res)
869{
870 struct cam_vfe_bus_ver2_wm_resource_data *rsrc_data;
871
872 wm_res->res_state = CAM_ISP_RESOURCE_STATE_UNAVAILABLE;
873 INIT_LIST_HEAD(&wm_res->list);
874
875 wm_res->start = NULL;
876 wm_res->stop = NULL;
877 wm_res->top_half_handler = NULL;
878 wm_res->bottom_half_handler = NULL;
879 wm_res->hw_intf = NULL;
880
881 rsrc_data = wm_res->res_priv;
882 wm_res->res_priv = NULL;
883 if (!rsrc_data) {
884 pr_err("Error! WM res priv is NULL\n");
885 return -ENOMEM;
886 }
887 kfree(rsrc_data);
888
889 return 0;
Harsh Shaha1af8822017-05-11 22:06:36 -0700890}
891
892static void cam_vfe_bus_add_wm_to_comp_grp(
893 struct cam_isp_resource_node *comp_grp,
894 uint32_t composite_mask)
895{
896 struct cam_vfe_bus_ver2_comp_grp_data *rsrc_data = comp_grp->res_priv;
897
898 rsrc_data->composite_mask |= composite_mask;
899}
900
901static void cam_vfe_bus_match_comp_grp(
902 struct cam_vfe_bus_ver2_priv *ver2_bus_priv,
903 struct cam_isp_resource_node **comp_grp,
904 uint32_t comp_grp_local_idx,
905 uint32_t unique_id)
906{
907 struct cam_vfe_bus_ver2_comp_grp_data *rsrc_data = NULL;
908 struct cam_isp_resource_node *comp_grp_local = NULL;
909
910 list_for_each_entry(comp_grp_local,
911 &ver2_bus_priv->used_comp_grp, list) {
912 rsrc_data = comp_grp_local->res_priv;
913 if (rsrc_data->comp_grp_local_idx == comp_grp_local_idx &&
914 rsrc_data->unique_id == unique_id) {
915 /* Match found */
916 *comp_grp = comp_grp_local;
917 return;
918 }
919 }
920
921 *comp_grp = NULL;
922}
923
924static int cam_vfe_bus_acquire_comp_grp(
925 struct cam_vfe_bus_ver2_priv *ver2_bus_priv,
926 struct cam_isp_out_port_info *out_port_info,
927 uint32_t unique_id,
928 uint32_t is_dual,
929 uint32_t is_master,
930 enum cam_vfe_bus_ver2_vfe_core_id dual_slave_core,
931 struct cam_isp_resource_node **comp_grp)
932{
933 int rc = 0;
934 struct cam_isp_resource_node *comp_grp_local = NULL;
935 struct cam_vfe_bus_ver2_comp_grp_data *rsrc_data = NULL;
936
937 /* Check if matching comp_grp already acquired */
938 cam_vfe_bus_match_comp_grp(ver2_bus_priv, &comp_grp_local,
939 out_port_info->comp_grp_id, unique_id);
940
941 if (!comp_grp_local) {
942 /* First find a free group */
943 if (is_dual) {
944 if (list_empty(&ver2_bus_priv->free_dual_comp_grp)) {
945 pr_err("No Free Composite Group\n");
946 return -ENODEV;
947 }
948 comp_grp_local = list_first_entry(
949 &ver2_bus_priv->free_dual_comp_grp,
950 struct cam_isp_resource_node, list);
951 rsrc_data = comp_grp_local->res_priv;
952 rc = cam_vfe_bus_ver2_get_intra_client_mask(
953 dual_slave_core,
954 comp_grp_local->hw_intf->hw_idx,
955 &rsrc_data->intra_client_mask);
956 } else {
957 if (list_empty(&ver2_bus_priv->free_comp_grp)) {
958 pr_err("No Free Composite Group\n");
959 return -ENODEV;
960 }
961 comp_grp_local = list_first_entry(
962 &ver2_bus_priv->free_comp_grp,
963 struct cam_isp_resource_node, list);
964 rsrc_data = comp_grp_local->res_priv;
965 }
966
967 list_del(&comp_grp_local->list);
968 comp_grp_local->res_state = CAM_ISP_RESOURCE_STATE_RESERVED;
969
970 rsrc_data->is_master = is_master;
971 rsrc_data->composite_mask = 0;
972 rsrc_data->unique_id = unique_id;
973 rsrc_data->comp_grp_local_idx = out_port_info->comp_grp_id;
974
975 list_add_tail(&comp_grp_local->list,
976 &ver2_bus_priv->used_comp_grp);
977
978 } else {
979 rsrc_data = comp_grp_local->res_priv;
980 /* Do not support runtime change in composite mask */
981 if (comp_grp_local->res_state ==
982 CAM_ISP_RESOURCE_STATE_STREAMING) {
983 pr_err("Invalid State %d Comp Grp %u\n",
984 comp_grp_local->res_state,
985 rsrc_data->comp_grp_type);
986 return -EBUSY;
987 }
988 }
989
990 *comp_grp = comp_grp_local;
991
992 return rc;
993}
994
995static int cam_vfe_bus_release_comp_grp(
996 struct cam_vfe_bus_ver2_priv *ver2_bus_priv,
997 struct cam_isp_resource_node *in_comp_grp)
998{
999 struct cam_isp_resource_node *comp_grp = NULL;
1000 struct cam_vfe_bus_ver2_comp_grp_data *in_rsrc_data = NULL;
1001 int match_found = 0;
1002
1003 if (!in_comp_grp) {
1004 pr_err("Invalid Params Comp Grp %pK\n", in_rsrc_data);
1005 return -EINVAL;
1006 }
1007
1008 if (in_comp_grp->res_state == CAM_ISP_RESOURCE_STATE_AVAILABLE) {
1009 /* Already Released. Do Nothing */
1010 return 0;
1011 }
1012
1013 in_rsrc_data = in_comp_grp->res_priv;
1014
1015 list_for_each_entry(comp_grp, &ver2_bus_priv->used_comp_grp, list) {
1016 if (comp_grp == in_comp_grp) {
1017 match_found = 1;
1018 break;
1019 }
1020 }
1021
1022 if (!match_found) {
1023 pr_err("Could not find matching Comp Grp type %u\n",
1024 in_rsrc_data->comp_grp_type);
1025 return -ENODEV;
1026 }
1027
1028
1029 list_del(&comp_grp->list);
1030 if (in_rsrc_data->comp_grp_type >= CAM_VFE_BUS_VER2_COMP_GRP_DUAL_0 &&
1031 in_rsrc_data->comp_grp_type <= CAM_VFE_BUS_VER2_COMP_GRP_DUAL_5)
1032 list_add_tail(&comp_grp->list,
1033 &ver2_bus_priv->free_dual_comp_grp);
Jing Zhoue71fd4a2017-05-15 19:44:34 -07001034 else if (in_rsrc_data->comp_grp_type >= CAM_VFE_BUS_VER2_COMP_GRP_0
1035 && in_rsrc_data->comp_grp_type <= CAM_VFE_BUS_VER2_COMP_GRP_5)
Harsh Shaha1af8822017-05-11 22:06:36 -07001036 list_add_tail(&comp_grp->list, &ver2_bus_priv->free_comp_grp);
1037
Harsh Shaha1af8822017-05-11 22:06:36 -07001038 in_rsrc_data->unique_id = 0;
1039 in_rsrc_data->comp_grp_local_idx = 0;
1040 in_rsrc_data->composite_mask = 0;
1041 in_rsrc_data->dual_slave_core = CAM_VFE_BUS_VER2_VFE_CORE_MAX;
1042
1043 comp_grp->res_state = CAM_ISP_RESOURCE_STATE_AVAILABLE;
1044
Jing Zhoue71fd4a2017-05-15 19:44:34 -07001045 return 0;
Harsh Shaha1af8822017-05-11 22:06:36 -07001046}
1047
1048static int cam_vfe_bus_start_comp_grp(struct cam_isp_resource_node *comp_grp)
1049{
1050 int rc = 0;
1051 struct cam_vfe_bus_ver2_comp_grp_data *rsrc_data =
1052 comp_grp->res_priv;
1053 struct cam_vfe_bus_ver2_common_data *common_data =
1054 rsrc_data->common_data;
1055
1056 /*
1057 * Individual Comp_Grp Subscribe IRQ can be done here once
1058 * dynamic IRQ enable support is added.
1059 */
Harsh Shaha1af8822017-05-11 22:06:36 -07001060
1061 cam_io_w_mb(rsrc_data->composite_mask, common_data->mem_base +
1062 rsrc_data->hw_regs->comp_mask);
1063
1064 CDBG("composite_mask is 0x%x\n", rsrc_data->composite_mask);
1065 CDBG("composite_mask addr 0x%x\n", rsrc_data->hw_regs->comp_mask);
1066
1067 if (rsrc_data->comp_grp_type >= CAM_VFE_BUS_VER2_COMP_GRP_DUAL_0 &&
1068 rsrc_data->comp_grp_type <= CAM_VFE_BUS_VER2_COMP_GRP_DUAL_5 &&
1069 rsrc_data->is_master) {
1070 int dual_comp_grp = (rsrc_data->comp_grp_type -
1071 CAM_VFE_BUS_VER2_COMP_GRP_DUAL_0);
1072 int intra_client_en = cam_io_r_mb(common_data->mem_base +
1073 common_data->common_reg->dual_master_comp_cfg);
1074
1075 /* 2 Bits per comp_grp. Hence left shift by comp_grp * 2 */
1076 intra_client_en |=
1077 (rsrc_data->intra_client_mask << dual_comp_grp * 2);
1078
1079 cam_io_w_mb(intra_client_en, common_data->mem_base +
1080 common_data->common_reg->dual_master_comp_cfg);
1081 }
1082
1083 comp_grp->res_state = CAM_ISP_RESOURCE_STATE_STREAMING;
1084 return rc;
1085}
1086
1087static int cam_vfe_bus_stop_comp_grp(struct cam_isp_resource_node *comp_grp)
1088{
1089 int rc = 0;
1090 struct cam_vfe_bus_ver2_comp_grp_data *rsrc_data =
1091 comp_grp->res_priv;
1092 struct cam_vfe_bus_ver2_common_data *common_data =
1093 rsrc_data->common_data;
1094
1095 /* Unsubscribe IRQ */
1096
1097 cam_io_w_mb(rsrc_data->composite_mask, common_data->mem_base +
1098 rsrc_data->hw_regs->comp_mask);
1099 if (rsrc_data->comp_grp_type >= CAM_VFE_BUS_VER2_COMP_GRP_DUAL_0 &&
1100 rsrc_data->comp_grp_type <= CAM_VFE_BUS_VER2_COMP_GRP_DUAL_5 &&
1101 rsrc_data->is_master) {
1102 int dual_comp_grp = (rsrc_data->comp_grp_type -
1103 CAM_VFE_BUS_VER2_COMP_GRP_DUAL_0);
1104 int intra_client_en = cam_io_r_mb(common_data->mem_base +
1105 common_data->common_reg->dual_master_comp_cfg);
1106
1107 /* 2 Bits per comp_grp. Hence left shift by comp_grp * 2 */
1108 intra_client_en &=
1109 ~(rsrc_data->intra_client_mask << dual_comp_grp * 2);
1110
1111 cam_io_w_mb(intra_client_en, common_data->mem_base +
1112 common_data->common_reg->dual_master_comp_cfg);
1113 }
1114
1115 comp_grp->res_state = CAM_ISP_RESOURCE_STATE_RESERVED;
1116
1117 return rc;
1118}
1119
1120static int cam_vfe_bus_handle_comp_done_top_half(uint32_t evt_id,
1121 struct cam_irq_th_payload *th_payload)
1122{
1123 return -EPERM;
1124}
1125
1126static int cam_vfe_bus_handle_comp_done_bottom_half(
1127 void *handler_priv,
1128 void *evt_payload_priv)
1129{
1130 int rc = CAM_VFE_IRQ_STATUS_ERR;
1131 struct cam_isp_resource_node *comp_grp = handler_priv;
1132 struct cam_vfe_bus_irq_evt_payload *evt_payload = evt_payload_priv;
1133 struct cam_vfe_bus_ver2_comp_grp_data *rsrc_data = comp_grp->res_priv;
Harsh Shah23557ae2017-05-13 18:14:34 -07001134 uint32_t *cam_ife_irq_regs;
1135 uint32_t status_reg;
1136 uint32_t comp_err_reg;
1137 uint32_t comp_grp_id;
1138
1139 if (!evt_payload)
1140 return rc;
1141
1142 cam_ife_irq_regs = evt_payload->irq_reg_val;
Harsh Shaha1af8822017-05-11 22:06:36 -07001143
1144 CDBG("comp grp type %d\n", rsrc_data->comp_grp_type);
1145 switch (rsrc_data->comp_grp_type) {
1146 case CAM_VFE_BUS_VER2_COMP_GRP_0:
1147 case CAM_VFE_BUS_VER2_COMP_GRP_1:
1148 case CAM_VFE_BUS_VER2_COMP_GRP_2:
1149 case CAM_VFE_BUS_VER2_COMP_GRP_3:
1150 case CAM_VFE_BUS_VER2_COMP_GRP_4:
1151 case CAM_VFE_BUS_VER2_COMP_GRP_5:
Harsh Shah23557ae2017-05-13 18:14:34 -07001152 comp_grp_id = (rsrc_data->comp_grp_type -
Harsh Shaha1af8822017-05-11 22:06:36 -07001153 CAM_VFE_BUS_VER2_COMP_GRP_0);
1154
1155 /* Check for Regular composite error */
1156 status_reg = cam_ife_irq_regs[CAM_IFE_IRQ_BUS_REG_STATUS0];
1157
1158 comp_err_reg = cam_ife_irq_regs[CAM_IFE_IRQ_BUS_REG_COMP_ERR];
1159 if ((status_reg & BIT(11)) &&
1160 (comp_err_reg & rsrc_data->composite_mask)) {
1161 /* Check for Regular composite error */
1162 rc = CAM_VFE_IRQ_STATUS_ERR_COMP;
1163 break;
1164 }
1165
1166 comp_err_reg = cam_ife_irq_regs[CAM_IFE_IRQ_BUS_REG_COMP_OWRT];
1167 /* Check for Regular composite Overwrite */
1168 if ((status_reg & BIT(12)) &&
1169 (comp_err_reg & rsrc_data->composite_mask)) {
1170 rc = CAM_VFE_IRQ_STATUS_COMP_OWRT;
1171 break;
1172 }
1173
Harsh Shah23557ae2017-05-13 18:14:34 -07001174 /* Regular Composite SUCCESS */
1175 if (status_reg & BIT(comp_grp_id + 5)) {
1176 cam_ife_irq_regs[CAM_IFE_IRQ_BUS_REG_STATUS0] &=
1177 ~BIT(comp_grp_id + 5);
Harsh Shaha1af8822017-05-11 22:06:36 -07001178 rc = CAM_VFE_IRQ_STATUS_SUCCESS;
Harsh Shah23557ae2017-05-13 18:14:34 -07001179 }
Harsh Shaha1af8822017-05-11 22:06:36 -07001180
1181 CDBG("status reg = 0x%x, bit index = %d\n",
Harsh Shah23557ae2017-05-13 18:14:34 -07001182 status_reg, (comp_grp_id + 5));
Harsh Shaha1af8822017-05-11 22:06:36 -07001183 break;
1184
1185 case CAM_VFE_BUS_VER2_COMP_GRP_DUAL_0:
1186 case CAM_VFE_BUS_VER2_COMP_GRP_DUAL_1:
1187 case CAM_VFE_BUS_VER2_COMP_GRP_DUAL_2:
1188 case CAM_VFE_BUS_VER2_COMP_GRP_DUAL_3:
1189 case CAM_VFE_BUS_VER2_COMP_GRP_DUAL_4:
1190 case CAM_VFE_BUS_VER2_COMP_GRP_DUAL_5:
Harsh Shah23557ae2017-05-13 18:14:34 -07001191 comp_grp_id = (rsrc_data->comp_grp_type -
Harsh Shaha1af8822017-05-11 22:06:36 -07001192 CAM_VFE_BUS_VER2_COMP_GRP_DUAL_0);
1193
1194 /* Check for DUAL composite error */
1195 status_reg = cam_ife_irq_regs[CAM_IFE_IRQ_BUS_REG_STATUS2];
1196
1197 comp_err_reg = cam_ife_irq_regs[CAM_IFE_IRQ_BUS_DUAL_COMP_ERR];
1198 if ((status_reg & BIT(6)) &&
1199 (comp_err_reg & rsrc_data->composite_mask)) {
1200 /* Check for DUAL composite error */
1201 rc = CAM_VFE_IRQ_STATUS_ERR_COMP;
1202 break;
1203 }
1204
1205 /* Check for Dual composite Overwrite */
1206 comp_err_reg = cam_ife_irq_regs[CAM_IFE_IRQ_BUS_DUAL_COMP_OWRT];
1207 if ((status_reg & BIT(7)) &&
1208 (comp_err_reg & rsrc_data->composite_mask)) {
1209 rc = CAM_VFE_IRQ_STATUS_COMP_OWRT;
1210 break;
1211 }
1212
Harsh Shah23557ae2017-05-13 18:14:34 -07001213 /* DUAL Composite SUCCESS */
1214 if (status_reg & BIT(comp_grp_id)) {
1215 cam_ife_irq_regs[CAM_IFE_IRQ_BUS_REG_STATUS2] &=
1216 ~BIT(comp_grp_id + 5);
Harsh Shaha1af8822017-05-11 22:06:36 -07001217 rc = CAM_VFE_IRQ_STATUS_SUCCESS;
Harsh Shah23557ae2017-05-13 18:14:34 -07001218 }
Harsh Shaha1af8822017-05-11 22:06:36 -07001219
1220 break;
Harsh Shaha1af8822017-05-11 22:06:36 -07001221 default:
1222 rc = CAM_VFE_IRQ_STATUS_ERR;
1223 break;
1224 }
1225
1226 if (rc == CAM_VFE_IRQ_STATUS_SUCCESS)
1227 cam_vfe_bus_put_evt_payload(evt_payload->core_info,
1228 &evt_payload);
1229
1230 return rc;
1231}
1232
1233static int cam_vfe_bus_init_comp_grp(uint32_t index,
1234 struct cam_vfe_bus_ver2_priv *ver2_bus_priv,
1235 struct cam_vfe_bus_ver2_hw_info *ver2_hw_info,
1236 struct cam_isp_resource_node *comp_grp)
1237{
Harsh Shah545df9a2017-06-16 16:43:17 -07001238 struct cam_vfe_bus_ver2_comp_grp_data *rsrc_data = NULL;
Harsh Shaha1af8822017-05-11 22:06:36 -07001239
1240 rsrc_data = kzalloc(sizeof(struct cam_vfe_bus_ver2_comp_grp_data),
1241 GFP_KERNEL);
1242 if (!rsrc_data) {
1243 CDBG("Failed to alloc for comp_grp_priv\n");
1244 return -ENOMEM;
1245 }
1246 comp_grp->res_priv = rsrc_data;
1247
1248 comp_grp->res_state = CAM_ISP_RESOURCE_STATE_AVAILABLE;
1249 INIT_LIST_HEAD(&comp_grp->list);
1250
1251 rsrc_data->comp_grp_type = index;
1252 rsrc_data->common_data = &ver2_bus_priv->common_data;
1253 rsrc_data->hw_regs = &ver2_hw_info->comp_grp_reg[index];
1254 rsrc_data->dual_slave_core = CAM_VFE_BUS_VER2_VFE_CORE_MAX;
1255
Harsh Shaha1af8822017-05-11 22:06:36 -07001256 if (rsrc_data->comp_grp_type >= CAM_VFE_BUS_VER2_COMP_GRP_DUAL_0 &&
1257 rsrc_data->comp_grp_type <= CAM_VFE_BUS_VER2_COMP_GRP_DUAL_5)
1258 list_add_tail(&comp_grp->list,
1259 &ver2_bus_priv->free_dual_comp_grp);
1260 else if (rsrc_data->comp_grp_type >= CAM_VFE_BUS_VER2_COMP_GRP_0
1261 && rsrc_data->comp_grp_type <= CAM_VFE_BUS_VER2_COMP_GRP_5)
1262 list_add_tail(&comp_grp->list, &ver2_bus_priv->free_comp_grp);
1263
1264 comp_grp->start = cam_vfe_bus_start_comp_grp;
1265 comp_grp->stop = cam_vfe_bus_stop_comp_grp;
1266 comp_grp->top_half_handler = cam_vfe_bus_handle_comp_done_top_half;
1267 comp_grp->bottom_half_handler =
1268 cam_vfe_bus_handle_comp_done_bottom_half;
1269 comp_grp->hw_intf = ver2_bus_priv->common_data.hw_intf;
1270
1271 return 0;
1272}
1273
Harsh Shah545df9a2017-06-16 16:43:17 -07001274static int cam_vfe_bus_deinit_comp_grp(
1275 struct cam_isp_resource_node *comp_grp)
1276{
1277 struct cam_vfe_bus_ver2_comp_grp_data *rsrc_data =
1278 comp_grp->res_priv;
1279
1280 comp_grp->start = NULL;
1281 comp_grp->stop = NULL;
1282 comp_grp->top_half_handler = NULL;
1283 comp_grp->bottom_half_handler = NULL;
1284 comp_grp->hw_intf = NULL;
1285
1286 list_del_init(&comp_grp->list);
1287 comp_grp->res_state = CAM_ISP_RESOURCE_STATE_UNAVAILABLE;
1288
1289 comp_grp->res_priv = NULL;
1290
1291 if (!rsrc_data) {
1292 pr_err("Error! comp_grp_priv is NULL\n");
1293 return -ENODEV;
1294 }
1295 kfree(rsrc_data);
1296
1297 return 0;
1298}
1299
Harsh Shaha1af8822017-05-11 22:06:36 -07001300static int cam_vfe_bus_acquire_vfe_out(void *bus_priv, void *acquire_args)
1301{
1302 int rc = -ENODEV;
1303 int i;
1304 enum cam_vfe_bus_ver2_vfe_out_type vfe_out_res_id;
1305 uint32_t format;
1306 uint32_t num_wm;
1307 uint32_t subscribe_irq;
1308 uint32_t client_done_mask;
1309 struct cam_vfe_bus_ver2_priv *ver2_bus_priv = bus_priv;
1310 struct cam_vfe_acquire_args *acq_args = acquire_args;
1311 struct cam_vfe_hw_vfe_out_acquire_args *out_acquire_args;
1312 struct cam_isp_resource_node *rsrc_node = NULL;
1313 struct cam_vfe_bus_ver2_vfe_out_data *rsrc_data = NULL;
1314
1315 if (!bus_priv || !acquire_args) {
1316 pr_err("Invalid Param");
1317 return -EINVAL;
1318 }
1319
1320 out_acquire_args = &acq_args->vfe_out;
1321 format = out_acquire_args->out_port_info->format;
1322
1323 CDBG("Acquiring resource type 0x%x\n",
1324 out_acquire_args->out_port_info->res_type);
1325
1326 vfe_out_res_id = cam_vfe_bus_get_out_res_id(
1327 out_acquire_args->out_port_info->res_type);
1328 if (vfe_out_res_id == CAM_VFE_BUS_VER2_VFE_OUT_MAX)
1329 return -ENODEV;
1330
1331 num_wm = cam_vfe_bus_get_num_wm(vfe_out_res_id, format);
1332 if (num_wm < 1)
1333 return -EINVAL;
1334
1335 rsrc_node = &ver2_bus_priv->vfe_out[vfe_out_res_id];
1336 if (rsrc_node->res_state != CAM_ISP_RESOURCE_STATE_AVAILABLE) {
1337 pr_err("Resource not available: Res_id %d state:%d\n",
1338 vfe_out_res_id, rsrc_node->res_state);
1339 return -EBUSY;
1340 }
1341
1342 rsrc_data = rsrc_node->res_priv;
1343 rsrc_data->num_wm = num_wm;
1344 rsrc_node->res_id = out_acquire_args->out_port_info->res_type;
1345 rsrc_node->tasklet_info = acq_args->tasklet;
1346 rsrc_node->cdm_ops = out_acquire_args->cdm_ops;
1347 rsrc_data->cdm_util_ops = out_acquire_args->cdm_ops;
1348
1349 /* Reserve Composite Group */
1350 if (num_wm > 1 || (out_acquire_args->out_port_info->comp_grp_id >
1351 CAM_ISP_RES_COMP_GROUP_NONE &&
1352 out_acquire_args->out_port_info->comp_grp_id <
1353 CAM_ISP_RES_COMP_GROUP_ID_MAX)) {
1354 rc = cam_vfe_bus_acquire_comp_grp(ver2_bus_priv,
1355 out_acquire_args->out_port_info,
1356 out_acquire_args->unique_id,
1357 out_acquire_args->is_dual,
1358 out_acquire_args->is_master,
1359 out_acquire_args->dual_slave_core,
1360 &rsrc_data->comp_grp);
1361 if (rc < 0)
1362 return rc;
1363
1364 subscribe_irq = 0;
1365 } else
1366 subscribe_irq = 1;
1367
1368 /* Reserve WM */
1369 for (i = 0; i < num_wm; i++) {
1370 rc = cam_vfe_bus_acquire_wm(ver2_bus_priv,
1371 out_acquire_args->out_port_info,
1372 vfe_out_res_id,
1373 i,
1374 out_acquire_args->split_id,
1375 subscribe_irq,
1376 &rsrc_data->wm_res[i],
1377 &client_done_mask);
1378 if (rc < 0)
1379 goto release_wm;
1380
1381 if (rsrc_data->comp_grp)
1382 cam_vfe_bus_add_wm_to_comp_grp(rsrc_data->comp_grp,
1383 client_done_mask);
1384 }
1385
1386 rsrc_node->res_state = CAM_ISP_RESOURCE_STATE_RESERVED;
1387 out_acquire_args->rsrc_node = rsrc_node;
1388
1389 CDBG("Acquire successful\n");
1390 return rc;
1391
1392release_wm:
1393 for (i--; i >= 0; i--)
1394 cam_vfe_bus_release_wm(ver2_bus_priv, rsrc_data->wm_res[i]);
1395
1396 cam_vfe_bus_release_comp_grp(ver2_bus_priv,
1397 rsrc_data->comp_grp);
1398
1399 return rc;
1400}
1401
1402static int cam_vfe_bus_release_vfe_out(void *bus_priv,
1403 struct cam_isp_resource_node *vfe_out)
1404{
Jing Zhoue71fd4a2017-05-15 19:44:34 -07001405 uint32_t i;
1406 struct cam_vfe_bus_ver2_vfe_out_data *rsrc_data = vfe_out->res_priv;
1407
Harsh Shaha1af8822017-05-11 22:06:36 -07001408 if (vfe_out->res_state != CAM_ISP_RESOURCE_STATE_RESERVED) {
1409 pr_err("Error! Invalid resource state:%d\n",
1410 vfe_out->res_state);
1411 }
1412
Jing Zhoue71fd4a2017-05-15 19:44:34 -07001413 for (i = 0; i < rsrc_data->num_wm; i++)
1414 cam_vfe_bus_release_wm(bus_priv, rsrc_data->wm_res[i]);
1415 rsrc_data->num_wm = 0;
1416
1417 if (rsrc_data->comp_grp)
1418 cam_vfe_bus_release_comp_grp(bus_priv, rsrc_data->comp_grp);
1419 rsrc_data->comp_grp = NULL;
1420
1421 vfe_out->tasklet_info = NULL;
1422 vfe_out->cdm_ops = NULL;
1423 rsrc_data->cdm_util_ops = NULL;
1424
Harsh Shaha1af8822017-05-11 22:06:36 -07001425 if (vfe_out->res_state == CAM_ISP_RESOURCE_STATE_RESERVED)
1426 vfe_out->res_state = CAM_ISP_RESOURCE_STATE_AVAILABLE;
1427
1428 return 0;
1429}
1430
1431static int cam_vfe_bus_start_vfe_out(struct cam_isp_resource_node *vfe_out)
1432{
1433 int rc = 0, i;
Harsh Shah23557ae2017-05-13 18:14:34 -07001434 struct cam_vfe_bus_ver2_vfe_out_data *rsrc_data = vfe_out->res_priv;
1435 struct cam_vfe_bus_ver2_common_data *common_data =
1436 rsrc_data->common_data;
Harsh Shaha1af8822017-05-11 22:06:36 -07001437
1438 CDBG("Start resource index %d\n", rsrc_data->out_type);
1439
1440 if (vfe_out->res_state != CAM_ISP_RESOURCE_STATE_RESERVED) {
1441 pr_err("Error! Invalid resource state:%d\n",
1442 vfe_out->res_state);
1443 return -EACCES;
1444 }
1445
Harsh Shah23557ae2017-05-13 18:14:34 -07001446 /* Enable IRQ Mask */
Jing Zhoue71fd4a2017-05-15 19:44:34 -07001447 cam_io_w_mb(0x00001FE0, common_data->mem_base + 0x2044);
Harsh Shah23557ae2017-05-13 18:14:34 -07001448 cam_io_w_mb(0x000FFFE7, common_data->mem_base + 0x2048);
1449 cam_io_w_mb(0x000000FF, common_data->mem_base + 0x204c);
1450
Harsh Shaha1af8822017-05-11 22:06:36 -07001451 for (i = 0; i < rsrc_data->num_wm; i++)
1452 rc = cam_vfe_bus_start_wm(rsrc_data->wm_res[i]);
1453
1454 if (rsrc_data->comp_grp)
1455 rc = cam_vfe_bus_start_comp_grp(rsrc_data->comp_grp);
1456
1457 /* VFE_MODULE_BUS_CGC_OVERRIDE */
1458 cam_io_w_mb(0xFFFFFFFF, rsrc_data->common_data->mem_base + 0x0000003C);
1459 /* VFE_MODULE_COLOR_CGC_OVERRIDE */
1460 cam_io_w_mb(0xFFFFFFFF, rsrc_data->common_data->mem_base + 0x00000034);
1461 /* VFE_MODULE_ZOOM_CGC_OVERRIDE */
1462 cam_io_w_mb(0xFFFFFFFF, rsrc_data->common_data->mem_base + 0x38);
1463 /* VFE_MODULE_LENS_CGC_OVERRIDE */
1464 cam_io_w_mb(0xFFFFFFFF, rsrc_data->common_data->mem_base + 0x0000002C);
1465 /* VFE_MODULE_STATS_CGC_OVERRIDE */
1466 cam_io_w_mb(0xFFFFFFFF, rsrc_data->common_data->mem_base + 0x00000030);
1467
1468 /* BUS_WR_INPUT_IF_ADDR_SYNC_CFG */
1469 cam_io_w_mb(0x0, rsrc_data->common_data->mem_base + 0x0000207C);
1470 /* BUS_WR_INPUT_IF_ADDR_SYNC_FRAME_HEADER */
1471 cam_io_w_mb(0x0, rsrc_data->common_data->mem_base + 0x00002080);
1472 /* BUS_WR_INPUT_IF_ADDR_SYNC_NO_SYNC */
1473 cam_io_w_mb(0xFFFFF, rsrc_data->common_data->mem_base + 0x00002084);
Harsh Shaha1af8822017-05-11 22:06:36 -07001474 /* BUS_WR_INPUT_IF_ADDR_SYNC_0 */
1475 cam_io_w_mb(0x0, rsrc_data->common_data->mem_base + 0x00002088);
1476 cam_io_w_mb(0x0, rsrc_data->common_data->mem_base + 0x0000208c);
1477 cam_io_w_mb(0x0, rsrc_data->common_data->mem_base + 0x00002090);
1478 cam_io_w_mb(0x0, rsrc_data->common_data->mem_base + 0x00002094);
1479 cam_io_w_mb(0x0, rsrc_data->common_data->mem_base + 0x00002098);
1480 cam_io_w_mb(0x0, rsrc_data->common_data->mem_base + 0x0000209c);
1481 cam_io_w_mb(0x0, rsrc_data->common_data->mem_base + 0x000020a0);
1482 cam_io_w_mb(0x0, rsrc_data->common_data->mem_base + 0x000020a4);
1483
Harsh Shah23557ae2017-05-13 18:14:34 -07001484 /* no clock gating at bus input */
1485 cam_io_w_mb(0xFFFFF, rsrc_data->common_data->mem_base + 0x0000200C);
1486
1487 /* BUS_WR_TEST_BUS_CTRL */
1488 cam_io_w_mb(0x0, rsrc_data->common_data->mem_base + 0x0000211C);
1489
Harsh Shaha1af8822017-05-11 22:06:36 -07001490 return rc;
1491}
1492
1493static int cam_vfe_bus_stop_vfe_out(struct cam_isp_resource_node *vfe_out)
1494{
1495 int rc = 0, i;
1496 struct cam_vfe_bus_ver2_vfe_out_data *rsrc_data = vfe_out->res_priv;
1497
1498 if (vfe_out->res_state == CAM_ISP_RESOURCE_STATE_AVAILABLE ||
1499 vfe_out->res_state == CAM_ISP_RESOURCE_STATE_RESERVED) {
1500 return rc;
1501 }
1502
1503 if (rsrc_data->comp_grp)
1504 rc = cam_vfe_bus_stop_comp_grp(rsrc_data->comp_grp);
1505
1506 for (i = 0; i < rsrc_data->num_wm; i++)
1507 rc = cam_vfe_bus_stop_wm(rsrc_data->wm_res[i]);
1508
1509 vfe_out->res_state = CAM_ISP_RESOURCE_STATE_STREAMING;
1510
1511 vfe_out->res_state = CAM_ISP_RESOURCE_STATE_RESERVED;
1512 return rc;
1513}
1514
1515static int cam_vfe_bus_handle_vfe_out_done_top_half(uint32_t evt_id,
1516 struct cam_irq_th_payload *th_payload)
1517{
1518 return -EPERM;
1519}
1520
1521static int cam_vfe_bus_handle_vfe_out_done_bottom_half(
1522 void *handler_priv,
1523 void *evt_payload_priv)
1524{
1525 int rc = -EINVAL;
1526 struct cam_isp_resource_node *vfe_out = handler_priv;
1527 struct cam_vfe_bus_ver2_vfe_out_data *rsrc_data = vfe_out->res_priv;
1528
1529 /*
1530 * If this resource has Composite Group then we only handle
1531 * Composite done. We acquire Composite if number of WM > 1.
1532 * So Else case is only one individual buf_done = WM[0].
1533 */
1534 if (rsrc_data->comp_grp) {
1535 rc = rsrc_data->comp_grp->bottom_half_handler(
1536 rsrc_data->comp_grp, evt_payload_priv);
1537 } else {
1538 rc = rsrc_data->wm_res[0]->bottom_half_handler(
Harsh Shah23557ae2017-05-13 18:14:34 -07001539 rsrc_data->wm_res[0], evt_payload_priv);
Harsh Shaha1af8822017-05-11 22:06:36 -07001540 }
1541
1542 return rc;
1543}
1544
1545static int cam_vfe_bus_init_vfe_out_resource(uint32_t index,
1546 struct cam_vfe_bus_ver2_priv *ver2_bus_priv,
1547 struct cam_vfe_bus_ver2_hw_info *ver2_hw_info,
1548 struct cam_isp_resource_node *vfe_out)
1549{
1550 struct cam_vfe_bus_ver2_vfe_out_data *rsrc_data = NULL;
1551 int rc = 0;
1552
1553 rsrc_data = kzalloc(sizeof(struct cam_vfe_bus_ver2_vfe_out_data),
1554 GFP_KERNEL);
1555 if (!rsrc_data) {
1556 CDBG("Error! Failed to alloc for vfe out priv\n");
1557 rc = -ENOMEM;
1558 return rc;
1559 }
1560 vfe_out->res_priv = rsrc_data;
1561
1562 vfe_out->res_type = CAM_ISP_RESOURCE_VFE_OUT;
1563 vfe_out->res_state = CAM_ISP_RESOURCE_STATE_AVAILABLE;
1564 INIT_LIST_HEAD(&vfe_out->list);
1565
1566 rsrc_data->out_type = index;
1567 rsrc_data->common_data = &ver2_bus_priv->common_data;
1568 rsrc_data->max_width =
1569 ver2_hw_info->vfe_out_hw_info[index].max_width;
1570 rsrc_data->max_height =
1571 ver2_hw_info->vfe_out_hw_info[index].max_height;
1572
1573 vfe_out->start = cam_vfe_bus_start_vfe_out;
1574 vfe_out->stop = cam_vfe_bus_stop_vfe_out;
1575 vfe_out->top_half_handler = cam_vfe_bus_handle_vfe_out_done_top_half;
1576 vfe_out->bottom_half_handler =
1577 cam_vfe_bus_handle_vfe_out_done_bottom_half;
1578 vfe_out->hw_intf = ver2_bus_priv->common_data.hw_intf;
1579
1580 return 0;
1581}
1582
Harsh Shah545df9a2017-06-16 16:43:17 -07001583static int cam_vfe_bus_deinit_vfe_out_resource(
1584 struct cam_isp_resource_node *vfe_out)
1585{
1586 struct cam_vfe_bus_ver2_vfe_out_data *rsrc_data = vfe_out->res_priv;
1587
1588 vfe_out->start = NULL;
1589 vfe_out->stop = NULL;
1590 vfe_out->top_half_handler = NULL;
1591 vfe_out->bottom_half_handler = NULL;
1592 vfe_out->hw_intf = NULL;
1593
1594 vfe_out->res_state = CAM_ISP_RESOURCE_STATE_UNAVAILABLE;
1595 INIT_LIST_HEAD(&vfe_out->list);
1596 vfe_out->res_priv = NULL;
1597
1598 if (!rsrc_data) {
1599 pr_err("Error! vfe out priv is NULL\n");
1600 return -ENOMEM;
1601 }
1602 kfree(rsrc_data);
1603
1604 return 0;
1605}
1606
Harsh Shaha1af8822017-05-11 22:06:36 -07001607static int cam_vfe_bus_get_evt_payload(
1608 struct cam_vfe_bus_ver2_priv *bus_priv,
1609 struct cam_vfe_bus_irq_evt_payload **evt_payload)
1610{
1611 if (list_empty(&bus_priv->free_payload_list)) {
Harsh Shah23557ae2017-05-13 18:14:34 -07001612 *evt_payload = NULL;
Harsh Shaha1af8822017-05-11 22:06:36 -07001613 pr_err("No free payload\n");
1614 return -ENODEV;
1615 }
1616
1617 *evt_payload = list_first_entry(&bus_priv->free_payload_list,
1618 struct cam_vfe_bus_irq_evt_payload, list);
1619 list_del_init(&(*evt_payload)->list);
1620 return 0;
1621}
1622
1623static int cam_vfe_bus_put_evt_payload(void *core_info,
1624 struct cam_vfe_bus_irq_evt_payload **evt_payload)
1625{
1626 struct cam_vfe_bus_ver2_priv *bus_priv = NULL;
Harsh Shah23557ae2017-05-13 18:14:34 -07001627 uint32_t *cam_ife_irq_regs = (*evt_payload)->irq_reg_val;
1628 uint32_t status_reg0, status_reg1;
1629
1630 status_reg0 = cam_ife_irq_regs[CAM_IFE_IRQ_BUS_REG_STATUS0];
1631 status_reg1 = cam_ife_irq_regs[CAM_IFE_IRQ_BUS_REG_STATUS1];
1632
1633 if (status_reg0 || status_reg1) {
1634 CDBG("status0 0x%x status1 0x%x\n", status_reg0, status_reg1);
1635 return 0;
1636 }
Harsh Shaha1af8822017-05-11 22:06:36 -07001637
1638 if (!core_info) {
1639 pr_err("Invalid param core_info NULL");
1640 return -EINVAL;
1641 }
1642 if (*evt_payload == NULL) {
1643 pr_err("No payload to put\n");
1644 return -EINVAL;
1645 }
1646 bus_priv = (*evt_payload)->bus_priv;
1647 list_add_tail(&(*evt_payload)->list, &bus_priv->free_payload_list);
1648 *evt_payload = NULL;
1649 return 0;
1650}
1651
1652static int cam_vfe_bus_ver2_handle_irq(uint32_t evt_id,
1653 struct cam_irq_th_payload *th_payload)
1654{
1655 int32_t rc;
1656 int i;
1657 struct cam_vfe_irq_handler_priv *handler_priv;
1658 struct cam_vfe_hw_core_info *core_info;
1659 struct cam_vfe_bus_irq_evt_payload *evt_payload;
1660 struct cam_vfe_bus *bus_info;
1661 struct cam_vfe_bus_ver2_priv *bus_priv;
1662 struct cam_irq_controller_reg_info *reg_info;
Harsh Shah23557ae2017-05-13 18:14:34 -07001663 uint32_t irq_mask;
Harsh Shah35165dc2017-06-06 19:42:41 -07001664 int found = 0;
Harsh Shaha1af8822017-05-11 22:06:36 -07001665
1666 handler_priv = th_payload->handler_priv;
1667 core_info = handler_priv->core_info;
1668 bus_info = core_info->vfe_bus;
1669 bus_priv = bus_info->bus_priv;
1670 reg_info = &bus_priv->common_data.common_reg->irq_reg_info;
1671
1672 /*
1673 * add reset ack handling here once supported.
1674 * Just clear all the bus irq status registers and ignore the reset.
1675 */
1676
1677 CDBG("Enter\n");
1678 rc = cam_vfe_bus_get_evt_payload(bus_priv, &evt_payload);
1679 if (rc) {
1680 pr_err("No tasklet_cmd is free in queue\n");
1681 return rc;
1682 }
1683
1684 cam_isp_hw_get_timestamp(&evt_payload->ts);
1685
1686 evt_payload->core_index = handler_priv->core_index;
1687 evt_payload->core_info = handler_priv->core_info;
1688 evt_payload->bus_priv = bus_priv;
1689 CDBG("core_idx %d, core_info %llx\n", handler_priv->core_index,
1690 (uint64_t)handler_priv->core_info);
1691
1692 for (i = 0; i < CAM_IFE_BUS_IRQ_REGISTERS_MAX; i++) {
Harsh Shah23557ae2017-05-13 18:14:34 -07001693 irq_mask = cam_io_r(handler_priv->mem_base +
1694 irq_reg_offset[i] - (0xC * 2));
1695 evt_payload->irq_reg_val[i] = irq_mask &
1696 cam_io_r(handler_priv->mem_base + irq_reg_offset[i]);
Harsh Shah35165dc2017-06-06 19:42:41 -07001697 if (evt_payload->irq_reg_val[i])
1698 found = 1;
Harsh Shaha1af8822017-05-11 22:06:36 -07001699 CDBG("irq_status%d = 0x%x\n", i, evt_payload->irq_reg_val[i]);
1700 }
1701 for (i = 0; i <= CAM_IFE_IRQ_BUS_REG_STATUS2; i++) {
1702 cam_io_w(evt_payload->irq_reg_val[i], handler_priv->mem_base +
1703 reg_info->irq_reg_set[i].clear_reg_offset);
1704 CDBG("Clear irq_status%d = 0x%x offset 0x%x\n", i,
1705 evt_payload->irq_reg_val[i],
1706 reg_info->irq_reg_set[i].clear_reg_offset);
1707 }
1708 cam_io_w(reg_info->global_clear_bitmask, handler_priv->mem_base +
1709 reg_info->global_clear_offset);
1710 CDBG("Global clear bitmask = 0x%x offset 0x%x\n",
1711 reg_info->global_clear_bitmask,
1712 reg_info->global_clear_offset);
1713
Harsh Shah35165dc2017-06-06 19:42:41 -07001714 if (found)
1715 th_payload->evt_payload_priv = evt_payload;
1716 else {
1717 cam_vfe_bus_put_evt_payload(evt_payload->core_info,
1718 &evt_payload);
1719 rc = -ENOMSG;
1720 }
Harsh Shaha1af8822017-05-11 22:06:36 -07001721
1722 return rc;
1723}
1724
1725static int cam_vfe_bus_update_buf(void *priv, void *cmd_args,
1726 uint32_t arg_size)
1727{
1728 struct cam_vfe_bus_ver2_priv *bus_priv;
1729 struct cam_isp_hw_get_buf_update *update_buf;
Jing Zhoua4e9fbe2017-05-15 14:37:21 -07001730 struct cam_buf_io_cfg *io_cfg;
Harsh Shaha1af8822017-05-11 22:06:36 -07001731 struct cam_vfe_bus_ver2_vfe_out_data *vfe_out_data = NULL;
1732 struct cam_vfe_bus_ver2_wm_resource_data *wm_data = NULL;
Jing Zhoua4e9fbe2017-05-15 14:37:21 -07001733 uint32_t *reg_val_pair;
1734 uint32_t i, j, size = 0;
Junzhe Zou193d78c2017-05-16 15:10:54 -07001735 uint32_t frame_inc = 0;
Harsh Shaha1af8822017-05-11 22:06:36 -07001736
1737 /*
1738 * Need the entire buf io config so we can get the stride info
1739 * for the wm.
1740 */
1741
1742 bus_priv = (struct cam_vfe_bus_ver2_priv *) priv;
1743 update_buf = (struct cam_isp_hw_get_buf_update *) cmd_args;
1744
1745 vfe_out_data = (struct cam_vfe_bus_ver2_vfe_out_data *)
1746 update_buf->cdm.res->res_priv;
1747
1748 if (!vfe_out_data || !vfe_out_data->cdm_util_ops) {
1749 pr_err("Failed! Invalid data\n");
1750 return -EINVAL;
1751 }
1752
Jing Zhoua4e9fbe2017-05-15 14:37:21 -07001753 if (update_buf->num_buf != vfe_out_data->num_wm) {
Harsh Shaha1af8822017-05-11 22:06:36 -07001754 pr_err("Failed! Invalid number buffers:%d required:%d\n",
1755 update_buf->num_buf, vfe_out_data->num_wm);
Junzhe Zou193d78c2017-05-16 15:10:54 -07001756 return -EINVAL;
Harsh Shaha1af8822017-05-11 22:06:36 -07001757 }
1758
Jing Zhoua4e9fbe2017-05-15 14:37:21 -07001759 reg_val_pair = &vfe_out_data->common_data->io_buf_update[0];
1760 io_cfg = update_buf->io_cfg;
1761
1762 for (i = 0, j = 0; i < vfe_out_data->num_wm; i++) {
Junzhe Zou193d78c2017-05-16 15:10:54 -07001763 if (j >= (MAX_REG_VAL_PAIR_SIZE - MAX_BUF_UPDATE_REG_NUM * 2)) {
1764 pr_err("reg_val_pair %d exceeds the array limit %lu\n",
1765 j, MAX_REG_VAL_PAIR_SIZE);
1766 return -ENOMEM;
1767 }
1768
Jing Zhoua4e9fbe2017-05-15 14:37:21 -07001769 wm_data = vfe_out_data->wm_res[i]->res_priv;
1770
1771 /* For initial configuration program all bus registers */
1772 if (wm_data->stride != io_cfg->planes[i].plane_stride ||
1773 !wm_data->init_cfg_done) {
1774 CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j,
1775 wm_data->hw_regs->stride,
1776 io_cfg->planes[i].plane_stride);
1777 wm_data->stride = io_cfg->planes[i].plane_stride;
1778 }
1779 CDBG("image stride 0x%x\n", wm_data->stride);
1780
1781 if (wm_data->framedrop_pattern != io_cfg->framedrop_pattern ||
1782 !wm_data->init_cfg_done) {
1783 CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j,
1784 wm_data->hw_regs->framedrop_pattern,
1785 io_cfg->framedrop_pattern);
1786 wm_data->framedrop_pattern = io_cfg->framedrop_pattern;
1787 }
1788 CDBG("framedrop pattern 0x%x\n", wm_data->framedrop_pattern);
1789
1790 if (wm_data->framedrop_period != io_cfg->framedrop_period ||
1791 !wm_data->init_cfg_done) {
1792 CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j,
1793 wm_data->hw_regs->framedrop_period,
1794 io_cfg->framedrop_period);
1795 wm_data->framedrop_period = io_cfg->framedrop_period;
1796 }
1797 CDBG("framedrop period 0x%x\n", wm_data->framedrop_period);
1798
1799 if (wm_data->irq_subsample_period != io_cfg->subsample_period
1800 || !wm_data->init_cfg_done) {
1801 CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j,
1802 wm_data->hw_regs->irq_subsample_period,
1803 io_cfg->subsample_period);
1804 wm_data->irq_subsample_period =
1805 io_cfg->subsample_period;
1806 }
1807 CDBG("irq subsample period 0x%x\n",
1808 wm_data->irq_subsample_period);
1809
1810 if (wm_data->irq_subsample_pattern != io_cfg->subsample_pattern
1811 || !wm_data->init_cfg_done) {
1812 CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j,
1813 wm_data->hw_regs->irq_subsample_pattern,
1814 io_cfg->subsample_pattern);
1815 wm_data->irq_subsample_pattern =
1816 io_cfg->subsample_pattern;
1817 }
1818 CDBG("irq subsample pattern 0x%x\n",
1819 wm_data->irq_subsample_pattern);
1820
1821 if (wm_data->en_ubwc) {
1822 if (!wm_data->hw_regs->ubwc_regs) {
1823 pr_err("%s: No UBWC register to configure.\n",
1824 __func__);
1825 return -EINVAL;
1826 }
1827 if (wm_data->packer_cfg !=
1828 io_cfg->planes[i].packer_config ||
1829 !wm_data->init_cfg_done) {
1830 CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j,
1831 wm_data->hw_regs->packer_cfg,
1832 io_cfg->planes[i].packer_config);
1833 wm_data->packer_cfg =
1834 io_cfg->planes[i].packer_config;
1835 }
1836 CDBG("packer cfg 0x%x\n", wm_data->packer_cfg);
1837
1838 if (wm_data->tile_cfg != io_cfg->planes[i].tile_config
1839 || !wm_data->init_cfg_done) {
1840 CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j,
1841 wm_data->hw_regs->ubwc_regs->tile_cfg,
1842 io_cfg->planes[i].tile_config);
1843 wm_data->tile_cfg =
1844 io_cfg->planes[i].tile_config;
1845 }
1846 CDBG("tile cfg 0x%x\n", wm_data->tile_cfg);
1847
1848 if (wm_data->h_init != io_cfg->planes[i].h_init ||
1849 !wm_data->init_cfg_done) {
1850 CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j,
1851 wm_data->hw_regs->ubwc_regs->h_init,
1852 io_cfg->planes[i].h_init);
1853 wm_data->h_init = io_cfg->planes[i].h_init;
1854 }
1855 CDBG("h_init 0x%x\n", wm_data->h_init);
1856
1857 if (wm_data->v_init != io_cfg->planes[i].v_init ||
1858 !wm_data->init_cfg_done) {
1859 CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j,
1860 wm_data->hw_regs->ubwc_regs->v_init,
1861 io_cfg->planes[i].v_init);
1862 wm_data->v_init = io_cfg->planes[i].v_init;
1863 }
1864 CDBG("v_init 0x%x\n", wm_data->v_init);
1865
1866 if (wm_data->ubwc_meta_stride !=
1867 io_cfg->planes[i].meta_stride ||
1868 !wm_data->init_cfg_done) {
1869 CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j,
1870 wm_data->hw_regs->ubwc_regs->
1871 meta_stride,
1872 io_cfg->planes[i].meta_stride);
1873 wm_data->ubwc_meta_stride =
1874 io_cfg->planes[i].meta_stride;
1875 }
1876 CDBG("meta stride 0x%x\n", wm_data->ubwc_meta_stride);
1877
1878 if (wm_data->ubwc_mode_cfg !=
1879 io_cfg->planes[i].mode_config ||
1880 !wm_data->init_cfg_done) {
1881 CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j,
1882 wm_data->hw_regs->ubwc_regs->mode_cfg,
1883 io_cfg->planes[i].mode_config);
1884 wm_data->ubwc_mode_cfg =
1885 io_cfg->planes[i].mode_config;
1886 }
1887 CDBG("ubwc mode cfg 0x%x\n", wm_data->ubwc_mode_cfg);
1888
1889 if (wm_data->ubwc_meta_offset !=
1890 io_cfg->planes[i].meta_offset ||
1891 !wm_data->init_cfg_done) {
1892 CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j,
1893 wm_data->hw_regs->ubwc_regs->
1894 meta_offset,
1895 io_cfg->planes[i].meta_offset);
1896 wm_data->ubwc_meta_offset =
1897 io_cfg->planes[i].meta_offset;
1898 }
1899 CDBG("ubwc meta offset 0x%x\n",
1900 wm_data->ubwc_meta_offset);
1901
1902 /* UBWC meta address */
1903 CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j,
1904 wm_data->hw_regs->ubwc_regs->meta_addr,
1905 update_buf->image_buf[i]);
1906 CDBG("ubwc meta addr 0x%llx\n",
1907 update_buf->image_buf[i]);
1908 }
1909
1910 /* WM Image address */
1911 if (wm_data->en_ubwc)
1912 CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j,
1913 wm_data->hw_regs->image_addr,
1914 (update_buf->image_buf[i] +
1915 io_cfg->planes[i].meta_size));
1916 else
1917 CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j,
1918 wm_data->hw_regs->image_addr,
1919 update_buf->image_buf[i]);
1920
1921 CDBG("image address 0x%x\n", reg_val_pair[j-1]);
1922
Junzhe Zou193d78c2017-05-16 15:10:54 -07001923 frame_inc = io_cfg->planes[i].plane_stride *
1924 io_cfg->planes[i].slice_height;
1925 CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j,
1926 wm_data->hw_regs->frame_inc, frame_inc);
1927
Jing Zhoua4e9fbe2017-05-15 14:37:21 -07001928 /* enable the WM */
1929 CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j,
1930 wm_data->hw_regs->cfg,
1931 wm_data->en_cfg);
1932
1933 /* set initial configuration done */
1934 if (!wm_data->init_cfg_done)
1935 wm_data->init_cfg_done = 1;
1936 }
1937
1938 size = vfe_out_data->cdm_util_ops->cdm_required_size_reg_random(j/2);
Harsh Shaha1af8822017-05-11 22:06:36 -07001939
1940 /* cdm util returns dwords, need to convert to bytes */
1941 if ((size * 4) > update_buf->cdm.size) {
1942 pr_err("Failed! Buf size:%d insufficient, expected size:%d\n",
1943 update_buf->cdm.size, size);
1944 return -ENOMEM;
1945 }
1946
Harsh Shaha1af8822017-05-11 22:06:36 -07001947 vfe_out_data->cdm_util_ops->cdm_write_regrandom(
Jing Zhoua4e9fbe2017-05-15 14:37:21 -07001948 update_buf->cdm.cmd_buf_addr, j/2, reg_val_pair);
1949
Harsh Shaha1af8822017-05-11 22:06:36 -07001950 /* cdm util returns dwords, need to convert to bytes */
1951 update_buf->cdm.used_bytes = size * 4;
1952
1953 return 0;
1954}
1955
1956static int cam_vfe_bus_process_cmd(void *priv,
1957 uint32_t cmd_type, void *cmd_args, uint32_t arg_size)
1958{
1959 int rc = -EINVAL;
1960
1961 if (!priv || !cmd_args) {
1962 pr_err_ratelimited("Error! Invalid input arguments\n");
1963 return -EINVAL;
1964 }
1965
1966 switch (cmd_type) {
1967 case CAM_VFE_HW_CMD_GET_BUF_UPDATE:
1968 rc = cam_vfe_bus_update_buf(priv, cmd_args, arg_size);
1969 break;
1970 default:
1971 pr_err_ratelimited("Error! Invalid camif process command:%d\n",
1972 cmd_type);
1973 break;
1974 }
1975
1976 return rc;
1977}
1978
1979int cam_vfe_bus_ver2_init(
1980 void __iomem *mem_base,
1981 struct cam_hw_intf *hw_intf,
1982 void *bus_hw_info,
1983 void *vfe_irq_controller,
1984 struct cam_vfe_bus **vfe_bus)
1985{
1986 int i, rc = 0;
1987 struct cam_vfe_bus_ver2_priv *bus_priv = NULL;
1988 struct cam_vfe_bus *vfe_bus_local;
1989 struct cam_vfe_bus_ver2_hw_info *ver2_hw_info = bus_hw_info;
1990
1991 CDBG("Enter\n");
1992
1993 vfe_bus_local = kzalloc(sizeof(struct cam_vfe_bus), GFP_KERNEL);
1994 if (!vfe_bus_local) {
1995 CDBG("Failed to alloc for vfe_bus\n");
1996 rc = -ENOMEM;
Harsh Shah545df9a2017-06-16 16:43:17 -07001997 goto end;
Harsh Shaha1af8822017-05-11 22:06:36 -07001998 }
1999
2000 bus_priv = kzalloc(sizeof(struct cam_vfe_bus_ver2_priv),
2001 GFP_KERNEL);
2002 if (!bus_priv) {
2003 CDBG("Failed to alloc for vfe_bus_priv\n");
2004 rc = -ENOMEM;
Harsh Shah545df9a2017-06-16 16:43:17 -07002005 goto free_bus_local;
Harsh Shaha1af8822017-05-11 22:06:36 -07002006 }
2007 vfe_bus_local->bus_priv = bus_priv;
2008
2009 bus_priv->common_data.mem_base = mem_base;
2010 bus_priv->common_data.hw_intf = hw_intf;
2011 bus_priv->common_data.vfe_irq_controller = vfe_irq_controller;
2012 bus_priv->common_data.common_reg = &ver2_hw_info->common_reg;
2013
2014 INIT_LIST_HEAD(&bus_priv->free_comp_grp);
2015 INIT_LIST_HEAD(&bus_priv->free_dual_comp_grp);
2016 INIT_LIST_HEAD(&bus_priv->used_comp_grp);
2017
2018 for (i = 0; i < CAM_VFE_BUS_VER2_MAX_CLIENTS; i++) {
2019 rc = cam_vfe_bus_init_wm_resource(i, bus_priv, bus_hw_info,
2020 &bus_priv->bus_client[i]);
2021 if (rc < 0) {
Harsh Shah545df9a2017-06-16 16:43:17 -07002022 pr_err("Error! Init WM failed rc=%d\n", rc);
2023 goto deinit_wm;
Harsh Shaha1af8822017-05-11 22:06:36 -07002024 }
2025 }
2026
2027 for (i = 0; i < CAM_VFE_BUS_VER2_COMP_GRP_MAX; i++) {
2028 rc = cam_vfe_bus_init_comp_grp(i, bus_priv, bus_hw_info,
2029 &bus_priv->comp_grp[i]);
2030 if (rc < 0) {
Harsh Shah545df9a2017-06-16 16:43:17 -07002031 pr_err("Error! Init Comp Grp failed rc=%d\n", rc);
2032 goto deinit_comp_grp;
Harsh Shaha1af8822017-05-11 22:06:36 -07002033 }
2034 }
2035
2036 for (i = 0; i < CAM_VFE_BUS_VER2_VFE_OUT_MAX; i++) {
2037 rc = cam_vfe_bus_init_vfe_out_resource(i, bus_priv, bus_hw_info,
2038 &bus_priv->vfe_out[i]);
2039 if (rc < 0) {
Harsh Shah545df9a2017-06-16 16:43:17 -07002040 pr_err("Error! Init VFE Out failed rc=%d\n", rc);
2041 goto deinit_vfe_out;
Harsh Shaha1af8822017-05-11 22:06:36 -07002042 }
2043 }
2044
2045 INIT_LIST_HEAD(&bus_priv->free_payload_list);
2046 for (i = 0; i < 128; i++) {
2047 INIT_LIST_HEAD(&bus_priv->evt_payload[i].list);
2048 list_add_tail(&bus_priv->evt_payload[i].list,
2049 &bus_priv->free_payload_list);
2050 }
2051
2052 vfe_bus_local->acquire_resource = cam_vfe_bus_acquire_vfe_out;
2053 vfe_bus_local->release_resource = cam_vfe_bus_release_vfe_out;
2054 vfe_bus_local->start_resource = cam_vfe_bus_start_vfe_out;
2055 vfe_bus_local->stop_resource = cam_vfe_bus_stop_vfe_out;
2056 vfe_bus_local->top_half_handler = cam_vfe_bus_ver2_handle_irq;
2057 vfe_bus_local->bottom_half_handler = NULL;
2058 vfe_bus_local->process_cmd = cam_vfe_bus_process_cmd;
2059
2060 *vfe_bus = vfe_bus_local;
2061
Harsh Shah545df9a2017-06-16 16:43:17 -07002062 CDBG("Exit\n");
Harsh Shaha1af8822017-05-11 22:06:36 -07002063 return rc;
2064
Harsh Shah545df9a2017-06-16 16:43:17 -07002065deinit_vfe_out:
2066 if (i < 0)
2067 i = CAM_VFE_BUS_VER2_VFE_OUT_MAX;
2068 for (--i; i >= 0; i--)
2069 cam_vfe_bus_deinit_vfe_out_resource(&bus_priv->vfe_out[i]);
2070
2071deinit_comp_grp:
2072 if (i < 0)
2073 i = CAM_VFE_BUS_VER2_COMP_GRP_MAX;
2074 for (--i; i >= 0; i--)
2075 cam_vfe_bus_deinit_comp_grp(&bus_priv->comp_grp[i]);
2076
2077deinit_wm:
2078 if (i < 0)
2079 i = CAM_VFE_BUS_VER2_MAX_CLIENTS;
2080 for (--i; i >= 0; i--)
2081 cam_vfe_bus_deinit_wm_resource(&bus_priv->bus_client[i]);
2082
Harsh Shaha1af8822017-05-11 22:06:36 -07002083 kfree(vfe_bus_local->bus_priv);
Harsh Shah545df9a2017-06-16 16:43:17 -07002084
2085free_bus_local:
Harsh Shaha1af8822017-05-11 22:06:36 -07002086 kfree(vfe_bus_local);
Harsh Shah545df9a2017-06-16 16:43:17 -07002087
2088end:
Harsh Shaha1af8822017-05-11 22:06:36 -07002089 return rc;
2090}
Harsh Shah545df9a2017-06-16 16:43:17 -07002091
2092int cam_vfe_bus_ver2_deinit(
2093 struct cam_vfe_bus **vfe_bus)
2094{
2095 int i, rc = 0;
2096 struct cam_vfe_bus_ver2_priv *bus_priv = NULL;
2097 struct cam_vfe_bus *vfe_bus_local;
2098
2099 if (!vfe_bus || !*vfe_bus) {
2100 pr_err("Error! Invalid input\n");
2101 return -EINVAL;
2102 }
2103 vfe_bus_local = *vfe_bus;
2104
2105 bus_priv = vfe_bus_local->bus_priv;
2106 if (!bus_priv) {
2107 pr_err("Error! bus_priv is NULL\n");
2108 rc = -ENODEV;
2109 goto free_bus_local;
2110 }
2111
2112 INIT_LIST_HEAD(&bus_priv->free_payload_list);
2113 for (i = 0; i < 128; i++)
2114 INIT_LIST_HEAD(&bus_priv->evt_payload[i].list);
2115
2116 for (i = 0; i < CAM_VFE_BUS_VER2_MAX_CLIENTS; i++) {
2117 rc = cam_vfe_bus_deinit_wm_resource(&bus_priv->bus_client[i]);
2118 if (rc < 0)
2119 pr_err("Error! Deinit WM failed rc=%d\n", rc);
2120 }
2121
2122 for (i = 0; i < CAM_VFE_BUS_VER2_COMP_GRP_MAX; i++) {
2123 rc = cam_vfe_bus_deinit_comp_grp(&bus_priv->comp_grp[i]);
2124 if (rc < 0)
2125 pr_err("Error! Deinit Comp Grp failed rc=%d\n", rc);
2126 }
2127
2128 for (i = 0; i < CAM_VFE_BUS_VER2_VFE_OUT_MAX; i++) {
2129 rc = cam_vfe_bus_deinit_vfe_out_resource(&bus_priv->vfe_out[i]);
2130 if (rc < 0)
2131 pr_err("Error! Deinit VFE Out failed rc=%d\n", rc);
2132 }
2133
2134 INIT_LIST_HEAD(&bus_priv->free_comp_grp);
2135 INIT_LIST_HEAD(&bus_priv->free_dual_comp_grp);
2136 INIT_LIST_HEAD(&bus_priv->used_comp_grp);
2137
2138 kfree(vfe_bus_local->bus_priv);
2139
2140free_bus_local:
2141 kfree(vfe_bus_local);
2142
2143 *vfe_bus = NULL;
2144
2145 return rc;
2146}
2147