blob: 8dbefd8a0978ef1f0f820283c35af3fde323ee51 [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);
Jing Zhoue71fd4a2017-05-15 19:44:34 -0700986 else if (in_rsrc_data->comp_grp_type >= CAM_VFE_BUS_VER2_COMP_GRP_0
987 && in_rsrc_data->comp_grp_type <= CAM_VFE_BUS_VER2_COMP_GRP_5)
Harsh Shaha1af8822017-05-11 22:06:36 -0700988 list_add_tail(&comp_grp->list, &ver2_bus_priv->free_comp_grp);
989
Harsh Shaha1af8822017-05-11 22:06:36 -0700990 in_rsrc_data->unique_id = 0;
991 in_rsrc_data->comp_grp_local_idx = 0;
992 in_rsrc_data->composite_mask = 0;
993 in_rsrc_data->dual_slave_core = CAM_VFE_BUS_VER2_VFE_CORE_MAX;
994
995 comp_grp->res_state = CAM_ISP_RESOURCE_STATE_AVAILABLE;
996
Jing Zhoue71fd4a2017-05-15 19:44:34 -0700997 return 0;
Harsh Shaha1af8822017-05-11 22:06:36 -0700998}
999
1000static int cam_vfe_bus_start_comp_grp(struct cam_isp_resource_node *comp_grp)
1001{
1002 int rc = 0;
1003 struct cam_vfe_bus_ver2_comp_grp_data *rsrc_data =
1004 comp_grp->res_priv;
1005 struct cam_vfe_bus_ver2_common_data *common_data =
1006 rsrc_data->common_data;
1007
1008 /*
1009 * Individual Comp_Grp Subscribe IRQ can be done here once
1010 * dynamic IRQ enable support is added.
1011 */
Harsh Shaha1af8822017-05-11 22:06:36 -07001012
1013 cam_io_w_mb(rsrc_data->composite_mask, common_data->mem_base +
1014 rsrc_data->hw_regs->comp_mask);
1015
1016 CDBG("composite_mask is 0x%x\n", rsrc_data->composite_mask);
1017 CDBG("composite_mask addr 0x%x\n", rsrc_data->hw_regs->comp_mask);
1018
1019 if (rsrc_data->comp_grp_type >= CAM_VFE_BUS_VER2_COMP_GRP_DUAL_0 &&
1020 rsrc_data->comp_grp_type <= CAM_VFE_BUS_VER2_COMP_GRP_DUAL_5 &&
1021 rsrc_data->is_master) {
1022 int dual_comp_grp = (rsrc_data->comp_grp_type -
1023 CAM_VFE_BUS_VER2_COMP_GRP_DUAL_0);
1024 int intra_client_en = cam_io_r_mb(common_data->mem_base +
1025 common_data->common_reg->dual_master_comp_cfg);
1026
1027 /* 2 Bits per comp_grp. Hence left shift by comp_grp * 2 */
1028 intra_client_en |=
1029 (rsrc_data->intra_client_mask << dual_comp_grp * 2);
1030
1031 cam_io_w_mb(intra_client_en, common_data->mem_base +
1032 common_data->common_reg->dual_master_comp_cfg);
1033 }
1034
1035 comp_grp->res_state = CAM_ISP_RESOURCE_STATE_STREAMING;
1036 return rc;
1037}
1038
1039static int cam_vfe_bus_stop_comp_grp(struct cam_isp_resource_node *comp_grp)
1040{
1041 int rc = 0;
1042 struct cam_vfe_bus_ver2_comp_grp_data *rsrc_data =
1043 comp_grp->res_priv;
1044 struct cam_vfe_bus_ver2_common_data *common_data =
1045 rsrc_data->common_data;
1046
1047 /* Unsubscribe IRQ */
1048
1049 cam_io_w_mb(rsrc_data->composite_mask, common_data->mem_base +
1050 rsrc_data->hw_regs->comp_mask);
1051 if (rsrc_data->comp_grp_type >= CAM_VFE_BUS_VER2_COMP_GRP_DUAL_0 &&
1052 rsrc_data->comp_grp_type <= CAM_VFE_BUS_VER2_COMP_GRP_DUAL_5 &&
1053 rsrc_data->is_master) {
1054 int dual_comp_grp = (rsrc_data->comp_grp_type -
1055 CAM_VFE_BUS_VER2_COMP_GRP_DUAL_0);
1056 int intra_client_en = cam_io_r_mb(common_data->mem_base +
1057 common_data->common_reg->dual_master_comp_cfg);
1058
1059 /* 2 Bits per comp_grp. Hence left shift by comp_grp * 2 */
1060 intra_client_en &=
1061 ~(rsrc_data->intra_client_mask << dual_comp_grp * 2);
1062
1063 cam_io_w_mb(intra_client_en, common_data->mem_base +
1064 common_data->common_reg->dual_master_comp_cfg);
1065 }
1066
1067 comp_grp->res_state = CAM_ISP_RESOURCE_STATE_RESERVED;
1068
1069 return rc;
1070}
1071
1072static int cam_vfe_bus_handle_comp_done_top_half(uint32_t evt_id,
1073 struct cam_irq_th_payload *th_payload)
1074{
1075 return -EPERM;
1076}
1077
1078static int cam_vfe_bus_handle_comp_done_bottom_half(
1079 void *handler_priv,
1080 void *evt_payload_priv)
1081{
1082 int rc = CAM_VFE_IRQ_STATUS_ERR;
1083 struct cam_isp_resource_node *comp_grp = handler_priv;
1084 struct cam_vfe_bus_irq_evt_payload *evt_payload = evt_payload_priv;
1085 struct cam_vfe_bus_ver2_comp_grp_data *rsrc_data = comp_grp->res_priv;
Harsh Shah23557ae2017-05-13 18:14:34 -07001086 uint32_t *cam_ife_irq_regs;
1087 uint32_t status_reg;
1088 uint32_t comp_err_reg;
1089 uint32_t comp_grp_id;
1090
1091 if (!evt_payload)
1092 return rc;
1093
1094 cam_ife_irq_regs = evt_payload->irq_reg_val;
Harsh Shaha1af8822017-05-11 22:06:36 -07001095
1096 CDBG("comp grp type %d\n", rsrc_data->comp_grp_type);
1097 switch (rsrc_data->comp_grp_type) {
1098 case CAM_VFE_BUS_VER2_COMP_GRP_0:
1099 case CAM_VFE_BUS_VER2_COMP_GRP_1:
1100 case CAM_VFE_BUS_VER2_COMP_GRP_2:
1101 case CAM_VFE_BUS_VER2_COMP_GRP_3:
1102 case CAM_VFE_BUS_VER2_COMP_GRP_4:
1103 case CAM_VFE_BUS_VER2_COMP_GRP_5:
Harsh Shah23557ae2017-05-13 18:14:34 -07001104 comp_grp_id = (rsrc_data->comp_grp_type -
Harsh Shaha1af8822017-05-11 22:06:36 -07001105 CAM_VFE_BUS_VER2_COMP_GRP_0);
1106
1107 /* Check for Regular composite error */
1108 status_reg = cam_ife_irq_regs[CAM_IFE_IRQ_BUS_REG_STATUS0];
1109
1110 comp_err_reg = cam_ife_irq_regs[CAM_IFE_IRQ_BUS_REG_COMP_ERR];
1111 if ((status_reg & BIT(11)) &&
1112 (comp_err_reg & rsrc_data->composite_mask)) {
1113 /* Check for Regular composite error */
1114 rc = CAM_VFE_IRQ_STATUS_ERR_COMP;
1115 break;
1116 }
1117
1118 comp_err_reg = cam_ife_irq_regs[CAM_IFE_IRQ_BUS_REG_COMP_OWRT];
1119 /* Check for Regular composite Overwrite */
1120 if ((status_reg & BIT(12)) &&
1121 (comp_err_reg & rsrc_data->composite_mask)) {
1122 rc = CAM_VFE_IRQ_STATUS_COMP_OWRT;
1123 break;
1124 }
1125
Harsh Shah23557ae2017-05-13 18:14:34 -07001126 /* Regular Composite SUCCESS */
1127 if (status_reg & BIT(comp_grp_id + 5)) {
1128 cam_ife_irq_regs[CAM_IFE_IRQ_BUS_REG_STATUS0] &=
1129 ~BIT(comp_grp_id + 5);
Harsh Shaha1af8822017-05-11 22:06:36 -07001130 rc = CAM_VFE_IRQ_STATUS_SUCCESS;
Harsh Shah23557ae2017-05-13 18:14:34 -07001131 }
Harsh Shaha1af8822017-05-11 22:06:36 -07001132
1133 CDBG("status reg = 0x%x, bit index = %d\n",
Harsh Shah23557ae2017-05-13 18:14:34 -07001134 status_reg, (comp_grp_id + 5));
Harsh Shaha1af8822017-05-11 22:06:36 -07001135 break;
1136
1137 case CAM_VFE_BUS_VER2_COMP_GRP_DUAL_0:
1138 case CAM_VFE_BUS_VER2_COMP_GRP_DUAL_1:
1139 case CAM_VFE_BUS_VER2_COMP_GRP_DUAL_2:
1140 case CAM_VFE_BUS_VER2_COMP_GRP_DUAL_3:
1141 case CAM_VFE_BUS_VER2_COMP_GRP_DUAL_4:
1142 case CAM_VFE_BUS_VER2_COMP_GRP_DUAL_5:
Harsh Shah23557ae2017-05-13 18:14:34 -07001143 comp_grp_id = (rsrc_data->comp_grp_type -
Harsh Shaha1af8822017-05-11 22:06:36 -07001144 CAM_VFE_BUS_VER2_COMP_GRP_DUAL_0);
1145
1146 /* Check for DUAL composite error */
1147 status_reg = cam_ife_irq_regs[CAM_IFE_IRQ_BUS_REG_STATUS2];
1148
1149 comp_err_reg = cam_ife_irq_regs[CAM_IFE_IRQ_BUS_DUAL_COMP_ERR];
1150 if ((status_reg & BIT(6)) &&
1151 (comp_err_reg & rsrc_data->composite_mask)) {
1152 /* Check for DUAL composite error */
1153 rc = CAM_VFE_IRQ_STATUS_ERR_COMP;
1154 break;
1155 }
1156
1157 /* Check for Dual composite Overwrite */
1158 comp_err_reg = cam_ife_irq_regs[CAM_IFE_IRQ_BUS_DUAL_COMP_OWRT];
1159 if ((status_reg & BIT(7)) &&
1160 (comp_err_reg & rsrc_data->composite_mask)) {
1161 rc = CAM_VFE_IRQ_STATUS_COMP_OWRT;
1162 break;
1163 }
1164
Harsh Shah23557ae2017-05-13 18:14:34 -07001165 /* DUAL Composite SUCCESS */
1166 if (status_reg & BIT(comp_grp_id)) {
1167 cam_ife_irq_regs[CAM_IFE_IRQ_BUS_REG_STATUS2] &=
1168 ~BIT(comp_grp_id + 5);
Harsh Shaha1af8822017-05-11 22:06:36 -07001169 rc = CAM_VFE_IRQ_STATUS_SUCCESS;
Harsh Shah23557ae2017-05-13 18:14:34 -07001170 }
Harsh Shaha1af8822017-05-11 22:06:36 -07001171
1172 break;
Harsh Shaha1af8822017-05-11 22:06:36 -07001173 default:
1174 rc = CAM_VFE_IRQ_STATUS_ERR;
1175 break;
1176 }
1177
1178 if (rc == CAM_VFE_IRQ_STATUS_SUCCESS)
1179 cam_vfe_bus_put_evt_payload(evt_payload->core_info,
1180 &evt_payload);
1181
1182 return rc;
1183}
1184
1185static int cam_vfe_bus_init_comp_grp(uint32_t index,
1186 struct cam_vfe_bus_ver2_priv *ver2_bus_priv,
1187 struct cam_vfe_bus_ver2_hw_info *ver2_hw_info,
1188 struct cam_isp_resource_node *comp_grp)
1189{
1190 struct cam_vfe_bus_ver2_comp_grp_data *rsrc_data =
1191 comp_grp->res_priv;
1192
1193 rsrc_data = kzalloc(sizeof(struct cam_vfe_bus_ver2_comp_grp_data),
1194 GFP_KERNEL);
1195 if (!rsrc_data) {
1196 CDBG("Failed to alloc for comp_grp_priv\n");
1197 return -ENOMEM;
1198 }
1199 comp_grp->res_priv = rsrc_data;
1200
1201 comp_grp->res_state = CAM_ISP_RESOURCE_STATE_AVAILABLE;
1202 INIT_LIST_HEAD(&comp_grp->list);
1203
1204 rsrc_data->comp_grp_type = index;
1205 rsrc_data->common_data = &ver2_bus_priv->common_data;
1206 rsrc_data->hw_regs = &ver2_hw_info->comp_grp_reg[index];
1207 rsrc_data->dual_slave_core = CAM_VFE_BUS_VER2_VFE_CORE_MAX;
1208
1209
1210 if (rsrc_data->comp_grp_type >= CAM_VFE_BUS_VER2_COMP_GRP_DUAL_0 &&
1211 rsrc_data->comp_grp_type <= CAM_VFE_BUS_VER2_COMP_GRP_DUAL_5)
1212 list_add_tail(&comp_grp->list,
1213 &ver2_bus_priv->free_dual_comp_grp);
1214 else if (rsrc_data->comp_grp_type >= CAM_VFE_BUS_VER2_COMP_GRP_0
1215 && rsrc_data->comp_grp_type <= CAM_VFE_BUS_VER2_COMP_GRP_5)
1216 list_add_tail(&comp_grp->list, &ver2_bus_priv->free_comp_grp);
1217
1218 comp_grp->start = cam_vfe_bus_start_comp_grp;
1219 comp_grp->stop = cam_vfe_bus_stop_comp_grp;
1220 comp_grp->top_half_handler = cam_vfe_bus_handle_comp_done_top_half;
1221 comp_grp->bottom_half_handler =
1222 cam_vfe_bus_handle_comp_done_bottom_half;
1223 comp_grp->hw_intf = ver2_bus_priv->common_data.hw_intf;
1224
1225 return 0;
1226}
1227
1228static int cam_vfe_bus_acquire_vfe_out(void *bus_priv, void *acquire_args)
1229{
1230 int rc = -ENODEV;
1231 int i;
1232 enum cam_vfe_bus_ver2_vfe_out_type vfe_out_res_id;
1233 uint32_t format;
1234 uint32_t num_wm;
1235 uint32_t subscribe_irq;
1236 uint32_t client_done_mask;
1237 struct cam_vfe_bus_ver2_priv *ver2_bus_priv = bus_priv;
1238 struct cam_vfe_acquire_args *acq_args = acquire_args;
1239 struct cam_vfe_hw_vfe_out_acquire_args *out_acquire_args;
1240 struct cam_isp_resource_node *rsrc_node = NULL;
1241 struct cam_vfe_bus_ver2_vfe_out_data *rsrc_data = NULL;
1242
1243 if (!bus_priv || !acquire_args) {
1244 pr_err("Invalid Param");
1245 return -EINVAL;
1246 }
1247
1248 out_acquire_args = &acq_args->vfe_out;
1249 format = out_acquire_args->out_port_info->format;
1250
1251 CDBG("Acquiring resource type 0x%x\n",
1252 out_acquire_args->out_port_info->res_type);
1253
1254 vfe_out_res_id = cam_vfe_bus_get_out_res_id(
1255 out_acquire_args->out_port_info->res_type);
1256 if (vfe_out_res_id == CAM_VFE_BUS_VER2_VFE_OUT_MAX)
1257 return -ENODEV;
1258
1259 num_wm = cam_vfe_bus_get_num_wm(vfe_out_res_id, format);
1260 if (num_wm < 1)
1261 return -EINVAL;
1262
1263 rsrc_node = &ver2_bus_priv->vfe_out[vfe_out_res_id];
1264 if (rsrc_node->res_state != CAM_ISP_RESOURCE_STATE_AVAILABLE) {
1265 pr_err("Resource not available: Res_id %d state:%d\n",
1266 vfe_out_res_id, rsrc_node->res_state);
1267 return -EBUSY;
1268 }
1269
1270 rsrc_data = rsrc_node->res_priv;
1271 rsrc_data->num_wm = num_wm;
1272 rsrc_node->res_id = out_acquire_args->out_port_info->res_type;
1273 rsrc_node->tasklet_info = acq_args->tasklet;
1274 rsrc_node->cdm_ops = out_acquire_args->cdm_ops;
1275 rsrc_data->cdm_util_ops = out_acquire_args->cdm_ops;
1276
1277 /* Reserve Composite Group */
1278 if (num_wm > 1 || (out_acquire_args->out_port_info->comp_grp_id >
1279 CAM_ISP_RES_COMP_GROUP_NONE &&
1280 out_acquire_args->out_port_info->comp_grp_id <
1281 CAM_ISP_RES_COMP_GROUP_ID_MAX)) {
1282 rc = cam_vfe_bus_acquire_comp_grp(ver2_bus_priv,
1283 out_acquire_args->out_port_info,
1284 out_acquire_args->unique_id,
1285 out_acquire_args->is_dual,
1286 out_acquire_args->is_master,
1287 out_acquire_args->dual_slave_core,
1288 &rsrc_data->comp_grp);
1289 if (rc < 0)
1290 return rc;
1291
1292 subscribe_irq = 0;
1293 } else
1294 subscribe_irq = 1;
1295
1296 /* Reserve WM */
1297 for (i = 0; i < num_wm; i++) {
1298 rc = cam_vfe_bus_acquire_wm(ver2_bus_priv,
1299 out_acquire_args->out_port_info,
1300 vfe_out_res_id,
1301 i,
1302 out_acquire_args->split_id,
1303 subscribe_irq,
1304 &rsrc_data->wm_res[i],
1305 &client_done_mask);
1306 if (rc < 0)
1307 goto release_wm;
1308
1309 if (rsrc_data->comp_grp)
1310 cam_vfe_bus_add_wm_to_comp_grp(rsrc_data->comp_grp,
1311 client_done_mask);
1312 }
1313
1314 rsrc_node->res_state = CAM_ISP_RESOURCE_STATE_RESERVED;
1315 out_acquire_args->rsrc_node = rsrc_node;
1316
1317 CDBG("Acquire successful\n");
1318 return rc;
1319
1320release_wm:
1321 for (i--; i >= 0; i--)
1322 cam_vfe_bus_release_wm(ver2_bus_priv, rsrc_data->wm_res[i]);
1323
1324 cam_vfe_bus_release_comp_grp(ver2_bus_priv,
1325 rsrc_data->comp_grp);
1326
1327 return rc;
1328}
1329
1330static int cam_vfe_bus_release_vfe_out(void *bus_priv,
1331 struct cam_isp_resource_node *vfe_out)
1332{
Jing Zhoue71fd4a2017-05-15 19:44:34 -07001333 uint32_t i;
1334 struct cam_vfe_bus_ver2_vfe_out_data *rsrc_data = vfe_out->res_priv;
1335
Harsh Shaha1af8822017-05-11 22:06:36 -07001336 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
Jing Zhoue71fd4a2017-05-15 19:44:34 -07001341 for (i = 0; i < rsrc_data->num_wm; i++)
1342 cam_vfe_bus_release_wm(bus_priv, rsrc_data->wm_res[i]);
1343 rsrc_data->num_wm = 0;
1344
1345 if (rsrc_data->comp_grp)
1346 cam_vfe_bus_release_comp_grp(bus_priv, rsrc_data->comp_grp);
1347 rsrc_data->comp_grp = NULL;
1348
1349 vfe_out->tasklet_info = NULL;
1350 vfe_out->cdm_ops = NULL;
1351 rsrc_data->cdm_util_ops = NULL;
1352
Harsh Shaha1af8822017-05-11 22:06:36 -07001353 if (vfe_out->res_state == CAM_ISP_RESOURCE_STATE_RESERVED)
1354 vfe_out->res_state = CAM_ISP_RESOURCE_STATE_AVAILABLE;
1355
1356 return 0;
1357}
1358
1359static int cam_vfe_bus_start_vfe_out(struct cam_isp_resource_node *vfe_out)
1360{
1361 int rc = 0, i;
Harsh Shah23557ae2017-05-13 18:14:34 -07001362 struct cam_vfe_bus_ver2_vfe_out_data *rsrc_data = vfe_out->res_priv;
1363 struct cam_vfe_bus_ver2_common_data *common_data =
1364 rsrc_data->common_data;
Harsh Shaha1af8822017-05-11 22:06:36 -07001365
1366 CDBG("Start resource index %d\n", rsrc_data->out_type);
1367
1368 if (vfe_out->res_state != CAM_ISP_RESOURCE_STATE_RESERVED) {
1369 pr_err("Error! Invalid resource state:%d\n",
1370 vfe_out->res_state);
1371 return -EACCES;
1372 }
1373
Harsh Shah23557ae2017-05-13 18:14:34 -07001374 /* Enable IRQ Mask */
Jing Zhoue71fd4a2017-05-15 19:44:34 -07001375 cam_io_w_mb(0x00001FE0, common_data->mem_base + 0x2044);
Harsh Shah23557ae2017-05-13 18:14:34 -07001376 cam_io_w_mb(0x000FFFE7, common_data->mem_base + 0x2048);
1377 cam_io_w_mb(0x000000FF, common_data->mem_base + 0x204c);
1378
Harsh Shaha1af8822017-05-11 22:06:36 -07001379 for (i = 0; i < rsrc_data->num_wm; i++)
1380 rc = cam_vfe_bus_start_wm(rsrc_data->wm_res[i]);
1381
1382 if (rsrc_data->comp_grp)
1383 rc = cam_vfe_bus_start_comp_grp(rsrc_data->comp_grp);
1384
1385 /* VFE_MODULE_BUS_CGC_OVERRIDE */
1386 cam_io_w_mb(0xFFFFFFFF, rsrc_data->common_data->mem_base + 0x0000003C);
1387 /* VFE_MODULE_COLOR_CGC_OVERRIDE */
1388 cam_io_w_mb(0xFFFFFFFF, rsrc_data->common_data->mem_base + 0x00000034);
1389 /* VFE_MODULE_ZOOM_CGC_OVERRIDE */
1390 cam_io_w_mb(0xFFFFFFFF, rsrc_data->common_data->mem_base + 0x38);
1391 /* VFE_MODULE_LENS_CGC_OVERRIDE */
1392 cam_io_w_mb(0xFFFFFFFF, rsrc_data->common_data->mem_base + 0x0000002C);
1393 /* VFE_MODULE_STATS_CGC_OVERRIDE */
1394 cam_io_w_mb(0xFFFFFFFF, rsrc_data->common_data->mem_base + 0x00000030);
1395
1396 /* BUS_WR_INPUT_IF_ADDR_SYNC_CFG */
1397 cam_io_w_mb(0x0, rsrc_data->common_data->mem_base + 0x0000207C);
1398 /* BUS_WR_INPUT_IF_ADDR_SYNC_FRAME_HEADER */
1399 cam_io_w_mb(0x0, rsrc_data->common_data->mem_base + 0x00002080);
1400 /* BUS_WR_INPUT_IF_ADDR_SYNC_NO_SYNC */
1401 cam_io_w_mb(0xFFFFF, rsrc_data->common_data->mem_base + 0x00002084);
Harsh Shaha1af8822017-05-11 22:06:36 -07001402 /* BUS_WR_INPUT_IF_ADDR_SYNC_0 */
1403 cam_io_w_mb(0x0, rsrc_data->common_data->mem_base + 0x00002088);
1404 cam_io_w_mb(0x0, rsrc_data->common_data->mem_base + 0x0000208c);
1405 cam_io_w_mb(0x0, rsrc_data->common_data->mem_base + 0x00002090);
1406 cam_io_w_mb(0x0, rsrc_data->common_data->mem_base + 0x00002094);
1407 cam_io_w_mb(0x0, rsrc_data->common_data->mem_base + 0x00002098);
1408 cam_io_w_mb(0x0, rsrc_data->common_data->mem_base + 0x0000209c);
1409 cam_io_w_mb(0x0, rsrc_data->common_data->mem_base + 0x000020a0);
1410 cam_io_w_mb(0x0, rsrc_data->common_data->mem_base + 0x000020a4);
1411
Harsh Shah23557ae2017-05-13 18:14:34 -07001412 /* no clock gating at bus input */
1413 cam_io_w_mb(0xFFFFF, rsrc_data->common_data->mem_base + 0x0000200C);
1414
1415 /* BUS_WR_TEST_BUS_CTRL */
1416 cam_io_w_mb(0x0, rsrc_data->common_data->mem_base + 0x0000211C);
1417
Harsh Shaha1af8822017-05-11 22:06:36 -07001418 return rc;
1419}
1420
1421static int cam_vfe_bus_stop_vfe_out(struct cam_isp_resource_node *vfe_out)
1422{
1423 int rc = 0, i;
1424 struct cam_vfe_bus_ver2_vfe_out_data *rsrc_data = vfe_out->res_priv;
1425
1426 if (vfe_out->res_state == CAM_ISP_RESOURCE_STATE_AVAILABLE ||
1427 vfe_out->res_state == CAM_ISP_RESOURCE_STATE_RESERVED) {
1428 return rc;
1429 }
1430
1431 if (rsrc_data->comp_grp)
1432 rc = cam_vfe_bus_stop_comp_grp(rsrc_data->comp_grp);
1433
1434 for (i = 0; i < rsrc_data->num_wm; i++)
1435 rc = cam_vfe_bus_stop_wm(rsrc_data->wm_res[i]);
1436
1437 vfe_out->res_state = CAM_ISP_RESOURCE_STATE_STREAMING;
1438
1439 vfe_out->res_state = CAM_ISP_RESOURCE_STATE_RESERVED;
1440 return rc;
1441}
1442
1443static int cam_vfe_bus_handle_vfe_out_done_top_half(uint32_t evt_id,
1444 struct cam_irq_th_payload *th_payload)
1445{
1446 return -EPERM;
1447}
1448
1449static int cam_vfe_bus_handle_vfe_out_done_bottom_half(
1450 void *handler_priv,
1451 void *evt_payload_priv)
1452{
1453 int rc = -EINVAL;
1454 struct cam_isp_resource_node *vfe_out = handler_priv;
1455 struct cam_vfe_bus_ver2_vfe_out_data *rsrc_data = vfe_out->res_priv;
1456
1457 /*
1458 * If this resource has Composite Group then we only handle
1459 * Composite done. We acquire Composite if number of WM > 1.
1460 * So Else case is only one individual buf_done = WM[0].
1461 */
1462 if (rsrc_data->comp_grp) {
1463 rc = rsrc_data->comp_grp->bottom_half_handler(
1464 rsrc_data->comp_grp, evt_payload_priv);
1465 } else {
1466 rc = rsrc_data->wm_res[0]->bottom_half_handler(
Harsh Shah23557ae2017-05-13 18:14:34 -07001467 rsrc_data->wm_res[0], evt_payload_priv);
Harsh Shaha1af8822017-05-11 22:06:36 -07001468 }
1469
1470 return rc;
1471}
1472
1473static int cam_vfe_bus_init_vfe_out_resource(uint32_t index,
1474 struct cam_vfe_bus_ver2_priv *ver2_bus_priv,
1475 struct cam_vfe_bus_ver2_hw_info *ver2_hw_info,
1476 struct cam_isp_resource_node *vfe_out)
1477{
1478 struct cam_vfe_bus_ver2_vfe_out_data *rsrc_data = NULL;
1479 int rc = 0;
1480
1481 rsrc_data = kzalloc(sizeof(struct cam_vfe_bus_ver2_vfe_out_data),
1482 GFP_KERNEL);
1483 if (!rsrc_data) {
1484 CDBG("Error! Failed to alloc for vfe out priv\n");
1485 rc = -ENOMEM;
1486 return rc;
1487 }
1488 vfe_out->res_priv = rsrc_data;
1489
1490 vfe_out->res_type = CAM_ISP_RESOURCE_VFE_OUT;
1491 vfe_out->res_state = CAM_ISP_RESOURCE_STATE_AVAILABLE;
1492 INIT_LIST_HEAD(&vfe_out->list);
1493
1494 rsrc_data->out_type = index;
1495 rsrc_data->common_data = &ver2_bus_priv->common_data;
1496 rsrc_data->max_width =
1497 ver2_hw_info->vfe_out_hw_info[index].max_width;
1498 rsrc_data->max_height =
1499 ver2_hw_info->vfe_out_hw_info[index].max_height;
1500
1501 vfe_out->start = cam_vfe_bus_start_vfe_out;
1502 vfe_out->stop = cam_vfe_bus_stop_vfe_out;
1503 vfe_out->top_half_handler = cam_vfe_bus_handle_vfe_out_done_top_half;
1504 vfe_out->bottom_half_handler =
1505 cam_vfe_bus_handle_vfe_out_done_bottom_half;
1506 vfe_out->hw_intf = ver2_bus_priv->common_data.hw_intf;
1507
1508 return 0;
1509}
1510
1511static int cam_vfe_bus_get_evt_payload(
1512 struct cam_vfe_bus_ver2_priv *bus_priv,
1513 struct cam_vfe_bus_irq_evt_payload **evt_payload)
1514{
1515 if (list_empty(&bus_priv->free_payload_list)) {
Harsh Shah23557ae2017-05-13 18:14:34 -07001516 *evt_payload = NULL;
Harsh Shaha1af8822017-05-11 22:06:36 -07001517 pr_err("No free payload\n");
1518 return -ENODEV;
1519 }
1520
1521 *evt_payload = list_first_entry(&bus_priv->free_payload_list,
1522 struct cam_vfe_bus_irq_evt_payload, list);
1523 list_del_init(&(*evt_payload)->list);
1524 return 0;
1525}
1526
1527static int cam_vfe_bus_put_evt_payload(void *core_info,
1528 struct cam_vfe_bus_irq_evt_payload **evt_payload)
1529{
1530 struct cam_vfe_bus_ver2_priv *bus_priv = NULL;
Harsh Shah23557ae2017-05-13 18:14:34 -07001531 uint32_t *cam_ife_irq_regs = (*evt_payload)->irq_reg_val;
1532 uint32_t status_reg0, status_reg1;
1533
1534 status_reg0 = cam_ife_irq_regs[CAM_IFE_IRQ_BUS_REG_STATUS0];
1535 status_reg1 = cam_ife_irq_regs[CAM_IFE_IRQ_BUS_REG_STATUS1];
1536
1537 if (status_reg0 || status_reg1) {
1538 CDBG("status0 0x%x status1 0x%x\n", status_reg0, status_reg1);
1539 return 0;
1540 }
Harsh Shaha1af8822017-05-11 22:06:36 -07001541
1542 if (!core_info) {
1543 pr_err("Invalid param core_info NULL");
1544 return -EINVAL;
1545 }
1546 if (*evt_payload == NULL) {
1547 pr_err("No payload to put\n");
1548 return -EINVAL;
1549 }
1550 bus_priv = (*evt_payload)->bus_priv;
1551 list_add_tail(&(*evt_payload)->list, &bus_priv->free_payload_list);
1552 *evt_payload = NULL;
1553 return 0;
1554}
1555
1556static int cam_vfe_bus_ver2_handle_irq(uint32_t evt_id,
1557 struct cam_irq_th_payload *th_payload)
1558{
1559 int32_t rc;
1560 int i;
1561 struct cam_vfe_irq_handler_priv *handler_priv;
1562 struct cam_vfe_hw_core_info *core_info;
1563 struct cam_vfe_bus_irq_evt_payload *evt_payload;
1564 struct cam_vfe_bus *bus_info;
1565 struct cam_vfe_bus_ver2_priv *bus_priv;
1566 struct cam_irq_controller_reg_info *reg_info;
Harsh Shah23557ae2017-05-13 18:14:34 -07001567 uint32_t irq_mask;
Harsh Shaha1af8822017-05-11 22:06:36 -07001568
1569 handler_priv = th_payload->handler_priv;
1570 core_info = handler_priv->core_info;
1571 bus_info = core_info->vfe_bus;
1572 bus_priv = bus_info->bus_priv;
1573 reg_info = &bus_priv->common_data.common_reg->irq_reg_info;
1574
1575 /*
1576 * add reset ack handling here once supported.
1577 * Just clear all the bus irq status registers and ignore the reset.
1578 */
1579
1580 CDBG("Enter\n");
1581 rc = cam_vfe_bus_get_evt_payload(bus_priv, &evt_payload);
1582 if (rc) {
1583 pr_err("No tasklet_cmd is free in queue\n");
1584 return rc;
1585 }
1586
1587 cam_isp_hw_get_timestamp(&evt_payload->ts);
1588
1589 evt_payload->core_index = handler_priv->core_index;
1590 evt_payload->core_info = handler_priv->core_info;
1591 evt_payload->bus_priv = bus_priv;
1592 CDBG("core_idx %d, core_info %llx\n", handler_priv->core_index,
1593 (uint64_t)handler_priv->core_info);
1594
1595 for (i = 0; i < CAM_IFE_BUS_IRQ_REGISTERS_MAX; i++) {
Harsh Shah23557ae2017-05-13 18:14:34 -07001596 irq_mask = cam_io_r(handler_priv->mem_base +
1597 irq_reg_offset[i] - (0xC * 2));
1598 evt_payload->irq_reg_val[i] = irq_mask &
1599 cam_io_r(handler_priv->mem_base + irq_reg_offset[i]);
Harsh Shaha1af8822017-05-11 22:06:36 -07001600 CDBG("irq_status%d = 0x%x\n", i, evt_payload->irq_reg_val[i]);
1601 }
1602 for (i = 0; i <= CAM_IFE_IRQ_BUS_REG_STATUS2; i++) {
1603 cam_io_w(evt_payload->irq_reg_val[i], handler_priv->mem_base +
1604 reg_info->irq_reg_set[i].clear_reg_offset);
1605 CDBG("Clear irq_status%d = 0x%x offset 0x%x\n", i,
1606 evt_payload->irq_reg_val[i],
1607 reg_info->irq_reg_set[i].clear_reg_offset);
1608 }
1609 cam_io_w(reg_info->global_clear_bitmask, handler_priv->mem_base +
1610 reg_info->global_clear_offset);
1611 CDBG("Global clear bitmask = 0x%x offset 0x%x\n",
1612 reg_info->global_clear_bitmask,
1613 reg_info->global_clear_offset);
1614
1615 th_payload->evt_payload_priv = evt_payload;
1616
1617 return rc;
1618}
1619
1620static int cam_vfe_bus_update_buf(void *priv, void *cmd_args,
1621 uint32_t arg_size)
1622{
1623 struct cam_vfe_bus_ver2_priv *bus_priv;
1624 struct cam_isp_hw_get_buf_update *update_buf;
1625 struct cam_vfe_bus_ver2_vfe_out_data *vfe_out_data = NULL;
1626 struct cam_vfe_bus_ver2_wm_resource_data *wm_data = NULL;
Harsh Shah23557ae2017-05-13 18:14:34 -07001627 uint32_t reg_val_pair[8];
Harsh Shaha1af8822017-05-11 22:06:36 -07001628 uint32_t i, size = 0;
1629
1630 /*
1631 * Need the entire buf io config so we can get the stride info
1632 * for the wm.
1633 */
1634
1635 bus_priv = (struct cam_vfe_bus_ver2_priv *) priv;
1636 update_buf = (struct cam_isp_hw_get_buf_update *) cmd_args;
1637
1638 vfe_out_data = (struct cam_vfe_bus_ver2_vfe_out_data *)
1639 update_buf->cdm.res->res_priv;
1640
1641 if (!vfe_out_data || !vfe_out_data->cdm_util_ops) {
1642 pr_err("Failed! Invalid data\n");
1643 return -EINVAL;
1644 }
1645
1646 if (update_buf->num_buf < vfe_out_data->num_wm) {
1647 pr_err("Failed! Invalid number buffers:%d required:%d\n",
1648 update_buf->num_buf, vfe_out_data->num_wm);
1649 return -ENOMEM;
1650 }
1651
1652 size = vfe_out_data->cdm_util_ops->cdm_required_size_reg_random(
1653 vfe_out_data->num_wm);
1654
1655 /* cdm util returns dwords, need to convert to bytes */
1656 if ((size * 4) > update_buf->cdm.size) {
1657 pr_err("Failed! Buf size:%d insufficient, expected size:%d\n",
1658 update_buf->cdm.size, size);
1659 return -ENOMEM;
1660 }
1661
1662 for (i = 0 ; i < vfe_out_data->num_wm; i++) {
1663 wm_data = vfe_out_data->wm_res[i]->res_priv;
1664 reg_val_pair[2 * i] = wm_data->hw_regs->image_addr;
1665 reg_val_pair[2 * i + 1] = update_buf->image_buf[i];
1666 CDBG("offset 0x%x, value 0x%llx\n",
1667 wm_data->hw_regs->image_addr,
1668 (uint64_t) update_buf->image_buf[i]);
1669 }
1670
1671 vfe_out_data->cdm_util_ops->cdm_write_regrandom(
1672 update_buf->cdm.cmd_buf_addr,
1673 vfe_out_data->num_wm, reg_val_pair);
1674 /* cdm util returns dwords, need to convert to bytes */
1675 update_buf->cdm.used_bytes = size * 4;
1676
1677 return 0;
1678}
1679
1680static int cam_vfe_bus_process_cmd(void *priv,
1681 uint32_t cmd_type, void *cmd_args, uint32_t arg_size)
1682{
1683 int rc = -EINVAL;
1684
1685 if (!priv || !cmd_args) {
1686 pr_err_ratelimited("Error! Invalid input arguments\n");
1687 return -EINVAL;
1688 }
1689
1690 switch (cmd_type) {
1691 case CAM_VFE_HW_CMD_GET_BUF_UPDATE:
1692 rc = cam_vfe_bus_update_buf(priv, cmd_args, arg_size);
1693 break;
1694 default:
1695 pr_err_ratelimited("Error! Invalid camif process command:%d\n",
1696 cmd_type);
1697 break;
1698 }
1699
1700 return rc;
1701}
1702
1703int cam_vfe_bus_ver2_init(
1704 void __iomem *mem_base,
1705 struct cam_hw_intf *hw_intf,
1706 void *bus_hw_info,
1707 void *vfe_irq_controller,
1708 struct cam_vfe_bus **vfe_bus)
1709{
1710 int i, rc = 0;
1711 struct cam_vfe_bus_ver2_priv *bus_priv = NULL;
1712 struct cam_vfe_bus *vfe_bus_local;
1713 struct cam_vfe_bus_ver2_hw_info *ver2_hw_info = bus_hw_info;
1714
1715 CDBG("Enter\n");
1716
1717 vfe_bus_local = kzalloc(sizeof(struct cam_vfe_bus), GFP_KERNEL);
1718 if (!vfe_bus_local) {
1719 CDBG("Failed to alloc for vfe_bus\n");
1720 rc = -ENOMEM;
1721 goto err_alloc_bus;
1722 }
1723
1724 bus_priv = kzalloc(sizeof(struct cam_vfe_bus_ver2_priv),
1725 GFP_KERNEL);
1726 if (!bus_priv) {
1727 CDBG("Failed to alloc for vfe_bus_priv\n");
1728 rc = -ENOMEM;
1729 goto err_alloc_priv;
1730 }
1731 vfe_bus_local->bus_priv = bus_priv;
1732
1733 bus_priv->common_data.mem_base = mem_base;
1734 bus_priv->common_data.hw_intf = hw_intf;
1735 bus_priv->common_data.vfe_irq_controller = vfe_irq_controller;
1736 bus_priv->common_data.common_reg = &ver2_hw_info->common_reg;
1737
1738 INIT_LIST_HEAD(&bus_priv->free_comp_grp);
1739 INIT_LIST_HEAD(&bus_priv->free_dual_comp_grp);
1740 INIT_LIST_HEAD(&bus_priv->used_comp_grp);
1741
1742 for (i = 0; i < CAM_VFE_BUS_VER2_MAX_CLIENTS; i++) {
1743 rc = cam_vfe_bus_init_wm_resource(i, bus_priv, bus_hw_info,
1744 &bus_priv->bus_client[i]);
1745 if (rc < 0) {
1746 pr_err("Error! Init WM failed\n");
1747 goto err_init_wm;
1748 }
1749 }
1750
1751 for (i = 0; i < CAM_VFE_BUS_VER2_COMP_GRP_MAX; i++) {
1752 rc = cam_vfe_bus_init_comp_grp(i, bus_priv, bus_hw_info,
1753 &bus_priv->comp_grp[i]);
1754 if (rc < 0) {
1755 pr_err("Error! Init Comp Grp failed\n");
1756 goto err_init_comp_grp;
1757 }
1758 }
1759
1760 for (i = 0; i < CAM_VFE_BUS_VER2_VFE_OUT_MAX; i++) {
1761 rc = cam_vfe_bus_init_vfe_out_resource(i, bus_priv, bus_hw_info,
1762 &bus_priv->vfe_out[i]);
1763 if (rc < 0) {
1764 pr_err("Error! Init VFE Out failed\n");
1765 goto err_init_vfe_out;
1766 }
1767 }
1768
1769 INIT_LIST_HEAD(&bus_priv->free_payload_list);
1770 for (i = 0; i < 128; i++) {
1771 INIT_LIST_HEAD(&bus_priv->evt_payload[i].list);
1772 list_add_tail(&bus_priv->evt_payload[i].list,
1773 &bus_priv->free_payload_list);
1774 }
1775
1776 vfe_bus_local->acquire_resource = cam_vfe_bus_acquire_vfe_out;
1777 vfe_bus_local->release_resource = cam_vfe_bus_release_vfe_out;
1778 vfe_bus_local->start_resource = cam_vfe_bus_start_vfe_out;
1779 vfe_bus_local->stop_resource = cam_vfe_bus_stop_vfe_out;
1780 vfe_bus_local->top_half_handler = cam_vfe_bus_ver2_handle_irq;
1781 vfe_bus_local->bottom_half_handler = NULL;
1782 vfe_bus_local->process_cmd = cam_vfe_bus_process_cmd;
1783
1784 *vfe_bus = vfe_bus_local;
1785
1786 return rc;
1787
1788err_init_vfe_out:
1789err_init_comp_grp:
1790err_init_wm:
1791 kfree(vfe_bus_local->bus_priv);
1792err_alloc_priv:
1793 kfree(vfe_bus_local);
1794err_alloc_bus:
1795 return rc;
1796}