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