blob: c7abc60da1a43994bc66c1ac3001d74f29575c31 [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:
374 return 1;
375 default:
376 break;
377 }
378 break;
379 case CAM_VFE_BUS_VER2_VFE_OUT_STATS_RS:
380 case CAM_VFE_BUS_VER2_VFE_OUT_STATS_IHIST:
381 switch (format) {
382 case CAM_FORMAT_PLAIN16_16:
383 return 1;
384 default:
385 break;
386 }
387 break;
388 default:
389 break;
390 }
391
392 pr_err("Unsupported format %u for resource_type %u", format, res_type);
393
394 return -EINVAL;
395}
396
397static int cam_vfe_bus_get_wm_idx(
398 enum cam_vfe_bus_ver2_vfe_out_type vfe_out_res_id,
399 enum cam_vfe_bus_plane_type plane)
400{
401 int wm_idx = -1;
402
403 switch (vfe_out_res_id) {
404 case CAM_VFE_BUS_VER2_VFE_OUT_FULL:
405 switch (plane) {
406 case PLANE_Y:
407 wm_idx = 3;
408 break;
409 case PLANE_C:
410 wm_idx = 4;
411 break;
412 default:
413 break;
414 }
415 break;
416 case CAM_VFE_BUS_VER2_VFE_OUT_DS4:
417 switch (plane) {
418 case PLANE_Y:
419 wm_idx = 5;
420 break;
421 default:
422 break;
423 }
424 break;
425 case CAM_VFE_BUS_VER2_VFE_OUT_DS16:
426 switch (plane) {
427 case PLANE_Y:
428 wm_idx = 6;
429 break;
430 default:
431 break;
432 }
433 break;
434 case CAM_VFE_BUS_VER2_VFE_OUT_FD:
435 switch (plane) {
436 case PLANE_Y:
437 wm_idx = 7;
438 break;
439 case PLANE_C:
440 wm_idx = 8;
441 break;
442 default:
443 break;
444 }
445 break;
446 case CAM_VFE_BUS_VER2_VFE_OUT_RAW_DUMP:
447 switch (plane) {
448 case PLANE_Y:
449 wm_idx = 9;
450 break;
451 default:
452 break;
453 }
454 break;
455 case CAM_VFE_BUS_VER2_VFE_OUT_PDAF:
456 switch (plane) {
457 case PLANE_Y:
458 wm_idx = 10;
459 break;
460 default:
461 break;
462 }
463 break;
464 case CAM_VFE_BUS_VER2_VFE_OUT_RDI0:
465 switch (plane) {
466 case PLANE_Y:
467 wm_idx = 0;
468 break;
469 default:
470 break;
471 }
472 break;
473 case CAM_VFE_BUS_VER2_VFE_OUT_RDI1:
474 switch (plane) {
475 case PLANE_Y:
476 wm_idx = 1;
477 break;
478 default:
479 break;
480 }
481 break;
482 case CAM_VFE_BUS_VER2_VFE_OUT_RDI2:
483 switch (plane) {
484 case PLANE_Y:
485 wm_idx = 2;
486 break;
487 default:
488 break;
489 }
490 break;
491 case CAM_VFE_BUS_VER2_VFE_OUT_STATS_HDR_BE:
492 switch (plane) {
493 case PLANE_Y:
494 wm_idx = 11;
495 break;
496 default:
497 break;
498 }
499 break;
500 case CAM_VFE_BUS_VER2_VFE_OUT_STATS_HDR_BHIST:
501 switch (plane) {
502 case PLANE_Y:
503 wm_idx = 12;
504 break;
505 default:
506 break;
507 }
508 break;
509 case CAM_VFE_BUS_VER2_VFE_OUT_STATS_TL_BG:
510 switch (plane) {
511 case PLANE_Y:
512 wm_idx = 13;
513 break;
514 default:
515 break;
516 }
517 break;
518 case CAM_VFE_BUS_VER2_VFE_OUT_STATS_BF:
519 switch (plane) {
520 case PLANE_Y:
521 wm_idx = 14;
522 break;
523 default:
524 break;
525 }
526 break;
527 case CAM_VFE_BUS_VER2_VFE_OUT_STATS_AWB_BG:
528 switch (plane) {
529 case PLANE_Y:
530 wm_idx = 15;
531 break;
532 default:
533 break;
534 }
535 break;
536 case CAM_VFE_BUS_VER2_VFE_OUT_STATS_BHIST:
537 switch (plane) {
538 case PLANE_Y:
539 wm_idx = 16;
540 break;
541 default:
542 break;
543 }
544 break;
545 case CAM_VFE_BUS_VER2_VFE_OUT_STATS_RS:
546 switch (plane) {
547 case PLANE_Y:
548 wm_idx = 17;
549 break;
550 default:
551 break;
552 }
553 break;
554 case CAM_VFE_BUS_VER2_VFE_OUT_STATS_CS:
555 switch (plane) {
556 case PLANE_Y:
557 wm_idx = 18;
558 break;
559 default:
560 break;
561 }
562 break;
563 case CAM_VFE_BUS_VER2_VFE_OUT_STATS_IHIST:
564 switch (plane) {
565 case PLANE_Y:
566 wm_idx = 19;
567 break;
568 default:
569 break;
570 }
571 break;
572 default:
573 break;
574 }
575
576 return wm_idx;
577}
578
579static enum cam_vfe_bus_packer_format
580 cam_vfe_bus_get_packer_fmt(uint32_t out_fmt)
581{
582 switch (out_fmt) {
583 case CAM_FORMAT_NV21:
584 case CAM_FORMAT_NV12:
585 return PACKER_FMT_PLAIN_8;
586 default:
587 return PACKER_FMT_MAX;
588 }
589}
590
591static int cam_vfe_bus_acquire_wm(
592 struct cam_vfe_bus_ver2_priv *ver2_bus_priv,
593 struct cam_isp_out_port_info *out_port_info,
594 enum cam_vfe_bus_ver2_vfe_out_type vfe_out_res_id,
595 enum cam_vfe_bus_plane_type plane,
596 enum cam_isp_hw_split_id split_id,
597 uint32_t subscribe_irq,
598 struct cam_isp_resource_node **wm_res,
599 uint32_t *client_done_mask)
600{
601 uint32_t wm_idx = 0;
602 struct cam_isp_resource_node *wm_res_local = NULL;
603 struct cam_vfe_bus_ver2_wm_resource_data *rsrc_data = NULL;
604
605 *wm_res = NULL;
606 *client_done_mask = 0;
607
608 /* No need to allocate for BUS VER2. VFE OUT to WM is fixed. */
609 wm_idx = cam_vfe_bus_get_wm_idx(vfe_out_res_id, plane);
610 if (wm_idx < 0 || wm_idx >= CAM_VFE_BUS_VER2_MAX_CLIENTS) {
611 pr_err("Unsupported VFE out %d plane %d\n",
612 vfe_out_res_id, plane);
613 return -EINVAL;
614 }
615
616 wm_res_local = &ver2_bus_priv->bus_client[wm_idx];
617 wm_res_local->res_state = CAM_ISP_RESOURCE_STATE_RESERVED;
618
619 rsrc_data = wm_res_local->res_priv;
620 rsrc_data->irq_enabled = subscribe_irq;
621 rsrc_data->format = out_port_info->format;
622 rsrc_data->pack_fmt = cam_vfe_bus_get_packer_fmt(rsrc_data->format);
623
624 rsrc_data->width = out_port_info->width;
625 rsrc_data->height = out_port_info->height;
Jing Zhoua4e9fbe2017-05-15 14:37:21 -0700626
627 if (rsrc_data->index < 3) {
628 rsrc_data->width = rsrc_data->width * 5/4 * rsrc_data->height;
629 rsrc_data->height = 1;
630 rsrc_data->pack_fmt = 0x0;
631 rsrc_data->en_cfg = 0x3;
632 } else if (rsrc_data->index < 5) {
633 switch (plane) {
634 case PLANE_Y:
635 switch (rsrc_data->format) {
636 case CAM_FORMAT_UBWC_NV12:
637 case CAM_FORMAT_UBWC_NV12_4R:
638 case CAM_FORMAT_UBWC_TP10:
639 rsrc_data->en_ubwc = 1;
640 break;
641 default:
642 break;
643 }
644 break;
645 case PLANE_C:
646 switch (rsrc_data->format) {
647 case CAM_FORMAT_NV21:
648 case CAM_FORMAT_NV12:
649 rsrc_data->height /= 2;
650 break;
651 case CAM_FORMAT_UBWC_NV12:
652 case CAM_FORMAT_UBWC_NV12_4R:
653 case CAM_FORMAT_UBWC_TP10:
654 rsrc_data->height /= 2;
655 rsrc_data->en_ubwc = 1;
656 break;
657 default:
658 break;
659 }
Harsh Shaha1af8822017-05-11 22:06:36 -0700660 break;
661 default:
Jing Zhoua4e9fbe2017-05-15 14:37:21 -0700662 pr_err("Invalid plane type %d\n", plane);
663 return -EINVAL;
Harsh Shaha1af8822017-05-11 22:06:36 -0700664 }
Jing Zhoua4e9fbe2017-05-15 14:37:21 -0700665 rsrc_data->pack_fmt = 0xE;
666 rsrc_data->en_cfg = 0x1;
667 } else {
668 rsrc_data->width = rsrc_data->width * 4;
669 rsrc_data->height = rsrc_data->height / 2;
670 rsrc_data->pack_fmt = 0x0;
671 rsrc_data->en_cfg = 0x1;
Harsh Shaha1af8822017-05-11 22:06:36 -0700672 }
673
674 if (vfe_out_res_id >= CAM_ISP_IFE_OUT_RES_RDI_0 &&
675 vfe_out_res_id <= CAM_ISP_IFE_OUT_RES_RDI_3)
676 rsrc_data->frame_based = 1;
677
678 *client_done_mask = (1 << wm_idx);
679 *wm_res = wm_res_local;
680
681 return 0;
682}
683
684static int cam_vfe_bus_release_wm(void *bus_priv,
685 struct cam_isp_resource_node *wm_res)
686{
687 struct cam_vfe_bus_ver2_wm_resource_data *rsrc_data =
688 wm_res->res_priv;
689
690 rsrc_data->irq_enabled = 0;
691 rsrc_data->offset = 0;
692 rsrc_data->width = 0;
693 rsrc_data->height = 0;
694 rsrc_data->stride = 0;
695 rsrc_data->format = 0;
696 rsrc_data->pack_fmt = 0;
697 rsrc_data->burst_len = 0;
698 rsrc_data->frame_based = 0;
699 rsrc_data->irq_subsample_period = 0;
700 rsrc_data->irq_subsample_pattern = 0;
701 rsrc_data->framedrop_period = 0;
702 rsrc_data->framedrop_pattern = 0;
Jing Zhoua4e9fbe2017-05-15 14:37:21 -0700703 rsrc_data->packer_cfg = 0;
704 rsrc_data->en_ubwc = 0;
705 rsrc_data->tile_cfg = 0;
706 rsrc_data->h_init = 0;
707 rsrc_data->v_init = 0;
708 rsrc_data->ubwc_meta_stride = 0;
709 rsrc_data->ubwc_mode_cfg = 0;
710 rsrc_data->ubwc_meta_offset = 0;
711 rsrc_data->init_cfg_done = 0;
712 rsrc_data->en_cfg = 0;
Harsh Shaha1af8822017-05-11 22:06:36 -0700713 wm_res->res_state = CAM_ISP_RESOURCE_STATE_AVAILABLE;
714
715 return 0;
716}
717
718static int cam_vfe_bus_start_wm(struct cam_isp_resource_node *wm_res)
719{
720 int rc = 0;
721 struct cam_vfe_bus_ver2_wm_resource_data *rsrc_data =
722 wm_res->res_priv;
723 struct cam_vfe_bus_ver2_common_data *common_data =
724 rsrc_data->common_data;
Harsh Shaha1af8822017-05-11 22:06:36 -0700725
Harsh Shah23557ae2017-05-13 18:14:34 -0700726 cam_io_w_mb(0, common_data->mem_base + rsrc_data->hw_regs->header_addr);
727 cam_io_w_mb(0, common_data->mem_base + rsrc_data->hw_regs->header_cfg);
728 cam_io_w_mb(0, common_data->mem_base + rsrc_data->hw_regs->frame_inc);
729 cam_io_w(0xf, common_data->mem_base + rsrc_data->hw_regs->burst_limit);
730
Jing Zhoua4e9fbe2017-05-15 14:37:21 -0700731 cam_io_w_mb(rsrc_data->width,
Harsh Shaha1af8822017-05-11 22:06:36 -0700732 common_data->mem_base + rsrc_data->hw_regs->buffer_width_cfg);
Jing Zhoua4e9fbe2017-05-15 14:37:21 -0700733 cam_io_w(rsrc_data->height,
Harsh Shaha1af8822017-05-11 22:06:36 -0700734 common_data->mem_base + rsrc_data->hw_regs->buffer_height_cfg);
Jing Zhoua4e9fbe2017-05-15 14:37:21 -0700735 cam_io_w(rsrc_data->pack_fmt,
Harsh Shaha1af8822017-05-11 22:06:36 -0700736 common_data->mem_base + rsrc_data->hw_regs->packer_cfg);
Harsh Shaha1af8822017-05-11 22:06:36 -0700737
738 cam_io_w(0xFFFFFFFF, common_data->mem_base +
739 rsrc_data->hw_regs->irq_subsample_pattern);
740 cam_io_w(0x0, common_data->mem_base +
741 rsrc_data->hw_regs->irq_subsample_period);
742
743 cam_io_w(0xFFFFFFFF,
Harsh Shah23557ae2017-05-13 18:14:34 -0700744 common_data->mem_base + rsrc_data->hw_regs->framedrop_pattern);
Harsh Shaha1af8822017-05-11 22:06:36 -0700745 cam_io_w(0x0,
Harsh Shah23557ae2017-05-13 18:14:34 -0700746 common_data->mem_base + rsrc_data->hw_regs->framedrop_period);
Harsh Shaha1af8822017-05-11 22:06:36 -0700747
Harsh Shah23557ae2017-05-13 18:14:34 -0700748 CDBG("WM res %d width = %d, height = %d\n", rsrc_data->index,
Jing Zhoua4e9fbe2017-05-15 14:37:21 -0700749 rsrc_data->width, rsrc_data->height);
Harsh Shah23557ae2017-05-13 18:14:34 -0700750 CDBG("WM res %d pk_fmt = %d\n", rsrc_data->index,
Jing Zhoua4e9fbe2017-05-15 14:37:21 -0700751 rsrc_data->pack_fmt & PACKER_FMT_MAX);
Harsh Shah23557ae2017-05-13 18:14:34 -0700752 CDBG("WM res %d stride = %d, burst len = %d\n",
Jing Zhoua4e9fbe2017-05-15 14:37:21 -0700753 rsrc_data->index, rsrc_data->stride, 0xf);
Harsh Shah23557ae2017-05-13 18:14:34 -0700754 CDBG("enable WM res %d offset 0x%x val 0x%x\n", rsrc_data->index,
Jing Zhoua4e9fbe2017-05-15 14:37:21 -0700755 (uint32_t) rsrc_data->hw_regs->cfg, rsrc_data->en_cfg);
Harsh Shaha1af8822017-05-11 22:06:36 -0700756
757 wm_res->res_state = CAM_ISP_RESOURCE_STATE_STREAMING;
758
759 return rc;
760}
761
762static int cam_vfe_bus_stop_wm(struct cam_isp_resource_node *wm_res)
763{
764 int rc = 0;
765 struct cam_vfe_bus_ver2_wm_resource_data *rsrc_data =
766 wm_res->res_priv;
767 struct cam_vfe_bus_ver2_common_data *common_data =
768 rsrc_data->common_data;
769
770 /* Disble WM */
771 cam_io_w_mb(0x0,
772 common_data->mem_base + rsrc_data->hw_regs->cfg);
773
774 CDBG("irq_enabled %d", rsrc_data->irq_enabled);
775 /* Unsubscribe IRQ */
776 if (rsrc_data->irq_enabled) {
777 /*
778 * Currently all WM IRQ are unsubscribed in one place. Need to
779 * make it dynamic.
780 */
781 }
782
783 /* Halt & Reset WM */
784 cam_io_w_mb(BIT(rsrc_data->index),
785 common_data->mem_base + common_data->common_reg->sw_reset);
786
787 wm_res->res_state = CAM_ISP_RESOURCE_STATE_RESERVED;
788
789 return rc;
790}
791
792static int cam_vfe_bus_handle_wm_done_top_half(uint32_t evt_id,
793 struct cam_irq_th_payload *th_payload)
794{
795 return -EPERM;
796}
797
798static int cam_vfe_bus_handle_wm_done_bottom_half(void *wm_node,
799 void *evt_payload_priv)
800{
801 int rc = CAM_VFE_IRQ_STATUS_ERR;
802 struct cam_isp_resource_node *wm_res = wm_node;
803 struct cam_vfe_bus_irq_evt_payload *evt_payload = evt_payload_priv;
Harsh Shah23557ae2017-05-13 18:14:34 -0700804 struct cam_vfe_bus_ver2_wm_resource_data *rsrc_data =
805 (wm_res == NULL) ? NULL : wm_res->res_priv;
806 uint32_t *cam_ife_irq_regs;
Harsh Shaha1af8822017-05-11 22:06:36 -0700807 uint32_t status_reg;
808
Harsh Shah23557ae2017-05-13 18:14:34 -0700809 if (!evt_payload || !rsrc_data)
810 return rc;
Harsh Shaha1af8822017-05-11 22:06:36 -0700811
Harsh Shah23557ae2017-05-13 18:14:34 -0700812 cam_ife_irq_regs = evt_payload->irq_reg_val;
813 status_reg = cam_ife_irq_regs[CAM_IFE_IRQ_BUS_REG_STATUS1];
814
815 if (status_reg & BIT(rsrc_data->index)) {
816 cam_ife_irq_regs[CAM_IFE_IRQ_BUS_REG_STATUS1] &=
817 ~BIT(rsrc_data->index);
Harsh Shaha1af8822017-05-11 22:06:36 -0700818 rc = CAM_VFE_IRQ_STATUS_SUCCESS;
Harsh Shah23557ae2017-05-13 18:14:34 -0700819 }
Harsh Shaha1af8822017-05-11 22:06:36 -0700820
821 if (rc == CAM_VFE_IRQ_STATUS_SUCCESS)
822 cam_vfe_bus_put_evt_payload(evt_payload->core_info,
823 &evt_payload);
824
825 return rc;
826}
827
828static int cam_vfe_bus_init_wm_resource(uint32_t index,
829 struct cam_vfe_bus_ver2_priv *ver2_bus_priv,
830 struct cam_vfe_bus_ver2_hw_info *ver2_hw_info,
831 struct cam_isp_resource_node *wm_res)
832{
833 int rc = 0;
834 struct cam_vfe_bus_ver2_wm_resource_data *rsrc_data;
835
836 rsrc_data = kzalloc(sizeof(struct cam_vfe_bus_ver2_wm_resource_data),
837 GFP_KERNEL);
838 if (!rsrc_data) {
839 CDBG("Failed to alloc for wm res priv\n");
840 rc = -ENOMEM;
841 return rc;
842 }
843 wm_res->res_priv = rsrc_data;
844
845 rsrc_data->index = index;
846 rsrc_data->hw_regs = &ver2_hw_info->bus_client_reg[index];
847 rsrc_data->common_data = &ver2_bus_priv->common_data;
848
849 wm_res->res_state = CAM_ISP_RESOURCE_STATE_AVAILABLE;
850 INIT_LIST_HEAD(&wm_res->list);
851
852 wm_res->start = cam_vfe_bus_start_wm;
853 wm_res->stop = cam_vfe_bus_stop_wm;
854 wm_res->top_half_handler = cam_vfe_bus_handle_wm_done_top_half;
855 wm_res->bottom_half_handler = cam_vfe_bus_handle_wm_done_bottom_half;
856 wm_res->hw_intf = ver2_bus_priv->common_data.hw_intf;
857
858 return rc;
859}
860
861static void cam_vfe_bus_add_wm_to_comp_grp(
862 struct cam_isp_resource_node *comp_grp,
863 uint32_t composite_mask)
864{
865 struct cam_vfe_bus_ver2_comp_grp_data *rsrc_data = comp_grp->res_priv;
866
867 rsrc_data->composite_mask |= composite_mask;
868}
869
870static void cam_vfe_bus_match_comp_grp(
871 struct cam_vfe_bus_ver2_priv *ver2_bus_priv,
872 struct cam_isp_resource_node **comp_grp,
873 uint32_t comp_grp_local_idx,
874 uint32_t unique_id)
875{
876 struct cam_vfe_bus_ver2_comp_grp_data *rsrc_data = NULL;
877 struct cam_isp_resource_node *comp_grp_local = NULL;
878
879 list_for_each_entry(comp_grp_local,
880 &ver2_bus_priv->used_comp_grp, list) {
881 rsrc_data = comp_grp_local->res_priv;
882 if (rsrc_data->comp_grp_local_idx == comp_grp_local_idx &&
883 rsrc_data->unique_id == unique_id) {
884 /* Match found */
885 *comp_grp = comp_grp_local;
886 return;
887 }
888 }
889
890 *comp_grp = NULL;
891}
892
893static int cam_vfe_bus_acquire_comp_grp(
894 struct cam_vfe_bus_ver2_priv *ver2_bus_priv,
895 struct cam_isp_out_port_info *out_port_info,
896 uint32_t unique_id,
897 uint32_t is_dual,
898 uint32_t is_master,
899 enum cam_vfe_bus_ver2_vfe_core_id dual_slave_core,
900 struct cam_isp_resource_node **comp_grp)
901{
902 int rc = 0;
903 struct cam_isp_resource_node *comp_grp_local = NULL;
904 struct cam_vfe_bus_ver2_comp_grp_data *rsrc_data = NULL;
905
906 /* Check if matching comp_grp already acquired */
907 cam_vfe_bus_match_comp_grp(ver2_bus_priv, &comp_grp_local,
908 out_port_info->comp_grp_id, unique_id);
909
910 if (!comp_grp_local) {
911 /* First find a free group */
912 if (is_dual) {
913 if (list_empty(&ver2_bus_priv->free_dual_comp_grp)) {
914 pr_err("No Free Composite Group\n");
915 return -ENODEV;
916 }
917 comp_grp_local = list_first_entry(
918 &ver2_bus_priv->free_dual_comp_grp,
919 struct cam_isp_resource_node, list);
920 rsrc_data = comp_grp_local->res_priv;
921 rc = cam_vfe_bus_ver2_get_intra_client_mask(
922 dual_slave_core,
923 comp_grp_local->hw_intf->hw_idx,
924 &rsrc_data->intra_client_mask);
925 } else {
926 if (list_empty(&ver2_bus_priv->free_comp_grp)) {
927 pr_err("No Free Composite Group\n");
928 return -ENODEV;
929 }
930 comp_grp_local = list_first_entry(
931 &ver2_bus_priv->free_comp_grp,
932 struct cam_isp_resource_node, list);
933 rsrc_data = comp_grp_local->res_priv;
934 }
935
936 list_del(&comp_grp_local->list);
937 comp_grp_local->res_state = CAM_ISP_RESOURCE_STATE_RESERVED;
938
939 rsrc_data->is_master = is_master;
940 rsrc_data->composite_mask = 0;
941 rsrc_data->unique_id = unique_id;
942 rsrc_data->comp_grp_local_idx = out_port_info->comp_grp_id;
943
944 list_add_tail(&comp_grp_local->list,
945 &ver2_bus_priv->used_comp_grp);
946
947 } else {
948 rsrc_data = comp_grp_local->res_priv;
949 /* Do not support runtime change in composite mask */
950 if (comp_grp_local->res_state ==
951 CAM_ISP_RESOURCE_STATE_STREAMING) {
952 pr_err("Invalid State %d Comp Grp %u\n",
953 comp_grp_local->res_state,
954 rsrc_data->comp_grp_type);
955 return -EBUSY;
956 }
957 }
958
959 *comp_grp = comp_grp_local;
960
961 return rc;
962}
963
964static int cam_vfe_bus_release_comp_grp(
965 struct cam_vfe_bus_ver2_priv *ver2_bus_priv,
966 struct cam_isp_resource_node *in_comp_grp)
967{
968 struct cam_isp_resource_node *comp_grp = NULL;
969 struct cam_vfe_bus_ver2_comp_grp_data *in_rsrc_data = NULL;
970 int match_found = 0;
971
972 if (!in_comp_grp) {
973 pr_err("Invalid Params Comp Grp %pK\n", in_rsrc_data);
974 return -EINVAL;
975 }
976
977 if (in_comp_grp->res_state == CAM_ISP_RESOURCE_STATE_AVAILABLE) {
978 /* Already Released. Do Nothing */
979 return 0;
980 }
981
982 in_rsrc_data = in_comp_grp->res_priv;
983
984 list_for_each_entry(comp_grp, &ver2_bus_priv->used_comp_grp, list) {
985 if (comp_grp == in_comp_grp) {
986 match_found = 1;
987 break;
988 }
989 }
990
991 if (!match_found) {
992 pr_err("Could not find matching Comp Grp type %u\n",
993 in_rsrc_data->comp_grp_type);
994 return -ENODEV;
995 }
996
997
998 list_del(&comp_grp->list);
999 if (in_rsrc_data->comp_grp_type >= CAM_VFE_BUS_VER2_COMP_GRP_DUAL_0 &&
1000 in_rsrc_data->comp_grp_type <= CAM_VFE_BUS_VER2_COMP_GRP_DUAL_5)
1001 list_add_tail(&comp_grp->list,
1002 &ver2_bus_priv->free_dual_comp_grp);
Jing Zhoue71fd4a2017-05-15 19:44:34 -07001003 else if (in_rsrc_data->comp_grp_type >= CAM_VFE_BUS_VER2_COMP_GRP_0
1004 && in_rsrc_data->comp_grp_type <= CAM_VFE_BUS_VER2_COMP_GRP_5)
Harsh Shaha1af8822017-05-11 22:06:36 -07001005 list_add_tail(&comp_grp->list, &ver2_bus_priv->free_comp_grp);
1006
Harsh Shaha1af8822017-05-11 22:06:36 -07001007 in_rsrc_data->unique_id = 0;
1008 in_rsrc_data->comp_grp_local_idx = 0;
1009 in_rsrc_data->composite_mask = 0;
1010 in_rsrc_data->dual_slave_core = CAM_VFE_BUS_VER2_VFE_CORE_MAX;
1011
1012 comp_grp->res_state = CAM_ISP_RESOURCE_STATE_AVAILABLE;
1013
Jing Zhoue71fd4a2017-05-15 19:44:34 -07001014 return 0;
Harsh Shaha1af8822017-05-11 22:06:36 -07001015}
1016
1017static int cam_vfe_bus_start_comp_grp(struct cam_isp_resource_node *comp_grp)
1018{
1019 int rc = 0;
1020 struct cam_vfe_bus_ver2_comp_grp_data *rsrc_data =
1021 comp_grp->res_priv;
1022 struct cam_vfe_bus_ver2_common_data *common_data =
1023 rsrc_data->common_data;
1024
1025 /*
1026 * Individual Comp_Grp Subscribe IRQ can be done here once
1027 * dynamic IRQ enable support is added.
1028 */
Harsh Shaha1af8822017-05-11 22:06:36 -07001029
1030 cam_io_w_mb(rsrc_data->composite_mask, common_data->mem_base +
1031 rsrc_data->hw_regs->comp_mask);
1032
1033 CDBG("composite_mask is 0x%x\n", rsrc_data->composite_mask);
1034 CDBG("composite_mask addr 0x%x\n", rsrc_data->hw_regs->comp_mask);
1035
1036 if (rsrc_data->comp_grp_type >= CAM_VFE_BUS_VER2_COMP_GRP_DUAL_0 &&
1037 rsrc_data->comp_grp_type <= CAM_VFE_BUS_VER2_COMP_GRP_DUAL_5 &&
1038 rsrc_data->is_master) {
1039 int dual_comp_grp = (rsrc_data->comp_grp_type -
1040 CAM_VFE_BUS_VER2_COMP_GRP_DUAL_0);
1041 int intra_client_en = cam_io_r_mb(common_data->mem_base +
1042 common_data->common_reg->dual_master_comp_cfg);
1043
1044 /* 2 Bits per comp_grp. Hence left shift by comp_grp * 2 */
1045 intra_client_en |=
1046 (rsrc_data->intra_client_mask << dual_comp_grp * 2);
1047
1048 cam_io_w_mb(intra_client_en, common_data->mem_base +
1049 common_data->common_reg->dual_master_comp_cfg);
1050 }
1051
1052 comp_grp->res_state = CAM_ISP_RESOURCE_STATE_STREAMING;
1053 return rc;
1054}
1055
1056static int cam_vfe_bus_stop_comp_grp(struct cam_isp_resource_node *comp_grp)
1057{
1058 int rc = 0;
1059 struct cam_vfe_bus_ver2_comp_grp_data *rsrc_data =
1060 comp_grp->res_priv;
1061 struct cam_vfe_bus_ver2_common_data *common_data =
1062 rsrc_data->common_data;
1063
1064 /* Unsubscribe IRQ */
1065
1066 cam_io_w_mb(rsrc_data->composite_mask, common_data->mem_base +
1067 rsrc_data->hw_regs->comp_mask);
1068 if (rsrc_data->comp_grp_type >= CAM_VFE_BUS_VER2_COMP_GRP_DUAL_0 &&
1069 rsrc_data->comp_grp_type <= CAM_VFE_BUS_VER2_COMP_GRP_DUAL_5 &&
1070 rsrc_data->is_master) {
1071 int dual_comp_grp = (rsrc_data->comp_grp_type -
1072 CAM_VFE_BUS_VER2_COMP_GRP_DUAL_0);
1073 int intra_client_en = cam_io_r_mb(common_data->mem_base +
1074 common_data->common_reg->dual_master_comp_cfg);
1075
1076 /* 2 Bits per comp_grp. Hence left shift by comp_grp * 2 */
1077 intra_client_en &=
1078 ~(rsrc_data->intra_client_mask << dual_comp_grp * 2);
1079
1080 cam_io_w_mb(intra_client_en, common_data->mem_base +
1081 common_data->common_reg->dual_master_comp_cfg);
1082 }
1083
1084 comp_grp->res_state = CAM_ISP_RESOURCE_STATE_RESERVED;
1085
1086 return rc;
1087}
1088
1089static int cam_vfe_bus_handle_comp_done_top_half(uint32_t evt_id,
1090 struct cam_irq_th_payload *th_payload)
1091{
1092 return -EPERM;
1093}
1094
1095static int cam_vfe_bus_handle_comp_done_bottom_half(
1096 void *handler_priv,
1097 void *evt_payload_priv)
1098{
1099 int rc = CAM_VFE_IRQ_STATUS_ERR;
1100 struct cam_isp_resource_node *comp_grp = handler_priv;
1101 struct cam_vfe_bus_irq_evt_payload *evt_payload = evt_payload_priv;
1102 struct cam_vfe_bus_ver2_comp_grp_data *rsrc_data = comp_grp->res_priv;
Harsh Shah23557ae2017-05-13 18:14:34 -07001103 uint32_t *cam_ife_irq_regs;
1104 uint32_t status_reg;
1105 uint32_t comp_err_reg;
1106 uint32_t comp_grp_id;
1107
1108 if (!evt_payload)
1109 return rc;
1110
1111 cam_ife_irq_regs = evt_payload->irq_reg_val;
Harsh Shaha1af8822017-05-11 22:06:36 -07001112
1113 CDBG("comp grp type %d\n", rsrc_data->comp_grp_type);
1114 switch (rsrc_data->comp_grp_type) {
1115 case CAM_VFE_BUS_VER2_COMP_GRP_0:
1116 case CAM_VFE_BUS_VER2_COMP_GRP_1:
1117 case CAM_VFE_BUS_VER2_COMP_GRP_2:
1118 case CAM_VFE_BUS_VER2_COMP_GRP_3:
1119 case CAM_VFE_BUS_VER2_COMP_GRP_4:
1120 case CAM_VFE_BUS_VER2_COMP_GRP_5:
Harsh Shah23557ae2017-05-13 18:14:34 -07001121 comp_grp_id = (rsrc_data->comp_grp_type -
Harsh Shaha1af8822017-05-11 22:06:36 -07001122 CAM_VFE_BUS_VER2_COMP_GRP_0);
1123
1124 /* Check for Regular composite error */
1125 status_reg = cam_ife_irq_regs[CAM_IFE_IRQ_BUS_REG_STATUS0];
1126
1127 comp_err_reg = cam_ife_irq_regs[CAM_IFE_IRQ_BUS_REG_COMP_ERR];
1128 if ((status_reg & BIT(11)) &&
1129 (comp_err_reg & rsrc_data->composite_mask)) {
1130 /* Check for Regular composite error */
1131 rc = CAM_VFE_IRQ_STATUS_ERR_COMP;
1132 break;
1133 }
1134
1135 comp_err_reg = cam_ife_irq_regs[CAM_IFE_IRQ_BUS_REG_COMP_OWRT];
1136 /* Check for Regular composite Overwrite */
1137 if ((status_reg & BIT(12)) &&
1138 (comp_err_reg & rsrc_data->composite_mask)) {
1139 rc = CAM_VFE_IRQ_STATUS_COMP_OWRT;
1140 break;
1141 }
1142
Harsh Shah23557ae2017-05-13 18:14:34 -07001143 /* Regular Composite SUCCESS */
1144 if (status_reg & BIT(comp_grp_id + 5)) {
1145 cam_ife_irq_regs[CAM_IFE_IRQ_BUS_REG_STATUS0] &=
1146 ~BIT(comp_grp_id + 5);
Harsh Shaha1af8822017-05-11 22:06:36 -07001147 rc = CAM_VFE_IRQ_STATUS_SUCCESS;
Harsh Shah23557ae2017-05-13 18:14:34 -07001148 }
Harsh Shaha1af8822017-05-11 22:06:36 -07001149
1150 CDBG("status reg = 0x%x, bit index = %d\n",
Harsh Shah23557ae2017-05-13 18:14:34 -07001151 status_reg, (comp_grp_id + 5));
Harsh Shaha1af8822017-05-11 22:06:36 -07001152 break;
1153
1154 case CAM_VFE_BUS_VER2_COMP_GRP_DUAL_0:
1155 case CAM_VFE_BUS_VER2_COMP_GRP_DUAL_1:
1156 case CAM_VFE_BUS_VER2_COMP_GRP_DUAL_2:
1157 case CAM_VFE_BUS_VER2_COMP_GRP_DUAL_3:
1158 case CAM_VFE_BUS_VER2_COMP_GRP_DUAL_4:
1159 case CAM_VFE_BUS_VER2_COMP_GRP_DUAL_5:
Harsh Shah23557ae2017-05-13 18:14:34 -07001160 comp_grp_id = (rsrc_data->comp_grp_type -
Harsh Shaha1af8822017-05-11 22:06:36 -07001161 CAM_VFE_BUS_VER2_COMP_GRP_DUAL_0);
1162
1163 /* Check for DUAL composite error */
1164 status_reg = cam_ife_irq_regs[CAM_IFE_IRQ_BUS_REG_STATUS2];
1165
1166 comp_err_reg = cam_ife_irq_regs[CAM_IFE_IRQ_BUS_DUAL_COMP_ERR];
1167 if ((status_reg & BIT(6)) &&
1168 (comp_err_reg & rsrc_data->composite_mask)) {
1169 /* Check for DUAL composite error */
1170 rc = CAM_VFE_IRQ_STATUS_ERR_COMP;
1171 break;
1172 }
1173
1174 /* Check for Dual composite Overwrite */
1175 comp_err_reg = cam_ife_irq_regs[CAM_IFE_IRQ_BUS_DUAL_COMP_OWRT];
1176 if ((status_reg & BIT(7)) &&
1177 (comp_err_reg & rsrc_data->composite_mask)) {
1178 rc = CAM_VFE_IRQ_STATUS_COMP_OWRT;
1179 break;
1180 }
1181
Harsh Shah23557ae2017-05-13 18:14:34 -07001182 /* DUAL Composite SUCCESS */
1183 if (status_reg & BIT(comp_grp_id)) {
1184 cam_ife_irq_regs[CAM_IFE_IRQ_BUS_REG_STATUS2] &=
1185 ~BIT(comp_grp_id + 5);
Harsh Shaha1af8822017-05-11 22:06:36 -07001186 rc = CAM_VFE_IRQ_STATUS_SUCCESS;
Harsh Shah23557ae2017-05-13 18:14:34 -07001187 }
Harsh Shaha1af8822017-05-11 22:06:36 -07001188
1189 break;
Harsh Shaha1af8822017-05-11 22:06:36 -07001190 default:
1191 rc = CAM_VFE_IRQ_STATUS_ERR;
1192 break;
1193 }
1194
1195 if (rc == CAM_VFE_IRQ_STATUS_SUCCESS)
1196 cam_vfe_bus_put_evt_payload(evt_payload->core_info,
1197 &evt_payload);
1198
1199 return rc;
1200}
1201
1202static int cam_vfe_bus_init_comp_grp(uint32_t index,
1203 struct cam_vfe_bus_ver2_priv *ver2_bus_priv,
1204 struct cam_vfe_bus_ver2_hw_info *ver2_hw_info,
1205 struct cam_isp_resource_node *comp_grp)
1206{
1207 struct cam_vfe_bus_ver2_comp_grp_data *rsrc_data =
1208 comp_grp->res_priv;
1209
1210 rsrc_data = kzalloc(sizeof(struct cam_vfe_bus_ver2_comp_grp_data),
1211 GFP_KERNEL);
1212 if (!rsrc_data) {
1213 CDBG("Failed to alloc for comp_grp_priv\n");
1214 return -ENOMEM;
1215 }
1216 comp_grp->res_priv = rsrc_data;
1217
1218 comp_grp->res_state = CAM_ISP_RESOURCE_STATE_AVAILABLE;
1219 INIT_LIST_HEAD(&comp_grp->list);
1220
1221 rsrc_data->comp_grp_type = index;
1222 rsrc_data->common_data = &ver2_bus_priv->common_data;
1223 rsrc_data->hw_regs = &ver2_hw_info->comp_grp_reg[index];
1224 rsrc_data->dual_slave_core = CAM_VFE_BUS_VER2_VFE_CORE_MAX;
1225
1226
1227 if (rsrc_data->comp_grp_type >= CAM_VFE_BUS_VER2_COMP_GRP_DUAL_0 &&
1228 rsrc_data->comp_grp_type <= CAM_VFE_BUS_VER2_COMP_GRP_DUAL_5)
1229 list_add_tail(&comp_grp->list,
1230 &ver2_bus_priv->free_dual_comp_grp);
1231 else if (rsrc_data->comp_grp_type >= CAM_VFE_BUS_VER2_COMP_GRP_0
1232 && rsrc_data->comp_grp_type <= CAM_VFE_BUS_VER2_COMP_GRP_5)
1233 list_add_tail(&comp_grp->list, &ver2_bus_priv->free_comp_grp);
1234
1235 comp_grp->start = cam_vfe_bus_start_comp_grp;
1236 comp_grp->stop = cam_vfe_bus_stop_comp_grp;
1237 comp_grp->top_half_handler = cam_vfe_bus_handle_comp_done_top_half;
1238 comp_grp->bottom_half_handler =
1239 cam_vfe_bus_handle_comp_done_bottom_half;
1240 comp_grp->hw_intf = ver2_bus_priv->common_data.hw_intf;
1241
1242 return 0;
1243}
1244
1245static int cam_vfe_bus_acquire_vfe_out(void *bus_priv, void *acquire_args)
1246{
1247 int rc = -ENODEV;
1248 int i;
1249 enum cam_vfe_bus_ver2_vfe_out_type vfe_out_res_id;
1250 uint32_t format;
1251 uint32_t num_wm;
1252 uint32_t subscribe_irq;
1253 uint32_t client_done_mask;
1254 struct cam_vfe_bus_ver2_priv *ver2_bus_priv = bus_priv;
1255 struct cam_vfe_acquire_args *acq_args = acquire_args;
1256 struct cam_vfe_hw_vfe_out_acquire_args *out_acquire_args;
1257 struct cam_isp_resource_node *rsrc_node = NULL;
1258 struct cam_vfe_bus_ver2_vfe_out_data *rsrc_data = NULL;
1259
1260 if (!bus_priv || !acquire_args) {
1261 pr_err("Invalid Param");
1262 return -EINVAL;
1263 }
1264
1265 out_acquire_args = &acq_args->vfe_out;
1266 format = out_acquire_args->out_port_info->format;
1267
1268 CDBG("Acquiring resource type 0x%x\n",
1269 out_acquire_args->out_port_info->res_type);
1270
1271 vfe_out_res_id = cam_vfe_bus_get_out_res_id(
1272 out_acquire_args->out_port_info->res_type);
1273 if (vfe_out_res_id == CAM_VFE_BUS_VER2_VFE_OUT_MAX)
1274 return -ENODEV;
1275
1276 num_wm = cam_vfe_bus_get_num_wm(vfe_out_res_id, format);
1277 if (num_wm < 1)
1278 return -EINVAL;
1279
1280 rsrc_node = &ver2_bus_priv->vfe_out[vfe_out_res_id];
1281 if (rsrc_node->res_state != CAM_ISP_RESOURCE_STATE_AVAILABLE) {
1282 pr_err("Resource not available: Res_id %d state:%d\n",
1283 vfe_out_res_id, rsrc_node->res_state);
1284 return -EBUSY;
1285 }
1286
1287 rsrc_data = rsrc_node->res_priv;
1288 rsrc_data->num_wm = num_wm;
1289 rsrc_node->res_id = out_acquire_args->out_port_info->res_type;
1290 rsrc_node->tasklet_info = acq_args->tasklet;
1291 rsrc_node->cdm_ops = out_acquire_args->cdm_ops;
1292 rsrc_data->cdm_util_ops = out_acquire_args->cdm_ops;
1293
1294 /* Reserve Composite Group */
1295 if (num_wm > 1 || (out_acquire_args->out_port_info->comp_grp_id >
1296 CAM_ISP_RES_COMP_GROUP_NONE &&
1297 out_acquire_args->out_port_info->comp_grp_id <
1298 CAM_ISP_RES_COMP_GROUP_ID_MAX)) {
1299 rc = cam_vfe_bus_acquire_comp_grp(ver2_bus_priv,
1300 out_acquire_args->out_port_info,
1301 out_acquire_args->unique_id,
1302 out_acquire_args->is_dual,
1303 out_acquire_args->is_master,
1304 out_acquire_args->dual_slave_core,
1305 &rsrc_data->comp_grp);
1306 if (rc < 0)
1307 return rc;
1308
1309 subscribe_irq = 0;
1310 } else
1311 subscribe_irq = 1;
1312
1313 /* Reserve WM */
1314 for (i = 0; i < num_wm; i++) {
1315 rc = cam_vfe_bus_acquire_wm(ver2_bus_priv,
1316 out_acquire_args->out_port_info,
1317 vfe_out_res_id,
1318 i,
1319 out_acquire_args->split_id,
1320 subscribe_irq,
1321 &rsrc_data->wm_res[i],
1322 &client_done_mask);
1323 if (rc < 0)
1324 goto release_wm;
1325
1326 if (rsrc_data->comp_grp)
1327 cam_vfe_bus_add_wm_to_comp_grp(rsrc_data->comp_grp,
1328 client_done_mask);
1329 }
1330
1331 rsrc_node->res_state = CAM_ISP_RESOURCE_STATE_RESERVED;
1332 out_acquire_args->rsrc_node = rsrc_node;
1333
1334 CDBG("Acquire successful\n");
1335 return rc;
1336
1337release_wm:
1338 for (i--; i >= 0; i--)
1339 cam_vfe_bus_release_wm(ver2_bus_priv, rsrc_data->wm_res[i]);
1340
1341 cam_vfe_bus_release_comp_grp(ver2_bus_priv,
1342 rsrc_data->comp_grp);
1343
1344 return rc;
1345}
1346
1347static int cam_vfe_bus_release_vfe_out(void *bus_priv,
1348 struct cam_isp_resource_node *vfe_out)
1349{
Jing Zhoue71fd4a2017-05-15 19:44:34 -07001350 uint32_t i;
1351 struct cam_vfe_bus_ver2_vfe_out_data *rsrc_data = vfe_out->res_priv;
1352
Harsh Shaha1af8822017-05-11 22:06:36 -07001353 if (vfe_out->res_state != CAM_ISP_RESOURCE_STATE_RESERVED) {
1354 pr_err("Error! Invalid resource state:%d\n",
1355 vfe_out->res_state);
1356 }
1357
Jing Zhoue71fd4a2017-05-15 19:44:34 -07001358 for (i = 0; i < rsrc_data->num_wm; i++)
1359 cam_vfe_bus_release_wm(bus_priv, rsrc_data->wm_res[i]);
1360 rsrc_data->num_wm = 0;
1361
1362 if (rsrc_data->comp_grp)
1363 cam_vfe_bus_release_comp_grp(bus_priv, rsrc_data->comp_grp);
1364 rsrc_data->comp_grp = NULL;
1365
1366 vfe_out->tasklet_info = NULL;
1367 vfe_out->cdm_ops = NULL;
1368 rsrc_data->cdm_util_ops = NULL;
1369
Harsh Shaha1af8822017-05-11 22:06:36 -07001370 if (vfe_out->res_state == CAM_ISP_RESOURCE_STATE_RESERVED)
1371 vfe_out->res_state = CAM_ISP_RESOURCE_STATE_AVAILABLE;
1372
1373 return 0;
1374}
1375
1376static int cam_vfe_bus_start_vfe_out(struct cam_isp_resource_node *vfe_out)
1377{
1378 int rc = 0, i;
Harsh Shah23557ae2017-05-13 18:14:34 -07001379 struct cam_vfe_bus_ver2_vfe_out_data *rsrc_data = vfe_out->res_priv;
1380 struct cam_vfe_bus_ver2_common_data *common_data =
1381 rsrc_data->common_data;
Harsh Shaha1af8822017-05-11 22:06:36 -07001382
1383 CDBG("Start resource index %d\n", rsrc_data->out_type);
1384
1385 if (vfe_out->res_state != CAM_ISP_RESOURCE_STATE_RESERVED) {
1386 pr_err("Error! Invalid resource state:%d\n",
1387 vfe_out->res_state);
1388 return -EACCES;
1389 }
1390
Harsh Shah23557ae2017-05-13 18:14:34 -07001391 /* Enable IRQ Mask */
Jing Zhoue71fd4a2017-05-15 19:44:34 -07001392 cam_io_w_mb(0x00001FE0, common_data->mem_base + 0x2044);
Harsh Shah23557ae2017-05-13 18:14:34 -07001393 cam_io_w_mb(0x000FFFE7, common_data->mem_base + 0x2048);
1394 cam_io_w_mb(0x000000FF, common_data->mem_base + 0x204c);
1395
Harsh Shaha1af8822017-05-11 22:06:36 -07001396 for (i = 0; i < rsrc_data->num_wm; i++)
1397 rc = cam_vfe_bus_start_wm(rsrc_data->wm_res[i]);
1398
1399 if (rsrc_data->comp_grp)
1400 rc = cam_vfe_bus_start_comp_grp(rsrc_data->comp_grp);
1401
1402 /* VFE_MODULE_BUS_CGC_OVERRIDE */
1403 cam_io_w_mb(0xFFFFFFFF, rsrc_data->common_data->mem_base + 0x0000003C);
1404 /* VFE_MODULE_COLOR_CGC_OVERRIDE */
1405 cam_io_w_mb(0xFFFFFFFF, rsrc_data->common_data->mem_base + 0x00000034);
1406 /* VFE_MODULE_ZOOM_CGC_OVERRIDE */
1407 cam_io_w_mb(0xFFFFFFFF, rsrc_data->common_data->mem_base + 0x38);
1408 /* VFE_MODULE_LENS_CGC_OVERRIDE */
1409 cam_io_w_mb(0xFFFFFFFF, rsrc_data->common_data->mem_base + 0x0000002C);
1410 /* VFE_MODULE_STATS_CGC_OVERRIDE */
1411 cam_io_w_mb(0xFFFFFFFF, rsrc_data->common_data->mem_base + 0x00000030);
1412
1413 /* BUS_WR_INPUT_IF_ADDR_SYNC_CFG */
1414 cam_io_w_mb(0x0, rsrc_data->common_data->mem_base + 0x0000207C);
1415 /* BUS_WR_INPUT_IF_ADDR_SYNC_FRAME_HEADER */
1416 cam_io_w_mb(0x0, rsrc_data->common_data->mem_base + 0x00002080);
1417 /* BUS_WR_INPUT_IF_ADDR_SYNC_NO_SYNC */
1418 cam_io_w_mb(0xFFFFF, rsrc_data->common_data->mem_base + 0x00002084);
Harsh Shaha1af8822017-05-11 22:06:36 -07001419 /* BUS_WR_INPUT_IF_ADDR_SYNC_0 */
1420 cam_io_w_mb(0x0, rsrc_data->common_data->mem_base + 0x00002088);
1421 cam_io_w_mb(0x0, rsrc_data->common_data->mem_base + 0x0000208c);
1422 cam_io_w_mb(0x0, rsrc_data->common_data->mem_base + 0x00002090);
1423 cam_io_w_mb(0x0, rsrc_data->common_data->mem_base + 0x00002094);
1424 cam_io_w_mb(0x0, rsrc_data->common_data->mem_base + 0x00002098);
1425 cam_io_w_mb(0x0, rsrc_data->common_data->mem_base + 0x0000209c);
1426 cam_io_w_mb(0x0, rsrc_data->common_data->mem_base + 0x000020a0);
1427 cam_io_w_mb(0x0, rsrc_data->common_data->mem_base + 0x000020a4);
1428
Harsh Shah23557ae2017-05-13 18:14:34 -07001429 /* no clock gating at bus input */
1430 cam_io_w_mb(0xFFFFF, rsrc_data->common_data->mem_base + 0x0000200C);
1431
1432 /* BUS_WR_TEST_BUS_CTRL */
1433 cam_io_w_mb(0x0, rsrc_data->common_data->mem_base + 0x0000211C);
1434
Harsh Shaha1af8822017-05-11 22:06:36 -07001435 return rc;
1436}
1437
1438static int cam_vfe_bus_stop_vfe_out(struct cam_isp_resource_node *vfe_out)
1439{
1440 int rc = 0, i;
1441 struct cam_vfe_bus_ver2_vfe_out_data *rsrc_data = vfe_out->res_priv;
1442
1443 if (vfe_out->res_state == CAM_ISP_RESOURCE_STATE_AVAILABLE ||
1444 vfe_out->res_state == CAM_ISP_RESOURCE_STATE_RESERVED) {
1445 return rc;
1446 }
1447
1448 if (rsrc_data->comp_grp)
1449 rc = cam_vfe_bus_stop_comp_grp(rsrc_data->comp_grp);
1450
1451 for (i = 0; i < rsrc_data->num_wm; i++)
1452 rc = cam_vfe_bus_stop_wm(rsrc_data->wm_res[i]);
1453
1454 vfe_out->res_state = CAM_ISP_RESOURCE_STATE_STREAMING;
1455
1456 vfe_out->res_state = CAM_ISP_RESOURCE_STATE_RESERVED;
1457 return rc;
1458}
1459
1460static int cam_vfe_bus_handle_vfe_out_done_top_half(uint32_t evt_id,
1461 struct cam_irq_th_payload *th_payload)
1462{
1463 return -EPERM;
1464}
1465
1466static int cam_vfe_bus_handle_vfe_out_done_bottom_half(
1467 void *handler_priv,
1468 void *evt_payload_priv)
1469{
1470 int rc = -EINVAL;
1471 struct cam_isp_resource_node *vfe_out = handler_priv;
1472 struct cam_vfe_bus_ver2_vfe_out_data *rsrc_data = vfe_out->res_priv;
1473
1474 /*
1475 * If this resource has Composite Group then we only handle
1476 * Composite done. We acquire Composite if number of WM > 1.
1477 * So Else case is only one individual buf_done = WM[0].
1478 */
1479 if (rsrc_data->comp_grp) {
1480 rc = rsrc_data->comp_grp->bottom_half_handler(
1481 rsrc_data->comp_grp, evt_payload_priv);
1482 } else {
1483 rc = rsrc_data->wm_res[0]->bottom_half_handler(
Harsh Shah23557ae2017-05-13 18:14:34 -07001484 rsrc_data->wm_res[0], evt_payload_priv);
Harsh Shaha1af8822017-05-11 22:06:36 -07001485 }
1486
1487 return rc;
1488}
1489
1490static int cam_vfe_bus_init_vfe_out_resource(uint32_t index,
1491 struct cam_vfe_bus_ver2_priv *ver2_bus_priv,
1492 struct cam_vfe_bus_ver2_hw_info *ver2_hw_info,
1493 struct cam_isp_resource_node *vfe_out)
1494{
1495 struct cam_vfe_bus_ver2_vfe_out_data *rsrc_data = NULL;
1496 int rc = 0;
1497
1498 rsrc_data = kzalloc(sizeof(struct cam_vfe_bus_ver2_vfe_out_data),
1499 GFP_KERNEL);
1500 if (!rsrc_data) {
1501 CDBG("Error! Failed to alloc for vfe out priv\n");
1502 rc = -ENOMEM;
1503 return rc;
1504 }
1505 vfe_out->res_priv = rsrc_data;
1506
1507 vfe_out->res_type = CAM_ISP_RESOURCE_VFE_OUT;
1508 vfe_out->res_state = CAM_ISP_RESOURCE_STATE_AVAILABLE;
1509 INIT_LIST_HEAD(&vfe_out->list);
1510
1511 rsrc_data->out_type = index;
1512 rsrc_data->common_data = &ver2_bus_priv->common_data;
1513 rsrc_data->max_width =
1514 ver2_hw_info->vfe_out_hw_info[index].max_width;
1515 rsrc_data->max_height =
1516 ver2_hw_info->vfe_out_hw_info[index].max_height;
1517
1518 vfe_out->start = cam_vfe_bus_start_vfe_out;
1519 vfe_out->stop = cam_vfe_bus_stop_vfe_out;
1520 vfe_out->top_half_handler = cam_vfe_bus_handle_vfe_out_done_top_half;
1521 vfe_out->bottom_half_handler =
1522 cam_vfe_bus_handle_vfe_out_done_bottom_half;
1523 vfe_out->hw_intf = ver2_bus_priv->common_data.hw_intf;
1524
1525 return 0;
1526}
1527
1528static int cam_vfe_bus_get_evt_payload(
1529 struct cam_vfe_bus_ver2_priv *bus_priv,
1530 struct cam_vfe_bus_irq_evt_payload **evt_payload)
1531{
1532 if (list_empty(&bus_priv->free_payload_list)) {
Harsh Shah23557ae2017-05-13 18:14:34 -07001533 *evt_payload = NULL;
Harsh Shaha1af8822017-05-11 22:06:36 -07001534 pr_err("No free payload\n");
1535 return -ENODEV;
1536 }
1537
1538 *evt_payload = list_first_entry(&bus_priv->free_payload_list,
1539 struct cam_vfe_bus_irq_evt_payload, list);
1540 list_del_init(&(*evt_payload)->list);
1541 return 0;
1542}
1543
1544static int cam_vfe_bus_put_evt_payload(void *core_info,
1545 struct cam_vfe_bus_irq_evt_payload **evt_payload)
1546{
1547 struct cam_vfe_bus_ver2_priv *bus_priv = NULL;
Harsh Shah23557ae2017-05-13 18:14:34 -07001548 uint32_t *cam_ife_irq_regs = (*evt_payload)->irq_reg_val;
1549 uint32_t status_reg0, status_reg1;
1550
1551 status_reg0 = cam_ife_irq_regs[CAM_IFE_IRQ_BUS_REG_STATUS0];
1552 status_reg1 = cam_ife_irq_regs[CAM_IFE_IRQ_BUS_REG_STATUS1];
1553
1554 if (status_reg0 || status_reg1) {
1555 CDBG("status0 0x%x status1 0x%x\n", status_reg0, status_reg1);
1556 return 0;
1557 }
Harsh Shaha1af8822017-05-11 22:06:36 -07001558
1559 if (!core_info) {
1560 pr_err("Invalid param core_info NULL");
1561 return -EINVAL;
1562 }
1563 if (*evt_payload == NULL) {
1564 pr_err("No payload to put\n");
1565 return -EINVAL;
1566 }
1567 bus_priv = (*evt_payload)->bus_priv;
1568 list_add_tail(&(*evt_payload)->list, &bus_priv->free_payload_list);
1569 *evt_payload = NULL;
1570 return 0;
1571}
1572
1573static int cam_vfe_bus_ver2_handle_irq(uint32_t evt_id,
1574 struct cam_irq_th_payload *th_payload)
1575{
1576 int32_t rc;
1577 int i;
1578 struct cam_vfe_irq_handler_priv *handler_priv;
1579 struct cam_vfe_hw_core_info *core_info;
1580 struct cam_vfe_bus_irq_evt_payload *evt_payload;
1581 struct cam_vfe_bus *bus_info;
1582 struct cam_vfe_bus_ver2_priv *bus_priv;
1583 struct cam_irq_controller_reg_info *reg_info;
Harsh Shah23557ae2017-05-13 18:14:34 -07001584 uint32_t irq_mask;
Harsh Shaha1af8822017-05-11 22:06:36 -07001585
1586 handler_priv = th_payload->handler_priv;
1587 core_info = handler_priv->core_info;
1588 bus_info = core_info->vfe_bus;
1589 bus_priv = bus_info->bus_priv;
1590 reg_info = &bus_priv->common_data.common_reg->irq_reg_info;
1591
1592 /*
1593 * add reset ack handling here once supported.
1594 * Just clear all the bus irq status registers and ignore the reset.
1595 */
1596
1597 CDBG("Enter\n");
1598 rc = cam_vfe_bus_get_evt_payload(bus_priv, &evt_payload);
1599 if (rc) {
1600 pr_err("No tasklet_cmd is free in queue\n");
1601 return rc;
1602 }
1603
1604 cam_isp_hw_get_timestamp(&evt_payload->ts);
1605
1606 evt_payload->core_index = handler_priv->core_index;
1607 evt_payload->core_info = handler_priv->core_info;
1608 evt_payload->bus_priv = bus_priv;
1609 CDBG("core_idx %d, core_info %llx\n", handler_priv->core_index,
1610 (uint64_t)handler_priv->core_info);
1611
1612 for (i = 0; i < CAM_IFE_BUS_IRQ_REGISTERS_MAX; i++) {
Harsh Shah23557ae2017-05-13 18:14:34 -07001613 irq_mask = cam_io_r(handler_priv->mem_base +
1614 irq_reg_offset[i] - (0xC * 2));
1615 evt_payload->irq_reg_val[i] = irq_mask &
1616 cam_io_r(handler_priv->mem_base + irq_reg_offset[i]);
Harsh Shaha1af8822017-05-11 22:06:36 -07001617 CDBG("irq_status%d = 0x%x\n", i, evt_payload->irq_reg_val[i]);
1618 }
1619 for (i = 0; i <= CAM_IFE_IRQ_BUS_REG_STATUS2; i++) {
1620 cam_io_w(evt_payload->irq_reg_val[i], handler_priv->mem_base +
1621 reg_info->irq_reg_set[i].clear_reg_offset);
1622 CDBG("Clear irq_status%d = 0x%x offset 0x%x\n", i,
1623 evt_payload->irq_reg_val[i],
1624 reg_info->irq_reg_set[i].clear_reg_offset);
1625 }
1626 cam_io_w(reg_info->global_clear_bitmask, handler_priv->mem_base +
1627 reg_info->global_clear_offset);
1628 CDBG("Global clear bitmask = 0x%x offset 0x%x\n",
1629 reg_info->global_clear_bitmask,
1630 reg_info->global_clear_offset);
1631
1632 th_payload->evt_payload_priv = evt_payload;
1633
1634 return rc;
1635}
1636
1637static int cam_vfe_bus_update_buf(void *priv, void *cmd_args,
1638 uint32_t arg_size)
1639{
1640 struct cam_vfe_bus_ver2_priv *bus_priv;
1641 struct cam_isp_hw_get_buf_update *update_buf;
Jing Zhoua4e9fbe2017-05-15 14:37:21 -07001642 struct cam_buf_io_cfg *io_cfg;
Harsh Shaha1af8822017-05-11 22:06:36 -07001643 struct cam_vfe_bus_ver2_vfe_out_data *vfe_out_data = NULL;
1644 struct cam_vfe_bus_ver2_wm_resource_data *wm_data = NULL;
Jing Zhoua4e9fbe2017-05-15 14:37:21 -07001645 uint32_t *reg_val_pair;
1646 uint32_t i, j, size = 0;
Junzhe Zou193d78c2017-05-16 15:10:54 -07001647 uint32_t frame_inc = 0;
Harsh Shaha1af8822017-05-11 22:06:36 -07001648
1649 /*
1650 * Need the entire buf io config so we can get the stride info
1651 * for the wm.
1652 */
1653
1654 bus_priv = (struct cam_vfe_bus_ver2_priv *) priv;
1655 update_buf = (struct cam_isp_hw_get_buf_update *) cmd_args;
1656
1657 vfe_out_data = (struct cam_vfe_bus_ver2_vfe_out_data *)
1658 update_buf->cdm.res->res_priv;
1659
1660 if (!vfe_out_data || !vfe_out_data->cdm_util_ops) {
1661 pr_err("Failed! Invalid data\n");
1662 return -EINVAL;
1663 }
1664
Jing Zhoua4e9fbe2017-05-15 14:37:21 -07001665 if (update_buf->num_buf != vfe_out_data->num_wm) {
Harsh Shaha1af8822017-05-11 22:06:36 -07001666 pr_err("Failed! Invalid number buffers:%d required:%d\n",
1667 update_buf->num_buf, vfe_out_data->num_wm);
Junzhe Zou193d78c2017-05-16 15:10:54 -07001668 return -EINVAL;
Harsh Shaha1af8822017-05-11 22:06:36 -07001669 }
1670
Jing Zhoua4e9fbe2017-05-15 14:37:21 -07001671 reg_val_pair = &vfe_out_data->common_data->io_buf_update[0];
1672 io_cfg = update_buf->io_cfg;
1673
1674 for (i = 0, j = 0; i < vfe_out_data->num_wm; i++) {
Junzhe Zou193d78c2017-05-16 15:10:54 -07001675 if (j >= (MAX_REG_VAL_PAIR_SIZE - MAX_BUF_UPDATE_REG_NUM * 2)) {
1676 pr_err("reg_val_pair %d exceeds the array limit %lu\n",
1677 j, MAX_REG_VAL_PAIR_SIZE);
1678 return -ENOMEM;
1679 }
1680
Jing Zhoua4e9fbe2017-05-15 14:37:21 -07001681 wm_data = vfe_out_data->wm_res[i]->res_priv;
1682
1683 /* For initial configuration program all bus registers */
1684 if (wm_data->stride != io_cfg->planes[i].plane_stride ||
1685 !wm_data->init_cfg_done) {
1686 CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j,
1687 wm_data->hw_regs->stride,
1688 io_cfg->planes[i].plane_stride);
1689 wm_data->stride = io_cfg->planes[i].plane_stride;
1690 }
1691 CDBG("image stride 0x%x\n", wm_data->stride);
1692
1693 if (wm_data->framedrop_pattern != io_cfg->framedrop_pattern ||
1694 !wm_data->init_cfg_done) {
1695 CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j,
1696 wm_data->hw_regs->framedrop_pattern,
1697 io_cfg->framedrop_pattern);
1698 wm_data->framedrop_pattern = io_cfg->framedrop_pattern;
1699 }
1700 CDBG("framedrop pattern 0x%x\n", wm_data->framedrop_pattern);
1701
1702 if (wm_data->framedrop_period != io_cfg->framedrop_period ||
1703 !wm_data->init_cfg_done) {
1704 CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j,
1705 wm_data->hw_regs->framedrop_period,
1706 io_cfg->framedrop_period);
1707 wm_data->framedrop_period = io_cfg->framedrop_period;
1708 }
1709 CDBG("framedrop period 0x%x\n", wm_data->framedrop_period);
1710
1711 if (wm_data->irq_subsample_period != io_cfg->subsample_period
1712 || !wm_data->init_cfg_done) {
1713 CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j,
1714 wm_data->hw_regs->irq_subsample_period,
1715 io_cfg->subsample_period);
1716 wm_data->irq_subsample_period =
1717 io_cfg->subsample_period;
1718 }
1719 CDBG("irq subsample period 0x%x\n",
1720 wm_data->irq_subsample_period);
1721
1722 if (wm_data->irq_subsample_pattern != io_cfg->subsample_pattern
1723 || !wm_data->init_cfg_done) {
1724 CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j,
1725 wm_data->hw_regs->irq_subsample_pattern,
1726 io_cfg->subsample_pattern);
1727 wm_data->irq_subsample_pattern =
1728 io_cfg->subsample_pattern;
1729 }
1730 CDBG("irq subsample pattern 0x%x\n",
1731 wm_data->irq_subsample_pattern);
1732
1733 if (wm_data->en_ubwc) {
1734 if (!wm_data->hw_regs->ubwc_regs) {
1735 pr_err("%s: No UBWC register to configure.\n",
1736 __func__);
1737 return -EINVAL;
1738 }
1739 if (wm_data->packer_cfg !=
1740 io_cfg->planes[i].packer_config ||
1741 !wm_data->init_cfg_done) {
1742 CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j,
1743 wm_data->hw_regs->packer_cfg,
1744 io_cfg->planes[i].packer_config);
1745 wm_data->packer_cfg =
1746 io_cfg->planes[i].packer_config;
1747 }
1748 CDBG("packer cfg 0x%x\n", wm_data->packer_cfg);
1749
1750 if (wm_data->tile_cfg != io_cfg->planes[i].tile_config
1751 || !wm_data->init_cfg_done) {
1752 CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j,
1753 wm_data->hw_regs->ubwc_regs->tile_cfg,
1754 io_cfg->planes[i].tile_config);
1755 wm_data->tile_cfg =
1756 io_cfg->planes[i].tile_config;
1757 }
1758 CDBG("tile cfg 0x%x\n", wm_data->tile_cfg);
1759
1760 if (wm_data->h_init != io_cfg->planes[i].h_init ||
1761 !wm_data->init_cfg_done) {
1762 CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j,
1763 wm_data->hw_regs->ubwc_regs->h_init,
1764 io_cfg->planes[i].h_init);
1765 wm_data->h_init = io_cfg->planes[i].h_init;
1766 }
1767 CDBG("h_init 0x%x\n", wm_data->h_init);
1768
1769 if (wm_data->v_init != io_cfg->planes[i].v_init ||
1770 !wm_data->init_cfg_done) {
1771 CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j,
1772 wm_data->hw_regs->ubwc_regs->v_init,
1773 io_cfg->planes[i].v_init);
1774 wm_data->v_init = io_cfg->planes[i].v_init;
1775 }
1776 CDBG("v_init 0x%x\n", wm_data->v_init);
1777
1778 if (wm_data->ubwc_meta_stride !=
1779 io_cfg->planes[i].meta_stride ||
1780 !wm_data->init_cfg_done) {
1781 CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j,
1782 wm_data->hw_regs->ubwc_regs->
1783 meta_stride,
1784 io_cfg->planes[i].meta_stride);
1785 wm_data->ubwc_meta_stride =
1786 io_cfg->planes[i].meta_stride;
1787 }
1788 CDBG("meta stride 0x%x\n", wm_data->ubwc_meta_stride);
1789
1790 if (wm_data->ubwc_mode_cfg !=
1791 io_cfg->planes[i].mode_config ||
1792 !wm_data->init_cfg_done) {
1793 CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j,
1794 wm_data->hw_regs->ubwc_regs->mode_cfg,
1795 io_cfg->planes[i].mode_config);
1796 wm_data->ubwc_mode_cfg =
1797 io_cfg->planes[i].mode_config;
1798 }
1799 CDBG("ubwc mode cfg 0x%x\n", wm_data->ubwc_mode_cfg);
1800
1801 if (wm_data->ubwc_meta_offset !=
1802 io_cfg->planes[i].meta_offset ||
1803 !wm_data->init_cfg_done) {
1804 CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j,
1805 wm_data->hw_regs->ubwc_regs->
1806 meta_offset,
1807 io_cfg->planes[i].meta_offset);
1808 wm_data->ubwc_meta_offset =
1809 io_cfg->planes[i].meta_offset;
1810 }
1811 CDBG("ubwc meta offset 0x%x\n",
1812 wm_data->ubwc_meta_offset);
1813
1814 /* UBWC meta address */
1815 CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j,
1816 wm_data->hw_regs->ubwc_regs->meta_addr,
1817 update_buf->image_buf[i]);
1818 CDBG("ubwc meta addr 0x%llx\n",
1819 update_buf->image_buf[i]);
1820 }
1821
1822 /* WM Image address */
1823 if (wm_data->en_ubwc)
1824 CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j,
1825 wm_data->hw_regs->image_addr,
1826 (update_buf->image_buf[i] +
1827 io_cfg->planes[i].meta_size));
1828 else
1829 CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j,
1830 wm_data->hw_regs->image_addr,
1831 update_buf->image_buf[i]);
1832
1833 CDBG("image address 0x%x\n", reg_val_pair[j-1]);
1834
Junzhe Zou193d78c2017-05-16 15:10:54 -07001835 frame_inc = io_cfg->planes[i].plane_stride *
1836 io_cfg->planes[i].slice_height;
1837 CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j,
1838 wm_data->hw_regs->frame_inc, frame_inc);
1839
Jing Zhoua4e9fbe2017-05-15 14:37:21 -07001840 /* enable the WM */
1841 CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j,
1842 wm_data->hw_regs->cfg,
1843 wm_data->en_cfg);
1844
1845 /* set initial configuration done */
1846 if (!wm_data->init_cfg_done)
1847 wm_data->init_cfg_done = 1;
1848 }
1849
1850 size = vfe_out_data->cdm_util_ops->cdm_required_size_reg_random(j/2);
Harsh Shaha1af8822017-05-11 22:06:36 -07001851
1852 /* cdm util returns dwords, need to convert to bytes */
1853 if ((size * 4) > update_buf->cdm.size) {
1854 pr_err("Failed! Buf size:%d insufficient, expected size:%d\n",
1855 update_buf->cdm.size, size);
1856 return -ENOMEM;
1857 }
1858
Harsh Shaha1af8822017-05-11 22:06:36 -07001859 vfe_out_data->cdm_util_ops->cdm_write_regrandom(
Jing Zhoua4e9fbe2017-05-15 14:37:21 -07001860 update_buf->cdm.cmd_buf_addr, j/2, reg_val_pair);
1861
Harsh Shaha1af8822017-05-11 22:06:36 -07001862 /* cdm util returns dwords, need to convert to bytes */
1863 update_buf->cdm.used_bytes = size * 4;
1864
1865 return 0;
1866}
1867
1868static int cam_vfe_bus_process_cmd(void *priv,
1869 uint32_t cmd_type, void *cmd_args, uint32_t arg_size)
1870{
1871 int rc = -EINVAL;
1872
1873 if (!priv || !cmd_args) {
1874 pr_err_ratelimited("Error! Invalid input arguments\n");
1875 return -EINVAL;
1876 }
1877
1878 switch (cmd_type) {
1879 case CAM_VFE_HW_CMD_GET_BUF_UPDATE:
1880 rc = cam_vfe_bus_update_buf(priv, cmd_args, arg_size);
1881 break;
1882 default:
1883 pr_err_ratelimited("Error! Invalid camif process command:%d\n",
1884 cmd_type);
1885 break;
1886 }
1887
1888 return rc;
1889}
1890
1891int cam_vfe_bus_ver2_init(
1892 void __iomem *mem_base,
1893 struct cam_hw_intf *hw_intf,
1894 void *bus_hw_info,
1895 void *vfe_irq_controller,
1896 struct cam_vfe_bus **vfe_bus)
1897{
1898 int i, rc = 0;
1899 struct cam_vfe_bus_ver2_priv *bus_priv = NULL;
1900 struct cam_vfe_bus *vfe_bus_local;
1901 struct cam_vfe_bus_ver2_hw_info *ver2_hw_info = bus_hw_info;
1902
1903 CDBG("Enter\n");
1904
1905 vfe_bus_local = kzalloc(sizeof(struct cam_vfe_bus), GFP_KERNEL);
1906 if (!vfe_bus_local) {
1907 CDBG("Failed to alloc for vfe_bus\n");
1908 rc = -ENOMEM;
1909 goto err_alloc_bus;
1910 }
1911
1912 bus_priv = kzalloc(sizeof(struct cam_vfe_bus_ver2_priv),
1913 GFP_KERNEL);
1914 if (!bus_priv) {
1915 CDBG("Failed to alloc for vfe_bus_priv\n");
1916 rc = -ENOMEM;
1917 goto err_alloc_priv;
1918 }
1919 vfe_bus_local->bus_priv = bus_priv;
1920
1921 bus_priv->common_data.mem_base = mem_base;
1922 bus_priv->common_data.hw_intf = hw_intf;
1923 bus_priv->common_data.vfe_irq_controller = vfe_irq_controller;
1924 bus_priv->common_data.common_reg = &ver2_hw_info->common_reg;
1925
1926 INIT_LIST_HEAD(&bus_priv->free_comp_grp);
1927 INIT_LIST_HEAD(&bus_priv->free_dual_comp_grp);
1928 INIT_LIST_HEAD(&bus_priv->used_comp_grp);
1929
1930 for (i = 0; i < CAM_VFE_BUS_VER2_MAX_CLIENTS; i++) {
1931 rc = cam_vfe_bus_init_wm_resource(i, bus_priv, bus_hw_info,
1932 &bus_priv->bus_client[i]);
1933 if (rc < 0) {
1934 pr_err("Error! Init WM failed\n");
1935 goto err_init_wm;
1936 }
1937 }
1938
1939 for (i = 0; i < CAM_VFE_BUS_VER2_COMP_GRP_MAX; i++) {
1940 rc = cam_vfe_bus_init_comp_grp(i, bus_priv, bus_hw_info,
1941 &bus_priv->comp_grp[i]);
1942 if (rc < 0) {
1943 pr_err("Error! Init Comp Grp failed\n");
1944 goto err_init_comp_grp;
1945 }
1946 }
1947
1948 for (i = 0; i < CAM_VFE_BUS_VER2_VFE_OUT_MAX; i++) {
1949 rc = cam_vfe_bus_init_vfe_out_resource(i, bus_priv, bus_hw_info,
1950 &bus_priv->vfe_out[i]);
1951 if (rc < 0) {
1952 pr_err("Error! Init VFE Out failed\n");
1953 goto err_init_vfe_out;
1954 }
1955 }
1956
1957 INIT_LIST_HEAD(&bus_priv->free_payload_list);
1958 for (i = 0; i < 128; i++) {
1959 INIT_LIST_HEAD(&bus_priv->evt_payload[i].list);
1960 list_add_tail(&bus_priv->evt_payload[i].list,
1961 &bus_priv->free_payload_list);
1962 }
1963
1964 vfe_bus_local->acquire_resource = cam_vfe_bus_acquire_vfe_out;
1965 vfe_bus_local->release_resource = cam_vfe_bus_release_vfe_out;
1966 vfe_bus_local->start_resource = cam_vfe_bus_start_vfe_out;
1967 vfe_bus_local->stop_resource = cam_vfe_bus_stop_vfe_out;
1968 vfe_bus_local->top_half_handler = cam_vfe_bus_ver2_handle_irq;
1969 vfe_bus_local->bottom_half_handler = NULL;
1970 vfe_bus_local->process_cmd = cam_vfe_bus_process_cmd;
1971
1972 *vfe_bus = vfe_bus_local;
1973
1974 return rc;
1975
1976err_init_vfe_out:
1977err_init_comp_grp:
1978err_init_wm:
1979 kfree(vfe_bus_local->bus_priv);
1980err_alloc_priv:
1981 kfree(vfe_bus_local);
1982err_alloc_bus:
1983 return rc;
1984}