blob: c4fae99c40728c22502d2aa66fe22ee1a1012cd2 [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{
841 int rc = 0;
842 struct cam_vfe_bus_ver2_wm_resource_data *rsrc_data;
843
844 rsrc_data = kzalloc(sizeof(struct cam_vfe_bus_ver2_wm_resource_data),
845 GFP_KERNEL);
846 if (!rsrc_data) {
847 CDBG("Failed to alloc for wm res priv\n");
848 rc = -ENOMEM;
849 return rc;
850 }
851 wm_res->res_priv = rsrc_data;
852
853 rsrc_data->index = index;
854 rsrc_data->hw_regs = &ver2_hw_info->bus_client_reg[index];
855 rsrc_data->common_data = &ver2_bus_priv->common_data;
856
857 wm_res->res_state = CAM_ISP_RESOURCE_STATE_AVAILABLE;
858 INIT_LIST_HEAD(&wm_res->list);
859
860 wm_res->start = cam_vfe_bus_start_wm;
861 wm_res->stop = cam_vfe_bus_stop_wm;
862 wm_res->top_half_handler = cam_vfe_bus_handle_wm_done_top_half;
863 wm_res->bottom_half_handler = cam_vfe_bus_handle_wm_done_bottom_half;
864 wm_res->hw_intf = ver2_bus_priv->common_data.hw_intf;
865
866 return rc;
867}
868
869static void cam_vfe_bus_add_wm_to_comp_grp(
870 struct cam_isp_resource_node *comp_grp,
871 uint32_t composite_mask)
872{
873 struct cam_vfe_bus_ver2_comp_grp_data *rsrc_data = comp_grp->res_priv;
874
875 rsrc_data->composite_mask |= composite_mask;
876}
877
878static void cam_vfe_bus_match_comp_grp(
879 struct cam_vfe_bus_ver2_priv *ver2_bus_priv,
880 struct cam_isp_resource_node **comp_grp,
881 uint32_t comp_grp_local_idx,
882 uint32_t unique_id)
883{
884 struct cam_vfe_bus_ver2_comp_grp_data *rsrc_data = NULL;
885 struct cam_isp_resource_node *comp_grp_local = NULL;
886
887 list_for_each_entry(comp_grp_local,
888 &ver2_bus_priv->used_comp_grp, list) {
889 rsrc_data = comp_grp_local->res_priv;
890 if (rsrc_data->comp_grp_local_idx == comp_grp_local_idx &&
891 rsrc_data->unique_id == unique_id) {
892 /* Match found */
893 *comp_grp = comp_grp_local;
894 return;
895 }
896 }
897
898 *comp_grp = NULL;
899}
900
901static int cam_vfe_bus_acquire_comp_grp(
902 struct cam_vfe_bus_ver2_priv *ver2_bus_priv,
903 struct cam_isp_out_port_info *out_port_info,
904 uint32_t unique_id,
905 uint32_t is_dual,
906 uint32_t is_master,
907 enum cam_vfe_bus_ver2_vfe_core_id dual_slave_core,
908 struct cam_isp_resource_node **comp_grp)
909{
910 int rc = 0;
911 struct cam_isp_resource_node *comp_grp_local = NULL;
912 struct cam_vfe_bus_ver2_comp_grp_data *rsrc_data = NULL;
913
914 /* Check if matching comp_grp already acquired */
915 cam_vfe_bus_match_comp_grp(ver2_bus_priv, &comp_grp_local,
916 out_port_info->comp_grp_id, unique_id);
917
918 if (!comp_grp_local) {
919 /* First find a free group */
920 if (is_dual) {
921 if (list_empty(&ver2_bus_priv->free_dual_comp_grp)) {
922 pr_err("No Free Composite Group\n");
923 return -ENODEV;
924 }
925 comp_grp_local = list_first_entry(
926 &ver2_bus_priv->free_dual_comp_grp,
927 struct cam_isp_resource_node, list);
928 rsrc_data = comp_grp_local->res_priv;
929 rc = cam_vfe_bus_ver2_get_intra_client_mask(
930 dual_slave_core,
931 comp_grp_local->hw_intf->hw_idx,
932 &rsrc_data->intra_client_mask);
933 } else {
934 if (list_empty(&ver2_bus_priv->free_comp_grp)) {
935 pr_err("No Free Composite Group\n");
936 return -ENODEV;
937 }
938 comp_grp_local = list_first_entry(
939 &ver2_bus_priv->free_comp_grp,
940 struct cam_isp_resource_node, list);
941 rsrc_data = comp_grp_local->res_priv;
942 }
943
944 list_del(&comp_grp_local->list);
945 comp_grp_local->res_state = CAM_ISP_RESOURCE_STATE_RESERVED;
946
947 rsrc_data->is_master = is_master;
948 rsrc_data->composite_mask = 0;
949 rsrc_data->unique_id = unique_id;
950 rsrc_data->comp_grp_local_idx = out_port_info->comp_grp_id;
951
952 list_add_tail(&comp_grp_local->list,
953 &ver2_bus_priv->used_comp_grp);
954
955 } else {
956 rsrc_data = comp_grp_local->res_priv;
957 /* Do not support runtime change in composite mask */
958 if (comp_grp_local->res_state ==
959 CAM_ISP_RESOURCE_STATE_STREAMING) {
960 pr_err("Invalid State %d Comp Grp %u\n",
961 comp_grp_local->res_state,
962 rsrc_data->comp_grp_type);
963 return -EBUSY;
964 }
965 }
966
967 *comp_grp = comp_grp_local;
968
969 return rc;
970}
971
972static int cam_vfe_bus_release_comp_grp(
973 struct cam_vfe_bus_ver2_priv *ver2_bus_priv,
974 struct cam_isp_resource_node *in_comp_grp)
975{
976 struct cam_isp_resource_node *comp_grp = NULL;
977 struct cam_vfe_bus_ver2_comp_grp_data *in_rsrc_data = NULL;
978 int match_found = 0;
979
980 if (!in_comp_grp) {
981 pr_err("Invalid Params Comp Grp %pK\n", in_rsrc_data);
982 return -EINVAL;
983 }
984
985 if (in_comp_grp->res_state == CAM_ISP_RESOURCE_STATE_AVAILABLE) {
986 /* Already Released. Do Nothing */
987 return 0;
988 }
989
990 in_rsrc_data = in_comp_grp->res_priv;
991
992 list_for_each_entry(comp_grp, &ver2_bus_priv->used_comp_grp, list) {
993 if (comp_grp == in_comp_grp) {
994 match_found = 1;
995 break;
996 }
997 }
998
999 if (!match_found) {
1000 pr_err("Could not find matching Comp Grp type %u\n",
1001 in_rsrc_data->comp_grp_type);
1002 return -ENODEV;
1003 }
1004
1005
1006 list_del(&comp_grp->list);
1007 if (in_rsrc_data->comp_grp_type >= CAM_VFE_BUS_VER2_COMP_GRP_DUAL_0 &&
1008 in_rsrc_data->comp_grp_type <= CAM_VFE_BUS_VER2_COMP_GRP_DUAL_5)
1009 list_add_tail(&comp_grp->list,
1010 &ver2_bus_priv->free_dual_comp_grp);
Jing Zhoue71fd4a2017-05-15 19:44:34 -07001011 else if (in_rsrc_data->comp_grp_type >= CAM_VFE_BUS_VER2_COMP_GRP_0
1012 && in_rsrc_data->comp_grp_type <= CAM_VFE_BUS_VER2_COMP_GRP_5)
Harsh Shaha1af8822017-05-11 22:06:36 -07001013 list_add_tail(&comp_grp->list, &ver2_bus_priv->free_comp_grp);
1014
Harsh Shaha1af8822017-05-11 22:06:36 -07001015 in_rsrc_data->unique_id = 0;
1016 in_rsrc_data->comp_grp_local_idx = 0;
1017 in_rsrc_data->composite_mask = 0;
1018 in_rsrc_data->dual_slave_core = CAM_VFE_BUS_VER2_VFE_CORE_MAX;
1019
1020 comp_grp->res_state = CAM_ISP_RESOURCE_STATE_AVAILABLE;
1021
Jing Zhoue71fd4a2017-05-15 19:44:34 -07001022 return 0;
Harsh Shaha1af8822017-05-11 22:06:36 -07001023}
1024
1025static int cam_vfe_bus_start_comp_grp(struct cam_isp_resource_node *comp_grp)
1026{
1027 int rc = 0;
1028 struct cam_vfe_bus_ver2_comp_grp_data *rsrc_data =
1029 comp_grp->res_priv;
1030 struct cam_vfe_bus_ver2_common_data *common_data =
1031 rsrc_data->common_data;
1032
1033 /*
1034 * Individual Comp_Grp Subscribe IRQ can be done here once
1035 * dynamic IRQ enable support is added.
1036 */
Harsh Shaha1af8822017-05-11 22:06:36 -07001037
1038 cam_io_w_mb(rsrc_data->composite_mask, common_data->mem_base +
1039 rsrc_data->hw_regs->comp_mask);
1040
1041 CDBG("composite_mask is 0x%x\n", rsrc_data->composite_mask);
1042 CDBG("composite_mask addr 0x%x\n", rsrc_data->hw_regs->comp_mask);
1043
1044 if (rsrc_data->comp_grp_type >= CAM_VFE_BUS_VER2_COMP_GRP_DUAL_0 &&
1045 rsrc_data->comp_grp_type <= CAM_VFE_BUS_VER2_COMP_GRP_DUAL_5 &&
1046 rsrc_data->is_master) {
1047 int dual_comp_grp = (rsrc_data->comp_grp_type -
1048 CAM_VFE_BUS_VER2_COMP_GRP_DUAL_0);
1049 int intra_client_en = cam_io_r_mb(common_data->mem_base +
1050 common_data->common_reg->dual_master_comp_cfg);
1051
1052 /* 2 Bits per comp_grp. Hence left shift by comp_grp * 2 */
1053 intra_client_en |=
1054 (rsrc_data->intra_client_mask << dual_comp_grp * 2);
1055
1056 cam_io_w_mb(intra_client_en, common_data->mem_base +
1057 common_data->common_reg->dual_master_comp_cfg);
1058 }
1059
1060 comp_grp->res_state = CAM_ISP_RESOURCE_STATE_STREAMING;
1061 return rc;
1062}
1063
1064static int cam_vfe_bus_stop_comp_grp(struct cam_isp_resource_node *comp_grp)
1065{
1066 int rc = 0;
1067 struct cam_vfe_bus_ver2_comp_grp_data *rsrc_data =
1068 comp_grp->res_priv;
1069 struct cam_vfe_bus_ver2_common_data *common_data =
1070 rsrc_data->common_data;
1071
1072 /* Unsubscribe IRQ */
1073
1074 cam_io_w_mb(rsrc_data->composite_mask, common_data->mem_base +
1075 rsrc_data->hw_regs->comp_mask);
1076 if (rsrc_data->comp_grp_type >= CAM_VFE_BUS_VER2_COMP_GRP_DUAL_0 &&
1077 rsrc_data->comp_grp_type <= CAM_VFE_BUS_VER2_COMP_GRP_DUAL_5 &&
1078 rsrc_data->is_master) {
1079 int dual_comp_grp = (rsrc_data->comp_grp_type -
1080 CAM_VFE_BUS_VER2_COMP_GRP_DUAL_0);
1081 int intra_client_en = cam_io_r_mb(common_data->mem_base +
1082 common_data->common_reg->dual_master_comp_cfg);
1083
1084 /* 2 Bits per comp_grp. Hence left shift by comp_grp * 2 */
1085 intra_client_en &=
1086 ~(rsrc_data->intra_client_mask << dual_comp_grp * 2);
1087
1088 cam_io_w_mb(intra_client_en, common_data->mem_base +
1089 common_data->common_reg->dual_master_comp_cfg);
1090 }
1091
1092 comp_grp->res_state = CAM_ISP_RESOURCE_STATE_RESERVED;
1093
1094 return rc;
1095}
1096
1097static int cam_vfe_bus_handle_comp_done_top_half(uint32_t evt_id,
1098 struct cam_irq_th_payload *th_payload)
1099{
1100 return -EPERM;
1101}
1102
1103static int cam_vfe_bus_handle_comp_done_bottom_half(
1104 void *handler_priv,
1105 void *evt_payload_priv)
1106{
1107 int rc = CAM_VFE_IRQ_STATUS_ERR;
1108 struct cam_isp_resource_node *comp_grp = handler_priv;
1109 struct cam_vfe_bus_irq_evt_payload *evt_payload = evt_payload_priv;
1110 struct cam_vfe_bus_ver2_comp_grp_data *rsrc_data = comp_grp->res_priv;
Harsh Shah23557ae2017-05-13 18:14:34 -07001111 uint32_t *cam_ife_irq_regs;
1112 uint32_t status_reg;
1113 uint32_t comp_err_reg;
1114 uint32_t comp_grp_id;
1115
1116 if (!evt_payload)
1117 return rc;
1118
1119 cam_ife_irq_regs = evt_payload->irq_reg_val;
Harsh Shaha1af8822017-05-11 22:06:36 -07001120
1121 CDBG("comp grp type %d\n", rsrc_data->comp_grp_type);
1122 switch (rsrc_data->comp_grp_type) {
1123 case CAM_VFE_BUS_VER2_COMP_GRP_0:
1124 case CAM_VFE_BUS_VER2_COMP_GRP_1:
1125 case CAM_VFE_BUS_VER2_COMP_GRP_2:
1126 case CAM_VFE_BUS_VER2_COMP_GRP_3:
1127 case CAM_VFE_BUS_VER2_COMP_GRP_4:
1128 case CAM_VFE_BUS_VER2_COMP_GRP_5:
Harsh Shah23557ae2017-05-13 18:14:34 -07001129 comp_grp_id = (rsrc_data->comp_grp_type -
Harsh Shaha1af8822017-05-11 22:06:36 -07001130 CAM_VFE_BUS_VER2_COMP_GRP_0);
1131
1132 /* Check for Regular composite error */
1133 status_reg = cam_ife_irq_regs[CAM_IFE_IRQ_BUS_REG_STATUS0];
1134
1135 comp_err_reg = cam_ife_irq_regs[CAM_IFE_IRQ_BUS_REG_COMP_ERR];
1136 if ((status_reg & BIT(11)) &&
1137 (comp_err_reg & rsrc_data->composite_mask)) {
1138 /* Check for Regular composite error */
1139 rc = CAM_VFE_IRQ_STATUS_ERR_COMP;
1140 break;
1141 }
1142
1143 comp_err_reg = cam_ife_irq_regs[CAM_IFE_IRQ_BUS_REG_COMP_OWRT];
1144 /* Check for Regular composite Overwrite */
1145 if ((status_reg & BIT(12)) &&
1146 (comp_err_reg & rsrc_data->composite_mask)) {
1147 rc = CAM_VFE_IRQ_STATUS_COMP_OWRT;
1148 break;
1149 }
1150
Harsh Shah23557ae2017-05-13 18:14:34 -07001151 /* Regular Composite SUCCESS */
1152 if (status_reg & BIT(comp_grp_id + 5)) {
1153 cam_ife_irq_regs[CAM_IFE_IRQ_BUS_REG_STATUS0] &=
1154 ~BIT(comp_grp_id + 5);
Harsh Shaha1af8822017-05-11 22:06:36 -07001155 rc = CAM_VFE_IRQ_STATUS_SUCCESS;
Harsh Shah23557ae2017-05-13 18:14:34 -07001156 }
Harsh Shaha1af8822017-05-11 22:06:36 -07001157
1158 CDBG("status reg = 0x%x, bit index = %d\n",
Harsh Shah23557ae2017-05-13 18:14:34 -07001159 status_reg, (comp_grp_id + 5));
Harsh Shaha1af8822017-05-11 22:06:36 -07001160 break;
1161
1162 case CAM_VFE_BUS_VER2_COMP_GRP_DUAL_0:
1163 case CAM_VFE_BUS_VER2_COMP_GRP_DUAL_1:
1164 case CAM_VFE_BUS_VER2_COMP_GRP_DUAL_2:
1165 case CAM_VFE_BUS_VER2_COMP_GRP_DUAL_3:
1166 case CAM_VFE_BUS_VER2_COMP_GRP_DUAL_4:
1167 case CAM_VFE_BUS_VER2_COMP_GRP_DUAL_5:
Harsh Shah23557ae2017-05-13 18:14:34 -07001168 comp_grp_id = (rsrc_data->comp_grp_type -
Harsh Shaha1af8822017-05-11 22:06:36 -07001169 CAM_VFE_BUS_VER2_COMP_GRP_DUAL_0);
1170
1171 /* Check for DUAL composite error */
1172 status_reg = cam_ife_irq_regs[CAM_IFE_IRQ_BUS_REG_STATUS2];
1173
1174 comp_err_reg = cam_ife_irq_regs[CAM_IFE_IRQ_BUS_DUAL_COMP_ERR];
1175 if ((status_reg & BIT(6)) &&
1176 (comp_err_reg & rsrc_data->composite_mask)) {
1177 /* Check for DUAL composite error */
1178 rc = CAM_VFE_IRQ_STATUS_ERR_COMP;
1179 break;
1180 }
1181
1182 /* Check for Dual composite Overwrite */
1183 comp_err_reg = cam_ife_irq_regs[CAM_IFE_IRQ_BUS_DUAL_COMP_OWRT];
1184 if ((status_reg & BIT(7)) &&
1185 (comp_err_reg & rsrc_data->composite_mask)) {
1186 rc = CAM_VFE_IRQ_STATUS_COMP_OWRT;
1187 break;
1188 }
1189
Harsh Shah23557ae2017-05-13 18:14:34 -07001190 /* DUAL Composite SUCCESS */
1191 if (status_reg & BIT(comp_grp_id)) {
1192 cam_ife_irq_regs[CAM_IFE_IRQ_BUS_REG_STATUS2] &=
1193 ~BIT(comp_grp_id + 5);
Harsh Shaha1af8822017-05-11 22:06:36 -07001194 rc = CAM_VFE_IRQ_STATUS_SUCCESS;
Harsh Shah23557ae2017-05-13 18:14:34 -07001195 }
Harsh Shaha1af8822017-05-11 22:06:36 -07001196
1197 break;
Harsh Shaha1af8822017-05-11 22:06:36 -07001198 default:
1199 rc = CAM_VFE_IRQ_STATUS_ERR;
1200 break;
1201 }
1202
1203 if (rc == CAM_VFE_IRQ_STATUS_SUCCESS)
1204 cam_vfe_bus_put_evt_payload(evt_payload->core_info,
1205 &evt_payload);
1206
1207 return rc;
1208}
1209
1210static int cam_vfe_bus_init_comp_grp(uint32_t index,
1211 struct cam_vfe_bus_ver2_priv *ver2_bus_priv,
1212 struct cam_vfe_bus_ver2_hw_info *ver2_hw_info,
1213 struct cam_isp_resource_node *comp_grp)
1214{
1215 struct cam_vfe_bus_ver2_comp_grp_data *rsrc_data =
1216 comp_grp->res_priv;
1217
1218 rsrc_data = kzalloc(sizeof(struct cam_vfe_bus_ver2_comp_grp_data),
1219 GFP_KERNEL);
1220 if (!rsrc_data) {
1221 CDBG("Failed to alloc for comp_grp_priv\n");
1222 return -ENOMEM;
1223 }
1224 comp_grp->res_priv = rsrc_data;
1225
1226 comp_grp->res_state = CAM_ISP_RESOURCE_STATE_AVAILABLE;
1227 INIT_LIST_HEAD(&comp_grp->list);
1228
1229 rsrc_data->comp_grp_type = index;
1230 rsrc_data->common_data = &ver2_bus_priv->common_data;
1231 rsrc_data->hw_regs = &ver2_hw_info->comp_grp_reg[index];
1232 rsrc_data->dual_slave_core = CAM_VFE_BUS_VER2_VFE_CORE_MAX;
1233
1234
1235 if (rsrc_data->comp_grp_type >= CAM_VFE_BUS_VER2_COMP_GRP_DUAL_0 &&
1236 rsrc_data->comp_grp_type <= CAM_VFE_BUS_VER2_COMP_GRP_DUAL_5)
1237 list_add_tail(&comp_grp->list,
1238 &ver2_bus_priv->free_dual_comp_grp);
1239 else if (rsrc_data->comp_grp_type >= CAM_VFE_BUS_VER2_COMP_GRP_0
1240 && rsrc_data->comp_grp_type <= CAM_VFE_BUS_VER2_COMP_GRP_5)
1241 list_add_tail(&comp_grp->list, &ver2_bus_priv->free_comp_grp);
1242
1243 comp_grp->start = cam_vfe_bus_start_comp_grp;
1244 comp_grp->stop = cam_vfe_bus_stop_comp_grp;
1245 comp_grp->top_half_handler = cam_vfe_bus_handle_comp_done_top_half;
1246 comp_grp->bottom_half_handler =
1247 cam_vfe_bus_handle_comp_done_bottom_half;
1248 comp_grp->hw_intf = ver2_bus_priv->common_data.hw_intf;
1249
1250 return 0;
1251}
1252
1253static int cam_vfe_bus_acquire_vfe_out(void *bus_priv, void *acquire_args)
1254{
1255 int rc = -ENODEV;
1256 int i;
1257 enum cam_vfe_bus_ver2_vfe_out_type vfe_out_res_id;
1258 uint32_t format;
1259 uint32_t num_wm;
1260 uint32_t subscribe_irq;
1261 uint32_t client_done_mask;
1262 struct cam_vfe_bus_ver2_priv *ver2_bus_priv = bus_priv;
1263 struct cam_vfe_acquire_args *acq_args = acquire_args;
1264 struct cam_vfe_hw_vfe_out_acquire_args *out_acquire_args;
1265 struct cam_isp_resource_node *rsrc_node = NULL;
1266 struct cam_vfe_bus_ver2_vfe_out_data *rsrc_data = NULL;
1267
1268 if (!bus_priv || !acquire_args) {
1269 pr_err("Invalid Param");
1270 return -EINVAL;
1271 }
1272
1273 out_acquire_args = &acq_args->vfe_out;
1274 format = out_acquire_args->out_port_info->format;
1275
1276 CDBG("Acquiring resource type 0x%x\n",
1277 out_acquire_args->out_port_info->res_type);
1278
1279 vfe_out_res_id = cam_vfe_bus_get_out_res_id(
1280 out_acquire_args->out_port_info->res_type);
1281 if (vfe_out_res_id == CAM_VFE_BUS_VER2_VFE_OUT_MAX)
1282 return -ENODEV;
1283
1284 num_wm = cam_vfe_bus_get_num_wm(vfe_out_res_id, format);
1285 if (num_wm < 1)
1286 return -EINVAL;
1287
1288 rsrc_node = &ver2_bus_priv->vfe_out[vfe_out_res_id];
1289 if (rsrc_node->res_state != CAM_ISP_RESOURCE_STATE_AVAILABLE) {
1290 pr_err("Resource not available: Res_id %d state:%d\n",
1291 vfe_out_res_id, rsrc_node->res_state);
1292 return -EBUSY;
1293 }
1294
1295 rsrc_data = rsrc_node->res_priv;
1296 rsrc_data->num_wm = num_wm;
1297 rsrc_node->res_id = out_acquire_args->out_port_info->res_type;
1298 rsrc_node->tasklet_info = acq_args->tasklet;
1299 rsrc_node->cdm_ops = out_acquire_args->cdm_ops;
1300 rsrc_data->cdm_util_ops = out_acquire_args->cdm_ops;
1301
1302 /* Reserve Composite Group */
1303 if (num_wm > 1 || (out_acquire_args->out_port_info->comp_grp_id >
1304 CAM_ISP_RES_COMP_GROUP_NONE &&
1305 out_acquire_args->out_port_info->comp_grp_id <
1306 CAM_ISP_RES_COMP_GROUP_ID_MAX)) {
1307 rc = cam_vfe_bus_acquire_comp_grp(ver2_bus_priv,
1308 out_acquire_args->out_port_info,
1309 out_acquire_args->unique_id,
1310 out_acquire_args->is_dual,
1311 out_acquire_args->is_master,
1312 out_acquire_args->dual_slave_core,
1313 &rsrc_data->comp_grp);
1314 if (rc < 0)
1315 return rc;
1316
1317 subscribe_irq = 0;
1318 } else
1319 subscribe_irq = 1;
1320
1321 /* Reserve WM */
1322 for (i = 0; i < num_wm; i++) {
1323 rc = cam_vfe_bus_acquire_wm(ver2_bus_priv,
1324 out_acquire_args->out_port_info,
1325 vfe_out_res_id,
1326 i,
1327 out_acquire_args->split_id,
1328 subscribe_irq,
1329 &rsrc_data->wm_res[i],
1330 &client_done_mask);
1331 if (rc < 0)
1332 goto release_wm;
1333
1334 if (rsrc_data->comp_grp)
1335 cam_vfe_bus_add_wm_to_comp_grp(rsrc_data->comp_grp,
1336 client_done_mask);
1337 }
1338
1339 rsrc_node->res_state = CAM_ISP_RESOURCE_STATE_RESERVED;
1340 out_acquire_args->rsrc_node = rsrc_node;
1341
1342 CDBG("Acquire successful\n");
1343 return rc;
1344
1345release_wm:
1346 for (i--; i >= 0; i--)
1347 cam_vfe_bus_release_wm(ver2_bus_priv, rsrc_data->wm_res[i]);
1348
1349 cam_vfe_bus_release_comp_grp(ver2_bus_priv,
1350 rsrc_data->comp_grp);
1351
1352 return rc;
1353}
1354
1355static int cam_vfe_bus_release_vfe_out(void *bus_priv,
1356 struct cam_isp_resource_node *vfe_out)
1357{
Jing Zhoue71fd4a2017-05-15 19:44:34 -07001358 uint32_t i;
1359 struct cam_vfe_bus_ver2_vfe_out_data *rsrc_data = vfe_out->res_priv;
1360
Harsh Shaha1af8822017-05-11 22:06:36 -07001361 if (vfe_out->res_state != CAM_ISP_RESOURCE_STATE_RESERVED) {
1362 pr_err("Error! Invalid resource state:%d\n",
1363 vfe_out->res_state);
1364 }
1365
Jing Zhoue71fd4a2017-05-15 19:44:34 -07001366 for (i = 0; i < rsrc_data->num_wm; i++)
1367 cam_vfe_bus_release_wm(bus_priv, rsrc_data->wm_res[i]);
1368 rsrc_data->num_wm = 0;
1369
1370 if (rsrc_data->comp_grp)
1371 cam_vfe_bus_release_comp_grp(bus_priv, rsrc_data->comp_grp);
1372 rsrc_data->comp_grp = NULL;
1373
1374 vfe_out->tasklet_info = NULL;
1375 vfe_out->cdm_ops = NULL;
1376 rsrc_data->cdm_util_ops = NULL;
1377
Harsh Shaha1af8822017-05-11 22:06:36 -07001378 if (vfe_out->res_state == CAM_ISP_RESOURCE_STATE_RESERVED)
1379 vfe_out->res_state = CAM_ISP_RESOURCE_STATE_AVAILABLE;
1380
1381 return 0;
1382}
1383
1384static int cam_vfe_bus_start_vfe_out(struct cam_isp_resource_node *vfe_out)
1385{
1386 int rc = 0, i;
Harsh Shah23557ae2017-05-13 18:14:34 -07001387 struct cam_vfe_bus_ver2_vfe_out_data *rsrc_data = vfe_out->res_priv;
1388 struct cam_vfe_bus_ver2_common_data *common_data =
1389 rsrc_data->common_data;
Harsh Shaha1af8822017-05-11 22:06:36 -07001390
1391 CDBG("Start resource index %d\n", rsrc_data->out_type);
1392
1393 if (vfe_out->res_state != CAM_ISP_RESOURCE_STATE_RESERVED) {
1394 pr_err("Error! Invalid resource state:%d\n",
1395 vfe_out->res_state);
1396 return -EACCES;
1397 }
1398
Harsh Shah23557ae2017-05-13 18:14:34 -07001399 /* Enable IRQ Mask */
Jing Zhoue71fd4a2017-05-15 19:44:34 -07001400 cam_io_w_mb(0x00001FE0, common_data->mem_base + 0x2044);
Harsh Shah23557ae2017-05-13 18:14:34 -07001401 cam_io_w_mb(0x000FFFE7, common_data->mem_base + 0x2048);
1402 cam_io_w_mb(0x000000FF, common_data->mem_base + 0x204c);
1403
Harsh Shaha1af8822017-05-11 22:06:36 -07001404 for (i = 0; i < rsrc_data->num_wm; i++)
1405 rc = cam_vfe_bus_start_wm(rsrc_data->wm_res[i]);
1406
1407 if (rsrc_data->comp_grp)
1408 rc = cam_vfe_bus_start_comp_grp(rsrc_data->comp_grp);
1409
1410 /* VFE_MODULE_BUS_CGC_OVERRIDE */
1411 cam_io_w_mb(0xFFFFFFFF, rsrc_data->common_data->mem_base + 0x0000003C);
1412 /* VFE_MODULE_COLOR_CGC_OVERRIDE */
1413 cam_io_w_mb(0xFFFFFFFF, rsrc_data->common_data->mem_base + 0x00000034);
1414 /* VFE_MODULE_ZOOM_CGC_OVERRIDE */
1415 cam_io_w_mb(0xFFFFFFFF, rsrc_data->common_data->mem_base + 0x38);
1416 /* VFE_MODULE_LENS_CGC_OVERRIDE */
1417 cam_io_w_mb(0xFFFFFFFF, rsrc_data->common_data->mem_base + 0x0000002C);
1418 /* VFE_MODULE_STATS_CGC_OVERRIDE */
1419 cam_io_w_mb(0xFFFFFFFF, rsrc_data->common_data->mem_base + 0x00000030);
1420
1421 /* BUS_WR_INPUT_IF_ADDR_SYNC_CFG */
1422 cam_io_w_mb(0x0, rsrc_data->common_data->mem_base + 0x0000207C);
1423 /* BUS_WR_INPUT_IF_ADDR_SYNC_FRAME_HEADER */
1424 cam_io_w_mb(0x0, rsrc_data->common_data->mem_base + 0x00002080);
1425 /* BUS_WR_INPUT_IF_ADDR_SYNC_NO_SYNC */
1426 cam_io_w_mb(0xFFFFF, rsrc_data->common_data->mem_base + 0x00002084);
Harsh Shaha1af8822017-05-11 22:06:36 -07001427 /* BUS_WR_INPUT_IF_ADDR_SYNC_0 */
1428 cam_io_w_mb(0x0, rsrc_data->common_data->mem_base + 0x00002088);
1429 cam_io_w_mb(0x0, rsrc_data->common_data->mem_base + 0x0000208c);
1430 cam_io_w_mb(0x0, rsrc_data->common_data->mem_base + 0x00002090);
1431 cam_io_w_mb(0x0, rsrc_data->common_data->mem_base + 0x00002094);
1432 cam_io_w_mb(0x0, rsrc_data->common_data->mem_base + 0x00002098);
1433 cam_io_w_mb(0x0, rsrc_data->common_data->mem_base + 0x0000209c);
1434 cam_io_w_mb(0x0, rsrc_data->common_data->mem_base + 0x000020a0);
1435 cam_io_w_mb(0x0, rsrc_data->common_data->mem_base + 0x000020a4);
1436
Harsh Shah23557ae2017-05-13 18:14:34 -07001437 /* no clock gating at bus input */
1438 cam_io_w_mb(0xFFFFF, rsrc_data->common_data->mem_base + 0x0000200C);
1439
1440 /* BUS_WR_TEST_BUS_CTRL */
1441 cam_io_w_mb(0x0, rsrc_data->common_data->mem_base + 0x0000211C);
1442
Harsh Shaha1af8822017-05-11 22:06:36 -07001443 return rc;
1444}
1445
1446static int cam_vfe_bus_stop_vfe_out(struct cam_isp_resource_node *vfe_out)
1447{
1448 int rc = 0, i;
1449 struct cam_vfe_bus_ver2_vfe_out_data *rsrc_data = vfe_out->res_priv;
1450
1451 if (vfe_out->res_state == CAM_ISP_RESOURCE_STATE_AVAILABLE ||
1452 vfe_out->res_state == CAM_ISP_RESOURCE_STATE_RESERVED) {
1453 return rc;
1454 }
1455
1456 if (rsrc_data->comp_grp)
1457 rc = cam_vfe_bus_stop_comp_grp(rsrc_data->comp_grp);
1458
1459 for (i = 0; i < rsrc_data->num_wm; i++)
1460 rc = cam_vfe_bus_stop_wm(rsrc_data->wm_res[i]);
1461
1462 vfe_out->res_state = CAM_ISP_RESOURCE_STATE_STREAMING;
1463
1464 vfe_out->res_state = CAM_ISP_RESOURCE_STATE_RESERVED;
1465 return rc;
1466}
1467
1468static int cam_vfe_bus_handle_vfe_out_done_top_half(uint32_t evt_id,
1469 struct cam_irq_th_payload *th_payload)
1470{
1471 return -EPERM;
1472}
1473
1474static int cam_vfe_bus_handle_vfe_out_done_bottom_half(
1475 void *handler_priv,
1476 void *evt_payload_priv)
1477{
1478 int rc = -EINVAL;
1479 struct cam_isp_resource_node *vfe_out = handler_priv;
1480 struct cam_vfe_bus_ver2_vfe_out_data *rsrc_data = vfe_out->res_priv;
1481
1482 /*
1483 * If this resource has Composite Group then we only handle
1484 * Composite done. We acquire Composite if number of WM > 1.
1485 * So Else case is only one individual buf_done = WM[0].
1486 */
1487 if (rsrc_data->comp_grp) {
1488 rc = rsrc_data->comp_grp->bottom_half_handler(
1489 rsrc_data->comp_grp, evt_payload_priv);
1490 } else {
1491 rc = rsrc_data->wm_res[0]->bottom_half_handler(
Harsh Shah23557ae2017-05-13 18:14:34 -07001492 rsrc_data->wm_res[0], evt_payload_priv);
Harsh Shaha1af8822017-05-11 22:06:36 -07001493 }
1494
1495 return rc;
1496}
1497
1498static int cam_vfe_bus_init_vfe_out_resource(uint32_t index,
1499 struct cam_vfe_bus_ver2_priv *ver2_bus_priv,
1500 struct cam_vfe_bus_ver2_hw_info *ver2_hw_info,
1501 struct cam_isp_resource_node *vfe_out)
1502{
1503 struct cam_vfe_bus_ver2_vfe_out_data *rsrc_data = NULL;
1504 int rc = 0;
1505
1506 rsrc_data = kzalloc(sizeof(struct cam_vfe_bus_ver2_vfe_out_data),
1507 GFP_KERNEL);
1508 if (!rsrc_data) {
1509 CDBG("Error! Failed to alloc for vfe out priv\n");
1510 rc = -ENOMEM;
1511 return rc;
1512 }
1513 vfe_out->res_priv = rsrc_data;
1514
1515 vfe_out->res_type = CAM_ISP_RESOURCE_VFE_OUT;
1516 vfe_out->res_state = CAM_ISP_RESOURCE_STATE_AVAILABLE;
1517 INIT_LIST_HEAD(&vfe_out->list);
1518
1519 rsrc_data->out_type = index;
1520 rsrc_data->common_data = &ver2_bus_priv->common_data;
1521 rsrc_data->max_width =
1522 ver2_hw_info->vfe_out_hw_info[index].max_width;
1523 rsrc_data->max_height =
1524 ver2_hw_info->vfe_out_hw_info[index].max_height;
1525
1526 vfe_out->start = cam_vfe_bus_start_vfe_out;
1527 vfe_out->stop = cam_vfe_bus_stop_vfe_out;
1528 vfe_out->top_half_handler = cam_vfe_bus_handle_vfe_out_done_top_half;
1529 vfe_out->bottom_half_handler =
1530 cam_vfe_bus_handle_vfe_out_done_bottom_half;
1531 vfe_out->hw_intf = ver2_bus_priv->common_data.hw_intf;
1532
1533 return 0;
1534}
1535
1536static int cam_vfe_bus_get_evt_payload(
1537 struct cam_vfe_bus_ver2_priv *bus_priv,
1538 struct cam_vfe_bus_irq_evt_payload **evt_payload)
1539{
1540 if (list_empty(&bus_priv->free_payload_list)) {
Harsh Shah23557ae2017-05-13 18:14:34 -07001541 *evt_payload = NULL;
Harsh Shaha1af8822017-05-11 22:06:36 -07001542 pr_err("No free payload\n");
1543 return -ENODEV;
1544 }
1545
1546 *evt_payload = list_first_entry(&bus_priv->free_payload_list,
1547 struct cam_vfe_bus_irq_evt_payload, list);
1548 list_del_init(&(*evt_payload)->list);
1549 return 0;
1550}
1551
1552static int cam_vfe_bus_put_evt_payload(void *core_info,
1553 struct cam_vfe_bus_irq_evt_payload **evt_payload)
1554{
1555 struct cam_vfe_bus_ver2_priv *bus_priv = NULL;
Harsh Shah23557ae2017-05-13 18:14:34 -07001556 uint32_t *cam_ife_irq_regs = (*evt_payload)->irq_reg_val;
1557 uint32_t status_reg0, status_reg1;
1558
1559 status_reg0 = cam_ife_irq_regs[CAM_IFE_IRQ_BUS_REG_STATUS0];
1560 status_reg1 = cam_ife_irq_regs[CAM_IFE_IRQ_BUS_REG_STATUS1];
1561
1562 if (status_reg0 || status_reg1) {
1563 CDBG("status0 0x%x status1 0x%x\n", status_reg0, status_reg1);
1564 return 0;
1565 }
Harsh Shaha1af8822017-05-11 22:06:36 -07001566
1567 if (!core_info) {
1568 pr_err("Invalid param core_info NULL");
1569 return -EINVAL;
1570 }
1571 if (*evt_payload == NULL) {
1572 pr_err("No payload to put\n");
1573 return -EINVAL;
1574 }
1575 bus_priv = (*evt_payload)->bus_priv;
1576 list_add_tail(&(*evt_payload)->list, &bus_priv->free_payload_list);
1577 *evt_payload = NULL;
1578 return 0;
1579}
1580
1581static int cam_vfe_bus_ver2_handle_irq(uint32_t evt_id,
1582 struct cam_irq_th_payload *th_payload)
1583{
1584 int32_t rc;
1585 int i;
1586 struct cam_vfe_irq_handler_priv *handler_priv;
1587 struct cam_vfe_hw_core_info *core_info;
1588 struct cam_vfe_bus_irq_evt_payload *evt_payload;
1589 struct cam_vfe_bus *bus_info;
1590 struct cam_vfe_bus_ver2_priv *bus_priv;
1591 struct cam_irq_controller_reg_info *reg_info;
Harsh Shah23557ae2017-05-13 18:14:34 -07001592 uint32_t irq_mask;
Harsh Shah35165dc2017-06-06 19:42:41 -07001593 int found = 0;
Harsh Shaha1af8822017-05-11 22:06:36 -07001594
1595 handler_priv = th_payload->handler_priv;
1596 core_info = handler_priv->core_info;
1597 bus_info = core_info->vfe_bus;
1598 bus_priv = bus_info->bus_priv;
1599 reg_info = &bus_priv->common_data.common_reg->irq_reg_info;
1600
1601 /*
1602 * add reset ack handling here once supported.
1603 * Just clear all the bus irq status registers and ignore the reset.
1604 */
1605
1606 CDBG("Enter\n");
1607 rc = cam_vfe_bus_get_evt_payload(bus_priv, &evt_payload);
1608 if (rc) {
1609 pr_err("No tasklet_cmd is free in queue\n");
1610 return rc;
1611 }
1612
1613 cam_isp_hw_get_timestamp(&evt_payload->ts);
1614
1615 evt_payload->core_index = handler_priv->core_index;
1616 evt_payload->core_info = handler_priv->core_info;
1617 evt_payload->bus_priv = bus_priv;
1618 CDBG("core_idx %d, core_info %llx\n", handler_priv->core_index,
1619 (uint64_t)handler_priv->core_info);
1620
1621 for (i = 0; i < CAM_IFE_BUS_IRQ_REGISTERS_MAX; i++) {
Harsh Shah23557ae2017-05-13 18:14:34 -07001622 irq_mask = cam_io_r(handler_priv->mem_base +
1623 irq_reg_offset[i] - (0xC * 2));
1624 evt_payload->irq_reg_val[i] = irq_mask &
1625 cam_io_r(handler_priv->mem_base + irq_reg_offset[i]);
Harsh Shah35165dc2017-06-06 19:42:41 -07001626 if (evt_payload->irq_reg_val[i])
1627 found = 1;
Harsh Shaha1af8822017-05-11 22:06:36 -07001628 CDBG("irq_status%d = 0x%x\n", i, evt_payload->irq_reg_val[i]);
1629 }
1630 for (i = 0; i <= CAM_IFE_IRQ_BUS_REG_STATUS2; i++) {
1631 cam_io_w(evt_payload->irq_reg_val[i], handler_priv->mem_base +
1632 reg_info->irq_reg_set[i].clear_reg_offset);
1633 CDBG("Clear irq_status%d = 0x%x offset 0x%x\n", i,
1634 evt_payload->irq_reg_val[i],
1635 reg_info->irq_reg_set[i].clear_reg_offset);
1636 }
1637 cam_io_w(reg_info->global_clear_bitmask, handler_priv->mem_base +
1638 reg_info->global_clear_offset);
1639 CDBG("Global clear bitmask = 0x%x offset 0x%x\n",
1640 reg_info->global_clear_bitmask,
1641 reg_info->global_clear_offset);
1642
Harsh Shah35165dc2017-06-06 19:42:41 -07001643 if (found)
1644 th_payload->evt_payload_priv = evt_payload;
1645 else {
1646 cam_vfe_bus_put_evt_payload(evt_payload->core_info,
1647 &evt_payload);
1648 rc = -ENOMSG;
1649 }
Harsh Shaha1af8822017-05-11 22:06:36 -07001650
1651 return rc;
1652}
1653
1654static int cam_vfe_bus_update_buf(void *priv, void *cmd_args,
1655 uint32_t arg_size)
1656{
1657 struct cam_vfe_bus_ver2_priv *bus_priv;
1658 struct cam_isp_hw_get_buf_update *update_buf;
Jing Zhoua4e9fbe2017-05-15 14:37:21 -07001659 struct cam_buf_io_cfg *io_cfg;
Harsh Shaha1af8822017-05-11 22:06:36 -07001660 struct cam_vfe_bus_ver2_vfe_out_data *vfe_out_data = NULL;
1661 struct cam_vfe_bus_ver2_wm_resource_data *wm_data = NULL;
Jing Zhoua4e9fbe2017-05-15 14:37:21 -07001662 uint32_t *reg_val_pair;
1663 uint32_t i, j, size = 0;
Junzhe Zou193d78c2017-05-16 15:10:54 -07001664 uint32_t frame_inc = 0;
Harsh Shaha1af8822017-05-11 22:06:36 -07001665
1666 /*
1667 * Need the entire buf io config so we can get the stride info
1668 * for the wm.
1669 */
1670
1671 bus_priv = (struct cam_vfe_bus_ver2_priv *) priv;
1672 update_buf = (struct cam_isp_hw_get_buf_update *) cmd_args;
1673
1674 vfe_out_data = (struct cam_vfe_bus_ver2_vfe_out_data *)
1675 update_buf->cdm.res->res_priv;
1676
1677 if (!vfe_out_data || !vfe_out_data->cdm_util_ops) {
1678 pr_err("Failed! Invalid data\n");
1679 return -EINVAL;
1680 }
1681
Jing Zhoua4e9fbe2017-05-15 14:37:21 -07001682 if (update_buf->num_buf != vfe_out_data->num_wm) {
Harsh Shaha1af8822017-05-11 22:06:36 -07001683 pr_err("Failed! Invalid number buffers:%d required:%d\n",
1684 update_buf->num_buf, vfe_out_data->num_wm);
Junzhe Zou193d78c2017-05-16 15:10:54 -07001685 return -EINVAL;
Harsh Shaha1af8822017-05-11 22:06:36 -07001686 }
1687
Jing Zhoua4e9fbe2017-05-15 14:37:21 -07001688 reg_val_pair = &vfe_out_data->common_data->io_buf_update[0];
1689 io_cfg = update_buf->io_cfg;
1690
1691 for (i = 0, j = 0; i < vfe_out_data->num_wm; i++) {
Junzhe Zou193d78c2017-05-16 15:10:54 -07001692 if (j >= (MAX_REG_VAL_PAIR_SIZE - MAX_BUF_UPDATE_REG_NUM * 2)) {
1693 pr_err("reg_val_pair %d exceeds the array limit %lu\n",
1694 j, MAX_REG_VAL_PAIR_SIZE);
1695 return -ENOMEM;
1696 }
1697
Jing Zhoua4e9fbe2017-05-15 14:37:21 -07001698 wm_data = vfe_out_data->wm_res[i]->res_priv;
1699
1700 /* For initial configuration program all bus registers */
1701 if (wm_data->stride != io_cfg->planes[i].plane_stride ||
1702 !wm_data->init_cfg_done) {
1703 CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j,
1704 wm_data->hw_regs->stride,
1705 io_cfg->planes[i].plane_stride);
1706 wm_data->stride = io_cfg->planes[i].plane_stride;
1707 }
1708 CDBG("image stride 0x%x\n", wm_data->stride);
1709
1710 if (wm_data->framedrop_pattern != io_cfg->framedrop_pattern ||
1711 !wm_data->init_cfg_done) {
1712 CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j,
1713 wm_data->hw_regs->framedrop_pattern,
1714 io_cfg->framedrop_pattern);
1715 wm_data->framedrop_pattern = io_cfg->framedrop_pattern;
1716 }
1717 CDBG("framedrop pattern 0x%x\n", wm_data->framedrop_pattern);
1718
1719 if (wm_data->framedrop_period != io_cfg->framedrop_period ||
1720 !wm_data->init_cfg_done) {
1721 CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j,
1722 wm_data->hw_regs->framedrop_period,
1723 io_cfg->framedrop_period);
1724 wm_data->framedrop_period = io_cfg->framedrop_period;
1725 }
1726 CDBG("framedrop period 0x%x\n", wm_data->framedrop_period);
1727
1728 if (wm_data->irq_subsample_period != io_cfg->subsample_period
1729 || !wm_data->init_cfg_done) {
1730 CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j,
1731 wm_data->hw_regs->irq_subsample_period,
1732 io_cfg->subsample_period);
1733 wm_data->irq_subsample_period =
1734 io_cfg->subsample_period;
1735 }
1736 CDBG("irq subsample period 0x%x\n",
1737 wm_data->irq_subsample_period);
1738
1739 if (wm_data->irq_subsample_pattern != io_cfg->subsample_pattern
1740 || !wm_data->init_cfg_done) {
1741 CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j,
1742 wm_data->hw_regs->irq_subsample_pattern,
1743 io_cfg->subsample_pattern);
1744 wm_data->irq_subsample_pattern =
1745 io_cfg->subsample_pattern;
1746 }
1747 CDBG("irq subsample pattern 0x%x\n",
1748 wm_data->irq_subsample_pattern);
1749
1750 if (wm_data->en_ubwc) {
1751 if (!wm_data->hw_regs->ubwc_regs) {
1752 pr_err("%s: No UBWC register to configure.\n",
1753 __func__);
1754 return -EINVAL;
1755 }
1756 if (wm_data->packer_cfg !=
1757 io_cfg->planes[i].packer_config ||
1758 !wm_data->init_cfg_done) {
1759 CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j,
1760 wm_data->hw_regs->packer_cfg,
1761 io_cfg->planes[i].packer_config);
1762 wm_data->packer_cfg =
1763 io_cfg->planes[i].packer_config;
1764 }
1765 CDBG("packer cfg 0x%x\n", wm_data->packer_cfg);
1766
1767 if (wm_data->tile_cfg != io_cfg->planes[i].tile_config
1768 || !wm_data->init_cfg_done) {
1769 CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j,
1770 wm_data->hw_regs->ubwc_regs->tile_cfg,
1771 io_cfg->planes[i].tile_config);
1772 wm_data->tile_cfg =
1773 io_cfg->planes[i].tile_config;
1774 }
1775 CDBG("tile cfg 0x%x\n", wm_data->tile_cfg);
1776
1777 if (wm_data->h_init != io_cfg->planes[i].h_init ||
1778 !wm_data->init_cfg_done) {
1779 CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j,
1780 wm_data->hw_regs->ubwc_regs->h_init,
1781 io_cfg->planes[i].h_init);
1782 wm_data->h_init = io_cfg->planes[i].h_init;
1783 }
1784 CDBG("h_init 0x%x\n", wm_data->h_init);
1785
1786 if (wm_data->v_init != io_cfg->planes[i].v_init ||
1787 !wm_data->init_cfg_done) {
1788 CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j,
1789 wm_data->hw_regs->ubwc_regs->v_init,
1790 io_cfg->planes[i].v_init);
1791 wm_data->v_init = io_cfg->planes[i].v_init;
1792 }
1793 CDBG("v_init 0x%x\n", wm_data->v_init);
1794
1795 if (wm_data->ubwc_meta_stride !=
1796 io_cfg->planes[i].meta_stride ||
1797 !wm_data->init_cfg_done) {
1798 CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j,
1799 wm_data->hw_regs->ubwc_regs->
1800 meta_stride,
1801 io_cfg->planes[i].meta_stride);
1802 wm_data->ubwc_meta_stride =
1803 io_cfg->planes[i].meta_stride;
1804 }
1805 CDBG("meta stride 0x%x\n", wm_data->ubwc_meta_stride);
1806
1807 if (wm_data->ubwc_mode_cfg !=
1808 io_cfg->planes[i].mode_config ||
1809 !wm_data->init_cfg_done) {
1810 CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j,
1811 wm_data->hw_regs->ubwc_regs->mode_cfg,
1812 io_cfg->planes[i].mode_config);
1813 wm_data->ubwc_mode_cfg =
1814 io_cfg->planes[i].mode_config;
1815 }
1816 CDBG("ubwc mode cfg 0x%x\n", wm_data->ubwc_mode_cfg);
1817
1818 if (wm_data->ubwc_meta_offset !=
1819 io_cfg->planes[i].meta_offset ||
1820 !wm_data->init_cfg_done) {
1821 CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j,
1822 wm_data->hw_regs->ubwc_regs->
1823 meta_offset,
1824 io_cfg->planes[i].meta_offset);
1825 wm_data->ubwc_meta_offset =
1826 io_cfg->planes[i].meta_offset;
1827 }
1828 CDBG("ubwc meta offset 0x%x\n",
1829 wm_data->ubwc_meta_offset);
1830
1831 /* UBWC meta address */
1832 CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j,
1833 wm_data->hw_regs->ubwc_regs->meta_addr,
1834 update_buf->image_buf[i]);
1835 CDBG("ubwc meta addr 0x%llx\n",
1836 update_buf->image_buf[i]);
1837 }
1838
1839 /* WM Image address */
1840 if (wm_data->en_ubwc)
1841 CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j,
1842 wm_data->hw_regs->image_addr,
1843 (update_buf->image_buf[i] +
1844 io_cfg->planes[i].meta_size));
1845 else
1846 CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j,
1847 wm_data->hw_regs->image_addr,
1848 update_buf->image_buf[i]);
1849
1850 CDBG("image address 0x%x\n", reg_val_pair[j-1]);
1851
Junzhe Zou193d78c2017-05-16 15:10:54 -07001852 frame_inc = io_cfg->planes[i].plane_stride *
1853 io_cfg->planes[i].slice_height;
1854 CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j,
1855 wm_data->hw_regs->frame_inc, frame_inc);
1856
Jing Zhoua4e9fbe2017-05-15 14:37:21 -07001857 /* enable the WM */
1858 CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j,
1859 wm_data->hw_regs->cfg,
1860 wm_data->en_cfg);
1861
1862 /* set initial configuration done */
1863 if (!wm_data->init_cfg_done)
1864 wm_data->init_cfg_done = 1;
1865 }
1866
1867 size = vfe_out_data->cdm_util_ops->cdm_required_size_reg_random(j/2);
Harsh Shaha1af8822017-05-11 22:06:36 -07001868
1869 /* cdm util returns dwords, need to convert to bytes */
1870 if ((size * 4) > update_buf->cdm.size) {
1871 pr_err("Failed! Buf size:%d insufficient, expected size:%d\n",
1872 update_buf->cdm.size, size);
1873 return -ENOMEM;
1874 }
1875
Harsh Shaha1af8822017-05-11 22:06:36 -07001876 vfe_out_data->cdm_util_ops->cdm_write_regrandom(
Jing Zhoua4e9fbe2017-05-15 14:37:21 -07001877 update_buf->cdm.cmd_buf_addr, j/2, reg_val_pair);
1878
Harsh Shaha1af8822017-05-11 22:06:36 -07001879 /* cdm util returns dwords, need to convert to bytes */
1880 update_buf->cdm.used_bytes = size * 4;
1881
1882 return 0;
1883}
1884
1885static int cam_vfe_bus_process_cmd(void *priv,
1886 uint32_t cmd_type, void *cmd_args, uint32_t arg_size)
1887{
1888 int rc = -EINVAL;
1889
1890 if (!priv || !cmd_args) {
1891 pr_err_ratelimited("Error! Invalid input arguments\n");
1892 return -EINVAL;
1893 }
1894
1895 switch (cmd_type) {
1896 case CAM_VFE_HW_CMD_GET_BUF_UPDATE:
1897 rc = cam_vfe_bus_update_buf(priv, cmd_args, arg_size);
1898 break;
1899 default:
1900 pr_err_ratelimited("Error! Invalid camif process command:%d\n",
1901 cmd_type);
1902 break;
1903 }
1904
1905 return rc;
1906}
1907
1908int cam_vfe_bus_ver2_init(
1909 void __iomem *mem_base,
1910 struct cam_hw_intf *hw_intf,
1911 void *bus_hw_info,
1912 void *vfe_irq_controller,
1913 struct cam_vfe_bus **vfe_bus)
1914{
1915 int i, rc = 0;
1916 struct cam_vfe_bus_ver2_priv *bus_priv = NULL;
1917 struct cam_vfe_bus *vfe_bus_local;
1918 struct cam_vfe_bus_ver2_hw_info *ver2_hw_info = bus_hw_info;
1919
1920 CDBG("Enter\n");
1921
1922 vfe_bus_local = kzalloc(sizeof(struct cam_vfe_bus), GFP_KERNEL);
1923 if (!vfe_bus_local) {
1924 CDBG("Failed to alloc for vfe_bus\n");
1925 rc = -ENOMEM;
1926 goto err_alloc_bus;
1927 }
1928
1929 bus_priv = kzalloc(sizeof(struct cam_vfe_bus_ver2_priv),
1930 GFP_KERNEL);
1931 if (!bus_priv) {
1932 CDBG("Failed to alloc for vfe_bus_priv\n");
1933 rc = -ENOMEM;
1934 goto err_alloc_priv;
1935 }
1936 vfe_bus_local->bus_priv = bus_priv;
1937
1938 bus_priv->common_data.mem_base = mem_base;
1939 bus_priv->common_data.hw_intf = hw_intf;
1940 bus_priv->common_data.vfe_irq_controller = vfe_irq_controller;
1941 bus_priv->common_data.common_reg = &ver2_hw_info->common_reg;
1942
1943 INIT_LIST_HEAD(&bus_priv->free_comp_grp);
1944 INIT_LIST_HEAD(&bus_priv->free_dual_comp_grp);
1945 INIT_LIST_HEAD(&bus_priv->used_comp_grp);
1946
1947 for (i = 0; i < CAM_VFE_BUS_VER2_MAX_CLIENTS; i++) {
1948 rc = cam_vfe_bus_init_wm_resource(i, bus_priv, bus_hw_info,
1949 &bus_priv->bus_client[i]);
1950 if (rc < 0) {
1951 pr_err("Error! Init WM failed\n");
1952 goto err_init_wm;
1953 }
1954 }
1955
1956 for (i = 0; i < CAM_VFE_BUS_VER2_COMP_GRP_MAX; i++) {
1957 rc = cam_vfe_bus_init_comp_grp(i, bus_priv, bus_hw_info,
1958 &bus_priv->comp_grp[i]);
1959 if (rc < 0) {
1960 pr_err("Error! Init Comp Grp failed\n");
1961 goto err_init_comp_grp;
1962 }
1963 }
1964
1965 for (i = 0; i < CAM_VFE_BUS_VER2_VFE_OUT_MAX; i++) {
1966 rc = cam_vfe_bus_init_vfe_out_resource(i, bus_priv, bus_hw_info,
1967 &bus_priv->vfe_out[i]);
1968 if (rc < 0) {
1969 pr_err("Error! Init VFE Out failed\n");
1970 goto err_init_vfe_out;
1971 }
1972 }
1973
1974 INIT_LIST_HEAD(&bus_priv->free_payload_list);
1975 for (i = 0; i < 128; i++) {
1976 INIT_LIST_HEAD(&bus_priv->evt_payload[i].list);
1977 list_add_tail(&bus_priv->evt_payload[i].list,
1978 &bus_priv->free_payload_list);
1979 }
1980
1981 vfe_bus_local->acquire_resource = cam_vfe_bus_acquire_vfe_out;
1982 vfe_bus_local->release_resource = cam_vfe_bus_release_vfe_out;
1983 vfe_bus_local->start_resource = cam_vfe_bus_start_vfe_out;
1984 vfe_bus_local->stop_resource = cam_vfe_bus_stop_vfe_out;
1985 vfe_bus_local->top_half_handler = cam_vfe_bus_ver2_handle_irq;
1986 vfe_bus_local->bottom_half_handler = NULL;
1987 vfe_bus_local->process_cmd = cam_vfe_bus_process_cmd;
1988
1989 *vfe_bus = vfe_bus_local;
1990
1991 return rc;
1992
1993err_init_vfe_out:
1994err_init_comp_grp:
1995err_init_wm:
1996 kfree(vfe_bus_local->bus_priv);
1997err_alloc_priv:
1998 kfree(vfe_bus_local);
1999err_alloc_bus:
2000 return rc;
2001}