blob: 7960874fe08fb0beb4dacf7348dbe3b87630e2b5 [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"
Harsh Shah19f55812017-06-26 18:58:49 -070020#include "cam_ife_hw_mgr.h"
Harsh Shaha1af8822017-05-11 22:06:36 -070021#include "cam_vfe_hw_intf.h"
22#include "cam_irq_controller.h"
Harsh Shah19f55812017-06-26 18:58:49 -070023#include "cam_tasklet_util.h"
Harsh Shaha1af8822017-05-11 22:06:36 -070024#include "cam_vfe_bus.h"
25#include "cam_vfe_bus_ver2.h"
26#include "cam_vfe_core.h"
27
28#undef CDBG
29#define CDBG(fmt, args...) pr_debug(fmt, ##args)
30
Harsh Shah19f55812017-06-26 18:58:49 -070031static const char drv_name[] = "vfe_bus";
32
33#define CAM_VFE_BUS_IRQ_REG0 0
34#define CAM_VFE_BUS_IRQ_REG1 1
35#define CAM_VFE_BUS_IRQ_REG2 2
36#define CAM_VFE_BUS_IRQ_MAX 3
37
38#define CAM_VFE_BUS_VER2_PAYLOAD_MAX 256
Harsh Shah23557ae2017-05-13 18:14:34 -070039
Junzhe Zou193d78c2017-05-16 15:10:54 -070040#define MAX_BUF_UPDATE_REG_NUM \
41 (sizeof(struct cam_vfe_bus_ver2_reg_offset_bus_client)/4)
Jing Zhoua4e9fbe2017-05-15 14:37:21 -070042#define MAX_REG_VAL_PAIR_SIZE \
Harsh Shah19f55812017-06-26 18:58:49 -070043 (MAX_BUF_UPDATE_REG_NUM * 2 * CAM_PACKET_MAX_PLANES)
Jing Zhoua4e9fbe2017-05-15 14:37:21 -070044
45#define CAM_VFE_ADD_REG_VAL_PAIR(buf_array, index, offset, val) \
Harsh Shah19f55812017-06-26 18:58:49 -070046 do { \
47 buf_array[index++] = offset; \
48 buf_array[index++] = val; \
49 } while (0)
Harsh Shaha1af8822017-05-11 22:06:36 -070050
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 {
Harsh Shah19f55812017-06-26 18:58:49 -070072 uint32_t core_index;
Harsh Shaha1af8822017-05-11 22:06:36 -070073 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[
Harsh Shah19f55812017-06-26 18:58:49 -070079 MAX_REG_VAL_PAIR_SIZE];
80
81 struct cam_vfe_bus_irq_evt_payload evt_payload[
82 CAM_VFE_BUS_VER2_PAYLOAD_MAX];
83 struct list_head free_payload_list;
Harsh Shaha1af8822017-05-11 22:06:36 -070084};
85
86struct cam_vfe_bus_ver2_wm_resource_data {
87 uint32_t index;
88 struct cam_vfe_bus_ver2_common_data *common_data;
89 struct cam_vfe_bus_ver2_reg_offset_bus_client *hw_regs;
Harsh Shah19f55812017-06-26 18:58:49 -070090 void *ctx;
Harsh Shaha1af8822017-05-11 22:06:36 -070091
92 uint32_t irq_enabled;
Jing Zhoua4e9fbe2017-05-15 14:37:21 -070093 uint32_t init_cfg_done;
Harsh Shah19f55812017-06-26 18:58:49 -070094
Harsh Shaha1af8822017-05-11 22:06:36 -070095 uint32_t offset;
96 uint32_t width;
97 uint32_t height;
98 uint32_t stride;
99 uint32_t format;
100 enum cam_vfe_bus_packer_format pack_fmt;
101
102 uint32_t burst_len;
103 uint32_t frame_based;
104
Jing Zhoua4e9fbe2017-05-15 14:37:21 -0700105 uint32_t en_ubwc;
106 uint32_t packer_cfg;
107 uint32_t tile_cfg;
108 uint32_t h_init;
109 uint32_t v_init;
110 uint32_t ubwc_meta_stride;
111 uint32_t ubwc_mode_cfg;
112 uint32_t ubwc_meta_offset;
113
Harsh Shaha1af8822017-05-11 22:06:36 -0700114 uint32_t irq_subsample_period;
115 uint32_t irq_subsample_pattern;
116 uint32_t framedrop_period;
117 uint32_t framedrop_pattern;
Jing Zhoua4e9fbe2017-05-15 14:37:21 -0700118
119 uint32_t en_cfg;
Harsh Shaha1af8822017-05-11 22:06:36 -0700120};
121
122struct cam_vfe_bus_ver2_comp_grp_data {
123 enum cam_vfe_bus_ver2_comp_grp_type comp_grp_type;
124 struct cam_vfe_bus_ver2_common_data *common_data;
125 struct cam_vfe_bus_ver2_reg_offset_comp_grp *hw_regs;
126
127 uint32_t irq_enabled;
128 uint32_t comp_grp_local_idx;
129 uint32_t unique_id;
130
131 uint32_t is_master;
132 uint32_t dual_slave_core;
133 uint32_t intra_client_mask;
134 uint32_t composite_mask;
Harsh Shah19f55812017-06-26 18:58:49 -0700135
136 void *ctx;
Harsh Shaha1af8822017-05-11 22:06:36 -0700137};
138
139struct cam_vfe_bus_ver2_vfe_out_data {
140 uint32_t out_type;
141 struct cam_vfe_bus_ver2_common_data *common_data;
142
143 uint32_t num_wm;
144 struct cam_isp_resource_node *wm_res[PLANE_MAX];
145
146 struct cam_isp_resource_node *comp_grp;
147 enum cam_isp_hw_sync_mode dual_comp_sync_mode;
148 uint32_t dual_hw_alternate_vfe_id;
149 struct list_head vfe_out_list;
150
151 uint32_t format;
152 uint32_t max_width;
153 uint32_t max_height;
154 struct cam_cdm_utils_ops *cdm_util_ops;
155};
156
Harsh Shaha1af8822017-05-11 22:06:36 -0700157struct cam_vfe_bus_ver2_priv {
158 struct cam_vfe_bus_ver2_common_data common_data;
159
160 struct cam_isp_resource_node bus_client[CAM_VFE_BUS_VER2_MAX_CLIENTS];
161 struct cam_isp_resource_node comp_grp[CAM_VFE_BUS_VER2_COMP_GRP_MAX];
162 struct cam_isp_resource_node vfe_out[CAM_VFE_BUS_VER2_VFE_OUT_MAX];
163
164 struct list_head free_comp_grp;
165 struct list_head free_dual_comp_grp;
166 struct list_head used_comp_grp;
167
Harsh Shah19f55812017-06-26 18:58:49 -0700168 uint32_t irq_handle;
Harsh Shaha1af8822017-05-11 22:06:36 -0700169};
170
Harsh Shah19f55812017-06-26 18:58:49 -0700171static int cam_vfe_bus_get_evt_payload(
172 struct cam_vfe_bus_ver2_common_data *common_data,
173 struct cam_vfe_bus_irq_evt_payload **evt_payload)
174{
175 if (list_empty(&common_data->free_payload_list)) {
176 *evt_payload = NULL;
177 pr_err("No free payload\n");
178 return -ENODEV;
179 }
180
181 *evt_payload = list_first_entry(&common_data->free_payload_list,
182 struct cam_vfe_bus_irq_evt_payload, list);
183 list_del_init(&(*evt_payload)->list);
184 return 0;
185}
186
Harsh Shaha1af8822017-05-11 22:06:36 -0700187static int cam_vfe_bus_put_evt_payload(void *core_info,
Harsh Shah19f55812017-06-26 18:58:49 -0700188 struct cam_vfe_bus_irq_evt_payload **evt_payload)
189{
190 struct cam_vfe_bus_ver2_common_data *common_data = NULL;
191 uint32_t *ife_irq_regs = NULL;
192 uint32_t status_reg0, status_reg1, status_reg2;
193
194 if (!core_info) {
195 pr_err("Invalid param core_info NULL");
196 return -EINVAL;
197 }
198 if (*evt_payload == NULL) {
199 pr_err("No payload to put\n");
200 return -EINVAL;
201 }
202
203 ife_irq_regs = (*evt_payload)->irq_reg_val;
204 status_reg0 = ife_irq_regs[CAM_IFE_IRQ_BUS_REG_STATUS0];
205 status_reg1 = ife_irq_regs[CAM_IFE_IRQ_BUS_REG_STATUS1];
206 status_reg2 = ife_irq_regs[CAM_IFE_IRQ_BUS_REG_STATUS2];
207
208 if (status_reg0 || status_reg1 || status_reg2) {
209 CDBG("status0 0x%x status1 0x%x status2 0x%x\n",
210 status_reg0, status_reg1, status_reg2);
211 return 0;
212 }
213
214 common_data = core_info;
215 list_add_tail(&(*evt_payload)->list,
216 &common_data->free_payload_list);
217 *evt_payload = NULL;
218
219 return 0;
220}
Harsh Shaha1af8822017-05-11 22:06:36 -0700221
222static int cam_vfe_bus_ver2_get_intra_client_mask(
223 enum cam_vfe_bus_ver2_vfe_core_id dual_slave_core,
224 enum cam_vfe_bus_ver2_vfe_core_id current_core,
225 uint32_t *intra_client_mask)
226{
227 int rc = 0;
228
229 *intra_client_mask = 0;
230
231 if (dual_slave_core == current_core) {
232 pr_err("Invalid params. Same core as Master and Slave\n");
233 return -EINVAL;
234 }
235
236 switch (current_core) {
237 case CAM_VFE_BUS_VER2_VFE_CORE_0:
238 switch (dual_slave_core) {
239 case CAM_VFE_BUS_VER2_VFE_CORE_1:
240 *intra_client_mask = 0x1;
241 break;
242 case CAM_VFE_BUS_VER2_VFE_CORE_2:
243 *intra_client_mask = 0x2;
244 break;
245 default:
246 pr_err("Invalid value for slave core %u\n",
247 dual_slave_core);
248 rc = -EINVAL;
249 break;
250 }
251 break;
252 case CAM_VFE_BUS_VER2_VFE_CORE_1:
253 switch (dual_slave_core) {
254 case CAM_VFE_BUS_VER2_VFE_CORE_0:
255 *intra_client_mask = 0x1;
256 break;
257 case CAM_VFE_BUS_VER2_VFE_CORE_2:
258 *intra_client_mask = 0x2;
259 break;
260 default:
261 pr_err("Invalid value for slave core %u\n",
262 dual_slave_core);
263 rc = -EINVAL;
264 break;
265 }
266 break;
267 case CAM_VFE_BUS_VER2_VFE_CORE_2:
268 switch (dual_slave_core) {
269 case CAM_VFE_BUS_VER2_VFE_CORE_0:
270 *intra_client_mask = 0x1;
271 break;
272 case CAM_VFE_BUS_VER2_VFE_CORE_1:
273 *intra_client_mask = 0x2;
274 break;
275 default:
276 pr_err("Invalid value for slave core %u\n",
277 dual_slave_core);
278 rc = -EINVAL;
279 break;
280 }
281 break;
282 default:
283 pr_err("Invalid value for master core %u\n", current_core);
284 rc = -EINVAL;
285 break;
286 }
287
288 return rc;
289}
290
291static enum cam_vfe_bus_ver2_vfe_out_type
292 cam_vfe_bus_get_out_res_id(uint32_t res_type)
293{
294 switch (res_type) {
295 case CAM_ISP_IFE_OUT_RES_FULL:
296 return CAM_VFE_BUS_VER2_VFE_OUT_FULL;
297 case CAM_ISP_IFE_OUT_RES_DS4:
298 return CAM_VFE_BUS_VER2_VFE_OUT_DS4;
299 case CAM_ISP_IFE_OUT_RES_DS16:
300 return CAM_VFE_BUS_VER2_VFE_OUT_DS16;
301 case CAM_ISP_IFE_OUT_RES_FD:
302 return CAM_VFE_BUS_VER2_VFE_OUT_FD;
303 case CAM_ISP_IFE_OUT_RES_RAW_DUMP:
304 return CAM_VFE_BUS_VER2_VFE_OUT_RAW_DUMP;
305 case CAM_ISP_IFE_OUT_RES_PDAF:
306 return CAM_VFE_BUS_VER2_VFE_OUT_PDAF;
307 case CAM_ISP_IFE_OUT_RES_RDI_0:
308 return CAM_VFE_BUS_VER2_VFE_OUT_RDI0;
309 case CAM_ISP_IFE_OUT_RES_RDI_1:
310 return CAM_VFE_BUS_VER2_VFE_OUT_RDI1;
311 case CAM_ISP_IFE_OUT_RES_RDI_2:
312 return CAM_VFE_BUS_VER2_VFE_OUT_RDI2;
313 case CAM_ISP_IFE_OUT_RES_STATS_HDR_BE:
314 return CAM_VFE_BUS_VER2_VFE_OUT_STATS_HDR_BE;
315 case CAM_ISP_IFE_OUT_RES_STATS_HDR_BHIST:
316 return CAM_VFE_BUS_VER2_VFE_OUT_STATS_HDR_BHIST;
317 case CAM_ISP_IFE_OUT_RES_STATS_TL_BG:
318 return CAM_VFE_BUS_VER2_VFE_OUT_STATS_TL_BG;
319 case CAM_ISP_IFE_OUT_RES_STATS_BF:
320 return CAM_VFE_BUS_VER2_VFE_OUT_STATS_BF;
321 case CAM_ISP_IFE_OUT_RES_STATS_AWB_BG:
322 return CAM_VFE_BUS_VER2_VFE_OUT_STATS_AWB_BG;
323 case CAM_ISP_IFE_OUT_RES_STATS_BHIST:
324 return CAM_VFE_BUS_VER2_VFE_OUT_STATS_BHIST;
325 case CAM_ISP_IFE_OUT_RES_STATS_RS:
326 return CAM_VFE_BUS_VER2_VFE_OUT_STATS_RS;
327 case CAM_ISP_IFE_OUT_RES_STATS_CS:
328 return CAM_VFE_BUS_VER2_VFE_OUT_STATS_CS;
329 case CAM_ISP_IFE_OUT_RES_STATS_IHIST:
330 return CAM_VFE_BUS_VER2_VFE_OUT_STATS_IHIST;
331 default:
332 return CAM_VFE_BUS_VER2_VFE_OUT_MAX;
333 }
334}
335
336static int cam_vfe_bus_get_num_wm(
337 enum cam_vfe_bus_ver2_vfe_out_type res_type,
338 uint32_t format)
339{
340 switch (res_type) {
341 case CAM_VFE_BUS_VER2_VFE_OUT_RDI0:
342 case CAM_VFE_BUS_VER2_VFE_OUT_RDI1:
343 case CAM_VFE_BUS_VER2_VFE_OUT_RDI2:
344 switch (format) {
345 case CAM_FORMAT_MIPI_RAW_8:
346 case CAM_FORMAT_MIPI_RAW_10:
347 case CAM_FORMAT_MIPI_RAW_12:
348 case CAM_FORMAT_MIPI_RAW_14:
349 case CAM_FORMAT_MIPI_RAW_16:
350 case CAM_FORMAT_MIPI_RAW_20:
351 case CAM_FORMAT_PLAIN128:
352 return 1;
353 default:
354 break;
355 }
356 break;
357 case CAM_VFE_BUS_VER2_VFE_OUT_FULL:
358 switch (format) {
359 case CAM_FORMAT_NV21:
360 case CAM_FORMAT_NV12:
361 case CAM_FORMAT_MIPI_RAW_8:
362 case CAM_FORMAT_PLAIN8:
363 case CAM_FORMAT_TP10:
364 case CAM_FORMAT_UBWC_NV12:
365 case CAM_FORMAT_UBWC_NV12_4R:
366 case CAM_FORMAT_UBWC_TP10:
367 case CAM_FORMAT_UBWC_P010:
368 return 2;
369 default:
370 break;
371 }
372 break;
373 case CAM_VFE_BUS_VER2_VFE_OUT_FD:
374 switch (format) {
375 case CAM_FORMAT_NV21:
376 case CAM_FORMAT_NV12:
377 case CAM_FORMAT_PLAIN8:
378 case CAM_FORMAT_TP10:
379 case CAM_FORMAT_PLAIN16_10:
380 return 2;
381 default:
382 break;
383 }
384 break;
385 case CAM_VFE_BUS_VER2_VFE_OUT_DS4:
386 case CAM_VFE_BUS_VER2_VFE_OUT_DS16:
387 switch (format) {
388 case CAM_FORMAT_PD8:
389 case CAM_FORMAT_PD10:
390 return 1;
391 default:
392 break;
393 }
394 break;
395 case CAM_VFE_BUS_VER2_VFE_OUT_RAW_DUMP:
396 switch (format) {
397 case CAM_FORMAT_ARGB_14:
398 case CAM_FORMAT_PLAIN8:
399 case CAM_FORMAT_PLAIN16_10:
400 case CAM_FORMAT_PLAIN16_12:
401 case CAM_FORMAT_PLAIN16_14:
402 return 1;
403 default:
404 break;
405 }
406 break;
407 case CAM_VFE_BUS_VER2_VFE_OUT_PDAF:
408 switch (format) {
409 case CAM_FORMAT_PLAIN8:
410 case CAM_FORMAT_PLAIN16_10:
411 case CAM_FORMAT_PLAIN16_12:
412 case CAM_FORMAT_PLAIN16_14:
413 return 1;
414 default:
415 break;
416 }
417 break;
418 case CAM_VFE_BUS_VER2_VFE_OUT_STATS_HDR_BE:
419 case CAM_VFE_BUS_VER2_VFE_OUT_STATS_HDR_BHIST:
420 case CAM_VFE_BUS_VER2_VFE_OUT_STATS_TL_BG:
421 case CAM_VFE_BUS_VER2_VFE_OUT_STATS_BF:
422 case CAM_VFE_BUS_VER2_VFE_OUT_STATS_AWB_BG:
423 case CAM_VFE_BUS_VER2_VFE_OUT_STATS_BHIST:
424 case CAM_VFE_BUS_VER2_VFE_OUT_STATS_CS:
425 switch (format) {
426 case CAM_FORMAT_PLAIN64:
427 return 1;
428 default:
429 break;
430 }
431 break;
432 case CAM_VFE_BUS_VER2_VFE_OUT_STATS_RS:
433 case CAM_VFE_BUS_VER2_VFE_OUT_STATS_IHIST:
434 switch (format) {
435 case CAM_FORMAT_PLAIN16_16:
436 return 1;
437 default:
438 break;
439 }
440 break;
441 default:
442 break;
443 }
444
445 pr_err("Unsupported format %u for resource_type %u", format, res_type);
446
447 return -EINVAL;
448}
449
450static int cam_vfe_bus_get_wm_idx(
451 enum cam_vfe_bus_ver2_vfe_out_type vfe_out_res_id,
452 enum cam_vfe_bus_plane_type plane)
453{
454 int wm_idx = -1;
455
456 switch (vfe_out_res_id) {
457 case CAM_VFE_BUS_VER2_VFE_OUT_FULL:
458 switch (plane) {
459 case PLANE_Y:
460 wm_idx = 3;
461 break;
462 case PLANE_C:
463 wm_idx = 4;
464 break;
465 default:
466 break;
467 }
468 break;
469 case CAM_VFE_BUS_VER2_VFE_OUT_DS4:
470 switch (plane) {
471 case PLANE_Y:
472 wm_idx = 5;
473 break;
474 default:
475 break;
476 }
477 break;
478 case CAM_VFE_BUS_VER2_VFE_OUT_DS16:
479 switch (plane) {
480 case PLANE_Y:
481 wm_idx = 6;
482 break;
483 default:
484 break;
485 }
486 break;
487 case CAM_VFE_BUS_VER2_VFE_OUT_FD:
488 switch (plane) {
489 case PLANE_Y:
490 wm_idx = 7;
491 break;
492 case PLANE_C:
493 wm_idx = 8;
494 break;
495 default:
496 break;
497 }
498 break;
499 case CAM_VFE_BUS_VER2_VFE_OUT_RAW_DUMP:
500 switch (plane) {
501 case PLANE_Y:
502 wm_idx = 9;
503 break;
504 default:
505 break;
506 }
507 break;
508 case CAM_VFE_BUS_VER2_VFE_OUT_PDAF:
509 switch (plane) {
510 case PLANE_Y:
511 wm_idx = 10;
512 break;
513 default:
514 break;
515 }
516 break;
517 case CAM_VFE_BUS_VER2_VFE_OUT_RDI0:
518 switch (plane) {
519 case PLANE_Y:
520 wm_idx = 0;
521 break;
522 default:
523 break;
524 }
525 break;
526 case CAM_VFE_BUS_VER2_VFE_OUT_RDI1:
527 switch (plane) {
528 case PLANE_Y:
529 wm_idx = 1;
530 break;
531 default:
532 break;
533 }
534 break;
535 case CAM_VFE_BUS_VER2_VFE_OUT_RDI2:
536 switch (plane) {
537 case PLANE_Y:
538 wm_idx = 2;
539 break;
540 default:
541 break;
542 }
543 break;
544 case CAM_VFE_BUS_VER2_VFE_OUT_STATS_HDR_BE:
545 switch (plane) {
546 case PLANE_Y:
547 wm_idx = 11;
548 break;
549 default:
550 break;
551 }
552 break;
553 case CAM_VFE_BUS_VER2_VFE_OUT_STATS_HDR_BHIST:
554 switch (plane) {
555 case PLANE_Y:
556 wm_idx = 12;
557 break;
558 default:
559 break;
560 }
561 break;
562 case CAM_VFE_BUS_VER2_VFE_OUT_STATS_TL_BG:
563 switch (plane) {
564 case PLANE_Y:
565 wm_idx = 13;
566 break;
567 default:
568 break;
569 }
570 break;
571 case CAM_VFE_BUS_VER2_VFE_OUT_STATS_BF:
572 switch (plane) {
573 case PLANE_Y:
574 wm_idx = 14;
575 break;
576 default:
577 break;
578 }
579 break;
580 case CAM_VFE_BUS_VER2_VFE_OUT_STATS_AWB_BG:
581 switch (plane) {
582 case PLANE_Y:
583 wm_idx = 15;
584 break;
585 default:
586 break;
587 }
588 break;
589 case CAM_VFE_BUS_VER2_VFE_OUT_STATS_BHIST:
590 switch (plane) {
591 case PLANE_Y:
592 wm_idx = 16;
593 break;
594 default:
595 break;
596 }
597 break;
598 case CAM_VFE_BUS_VER2_VFE_OUT_STATS_RS:
599 switch (plane) {
600 case PLANE_Y:
601 wm_idx = 17;
602 break;
603 default:
604 break;
605 }
606 break;
607 case CAM_VFE_BUS_VER2_VFE_OUT_STATS_CS:
608 switch (plane) {
609 case PLANE_Y:
610 wm_idx = 18;
611 break;
612 default:
613 break;
614 }
615 break;
616 case CAM_VFE_BUS_VER2_VFE_OUT_STATS_IHIST:
617 switch (plane) {
618 case PLANE_Y:
619 wm_idx = 19;
620 break;
621 default:
622 break;
623 }
624 break;
625 default:
626 break;
627 }
628
629 return wm_idx;
630}
631
632static enum cam_vfe_bus_packer_format
633 cam_vfe_bus_get_packer_fmt(uint32_t out_fmt)
634{
635 switch (out_fmt) {
636 case CAM_FORMAT_NV21:
637 case CAM_FORMAT_NV12:
Abhishek Kondaveeti170c8122017-07-06 04:45:12 +0530638 return PACKER_FMT_PLAIN_8_LSB_MSB_10;
639 case CAM_FORMAT_PLAIN16_16:
640 return PACKER_FMT_PLAIN_16_16BPP;
641 case CAM_FORMAT_PLAIN64:
642 return PACKER_FMT_PLAIN_64;
643 case CAM_FORMAT_MIPI_RAW_6:
644 case CAM_FORMAT_MIPI_RAW_8:
645 case CAM_FORMAT_MIPI_RAW_10:
646 case CAM_FORMAT_MIPI_RAW_12:
647 case CAM_FORMAT_MIPI_RAW_14:
648 case CAM_FORMAT_MIPI_RAW_16:
649 case CAM_FORMAT_MIPI_RAW_20:
650 case CAM_FORMAT_QTI_RAW_8:
651 case CAM_FORMAT_QTI_RAW_10:
652 case CAM_FORMAT_QTI_RAW_12:
653 case CAM_FORMAT_QTI_RAW_14:
654 case CAM_FORMAT_PLAIN128:
655 case CAM_FORMAT_PD8:
656 case CAM_FORMAT_PD10:
657 return PACKER_FMT_PLAIN_128;
Harsh Shaha1af8822017-05-11 22:06:36 -0700658 default:
659 return PACKER_FMT_MAX;
660 }
661}
662
663static int cam_vfe_bus_acquire_wm(
664 struct cam_vfe_bus_ver2_priv *ver2_bus_priv,
665 struct cam_isp_out_port_info *out_port_info,
Harsh Shah19f55812017-06-26 18:58:49 -0700666 void *tasklet,
667 void *ctx,
Harsh Shaha1af8822017-05-11 22:06:36 -0700668 enum cam_vfe_bus_ver2_vfe_out_type vfe_out_res_id,
669 enum cam_vfe_bus_plane_type plane,
670 enum cam_isp_hw_split_id split_id,
671 uint32_t subscribe_irq,
672 struct cam_isp_resource_node **wm_res,
673 uint32_t *client_done_mask)
674{
675 uint32_t wm_idx = 0;
676 struct cam_isp_resource_node *wm_res_local = NULL;
677 struct cam_vfe_bus_ver2_wm_resource_data *rsrc_data = NULL;
678
679 *wm_res = NULL;
680 *client_done_mask = 0;
681
682 /* No need to allocate for BUS VER2. VFE OUT to WM is fixed. */
683 wm_idx = cam_vfe_bus_get_wm_idx(vfe_out_res_id, plane);
684 if (wm_idx < 0 || wm_idx >= CAM_VFE_BUS_VER2_MAX_CLIENTS) {
685 pr_err("Unsupported VFE out %d plane %d\n",
686 vfe_out_res_id, plane);
687 return -EINVAL;
688 }
689
690 wm_res_local = &ver2_bus_priv->bus_client[wm_idx];
Harsh Shah19f55812017-06-26 18:58:49 -0700691 wm_res_local->tasklet_info = tasklet;
Harsh Shaha1af8822017-05-11 22:06:36 -0700692 wm_res_local->res_state = CAM_ISP_RESOURCE_STATE_RESERVED;
693
694 rsrc_data = wm_res_local->res_priv;
695 rsrc_data->irq_enabled = subscribe_irq;
Harsh Shah19f55812017-06-26 18:58:49 -0700696 rsrc_data->ctx = ctx;
Harsh Shaha1af8822017-05-11 22:06:36 -0700697 rsrc_data->format = out_port_info->format;
698 rsrc_data->pack_fmt = cam_vfe_bus_get_packer_fmt(rsrc_data->format);
699
700 rsrc_data->width = out_port_info->width;
701 rsrc_data->height = out_port_info->height;
Jing Zhoua4e9fbe2017-05-15 14:37:21 -0700702
703 if (rsrc_data->index < 3) {
704 rsrc_data->width = rsrc_data->width * 5/4 * rsrc_data->height;
705 rsrc_data->height = 1;
Jing Zhoua4e9fbe2017-05-15 14:37:21 -0700706 rsrc_data->en_cfg = 0x3;
Abhishek Kondaveetib31b46c2017-06-23 04:56:24 +0530707 } else if (rsrc_data->index < 5 ||
708 rsrc_data->index == 7 || rsrc_data->index == 8) {
Jing Zhoua4e9fbe2017-05-15 14:37:21 -0700709 switch (plane) {
710 case PLANE_Y:
711 switch (rsrc_data->format) {
712 case CAM_FORMAT_UBWC_NV12:
713 case CAM_FORMAT_UBWC_NV12_4R:
714 case CAM_FORMAT_UBWC_TP10:
715 rsrc_data->en_ubwc = 1;
716 break;
717 default:
718 break;
719 }
720 break;
721 case PLANE_C:
722 switch (rsrc_data->format) {
723 case CAM_FORMAT_NV21:
724 case CAM_FORMAT_NV12:
725 rsrc_data->height /= 2;
726 break;
727 case CAM_FORMAT_UBWC_NV12:
728 case CAM_FORMAT_UBWC_NV12_4R:
729 case CAM_FORMAT_UBWC_TP10:
730 rsrc_data->height /= 2;
731 rsrc_data->en_ubwc = 1;
732 break;
733 default:
734 break;
735 }
Harsh Shaha1af8822017-05-11 22:06:36 -0700736 break;
737 default:
Jing Zhoua4e9fbe2017-05-15 14:37:21 -0700738 pr_err("Invalid plane type %d\n", plane);
739 return -EINVAL;
Harsh Shaha1af8822017-05-11 22:06:36 -0700740 }
Jing Zhoua4e9fbe2017-05-15 14:37:21 -0700741 rsrc_data->en_cfg = 0x1;
Abhishek Kondaveetib31b46c2017-06-23 04:56:24 +0530742 } else if (rsrc_data->index >= 11) {
743 rsrc_data->width = 0;
744 rsrc_data->height = 0;
Abhishek Kondaveetib31b46c2017-06-23 04:56:24 +0530745 rsrc_data->stride = 1;
746 rsrc_data->en_cfg = 0x3;
Jing Zhoua4e9fbe2017-05-15 14:37:21 -0700747 } else {
748 rsrc_data->width = rsrc_data->width * 4;
749 rsrc_data->height = rsrc_data->height / 2;
Jing Zhoua4e9fbe2017-05-15 14:37:21 -0700750 rsrc_data->en_cfg = 0x1;
Harsh Shaha1af8822017-05-11 22:06:36 -0700751 }
752
753 if (vfe_out_res_id >= CAM_ISP_IFE_OUT_RES_RDI_0 &&
754 vfe_out_res_id <= CAM_ISP_IFE_OUT_RES_RDI_3)
755 rsrc_data->frame_based = 1;
756
757 *client_done_mask = (1 << wm_idx);
758 *wm_res = wm_res_local;
759
760 return 0;
761}
762
763static int cam_vfe_bus_release_wm(void *bus_priv,
764 struct cam_isp_resource_node *wm_res)
765{
766 struct cam_vfe_bus_ver2_wm_resource_data *rsrc_data =
767 wm_res->res_priv;
768
769 rsrc_data->irq_enabled = 0;
770 rsrc_data->offset = 0;
771 rsrc_data->width = 0;
772 rsrc_data->height = 0;
773 rsrc_data->stride = 0;
774 rsrc_data->format = 0;
775 rsrc_data->pack_fmt = 0;
776 rsrc_data->burst_len = 0;
777 rsrc_data->frame_based = 0;
778 rsrc_data->irq_subsample_period = 0;
779 rsrc_data->irq_subsample_pattern = 0;
780 rsrc_data->framedrop_period = 0;
781 rsrc_data->framedrop_pattern = 0;
Jing Zhoua4e9fbe2017-05-15 14:37:21 -0700782 rsrc_data->packer_cfg = 0;
783 rsrc_data->en_ubwc = 0;
784 rsrc_data->tile_cfg = 0;
785 rsrc_data->h_init = 0;
786 rsrc_data->v_init = 0;
787 rsrc_data->ubwc_meta_stride = 0;
788 rsrc_data->ubwc_mode_cfg = 0;
789 rsrc_data->ubwc_meta_offset = 0;
790 rsrc_data->init_cfg_done = 0;
791 rsrc_data->en_cfg = 0;
Harsh Shah19f55812017-06-26 18:58:49 -0700792
793 wm_res->tasklet_info = NULL;
Harsh Shaha1af8822017-05-11 22:06:36 -0700794 wm_res->res_state = CAM_ISP_RESOURCE_STATE_AVAILABLE;
795
796 return 0;
797}
798
799static int cam_vfe_bus_start_wm(struct cam_isp_resource_node *wm_res)
800{
801 int rc = 0;
802 struct cam_vfe_bus_ver2_wm_resource_data *rsrc_data =
803 wm_res->res_priv;
804 struct cam_vfe_bus_ver2_common_data *common_data =
805 rsrc_data->common_data;
Harsh Shah19f55812017-06-26 18:58:49 -0700806 uint32_t bus_irq_reg_mask[CAM_VFE_BUS_IRQ_MAX] = {0};
Harsh Shaha1af8822017-05-11 22:06:36 -0700807
Harsh Shah23557ae2017-05-13 18:14:34 -0700808 cam_io_w_mb(0, common_data->mem_base + rsrc_data->hw_regs->header_addr);
809 cam_io_w_mb(0, common_data->mem_base + rsrc_data->hw_regs->header_cfg);
810 cam_io_w_mb(0, common_data->mem_base + rsrc_data->hw_regs->frame_inc);
811 cam_io_w(0xf, common_data->mem_base + rsrc_data->hw_regs->burst_limit);
812
Jing Zhoua4e9fbe2017-05-15 14:37:21 -0700813 cam_io_w_mb(rsrc_data->width,
Harsh Shaha1af8822017-05-11 22:06:36 -0700814 common_data->mem_base + rsrc_data->hw_regs->buffer_width_cfg);
Jing Zhoua4e9fbe2017-05-15 14:37:21 -0700815 cam_io_w(rsrc_data->height,
Harsh Shaha1af8822017-05-11 22:06:36 -0700816 common_data->mem_base + rsrc_data->hw_regs->buffer_height_cfg);
Jing Zhoua4e9fbe2017-05-15 14:37:21 -0700817 cam_io_w(rsrc_data->pack_fmt,
Harsh Shaha1af8822017-05-11 22:06:36 -0700818 common_data->mem_base + rsrc_data->hw_regs->packer_cfg);
Harsh Shaha1af8822017-05-11 22:06:36 -0700819
820 cam_io_w(0xFFFFFFFF, common_data->mem_base +
821 rsrc_data->hw_regs->irq_subsample_pattern);
822 cam_io_w(0x0, common_data->mem_base +
823 rsrc_data->hw_regs->irq_subsample_period);
824
825 cam_io_w(0xFFFFFFFF,
Harsh Shah23557ae2017-05-13 18:14:34 -0700826 common_data->mem_base + rsrc_data->hw_regs->framedrop_pattern);
Harsh Shaha1af8822017-05-11 22:06:36 -0700827 cam_io_w(0x0,
Harsh Shah23557ae2017-05-13 18:14:34 -0700828 common_data->mem_base + rsrc_data->hw_regs->framedrop_period);
Harsh Shaha1af8822017-05-11 22:06:36 -0700829
Harsh Shah19f55812017-06-26 18:58:49 -0700830 /* Subscribe IRQ */
831 if (rsrc_data->irq_enabled) {
832 CDBG("Subscribe WM%d IRQ\n", rsrc_data->index);
833 bus_irq_reg_mask[CAM_VFE_BUS_IRQ_REG1] =
834 (1 << rsrc_data->index);
835 wm_res->irq_handle = cam_irq_controller_subscribe_irq(
836 common_data->bus_irq_controller, CAM_IRQ_PRIORITY_1,
837 bus_irq_reg_mask, wm_res,
838 wm_res->top_half_handler,
839 cam_ife_mgr_do_tasklet_buf_done,
840 wm_res->tasklet_info, cam_tasklet_enqueue_cmd);
841 if (wm_res->irq_handle < 0) {
842 pr_err("Subscribe IRQ failed for WM %d\n",
843 rsrc_data->index);
844 return -EFAULT;
845 }
846 }
847
Junzhe Zou3d292562017-07-12 17:59:58 -0700848 /* enable ubwc if needed*/
849 if (rsrc_data->en_ubwc) {
850 cam_io_w_mb(0x1, common_data->mem_base +
851 rsrc_data->hw_regs->ubwc_regs->mode_cfg);
852 }
853
Harsh Shah19f55812017-06-26 18:58:49 -0700854 /* Enable WM */
855 cam_io_w_mb(rsrc_data->en_cfg, common_data->mem_base +
856 rsrc_data->hw_regs->cfg);
857
Harsh Shah23557ae2017-05-13 18:14:34 -0700858 CDBG("WM res %d width = %d, height = %d\n", rsrc_data->index,
Jing Zhoua4e9fbe2017-05-15 14:37:21 -0700859 rsrc_data->width, rsrc_data->height);
Harsh Shah23557ae2017-05-13 18:14:34 -0700860 CDBG("WM res %d pk_fmt = %d\n", rsrc_data->index,
Jing Zhoua4e9fbe2017-05-15 14:37:21 -0700861 rsrc_data->pack_fmt & PACKER_FMT_MAX);
Harsh Shah23557ae2017-05-13 18:14:34 -0700862 CDBG("WM res %d stride = %d, burst len = %d\n",
Jing Zhoua4e9fbe2017-05-15 14:37:21 -0700863 rsrc_data->index, rsrc_data->stride, 0xf);
Harsh Shah23557ae2017-05-13 18:14:34 -0700864 CDBG("enable WM res %d offset 0x%x val 0x%x\n", rsrc_data->index,
Jing Zhoua4e9fbe2017-05-15 14:37:21 -0700865 (uint32_t) rsrc_data->hw_regs->cfg, rsrc_data->en_cfg);
Harsh Shaha1af8822017-05-11 22:06:36 -0700866
867 wm_res->res_state = CAM_ISP_RESOURCE_STATE_STREAMING;
868
869 return rc;
870}
871
872static int cam_vfe_bus_stop_wm(struct cam_isp_resource_node *wm_res)
873{
874 int rc = 0;
875 struct cam_vfe_bus_ver2_wm_resource_data *rsrc_data =
876 wm_res->res_priv;
877 struct cam_vfe_bus_ver2_common_data *common_data =
878 rsrc_data->common_data;
879
880 /* Disble WM */
881 cam_io_w_mb(0x0,
882 common_data->mem_base + rsrc_data->hw_regs->cfg);
883
884 CDBG("irq_enabled %d", rsrc_data->irq_enabled);
885 /* Unsubscribe IRQ */
Harsh Shah19f55812017-06-26 18:58:49 -0700886 if (rsrc_data->irq_enabled)
887 rc = cam_irq_controller_unsubscribe_irq(
888 common_data->bus_irq_controller,
889 wm_res->irq_handle);
Harsh Shaha1af8822017-05-11 22:06:36 -0700890
891 /* Halt & Reset WM */
892 cam_io_w_mb(BIT(rsrc_data->index),
893 common_data->mem_base + common_data->common_reg->sw_reset);
894
895 wm_res->res_state = CAM_ISP_RESOURCE_STATE_RESERVED;
896
897 return rc;
898}
899
900static int cam_vfe_bus_handle_wm_done_top_half(uint32_t evt_id,
901 struct cam_irq_th_payload *th_payload)
902{
Harsh Shah19f55812017-06-26 18:58:49 -0700903 int32_t rc;
904 int i;
905 struct cam_isp_resource_node *wm_res = NULL;
906 struct cam_vfe_bus_ver2_wm_resource_data *rsrc_data = NULL;
907 struct cam_vfe_bus_irq_evt_payload *evt_payload;
908
909 wm_res = th_payload->handler_priv;
910 if (!wm_res) {
911 pr_err_ratelimited("Error! No resource\n");
912 return -ENODEV;
913 }
914
915 rsrc_data = wm_res->res_priv;
916
917 CDBG("IRQ status_0 = %x\n", th_payload->evt_status_arr[0]);
918 CDBG("IRQ status_1 = %x\n", th_payload->evt_status_arr[1]);
919
920 rc = cam_vfe_bus_get_evt_payload(rsrc_data->common_data, &evt_payload);
921 if (rc) {
922 pr_err_ratelimited("No tasklet_cmd is free in queue\n");
923 return rc;
924 }
925
926 cam_isp_hw_get_timestamp(&evt_payload->ts);
927
928 evt_payload->ctx = rsrc_data->ctx;
929 evt_payload->core_index = rsrc_data->common_data->core_index;
930 evt_payload->evt_id = evt_id;
931
932 for (i = 0; i < th_payload->num_registers; i++)
933 evt_payload->irq_reg_val[i] = th_payload->evt_status_arr[i];
934
935 th_payload->evt_payload_priv = evt_payload;
936
937 CDBG("Exit\n");
938 return rc;
Harsh Shaha1af8822017-05-11 22:06:36 -0700939}
940
941static int cam_vfe_bus_handle_wm_done_bottom_half(void *wm_node,
942 void *evt_payload_priv)
943{
944 int rc = CAM_VFE_IRQ_STATUS_ERR;
945 struct cam_isp_resource_node *wm_res = wm_node;
946 struct cam_vfe_bus_irq_evt_payload *evt_payload = evt_payload_priv;
Harsh Shah23557ae2017-05-13 18:14:34 -0700947 struct cam_vfe_bus_ver2_wm_resource_data *rsrc_data =
948 (wm_res == NULL) ? NULL : wm_res->res_priv;
949 uint32_t *cam_ife_irq_regs;
Harsh Shaha1af8822017-05-11 22:06:36 -0700950 uint32_t status_reg;
951
Harsh Shah23557ae2017-05-13 18:14:34 -0700952 if (!evt_payload || !rsrc_data)
953 return rc;
Harsh Shaha1af8822017-05-11 22:06:36 -0700954
Harsh Shah23557ae2017-05-13 18:14:34 -0700955 cam_ife_irq_regs = evt_payload->irq_reg_val;
956 status_reg = cam_ife_irq_regs[CAM_IFE_IRQ_BUS_REG_STATUS1];
957
958 if (status_reg & BIT(rsrc_data->index)) {
959 cam_ife_irq_regs[CAM_IFE_IRQ_BUS_REG_STATUS1] &=
960 ~BIT(rsrc_data->index);
Harsh Shaha1af8822017-05-11 22:06:36 -0700961 rc = CAM_VFE_IRQ_STATUS_SUCCESS;
Harsh Shah23557ae2017-05-13 18:14:34 -0700962 }
Harsh Shah19f55812017-06-26 18:58:49 -0700963 CDBG("status_reg %x rc %d\n", status_reg, rc);
Harsh Shaha1af8822017-05-11 22:06:36 -0700964
965 if (rc == CAM_VFE_IRQ_STATUS_SUCCESS)
Harsh Shah19f55812017-06-26 18:58:49 -0700966 cam_vfe_bus_put_evt_payload(rsrc_data->common_data,
Harsh Shaha1af8822017-05-11 22:06:36 -0700967 &evt_payload);
968
969 return rc;
970}
971
972static int cam_vfe_bus_init_wm_resource(uint32_t index,
973 struct cam_vfe_bus_ver2_priv *ver2_bus_priv,
974 struct cam_vfe_bus_ver2_hw_info *ver2_hw_info,
975 struct cam_isp_resource_node *wm_res)
976{
Harsh Shaha1af8822017-05-11 22:06:36 -0700977 struct cam_vfe_bus_ver2_wm_resource_data *rsrc_data;
978
979 rsrc_data = kzalloc(sizeof(struct cam_vfe_bus_ver2_wm_resource_data),
980 GFP_KERNEL);
981 if (!rsrc_data) {
Harsh Shah545df9a2017-06-16 16:43:17 -0700982 CDBG("Failed to alloc for WM res priv\n");
983 return -ENOMEM;
Harsh Shaha1af8822017-05-11 22:06:36 -0700984 }
985 wm_res->res_priv = rsrc_data;
986
987 rsrc_data->index = index;
988 rsrc_data->hw_regs = &ver2_hw_info->bus_client_reg[index];
989 rsrc_data->common_data = &ver2_bus_priv->common_data;
990
991 wm_res->res_state = CAM_ISP_RESOURCE_STATE_AVAILABLE;
992 INIT_LIST_HEAD(&wm_res->list);
993
994 wm_res->start = cam_vfe_bus_start_wm;
995 wm_res->stop = cam_vfe_bus_stop_wm;
996 wm_res->top_half_handler = cam_vfe_bus_handle_wm_done_top_half;
997 wm_res->bottom_half_handler = cam_vfe_bus_handle_wm_done_bottom_half;
998 wm_res->hw_intf = ver2_bus_priv->common_data.hw_intf;
999
Harsh Shah545df9a2017-06-16 16:43:17 -07001000 return 0;
1001}
1002
1003static int cam_vfe_bus_deinit_wm_resource(
1004 struct cam_isp_resource_node *wm_res)
1005{
1006 struct cam_vfe_bus_ver2_wm_resource_data *rsrc_data;
1007
1008 wm_res->res_state = CAM_ISP_RESOURCE_STATE_UNAVAILABLE;
1009 INIT_LIST_HEAD(&wm_res->list);
1010
1011 wm_res->start = NULL;
1012 wm_res->stop = NULL;
1013 wm_res->top_half_handler = NULL;
1014 wm_res->bottom_half_handler = NULL;
1015 wm_res->hw_intf = NULL;
1016
1017 rsrc_data = wm_res->res_priv;
1018 wm_res->res_priv = NULL;
1019 if (!rsrc_data) {
1020 pr_err("Error! WM res priv is NULL\n");
1021 return -ENOMEM;
1022 }
1023 kfree(rsrc_data);
1024
1025 return 0;
Harsh Shaha1af8822017-05-11 22:06:36 -07001026}
1027
1028static void cam_vfe_bus_add_wm_to_comp_grp(
1029 struct cam_isp_resource_node *comp_grp,
1030 uint32_t composite_mask)
1031{
1032 struct cam_vfe_bus_ver2_comp_grp_data *rsrc_data = comp_grp->res_priv;
1033
1034 rsrc_data->composite_mask |= composite_mask;
1035}
1036
1037static void cam_vfe_bus_match_comp_grp(
1038 struct cam_vfe_bus_ver2_priv *ver2_bus_priv,
1039 struct cam_isp_resource_node **comp_grp,
1040 uint32_t comp_grp_local_idx,
1041 uint32_t unique_id)
1042{
1043 struct cam_vfe_bus_ver2_comp_grp_data *rsrc_data = NULL;
1044 struct cam_isp_resource_node *comp_grp_local = NULL;
1045
1046 list_for_each_entry(comp_grp_local,
1047 &ver2_bus_priv->used_comp_grp, list) {
1048 rsrc_data = comp_grp_local->res_priv;
1049 if (rsrc_data->comp_grp_local_idx == comp_grp_local_idx &&
1050 rsrc_data->unique_id == unique_id) {
1051 /* Match found */
1052 *comp_grp = comp_grp_local;
1053 return;
1054 }
1055 }
1056
1057 *comp_grp = NULL;
1058}
1059
1060static int cam_vfe_bus_acquire_comp_grp(
1061 struct cam_vfe_bus_ver2_priv *ver2_bus_priv,
1062 struct cam_isp_out_port_info *out_port_info,
Harsh Shah19f55812017-06-26 18:58:49 -07001063 void *tasklet,
1064 void *ctx,
Harsh Shaha1af8822017-05-11 22:06:36 -07001065 uint32_t unique_id,
1066 uint32_t is_dual,
1067 uint32_t is_master,
1068 enum cam_vfe_bus_ver2_vfe_core_id dual_slave_core,
1069 struct cam_isp_resource_node **comp_grp)
1070{
1071 int rc = 0;
1072 struct cam_isp_resource_node *comp_grp_local = NULL;
1073 struct cam_vfe_bus_ver2_comp_grp_data *rsrc_data = NULL;
1074
1075 /* Check if matching comp_grp already acquired */
1076 cam_vfe_bus_match_comp_grp(ver2_bus_priv, &comp_grp_local,
1077 out_port_info->comp_grp_id, unique_id);
1078
1079 if (!comp_grp_local) {
1080 /* First find a free group */
1081 if (is_dual) {
1082 if (list_empty(&ver2_bus_priv->free_dual_comp_grp)) {
1083 pr_err("No Free Composite Group\n");
1084 return -ENODEV;
1085 }
1086 comp_grp_local = list_first_entry(
1087 &ver2_bus_priv->free_dual_comp_grp,
1088 struct cam_isp_resource_node, list);
1089 rsrc_data = comp_grp_local->res_priv;
1090 rc = cam_vfe_bus_ver2_get_intra_client_mask(
1091 dual_slave_core,
1092 comp_grp_local->hw_intf->hw_idx,
1093 &rsrc_data->intra_client_mask);
1094 } else {
1095 if (list_empty(&ver2_bus_priv->free_comp_grp)) {
1096 pr_err("No Free Composite Group\n");
1097 return -ENODEV;
1098 }
1099 comp_grp_local = list_first_entry(
1100 &ver2_bus_priv->free_comp_grp,
1101 struct cam_isp_resource_node, list);
1102 rsrc_data = comp_grp_local->res_priv;
1103 }
1104
1105 list_del(&comp_grp_local->list);
Harsh Shah19f55812017-06-26 18:58:49 -07001106 comp_grp_local->tasklet_info = tasklet;
Harsh Shaha1af8822017-05-11 22:06:36 -07001107 comp_grp_local->res_state = CAM_ISP_RESOURCE_STATE_RESERVED;
1108
1109 rsrc_data->is_master = is_master;
1110 rsrc_data->composite_mask = 0;
1111 rsrc_data->unique_id = unique_id;
1112 rsrc_data->comp_grp_local_idx = out_port_info->comp_grp_id;
1113
1114 list_add_tail(&comp_grp_local->list,
1115 &ver2_bus_priv->used_comp_grp);
1116
1117 } else {
1118 rsrc_data = comp_grp_local->res_priv;
1119 /* Do not support runtime change in composite mask */
1120 if (comp_grp_local->res_state ==
1121 CAM_ISP_RESOURCE_STATE_STREAMING) {
1122 pr_err("Invalid State %d Comp Grp %u\n",
1123 comp_grp_local->res_state,
1124 rsrc_data->comp_grp_type);
1125 return -EBUSY;
1126 }
1127 }
1128
Harsh Shah19f55812017-06-26 18:58:49 -07001129 rsrc_data->ctx = ctx;
Harsh Shaha1af8822017-05-11 22:06:36 -07001130 *comp_grp = comp_grp_local;
1131
1132 return rc;
1133}
1134
1135static int cam_vfe_bus_release_comp_grp(
1136 struct cam_vfe_bus_ver2_priv *ver2_bus_priv,
1137 struct cam_isp_resource_node *in_comp_grp)
1138{
1139 struct cam_isp_resource_node *comp_grp = NULL;
1140 struct cam_vfe_bus_ver2_comp_grp_data *in_rsrc_data = NULL;
1141 int match_found = 0;
1142
1143 if (!in_comp_grp) {
1144 pr_err("Invalid Params Comp Grp %pK\n", in_rsrc_data);
1145 return -EINVAL;
1146 }
1147
1148 if (in_comp_grp->res_state == CAM_ISP_RESOURCE_STATE_AVAILABLE) {
1149 /* Already Released. Do Nothing */
1150 return 0;
1151 }
1152
1153 in_rsrc_data = in_comp_grp->res_priv;
1154
1155 list_for_each_entry(comp_grp, &ver2_bus_priv->used_comp_grp, list) {
1156 if (comp_grp == in_comp_grp) {
1157 match_found = 1;
1158 break;
1159 }
1160 }
1161
1162 if (!match_found) {
1163 pr_err("Could not find matching Comp Grp type %u\n",
1164 in_rsrc_data->comp_grp_type);
1165 return -ENODEV;
1166 }
1167
1168
1169 list_del(&comp_grp->list);
1170 if (in_rsrc_data->comp_grp_type >= CAM_VFE_BUS_VER2_COMP_GRP_DUAL_0 &&
1171 in_rsrc_data->comp_grp_type <= CAM_VFE_BUS_VER2_COMP_GRP_DUAL_5)
1172 list_add_tail(&comp_grp->list,
1173 &ver2_bus_priv->free_dual_comp_grp);
Jing Zhoue71fd4a2017-05-15 19:44:34 -07001174 else if (in_rsrc_data->comp_grp_type >= CAM_VFE_BUS_VER2_COMP_GRP_0
1175 && in_rsrc_data->comp_grp_type <= CAM_VFE_BUS_VER2_COMP_GRP_5)
Harsh Shaha1af8822017-05-11 22:06:36 -07001176 list_add_tail(&comp_grp->list, &ver2_bus_priv->free_comp_grp);
1177
Harsh Shaha1af8822017-05-11 22:06:36 -07001178 in_rsrc_data->unique_id = 0;
1179 in_rsrc_data->comp_grp_local_idx = 0;
1180 in_rsrc_data->composite_mask = 0;
1181 in_rsrc_data->dual_slave_core = CAM_VFE_BUS_VER2_VFE_CORE_MAX;
1182
Harsh Shah19f55812017-06-26 18:58:49 -07001183 comp_grp->tasklet_info = NULL;
Harsh Shaha1af8822017-05-11 22:06:36 -07001184 comp_grp->res_state = CAM_ISP_RESOURCE_STATE_AVAILABLE;
1185
Jing Zhoue71fd4a2017-05-15 19:44:34 -07001186 return 0;
Harsh Shaha1af8822017-05-11 22:06:36 -07001187}
1188
1189static int cam_vfe_bus_start_comp_grp(struct cam_isp_resource_node *comp_grp)
1190{
1191 int rc = 0;
1192 struct cam_vfe_bus_ver2_comp_grp_data *rsrc_data =
1193 comp_grp->res_priv;
1194 struct cam_vfe_bus_ver2_common_data *common_data =
1195 rsrc_data->common_data;
Harsh Shah19f55812017-06-26 18:58:49 -07001196 uint32_t bus_irq_reg_mask[CAM_VFE_BUS_IRQ_MAX] = {0};
Harsh Shaha1af8822017-05-11 22:06:36 -07001197
1198 cam_io_w_mb(rsrc_data->composite_mask, common_data->mem_base +
1199 rsrc_data->hw_regs->comp_mask);
1200
1201 CDBG("composite_mask is 0x%x\n", rsrc_data->composite_mask);
1202 CDBG("composite_mask addr 0x%x\n", rsrc_data->hw_regs->comp_mask);
1203
1204 if (rsrc_data->comp_grp_type >= CAM_VFE_BUS_VER2_COMP_GRP_DUAL_0 &&
1205 rsrc_data->comp_grp_type <= CAM_VFE_BUS_VER2_COMP_GRP_DUAL_5 &&
1206 rsrc_data->is_master) {
1207 int dual_comp_grp = (rsrc_data->comp_grp_type -
1208 CAM_VFE_BUS_VER2_COMP_GRP_DUAL_0);
1209 int intra_client_en = cam_io_r_mb(common_data->mem_base +
1210 common_data->common_reg->dual_master_comp_cfg);
1211
1212 /* 2 Bits per comp_grp. Hence left shift by comp_grp * 2 */
1213 intra_client_en |=
1214 (rsrc_data->intra_client_mask << dual_comp_grp * 2);
1215
1216 cam_io_w_mb(intra_client_en, common_data->mem_base +
1217 common_data->common_reg->dual_master_comp_cfg);
Harsh Shah19f55812017-06-26 18:58:49 -07001218
1219 bus_irq_reg_mask[CAM_VFE_BUS_IRQ_REG2] = (1 << dual_comp_grp);
1220 } else {
1221 /* IRQ bits for COMP GRP start at 5. So add 5 to the shift */
1222 bus_irq_reg_mask[CAM_VFE_BUS_IRQ_REG0] =
1223 (1 << (rsrc_data->comp_grp_type + 5));
1224 }
1225
1226 /* Subscribe IRQ */
1227 CDBG("Subscribe COMP_GRP%d IRQ\n", rsrc_data->comp_grp_type);
1228 comp_grp->irq_handle = cam_irq_controller_subscribe_irq(
1229 common_data->bus_irq_controller, CAM_IRQ_PRIORITY_1,
1230 bus_irq_reg_mask, comp_grp,
1231 comp_grp->top_half_handler,
1232 cam_ife_mgr_do_tasklet_buf_done,
1233 comp_grp->tasklet_info, cam_tasklet_enqueue_cmd);
1234 if (comp_grp->irq_handle < 0) {
1235 pr_err("Subscribe IRQ failed for comp_grp %d\n",
1236 rsrc_data->comp_grp_type);
1237 return -EFAULT;
Harsh Shaha1af8822017-05-11 22:06:36 -07001238 }
1239
1240 comp_grp->res_state = CAM_ISP_RESOURCE_STATE_STREAMING;
Harsh Shah19f55812017-06-26 18:58:49 -07001241
Harsh Shaha1af8822017-05-11 22:06:36 -07001242 return rc;
1243}
1244
1245static int cam_vfe_bus_stop_comp_grp(struct cam_isp_resource_node *comp_grp)
1246{
1247 int rc = 0;
1248 struct cam_vfe_bus_ver2_comp_grp_data *rsrc_data =
1249 comp_grp->res_priv;
1250 struct cam_vfe_bus_ver2_common_data *common_data =
1251 rsrc_data->common_data;
1252
1253 /* Unsubscribe IRQ */
Harsh Shah19f55812017-06-26 18:58:49 -07001254 rc = cam_irq_controller_unsubscribe_irq(
1255 common_data->bus_irq_controller,
1256 comp_grp->irq_handle);
Harsh Shaha1af8822017-05-11 22:06:36 -07001257
1258 cam_io_w_mb(rsrc_data->composite_mask, common_data->mem_base +
1259 rsrc_data->hw_regs->comp_mask);
1260 if (rsrc_data->comp_grp_type >= CAM_VFE_BUS_VER2_COMP_GRP_DUAL_0 &&
1261 rsrc_data->comp_grp_type <= CAM_VFE_BUS_VER2_COMP_GRP_DUAL_5 &&
1262 rsrc_data->is_master) {
1263 int dual_comp_grp = (rsrc_data->comp_grp_type -
1264 CAM_VFE_BUS_VER2_COMP_GRP_DUAL_0);
1265 int intra_client_en = cam_io_r_mb(common_data->mem_base +
1266 common_data->common_reg->dual_master_comp_cfg);
1267
1268 /* 2 Bits per comp_grp. Hence left shift by comp_grp * 2 */
1269 intra_client_en &=
1270 ~(rsrc_data->intra_client_mask << dual_comp_grp * 2);
1271
1272 cam_io_w_mb(intra_client_en, common_data->mem_base +
1273 common_data->common_reg->dual_master_comp_cfg);
1274 }
1275
1276 comp_grp->res_state = CAM_ISP_RESOURCE_STATE_RESERVED;
1277
1278 return rc;
1279}
1280
1281static int cam_vfe_bus_handle_comp_done_top_half(uint32_t evt_id,
1282 struct cam_irq_th_payload *th_payload)
1283{
Harsh Shah19f55812017-06-26 18:58:49 -07001284 int32_t rc;
1285 int i;
1286 struct cam_isp_resource_node *comp_grp = NULL;
1287 struct cam_vfe_bus_ver2_comp_grp_data *rsrc_data = NULL;
1288 struct cam_vfe_bus_irq_evt_payload *evt_payload;
1289
1290 comp_grp = th_payload->handler_priv;
1291 if (!comp_grp) {
1292 pr_err_ratelimited("Error! No resource\n");
1293 return -ENODEV;
1294 }
1295
1296 rsrc_data = comp_grp->res_priv;
1297
1298 CDBG("IRQ status_0 = %x\n", th_payload->evt_status_arr[0]);
1299 CDBG("IRQ status_1 = %x\n", th_payload->evt_status_arr[1]);
1300
1301 rc = cam_vfe_bus_get_evt_payload(rsrc_data->common_data, &evt_payload);
1302 if (rc) {
1303 pr_err_ratelimited("No tasklet_cmd is free in queue\n");
1304 return rc;
1305 }
1306
1307 cam_isp_hw_get_timestamp(&evt_payload->ts);
1308
1309 evt_payload->ctx = rsrc_data->ctx;
1310 evt_payload->core_index = rsrc_data->common_data->core_index;
1311 evt_payload->evt_id = evt_id;
1312
1313 for (i = 0; i < th_payload->num_registers; i++)
1314 evt_payload->irq_reg_val[i] = th_payload->evt_status_arr[i];
1315
1316 th_payload->evt_payload_priv = evt_payload;
1317
1318 CDBG("Exit\n");
1319 return rc;
Harsh Shaha1af8822017-05-11 22:06:36 -07001320}
1321
1322static int cam_vfe_bus_handle_comp_done_bottom_half(
1323 void *handler_priv,
1324 void *evt_payload_priv)
1325{
1326 int rc = CAM_VFE_IRQ_STATUS_ERR;
1327 struct cam_isp_resource_node *comp_grp = handler_priv;
1328 struct cam_vfe_bus_irq_evt_payload *evt_payload = evt_payload_priv;
1329 struct cam_vfe_bus_ver2_comp_grp_data *rsrc_data = comp_grp->res_priv;
Harsh Shah23557ae2017-05-13 18:14:34 -07001330 uint32_t *cam_ife_irq_regs;
1331 uint32_t status_reg;
1332 uint32_t comp_err_reg;
1333 uint32_t comp_grp_id;
1334
Harsh Shah19f55812017-06-26 18:58:49 -07001335 CDBG("comp grp type %d\n", rsrc_data->comp_grp_type);
1336
Harsh Shah23557ae2017-05-13 18:14:34 -07001337 if (!evt_payload)
1338 return rc;
1339
1340 cam_ife_irq_regs = evt_payload->irq_reg_val;
Harsh Shaha1af8822017-05-11 22:06:36 -07001341
Harsh Shaha1af8822017-05-11 22:06:36 -07001342 switch (rsrc_data->comp_grp_type) {
1343 case CAM_VFE_BUS_VER2_COMP_GRP_0:
1344 case CAM_VFE_BUS_VER2_COMP_GRP_1:
1345 case CAM_VFE_BUS_VER2_COMP_GRP_2:
1346 case CAM_VFE_BUS_VER2_COMP_GRP_3:
1347 case CAM_VFE_BUS_VER2_COMP_GRP_4:
1348 case CAM_VFE_BUS_VER2_COMP_GRP_5:
Harsh Shah23557ae2017-05-13 18:14:34 -07001349 comp_grp_id = (rsrc_data->comp_grp_type -
Harsh Shaha1af8822017-05-11 22:06:36 -07001350 CAM_VFE_BUS_VER2_COMP_GRP_0);
1351
1352 /* Check for Regular composite error */
1353 status_reg = cam_ife_irq_regs[CAM_IFE_IRQ_BUS_REG_STATUS0];
1354
1355 comp_err_reg = cam_ife_irq_regs[CAM_IFE_IRQ_BUS_REG_COMP_ERR];
1356 if ((status_reg & BIT(11)) &&
1357 (comp_err_reg & rsrc_data->composite_mask)) {
1358 /* Check for Regular composite error */
1359 rc = CAM_VFE_IRQ_STATUS_ERR_COMP;
1360 break;
1361 }
1362
1363 comp_err_reg = cam_ife_irq_regs[CAM_IFE_IRQ_BUS_REG_COMP_OWRT];
1364 /* Check for Regular composite Overwrite */
1365 if ((status_reg & BIT(12)) &&
1366 (comp_err_reg & rsrc_data->composite_mask)) {
1367 rc = CAM_VFE_IRQ_STATUS_COMP_OWRT;
1368 break;
1369 }
1370
Harsh Shah23557ae2017-05-13 18:14:34 -07001371 /* Regular Composite SUCCESS */
1372 if (status_reg & BIT(comp_grp_id + 5)) {
1373 cam_ife_irq_regs[CAM_IFE_IRQ_BUS_REG_STATUS0] &=
1374 ~BIT(comp_grp_id + 5);
Harsh Shaha1af8822017-05-11 22:06:36 -07001375 rc = CAM_VFE_IRQ_STATUS_SUCCESS;
Harsh Shah23557ae2017-05-13 18:14:34 -07001376 }
Harsh Shaha1af8822017-05-11 22:06:36 -07001377
Harsh Shah19f55812017-06-26 18:58:49 -07001378 CDBG("status reg = 0x%x, bit index = %d rc %d\n",
1379 status_reg, (comp_grp_id + 5), rc);
Harsh Shaha1af8822017-05-11 22:06:36 -07001380 break;
1381
1382 case CAM_VFE_BUS_VER2_COMP_GRP_DUAL_0:
1383 case CAM_VFE_BUS_VER2_COMP_GRP_DUAL_1:
1384 case CAM_VFE_BUS_VER2_COMP_GRP_DUAL_2:
1385 case CAM_VFE_BUS_VER2_COMP_GRP_DUAL_3:
1386 case CAM_VFE_BUS_VER2_COMP_GRP_DUAL_4:
1387 case CAM_VFE_BUS_VER2_COMP_GRP_DUAL_5:
Harsh Shah23557ae2017-05-13 18:14:34 -07001388 comp_grp_id = (rsrc_data->comp_grp_type -
Harsh Shaha1af8822017-05-11 22:06:36 -07001389 CAM_VFE_BUS_VER2_COMP_GRP_DUAL_0);
1390
1391 /* Check for DUAL composite error */
1392 status_reg = cam_ife_irq_regs[CAM_IFE_IRQ_BUS_REG_STATUS2];
1393
1394 comp_err_reg = cam_ife_irq_regs[CAM_IFE_IRQ_BUS_DUAL_COMP_ERR];
1395 if ((status_reg & BIT(6)) &&
1396 (comp_err_reg & rsrc_data->composite_mask)) {
1397 /* Check for DUAL composite error */
1398 rc = CAM_VFE_IRQ_STATUS_ERR_COMP;
1399 break;
1400 }
1401
1402 /* Check for Dual composite Overwrite */
1403 comp_err_reg = cam_ife_irq_regs[CAM_IFE_IRQ_BUS_DUAL_COMP_OWRT];
1404 if ((status_reg & BIT(7)) &&
1405 (comp_err_reg & rsrc_data->composite_mask)) {
1406 rc = CAM_VFE_IRQ_STATUS_COMP_OWRT;
1407 break;
1408 }
1409
Harsh Shah23557ae2017-05-13 18:14:34 -07001410 /* DUAL Composite SUCCESS */
1411 if (status_reg & BIT(comp_grp_id)) {
1412 cam_ife_irq_regs[CAM_IFE_IRQ_BUS_REG_STATUS2] &=
1413 ~BIT(comp_grp_id + 5);
Harsh Shaha1af8822017-05-11 22:06:36 -07001414 rc = CAM_VFE_IRQ_STATUS_SUCCESS;
Harsh Shah23557ae2017-05-13 18:14:34 -07001415 }
Harsh Shaha1af8822017-05-11 22:06:36 -07001416
1417 break;
Harsh Shaha1af8822017-05-11 22:06:36 -07001418 default:
1419 rc = CAM_VFE_IRQ_STATUS_ERR;
Harsh Shah19f55812017-06-26 18:58:49 -07001420 pr_err("Error! Invalid comp_grp_type %u\n",
1421 rsrc_data->comp_grp_type);
Harsh Shaha1af8822017-05-11 22:06:36 -07001422 break;
1423 }
1424
1425 if (rc == CAM_VFE_IRQ_STATUS_SUCCESS)
Harsh Shah19f55812017-06-26 18:58:49 -07001426 cam_vfe_bus_put_evt_payload(rsrc_data->common_data,
Harsh Shaha1af8822017-05-11 22:06:36 -07001427 &evt_payload);
1428
1429 return rc;
1430}
1431
1432static int cam_vfe_bus_init_comp_grp(uint32_t index,
1433 struct cam_vfe_bus_ver2_priv *ver2_bus_priv,
1434 struct cam_vfe_bus_ver2_hw_info *ver2_hw_info,
1435 struct cam_isp_resource_node *comp_grp)
1436{
Harsh Shah545df9a2017-06-16 16:43:17 -07001437 struct cam_vfe_bus_ver2_comp_grp_data *rsrc_data = NULL;
Harsh Shaha1af8822017-05-11 22:06:36 -07001438
1439 rsrc_data = kzalloc(sizeof(struct cam_vfe_bus_ver2_comp_grp_data),
1440 GFP_KERNEL);
1441 if (!rsrc_data) {
1442 CDBG("Failed to alloc for comp_grp_priv\n");
1443 return -ENOMEM;
1444 }
1445 comp_grp->res_priv = rsrc_data;
1446
1447 comp_grp->res_state = CAM_ISP_RESOURCE_STATE_AVAILABLE;
1448 INIT_LIST_HEAD(&comp_grp->list);
1449
1450 rsrc_data->comp_grp_type = index;
1451 rsrc_data->common_data = &ver2_bus_priv->common_data;
1452 rsrc_data->hw_regs = &ver2_hw_info->comp_grp_reg[index];
1453 rsrc_data->dual_slave_core = CAM_VFE_BUS_VER2_VFE_CORE_MAX;
1454
Harsh Shaha1af8822017-05-11 22:06:36 -07001455 if (rsrc_data->comp_grp_type >= CAM_VFE_BUS_VER2_COMP_GRP_DUAL_0 &&
1456 rsrc_data->comp_grp_type <= CAM_VFE_BUS_VER2_COMP_GRP_DUAL_5)
1457 list_add_tail(&comp_grp->list,
1458 &ver2_bus_priv->free_dual_comp_grp);
1459 else if (rsrc_data->comp_grp_type >= CAM_VFE_BUS_VER2_COMP_GRP_0
1460 && rsrc_data->comp_grp_type <= CAM_VFE_BUS_VER2_COMP_GRP_5)
1461 list_add_tail(&comp_grp->list, &ver2_bus_priv->free_comp_grp);
1462
1463 comp_grp->start = cam_vfe_bus_start_comp_grp;
1464 comp_grp->stop = cam_vfe_bus_stop_comp_grp;
1465 comp_grp->top_half_handler = cam_vfe_bus_handle_comp_done_top_half;
1466 comp_grp->bottom_half_handler =
1467 cam_vfe_bus_handle_comp_done_bottom_half;
1468 comp_grp->hw_intf = ver2_bus_priv->common_data.hw_intf;
1469
1470 return 0;
1471}
1472
Harsh Shah545df9a2017-06-16 16:43:17 -07001473static int cam_vfe_bus_deinit_comp_grp(
1474 struct cam_isp_resource_node *comp_grp)
1475{
1476 struct cam_vfe_bus_ver2_comp_grp_data *rsrc_data =
1477 comp_grp->res_priv;
1478
1479 comp_grp->start = NULL;
1480 comp_grp->stop = NULL;
1481 comp_grp->top_half_handler = NULL;
1482 comp_grp->bottom_half_handler = NULL;
1483 comp_grp->hw_intf = NULL;
1484
1485 list_del_init(&comp_grp->list);
1486 comp_grp->res_state = CAM_ISP_RESOURCE_STATE_UNAVAILABLE;
1487
1488 comp_grp->res_priv = NULL;
1489
1490 if (!rsrc_data) {
1491 pr_err("Error! comp_grp_priv is NULL\n");
1492 return -ENODEV;
1493 }
1494 kfree(rsrc_data);
1495
1496 return 0;
1497}
1498
Harsh Shah19f55812017-06-26 18:58:49 -07001499static int cam_vfe_bus_acquire_vfe_out(void *bus_priv, void *acquire_args,
1500 uint32_t args_size)
Harsh Shaha1af8822017-05-11 22:06:36 -07001501{
1502 int rc = -ENODEV;
1503 int i;
1504 enum cam_vfe_bus_ver2_vfe_out_type vfe_out_res_id;
1505 uint32_t format;
1506 uint32_t num_wm;
1507 uint32_t subscribe_irq;
1508 uint32_t client_done_mask;
1509 struct cam_vfe_bus_ver2_priv *ver2_bus_priv = bus_priv;
1510 struct cam_vfe_acquire_args *acq_args = acquire_args;
1511 struct cam_vfe_hw_vfe_out_acquire_args *out_acquire_args;
1512 struct cam_isp_resource_node *rsrc_node = NULL;
1513 struct cam_vfe_bus_ver2_vfe_out_data *rsrc_data = NULL;
1514
1515 if (!bus_priv || !acquire_args) {
1516 pr_err("Invalid Param");
1517 return -EINVAL;
1518 }
1519
1520 out_acquire_args = &acq_args->vfe_out;
1521 format = out_acquire_args->out_port_info->format;
1522
1523 CDBG("Acquiring resource type 0x%x\n",
1524 out_acquire_args->out_port_info->res_type);
1525
1526 vfe_out_res_id = cam_vfe_bus_get_out_res_id(
1527 out_acquire_args->out_port_info->res_type);
1528 if (vfe_out_res_id == CAM_VFE_BUS_VER2_VFE_OUT_MAX)
1529 return -ENODEV;
1530
1531 num_wm = cam_vfe_bus_get_num_wm(vfe_out_res_id, format);
1532 if (num_wm < 1)
1533 return -EINVAL;
1534
1535 rsrc_node = &ver2_bus_priv->vfe_out[vfe_out_res_id];
1536 if (rsrc_node->res_state != CAM_ISP_RESOURCE_STATE_AVAILABLE) {
1537 pr_err("Resource not available: Res_id %d state:%d\n",
1538 vfe_out_res_id, rsrc_node->res_state);
1539 return -EBUSY;
1540 }
1541
1542 rsrc_data = rsrc_node->res_priv;
1543 rsrc_data->num_wm = num_wm;
1544 rsrc_node->res_id = out_acquire_args->out_port_info->res_type;
1545 rsrc_node->tasklet_info = acq_args->tasklet;
1546 rsrc_node->cdm_ops = out_acquire_args->cdm_ops;
1547 rsrc_data->cdm_util_ops = out_acquire_args->cdm_ops;
1548
1549 /* Reserve Composite Group */
1550 if (num_wm > 1 || (out_acquire_args->out_port_info->comp_grp_id >
1551 CAM_ISP_RES_COMP_GROUP_NONE &&
1552 out_acquire_args->out_port_info->comp_grp_id <
1553 CAM_ISP_RES_COMP_GROUP_ID_MAX)) {
1554 rc = cam_vfe_bus_acquire_comp_grp(ver2_bus_priv,
1555 out_acquire_args->out_port_info,
Harsh Shah19f55812017-06-26 18:58:49 -07001556 acq_args->tasklet,
1557 out_acquire_args->ctx,
Harsh Shaha1af8822017-05-11 22:06:36 -07001558 out_acquire_args->unique_id,
1559 out_acquire_args->is_dual,
1560 out_acquire_args->is_master,
1561 out_acquire_args->dual_slave_core,
1562 &rsrc_data->comp_grp);
Harsh Shah19f55812017-06-26 18:58:49 -07001563 if (rc) {
1564 pr_err("VFE%d Comp_Grp acquire failed for Out %d rc=%d\n",
1565 rsrc_data->common_data->core_index,
1566 vfe_out_res_id, rc);
Harsh Shaha1af8822017-05-11 22:06:36 -07001567 return rc;
Harsh Shah19f55812017-06-26 18:58:49 -07001568 }
Harsh Shaha1af8822017-05-11 22:06:36 -07001569
1570 subscribe_irq = 0;
Harsh Shah19f55812017-06-26 18:58:49 -07001571 } else {
Harsh Shaha1af8822017-05-11 22:06:36 -07001572 subscribe_irq = 1;
Harsh Shah19f55812017-06-26 18:58:49 -07001573 }
Harsh Shaha1af8822017-05-11 22:06:36 -07001574
1575 /* Reserve WM */
1576 for (i = 0; i < num_wm; i++) {
1577 rc = cam_vfe_bus_acquire_wm(ver2_bus_priv,
1578 out_acquire_args->out_port_info,
Harsh Shah19f55812017-06-26 18:58:49 -07001579 acq_args->tasklet,
1580 out_acquire_args->ctx,
Harsh Shaha1af8822017-05-11 22:06:36 -07001581 vfe_out_res_id,
1582 i,
1583 out_acquire_args->split_id,
1584 subscribe_irq,
1585 &rsrc_data->wm_res[i],
1586 &client_done_mask);
Harsh Shah19f55812017-06-26 18:58:49 -07001587 if (rc) {
1588 pr_err("VFE%d WM acquire failed for Out %d rc=%d\n",
1589 rsrc_data->common_data->core_index,
1590 vfe_out_res_id, rc);
Harsh Shaha1af8822017-05-11 22:06:36 -07001591 goto release_wm;
Harsh Shah19f55812017-06-26 18:58:49 -07001592 }
Harsh Shaha1af8822017-05-11 22:06:36 -07001593
1594 if (rsrc_data->comp_grp)
1595 cam_vfe_bus_add_wm_to_comp_grp(rsrc_data->comp_grp,
1596 client_done_mask);
1597 }
1598
1599 rsrc_node->res_state = CAM_ISP_RESOURCE_STATE_RESERVED;
1600 out_acquire_args->rsrc_node = rsrc_node;
1601
1602 CDBG("Acquire successful\n");
1603 return rc;
1604
1605release_wm:
1606 for (i--; i >= 0; i--)
1607 cam_vfe_bus_release_wm(ver2_bus_priv, rsrc_data->wm_res[i]);
1608
1609 cam_vfe_bus_release_comp_grp(ver2_bus_priv,
1610 rsrc_data->comp_grp);
1611
1612 return rc;
1613}
1614
Harsh Shah19f55812017-06-26 18:58:49 -07001615static int cam_vfe_bus_release_vfe_out(void *bus_priv, void *release_args,
1616 uint32_t args_size)
Harsh Shaha1af8822017-05-11 22:06:36 -07001617{
Jing Zhoue71fd4a2017-05-15 19:44:34 -07001618 uint32_t i;
Harsh Shah19f55812017-06-26 18:58:49 -07001619 struct cam_isp_resource_node *vfe_out = NULL;
1620 struct cam_vfe_bus_ver2_vfe_out_data *rsrc_data = NULL;
1621
1622 if (!bus_priv || !release_args) {
1623 pr_err("Invalid input bus_priv %pK release_args %pK\n",
1624 bus_priv, release_args);
1625 return -EINVAL;
1626 }
1627
1628 vfe_out = release_args;
1629 rsrc_data = vfe_out->res_priv;
Jing Zhoue71fd4a2017-05-15 19:44:34 -07001630
Harsh Shaha1af8822017-05-11 22:06:36 -07001631 if (vfe_out->res_state != CAM_ISP_RESOURCE_STATE_RESERVED) {
1632 pr_err("Error! Invalid resource state:%d\n",
1633 vfe_out->res_state);
1634 }
1635
Jing Zhoue71fd4a2017-05-15 19:44:34 -07001636 for (i = 0; i < rsrc_data->num_wm; i++)
1637 cam_vfe_bus_release_wm(bus_priv, rsrc_data->wm_res[i]);
1638 rsrc_data->num_wm = 0;
1639
1640 if (rsrc_data->comp_grp)
1641 cam_vfe_bus_release_comp_grp(bus_priv, rsrc_data->comp_grp);
1642 rsrc_data->comp_grp = NULL;
1643
1644 vfe_out->tasklet_info = NULL;
1645 vfe_out->cdm_ops = NULL;
1646 rsrc_data->cdm_util_ops = NULL;
1647
Harsh Shaha1af8822017-05-11 22:06:36 -07001648 if (vfe_out->res_state == CAM_ISP_RESOURCE_STATE_RESERVED)
1649 vfe_out->res_state = CAM_ISP_RESOURCE_STATE_AVAILABLE;
1650
1651 return 0;
1652}
1653
Harsh Shah19f55812017-06-26 18:58:49 -07001654static int cam_vfe_bus_start_vfe_out(
1655 struct cam_isp_resource_node *vfe_out)
Harsh Shaha1af8822017-05-11 22:06:36 -07001656{
1657 int rc = 0, i;
Harsh Shah19f55812017-06-26 18:58:49 -07001658 struct cam_vfe_bus_ver2_vfe_out_data *rsrc_data = NULL;
1659 struct cam_vfe_bus_ver2_common_data *common_data = NULL;
1660
1661 if (!vfe_out) {
1662 pr_err("Invalid input\n");
1663 return -EINVAL;
1664 }
1665
1666 rsrc_data = vfe_out->res_priv;
1667 common_data = rsrc_data->common_data;
Harsh Shaha1af8822017-05-11 22:06:36 -07001668
1669 CDBG("Start resource index %d\n", rsrc_data->out_type);
1670
1671 if (vfe_out->res_state != CAM_ISP_RESOURCE_STATE_RESERVED) {
1672 pr_err("Error! Invalid resource state:%d\n",
1673 vfe_out->res_state);
1674 return -EACCES;
1675 }
1676
1677 for (i = 0; i < rsrc_data->num_wm; i++)
1678 rc = cam_vfe_bus_start_wm(rsrc_data->wm_res[i]);
1679
1680 if (rsrc_data->comp_grp)
1681 rc = cam_vfe_bus_start_comp_grp(rsrc_data->comp_grp);
1682
Harsh Shaha1af8822017-05-11 22:06:36 -07001683 /* BUS_WR_INPUT_IF_ADDR_SYNC_CFG */
1684 cam_io_w_mb(0x0, rsrc_data->common_data->mem_base + 0x0000207C);
1685 /* BUS_WR_INPUT_IF_ADDR_SYNC_FRAME_HEADER */
1686 cam_io_w_mb(0x0, rsrc_data->common_data->mem_base + 0x00002080);
1687 /* BUS_WR_INPUT_IF_ADDR_SYNC_NO_SYNC */
1688 cam_io_w_mb(0xFFFFF, rsrc_data->common_data->mem_base + 0x00002084);
Harsh Shaha1af8822017-05-11 22:06:36 -07001689 /* BUS_WR_INPUT_IF_ADDR_SYNC_0 */
1690 cam_io_w_mb(0x0, rsrc_data->common_data->mem_base + 0x00002088);
1691 cam_io_w_mb(0x0, rsrc_data->common_data->mem_base + 0x0000208c);
1692 cam_io_w_mb(0x0, rsrc_data->common_data->mem_base + 0x00002090);
1693 cam_io_w_mb(0x0, rsrc_data->common_data->mem_base + 0x00002094);
1694 cam_io_w_mb(0x0, rsrc_data->common_data->mem_base + 0x00002098);
1695 cam_io_w_mb(0x0, rsrc_data->common_data->mem_base + 0x0000209c);
1696 cam_io_w_mb(0x0, rsrc_data->common_data->mem_base + 0x000020a0);
1697 cam_io_w_mb(0x0, rsrc_data->common_data->mem_base + 0x000020a4);
1698
Harsh Shah23557ae2017-05-13 18:14:34 -07001699 /* no clock gating at bus input */
1700 cam_io_w_mb(0xFFFFF, rsrc_data->common_data->mem_base + 0x0000200C);
1701
1702 /* BUS_WR_TEST_BUS_CTRL */
1703 cam_io_w_mb(0x0, rsrc_data->common_data->mem_base + 0x0000211C);
1704
Abhishek Kondaveeti157ae882017-07-08 06:56:48 +05301705 vfe_out->res_state = CAM_ISP_RESOURCE_STATE_STREAMING;
Harsh Shaha1af8822017-05-11 22:06:36 -07001706 return rc;
1707}
1708
Harsh Shah19f55812017-06-26 18:58:49 -07001709static int cam_vfe_bus_stop_vfe_out(
1710 struct cam_isp_resource_node *vfe_out)
Harsh Shaha1af8822017-05-11 22:06:36 -07001711{
1712 int rc = 0, i;
Harsh Shah19f55812017-06-26 18:58:49 -07001713 struct cam_vfe_bus_ver2_vfe_out_data *rsrc_data = NULL;
1714
1715 if (!vfe_out) {
1716 pr_err("Invalid input\n");
1717 return -EINVAL;
1718 }
1719
1720 rsrc_data = vfe_out->res_priv;
Harsh Shaha1af8822017-05-11 22:06:36 -07001721
1722 if (vfe_out->res_state == CAM_ISP_RESOURCE_STATE_AVAILABLE ||
1723 vfe_out->res_state == CAM_ISP_RESOURCE_STATE_RESERVED) {
1724 return rc;
1725 }
1726
1727 if (rsrc_data->comp_grp)
1728 rc = cam_vfe_bus_stop_comp_grp(rsrc_data->comp_grp);
1729
1730 for (i = 0; i < rsrc_data->num_wm; i++)
1731 rc = cam_vfe_bus_stop_wm(rsrc_data->wm_res[i]);
1732
Harsh Shaha1af8822017-05-11 22:06:36 -07001733
1734 vfe_out->res_state = CAM_ISP_RESOURCE_STATE_RESERVED;
1735 return rc;
1736}
1737
1738static int cam_vfe_bus_handle_vfe_out_done_top_half(uint32_t evt_id,
1739 struct cam_irq_th_payload *th_payload)
1740{
1741 return -EPERM;
1742}
1743
1744static int cam_vfe_bus_handle_vfe_out_done_bottom_half(
1745 void *handler_priv,
1746 void *evt_payload_priv)
1747{
1748 int rc = -EINVAL;
1749 struct cam_isp_resource_node *vfe_out = handler_priv;
1750 struct cam_vfe_bus_ver2_vfe_out_data *rsrc_data = vfe_out->res_priv;
1751
1752 /*
1753 * If this resource has Composite Group then we only handle
1754 * Composite done. We acquire Composite if number of WM > 1.
1755 * So Else case is only one individual buf_done = WM[0].
1756 */
1757 if (rsrc_data->comp_grp) {
1758 rc = rsrc_data->comp_grp->bottom_half_handler(
1759 rsrc_data->comp_grp, evt_payload_priv);
1760 } else {
1761 rc = rsrc_data->wm_res[0]->bottom_half_handler(
Harsh Shah23557ae2017-05-13 18:14:34 -07001762 rsrc_data->wm_res[0], evt_payload_priv);
Harsh Shaha1af8822017-05-11 22:06:36 -07001763 }
1764
1765 return rc;
1766}
1767
1768static int cam_vfe_bus_init_vfe_out_resource(uint32_t index,
1769 struct cam_vfe_bus_ver2_priv *ver2_bus_priv,
1770 struct cam_vfe_bus_ver2_hw_info *ver2_hw_info,
1771 struct cam_isp_resource_node *vfe_out)
1772{
1773 struct cam_vfe_bus_ver2_vfe_out_data *rsrc_data = NULL;
1774 int rc = 0;
1775
1776 rsrc_data = kzalloc(sizeof(struct cam_vfe_bus_ver2_vfe_out_data),
1777 GFP_KERNEL);
1778 if (!rsrc_data) {
1779 CDBG("Error! Failed to alloc for vfe out priv\n");
1780 rc = -ENOMEM;
1781 return rc;
1782 }
1783 vfe_out->res_priv = rsrc_data;
1784
1785 vfe_out->res_type = CAM_ISP_RESOURCE_VFE_OUT;
1786 vfe_out->res_state = CAM_ISP_RESOURCE_STATE_AVAILABLE;
1787 INIT_LIST_HEAD(&vfe_out->list);
1788
1789 rsrc_data->out_type = index;
1790 rsrc_data->common_data = &ver2_bus_priv->common_data;
1791 rsrc_data->max_width =
1792 ver2_hw_info->vfe_out_hw_info[index].max_width;
1793 rsrc_data->max_height =
1794 ver2_hw_info->vfe_out_hw_info[index].max_height;
1795
1796 vfe_out->start = cam_vfe_bus_start_vfe_out;
1797 vfe_out->stop = cam_vfe_bus_stop_vfe_out;
1798 vfe_out->top_half_handler = cam_vfe_bus_handle_vfe_out_done_top_half;
1799 vfe_out->bottom_half_handler =
1800 cam_vfe_bus_handle_vfe_out_done_bottom_half;
1801 vfe_out->hw_intf = ver2_bus_priv->common_data.hw_intf;
1802
1803 return 0;
1804}
1805
Harsh Shah545df9a2017-06-16 16:43:17 -07001806static int cam_vfe_bus_deinit_vfe_out_resource(
1807 struct cam_isp_resource_node *vfe_out)
1808{
1809 struct cam_vfe_bus_ver2_vfe_out_data *rsrc_data = vfe_out->res_priv;
1810
1811 vfe_out->start = NULL;
1812 vfe_out->stop = NULL;
1813 vfe_out->top_half_handler = NULL;
1814 vfe_out->bottom_half_handler = NULL;
1815 vfe_out->hw_intf = NULL;
1816
1817 vfe_out->res_state = CAM_ISP_RESOURCE_STATE_UNAVAILABLE;
1818 INIT_LIST_HEAD(&vfe_out->list);
1819 vfe_out->res_priv = NULL;
1820
1821 if (!rsrc_data) {
1822 pr_err("Error! vfe out priv is NULL\n");
1823 return -ENOMEM;
1824 }
1825 kfree(rsrc_data);
1826
1827 return 0;
1828}
1829
Harsh Shaha1af8822017-05-11 22:06:36 -07001830static int cam_vfe_bus_ver2_handle_irq(uint32_t evt_id,
1831 struct cam_irq_th_payload *th_payload)
1832{
Harsh Shaha1af8822017-05-11 22:06:36 -07001833 struct cam_vfe_bus_ver2_priv *bus_priv;
Harsh Shaha1af8822017-05-11 22:06:36 -07001834
Harsh Shah19f55812017-06-26 18:58:49 -07001835 bus_priv = th_payload->handler_priv;
Harsh Shaha1af8822017-05-11 22:06:36 -07001836 CDBG("Enter\n");
Harsh Shah19f55812017-06-26 18:58:49 -07001837 return cam_irq_controller_handle_irq(evt_id,
1838 bus_priv->common_data.bus_irq_controller);
Harsh Shaha1af8822017-05-11 22:06:36 -07001839}
1840
1841static int cam_vfe_bus_update_buf(void *priv, void *cmd_args,
1842 uint32_t arg_size)
1843{
1844 struct cam_vfe_bus_ver2_priv *bus_priv;
1845 struct cam_isp_hw_get_buf_update *update_buf;
Jing Zhoua4e9fbe2017-05-15 14:37:21 -07001846 struct cam_buf_io_cfg *io_cfg;
Harsh Shaha1af8822017-05-11 22:06:36 -07001847 struct cam_vfe_bus_ver2_vfe_out_data *vfe_out_data = NULL;
1848 struct cam_vfe_bus_ver2_wm_resource_data *wm_data = NULL;
Jing Zhoua4e9fbe2017-05-15 14:37:21 -07001849 uint32_t *reg_val_pair;
1850 uint32_t i, j, size = 0;
Junzhe Zou193d78c2017-05-16 15:10:54 -07001851 uint32_t frame_inc = 0;
Harsh Shaha1af8822017-05-11 22:06:36 -07001852
1853 /*
1854 * Need the entire buf io config so we can get the stride info
1855 * for the wm.
1856 */
1857
1858 bus_priv = (struct cam_vfe_bus_ver2_priv *) priv;
1859 update_buf = (struct cam_isp_hw_get_buf_update *) cmd_args;
1860
1861 vfe_out_data = (struct cam_vfe_bus_ver2_vfe_out_data *)
1862 update_buf->cdm.res->res_priv;
1863
1864 if (!vfe_out_data || !vfe_out_data->cdm_util_ops) {
1865 pr_err("Failed! Invalid data\n");
1866 return -EINVAL;
1867 }
1868
Jing Zhoua4e9fbe2017-05-15 14:37:21 -07001869 if (update_buf->num_buf != vfe_out_data->num_wm) {
Harsh Shaha1af8822017-05-11 22:06:36 -07001870 pr_err("Failed! Invalid number buffers:%d required:%d\n",
1871 update_buf->num_buf, vfe_out_data->num_wm);
Junzhe Zou193d78c2017-05-16 15:10:54 -07001872 return -EINVAL;
Harsh Shaha1af8822017-05-11 22:06:36 -07001873 }
1874
Jing Zhoua4e9fbe2017-05-15 14:37:21 -07001875 reg_val_pair = &vfe_out_data->common_data->io_buf_update[0];
1876 io_cfg = update_buf->io_cfg;
1877
1878 for (i = 0, j = 0; i < vfe_out_data->num_wm; i++) {
Junzhe Zou193d78c2017-05-16 15:10:54 -07001879 if (j >= (MAX_REG_VAL_PAIR_SIZE - MAX_BUF_UPDATE_REG_NUM * 2)) {
1880 pr_err("reg_val_pair %d exceeds the array limit %lu\n",
1881 j, MAX_REG_VAL_PAIR_SIZE);
1882 return -ENOMEM;
1883 }
1884
Jing Zhoua4e9fbe2017-05-15 14:37:21 -07001885 wm_data = vfe_out_data->wm_res[i]->res_priv;
1886
1887 /* For initial configuration program all bus registers */
1888 if (wm_data->stride != io_cfg->planes[i].plane_stride ||
1889 !wm_data->init_cfg_done) {
1890 CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j,
1891 wm_data->hw_regs->stride,
1892 io_cfg->planes[i].plane_stride);
1893 wm_data->stride = io_cfg->planes[i].plane_stride;
1894 }
1895 CDBG("image stride 0x%x\n", wm_data->stride);
1896
1897 if (wm_data->framedrop_pattern != io_cfg->framedrop_pattern ||
1898 !wm_data->init_cfg_done) {
1899 CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j,
1900 wm_data->hw_regs->framedrop_pattern,
1901 io_cfg->framedrop_pattern);
1902 wm_data->framedrop_pattern = io_cfg->framedrop_pattern;
1903 }
1904 CDBG("framedrop pattern 0x%x\n", wm_data->framedrop_pattern);
1905
1906 if (wm_data->framedrop_period != io_cfg->framedrop_period ||
1907 !wm_data->init_cfg_done) {
1908 CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j,
1909 wm_data->hw_regs->framedrop_period,
1910 io_cfg->framedrop_period);
1911 wm_data->framedrop_period = io_cfg->framedrop_period;
1912 }
1913 CDBG("framedrop period 0x%x\n", wm_data->framedrop_period);
1914
1915 if (wm_data->irq_subsample_period != io_cfg->subsample_period
1916 || !wm_data->init_cfg_done) {
1917 CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j,
1918 wm_data->hw_regs->irq_subsample_period,
1919 io_cfg->subsample_period);
1920 wm_data->irq_subsample_period =
1921 io_cfg->subsample_period;
1922 }
1923 CDBG("irq subsample period 0x%x\n",
1924 wm_data->irq_subsample_period);
1925
1926 if (wm_data->irq_subsample_pattern != io_cfg->subsample_pattern
1927 || !wm_data->init_cfg_done) {
1928 CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j,
1929 wm_data->hw_regs->irq_subsample_pattern,
1930 io_cfg->subsample_pattern);
1931 wm_data->irq_subsample_pattern =
1932 io_cfg->subsample_pattern;
1933 }
1934 CDBG("irq subsample pattern 0x%x\n",
1935 wm_data->irq_subsample_pattern);
1936
1937 if (wm_data->en_ubwc) {
1938 if (!wm_data->hw_regs->ubwc_regs) {
1939 pr_err("%s: No UBWC register to configure.\n",
1940 __func__);
1941 return -EINVAL;
1942 }
1943 if (wm_data->packer_cfg !=
1944 io_cfg->planes[i].packer_config ||
1945 !wm_data->init_cfg_done) {
1946 CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j,
1947 wm_data->hw_regs->packer_cfg,
1948 io_cfg->planes[i].packer_config);
1949 wm_data->packer_cfg =
1950 io_cfg->planes[i].packer_config;
1951 }
1952 CDBG("packer cfg 0x%x\n", wm_data->packer_cfg);
1953
1954 if (wm_data->tile_cfg != io_cfg->planes[i].tile_config
1955 || !wm_data->init_cfg_done) {
1956 CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j,
1957 wm_data->hw_regs->ubwc_regs->tile_cfg,
1958 io_cfg->planes[i].tile_config);
1959 wm_data->tile_cfg =
1960 io_cfg->planes[i].tile_config;
1961 }
1962 CDBG("tile cfg 0x%x\n", wm_data->tile_cfg);
1963
1964 if (wm_data->h_init != io_cfg->planes[i].h_init ||
1965 !wm_data->init_cfg_done) {
1966 CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j,
1967 wm_data->hw_regs->ubwc_regs->h_init,
1968 io_cfg->planes[i].h_init);
1969 wm_data->h_init = io_cfg->planes[i].h_init;
1970 }
1971 CDBG("h_init 0x%x\n", wm_data->h_init);
1972
1973 if (wm_data->v_init != io_cfg->planes[i].v_init ||
1974 !wm_data->init_cfg_done) {
1975 CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j,
1976 wm_data->hw_regs->ubwc_regs->v_init,
1977 io_cfg->planes[i].v_init);
1978 wm_data->v_init = io_cfg->planes[i].v_init;
1979 }
1980 CDBG("v_init 0x%x\n", wm_data->v_init);
1981
1982 if (wm_data->ubwc_meta_stride !=
1983 io_cfg->planes[i].meta_stride ||
1984 !wm_data->init_cfg_done) {
1985 CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j,
1986 wm_data->hw_regs->ubwc_regs->
1987 meta_stride,
1988 io_cfg->planes[i].meta_stride);
1989 wm_data->ubwc_meta_stride =
1990 io_cfg->planes[i].meta_stride;
1991 }
1992 CDBG("meta stride 0x%x\n", wm_data->ubwc_meta_stride);
1993
1994 if (wm_data->ubwc_mode_cfg !=
1995 io_cfg->planes[i].mode_config ||
1996 !wm_data->init_cfg_done) {
1997 CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j,
1998 wm_data->hw_regs->ubwc_regs->mode_cfg,
1999 io_cfg->planes[i].mode_config);
2000 wm_data->ubwc_mode_cfg =
2001 io_cfg->planes[i].mode_config;
2002 }
2003 CDBG("ubwc mode cfg 0x%x\n", wm_data->ubwc_mode_cfg);
2004
2005 if (wm_data->ubwc_meta_offset !=
2006 io_cfg->planes[i].meta_offset ||
2007 !wm_data->init_cfg_done) {
2008 CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j,
2009 wm_data->hw_regs->ubwc_regs->
2010 meta_offset,
2011 io_cfg->planes[i].meta_offset);
2012 wm_data->ubwc_meta_offset =
2013 io_cfg->planes[i].meta_offset;
2014 }
2015 CDBG("ubwc meta offset 0x%x\n",
2016 wm_data->ubwc_meta_offset);
2017
2018 /* UBWC meta address */
2019 CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j,
2020 wm_data->hw_regs->ubwc_regs->meta_addr,
2021 update_buf->image_buf[i]);
2022 CDBG("ubwc meta addr 0x%llx\n",
2023 update_buf->image_buf[i]);
2024 }
2025
2026 /* WM Image address */
2027 if (wm_data->en_ubwc)
2028 CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j,
2029 wm_data->hw_regs->image_addr,
2030 (update_buf->image_buf[i] +
2031 io_cfg->planes[i].meta_size));
2032 else
2033 CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j,
2034 wm_data->hw_regs->image_addr,
2035 update_buf->image_buf[i]);
2036
2037 CDBG("image address 0x%x\n", reg_val_pair[j-1]);
2038
Junzhe Zou193d78c2017-05-16 15:10:54 -07002039 frame_inc = io_cfg->planes[i].plane_stride *
2040 io_cfg->planes[i].slice_height;
2041 CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j,
2042 wm_data->hw_regs->frame_inc, frame_inc);
2043
Jing Zhoua4e9fbe2017-05-15 14:37:21 -07002044 /* enable the WM */
2045 CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j,
2046 wm_data->hw_regs->cfg,
2047 wm_data->en_cfg);
2048
2049 /* set initial configuration done */
2050 if (!wm_data->init_cfg_done)
2051 wm_data->init_cfg_done = 1;
2052 }
2053
2054 size = vfe_out_data->cdm_util_ops->cdm_required_size_reg_random(j/2);
Harsh Shaha1af8822017-05-11 22:06:36 -07002055
2056 /* cdm util returns dwords, need to convert to bytes */
2057 if ((size * 4) > update_buf->cdm.size) {
2058 pr_err("Failed! Buf size:%d insufficient, expected size:%d\n",
2059 update_buf->cdm.size, size);
2060 return -ENOMEM;
2061 }
2062
Harsh Shaha1af8822017-05-11 22:06:36 -07002063 vfe_out_data->cdm_util_ops->cdm_write_regrandom(
Jing Zhoua4e9fbe2017-05-15 14:37:21 -07002064 update_buf->cdm.cmd_buf_addr, j/2, reg_val_pair);
2065
Harsh Shaha1af8822017-05-11 22:06:36 -07002066 /* cdm util returns dwords, need to convert to bytes */
2067 update_buf->cdm.used_bytes = size * 4;
2068
2069 return 0;
2070}
2071
Harsh Shah19f55812017-06-26 18:58:49 -07002072static int cam_vfe_bus_start_hw(void *hw_priv,
2073 void *start_hw_args, uint32_t arg_size)
2074{
2075 return cam_vfe_bus_start_vfe_out(hw_priv);
2076}
2077
2078static int cam_vfe_bus_stop_hw(void *hw_priv,
2079 void *stop_hw_args, uint32_t arg_size)
2080{
2081 return cam_vfe_bus_stop_vfe_out(hw_priv);
2082}
2083
2084static int cam_vfe_bus_init_hw(void *hw_priv,
2085 void *init_hw_args, uint32_t arg_size)
2086{
2087 struct cam_vfe_bus_ver2_priv *bus_priv = hw_priv;
2088 uint32_t top_irq_reg_mask[2] = {0};
2089
2090 if (!bus_priv) {
2091 pr_err("Error! Invalid args\n");
2092 return -EINVAL;
2093 }
2094
2095 top_irq_reg_mask[0] = (1 << 9);
2096
2097 bus_priv->irq_handle = cam_irq_controller_subscribe_irq(
2098 bus_priv->common_data.vfe_irq_controller,
2099 CAM_IRQ_PRIORITY_2,
2100 top_irq_reg_mask,
2101 bus_priv,
2102 cam_vfe_bus_ver2_handle_irq,
2103 NULL,
2104 NULL,
2105 NULL);
2106
2107 if (bus_priv->irq_handle <= 0) {
2108 pr_err("Failed to subscribe BUS IRQ\n");
2109 return -EFAULT;
2110 }
2111
2112 return 0;
2113}
2114
2115static int cam_vfe_bus_deinit_hw(void *hw_priv,
2116 void *deinit_hw_args, uint32_t arg_size)
2117{
2118 struct cam_vfe_bus_ver2_priv *bus_priv = hw_priv;
2119 int rc;
2120
2121 if (!bus_priv || (bus_priv->irq_handle <= 0)) {
2122 pr_err("Error! Invalid args\n");
2123 return -EINVAL;
2124 }
2125
2126 rc = cam_irq_controller_unsubscribe_irq(
2127 bus_priv->common_data.vfe_irq_controller,
2128 bus_priv->irq_handle);
2129 if (rc)
2130 pr_err("Failed to unsubscribe irq rc=%d\n", rc);
2131
2132 return rc;
2133}
2134
Harsh Shaha1af8822017-05-11 22:06:36 -07002135static int cam_vfe_bus_process_cmd(void *priv,
2136 uint32_t cmd_type, void *cmd_args, uint32_t arg_size)
2137{
2138 int rc = -EINVAL;
2139
2140 if (!priv || !cmd_args) {
2141 pr_err_ratelimited("Error! Invalid input arguments\n");
2142 return -EINVAL;
2143 }
2144
2145 switch (cmd_type) {
2146 case CAM_VFE_HW_CMD_GET_BUF_UPDATE:
2147 rc = cam_vfe_bus_update_buf(priv, cmd_args, arg_size);
2148 break;
2149 default:
2150 pr_err_ratelimited("Error! Invalid camif process command:%d\n",
2151 cmd_type);
2152 break;
2153 }
2154
2155 return rc;
2156}
2157
2158int cam_vfe_bus_ver2_init(
Harsh Shah19f55812017-06-26 18:58:49 -07002159 struct cam_hw_soc_info *soc_info,
Harsh Shaha1af8822017-05-11 22:06:36 -07002160 struct cam_hw_intf *hw_intf,
2161 void *bus_hw_info,
2162 void *vfe_irq_controller,
2163 struct cam_vfe_bus **vfe_bus)
2164{
2165 int i, rc = 0;
2166 struct cam_vfe_bus_ver2_priv *bus_priv = NULL;
2167 struct cam_vfe_bus *vfe_bus_local;
2168 struct cam_vfe_bus_ver2_hw_info *ver2_hw_info = bus_hw_info;
2169
2170 CDBG("Enter\n");
2171
Harsh Shah19f55812017-06-26 18:58:49 -07002172 if (!soc_info || !hw_intf || !bus_hw_info || !vfe_irq_controller) {
2173 pr_err("Error! Invalid params soc_info %pK hw_intf %pK hw_info %pK controller %pK\n",
2174 soc_info, hw_intf, bus_hw_info, vfe_irq_controller);
2175 rc = -EINVAL;
2176 goto end;
2177 }
2178
Harsh Shaha1af8822017-05-11 22:06:36 -07002179 vfe_bus_local = kzalloc(sizeof(struct cam_vfe_bus), GFP_KERNEL);
2180 if (!vfe_bus_local) {
2181 CDBG("Failed to alloc for vfe_bus\n");
2182 rc = -ENOMEM;
Harsh Shah545df9a2017-06-16 16:43:17 -07002183 goto end;
Harsh Shaha1af8822017-05-11 22:06:36 -07002184 }
2185
2186 bus_priv = kzalloc(sizeof(struct cam_vfe_bus_ver2_priv),
2187 GFP_KERNEL);
2188 if (!bus_priv) {
2189 CDBG("Failed to alloc for vfe_bus_priv\n");
2190 rc = -ENOMEM;
Harsh Shah545df9a2017-06-16 16:43:17 -07002191 goto free_bus_local;
Harsh Shaha1af8822017-05-11 22:06:36 -07002192 }
2193 vfe_bus_local->bus_priv = bus_priv;
2194
Harsh Shah19f55812017-06-26 18:58:49 -07002195 bus_priv->common_data.core_index = soc_info->index;
2196 bus_priv->common_data.mem_base =
2197 CAM_SOC_GET_REG_MAP_START(soc_info, VFE_CORE_BASE_IDX);
Harsh Shaha1af8822017-05-11 22:06:36 -07002198 bus_priv->common_data.hw_intf = hw_intf;
2199 bus_priv->common_data.vfe_irq_controller = vfe_irq_controller;
2200 bus_priv->common_data.common_reg = &ver2_hw_info->common_reg;
2201
Harsh Shah19f55812017-06-26 18:58:49 -07002202 rc = cam_irq_controller_init(drv_name, bus_priv->common_data.mem_base,
2203 &ver2_hw_info->common_reg.irq_reg_info,
2204 &bus_priv->common_data.bus_irq_controller);
2205 if (rc) {
2206 pr_err("Error! cam_irq_controller_init failed\n");
2207 goto free_bus_priv;
2208 }
2209
Harsh Shaha1af8822017-05-11 22:06:36 -07002210 INIT_LIST_HEAD(&bus_priv->free_comp_grp);
2211 INIT_LIST_HEAD(&bus_priv->free_dual_comp_grp);
2212 INIT_LIST_HEAD(&bus_priv->used_comp_grp);
2213
2214 for (i = 0; i < CAM_VFE_BUS_VER2_MAX_CLIENTS; i++) {
2215 rc = cam_vfe_bus_init_wm_resource(i, bus_priv, bus_hw_info,
2216 &bus_priv->bus_client[i]);
2217 if (rc < 0) {
Harsh Shah545df9a2017-06-16 16:43:17 -07002218 pr_err("Error! Init WM failed rc=%d\n", rc);
2219 goto deinit_wm;
Harsh Shaha1af8822017-05-11 22:06:36 -07002220 }
2221 }
2222
2223 for (i = 0; i < CAM_VFE_BUS_VER2_COMP_GRP_MAX; i++) {
2224 rc = cam_vfe_bus_init_comp_grp(i, bus_priv, bus_hw_info,
2225 &bus_priv->comp_grp[i]);
2226 if (rc < 0) {
Harsh Shah545df9a2017-06-16 16:43:17 -07002227 pr_err("Error! Init Comp Grp failed rc=%d\n", rc);
2228 goto deinit_comp_grp;
Harsh Shaha1af8822017-05-11 22:06:36 -07002229 }
2230 }
2231
2232 for (i = 0; i < CAM_VFE_BUS_VER2_VFE_OUT_MAX; i++) {
2233 rc = cam_vfe_bus_init_vfe_out_resource(i, bus_priv, bus_hw_info,
2234 &bus_priv->vfe_out[i]);
2235 if (rc < 0) {
Harsh Shah545df9a2017-06-16 16:43:17 -07002236 pr_err("Error! Init VFE Out failed rc=%d\n", rc);
2237 goto deinit_vfe_out;
Harsh Shaha1af8822017-05-11 22:06:36 -07002238 }
2239 }
2240
Harsh Shah19f55812017-06-26 18:58:49 -07002241 INIT_LIST_HEAD(&bus_priv->common_data.free_payload_list);
2242 for (i = 0; i < CAM_VFE_BUS_VER2_PAYLOAD_MAX; i++) {
2243 INIT_LIST_HEAD(&bus_priv->common_data.evt_payload[i].list);
2244 list_add_tail(&bus_priv->common_data.evt_payload[i].list,
2245 &bus_priv->common_data.free_payload_list);
Harsh Shaha1af8822017-05-11 22:06:36 -07002246 }
2247
Harsh Shah19f55812017-06-26 18:58:49 -07002248 vfe_bus_local->hw_ops.reserve = cam_vfe_bus_acquire_vfe_out;
2249 vfe_bus_local->hw_ops.release = cam_vfe_bus_release_vfe_out;
2250 vfe_bus_local->hw_ops.start = cam_vfe_bus_start_hw;
2251 vfe_bus_local->hw_ops.stop = cam_vfe_bus_stop_hw;
2252 vfe_bus_local->hw_ops.init = cam_vfe_bus_init_hw;
2253 vfe_bus_local->hw_ops.deinit = cam_vfe_bus_deinit_hw;
2254 vfe_bus_local->top_half_handler = cam_vfe_bus_ver2_handle_irq;
Harsh Shaha1af8822017-05-11 22:06:36 -07002255 vfe_bus_local->bottom_half_handler = NULL;
Harsh Shah19f55812017-06-26 18:58:49 -07002256 vfe_bus_local->hw_ops.process_cmd = cam_vfe_bus_process_cmd;
Harsh Shaha1af8822017-05-11 22:06:36 -07002257
2258 *vfe_bus = vfe_bus_local;
2259
Harsh Shah545df9a2017-06-16 16:43:17 -07002260 CDBG("Exit\n");
Harsh Shaha1af8822017-05-11 22:06:36 -07002261 return rc;
2262
Harsh Shah545df9a2017-06-16 16:43:17 -07002263deinit_vfe_out:
2264 if (i < 0)
2265 i = CAM_VFE_BUS_VER2_VFE_OUT_MAX;
2266 for (--i; i >= 0; i--)
2267 cam_vfe_bus_deinit_vfe_out_resource(&bus_priv->vfe_out[i]);
2268
2269deinit_comp_grp:
2270 if (i < 0)
2271 i = CAM_VFE_BUS_VER2_COMP_GRP_MAX;
2272 for (--i; i >= 0; i--)
2273 cam_vfe_bus_deinit_comp_grp(&bus_priv->comp_grp[i]);
2274
2275deinit_wm:
2276 if (i < 0)
2277 i = CAM_VFE_BUS_VER2_MAX_CLIENTS;
2278 for (--i; i >= 0; i--)
2279 cam_vfe_bus_deinit_wm_resource(&bus_priv->bus_client[i]);
2280
Harsh Shah19f55812017-06-26 18:58:49 -07002281free_bus_priv:
Harsh Shaha1af8822017-05-11 22:06:36 -07002282 kfree(vfe_bus_local->bus_priv);
Harsh Shah545df9a2017-06-16 16:43:17 -07002283
2284free_bus_local:
Harsh Shaha1af8822017-05-11 22:06:36 -07002285 kfree(vfe_bus_local);
Harsh Shah545df9a2017-06-16 16:43:17 -07002286
2287end:
Harsh Shaha1af8822017-05-11 22:06:36 -07002288 return rc;
2289}
Harsh Shah545df9a2017-06-16 16:43:17 -07002290
2291int cam_vfe_bus_ver2_deinit(
2292 struct cam_vfe_bus **vfe_bus)
2293{
2294 int i, rc = 0;
2295 struct cam_vfe_bus_ver2_priv *bus_priv = NULL;
2296 struct cam_vfe_bus *vfe_bus_local;
2297
2298 if (!vfe_bus || !*vfe_bus) {
2299 pr_err("Error! Invalid input\n");
2300 return -EINVAL;
2301 }
2302 vfe_bus_local = *vfe_bus;
2303
2304 bus_priv = vfe_bus_local->bus_priv;
2305 if (!bus_priv) {
2306 pr_err("Error! bus_priv is NULL\n");
2307 rc = -ENODEV;
2308 goto free_bus_local;
2309 }
2310
Harsh Shah19f55812017-06-26 18:58:49 -07002311 INIT_LIST_HEAD(&bus_priv->common_data.free_payload_list);
2312 for (i = 0; i < CAM_VFE_BUS_VER2_PAYLOAD_MAX; i++)
2313 INIT_LIST_HEAD(&bus_priv->common_data.evt_payload[i].list);
Harsh Shah545df9a2017-06-16 16:43:17 -07002314
2315 for (i = 0; i < CAM_VFE_BUS_VER2_MAX_CLIENTS; i++) {
2316 rc = cam_vfe_bus_deinit_wm_resource(&bus_priv->bus_client[i]);
2317 if (rc < 0)
2318 pr_err("Error! Deinit WM failed rc=%d\n", rc);
2319 }
2320
2321 for (i = 0; i < CAM_VFE_BUS_VER2_COMP_GRP_MAX; i++) {
2322 rc = cam_vfe_bus_deinit_comp_grp(&bus_priv->comp_grp[i]);
2323 if (rc < 0)
2324 pr_err("Error! Deinit Comp Grp failed rc=%d\n", rc);
2325 }
2326
2327 for (i = 0; i < CAM_VFE_BUS_VER2_VFE_OUT_MAX; i++) {
2328 rc = cam_vfe_bus_deinit_vfe_out_resource(&bus_priv->vfe_out[i]);
2329 if (rc < 0)
2330 pr_err("Error! Deinit VFE Out failed rc=%d\n", rc);
2331 }
2332
2333 INIT_LIST_HEAD(&bus_priv->free_comp_grp);
2334 INIT_LIST_HEAD(&bus_priv->free_dual_comp_grp);
2335 INIT_LIST_HEAD(&bus_priv->used_comp_grp);
2336
Harsh Shah19f55812017-06-26 18:58:49 -07002337 rc = cam_irq_controller_deinit(
2338 &bus_priv->common_data.bus_irq_controller);
2339 if (rc)
2340 pr_err("Error! Deinit IRQ Controller failed rc=%d\n", rc);
2341
Harsh Shah545df9a2017-06-16 16:43:17 -07002342 kfree(vfe_bus_local->bus_priv);
2343
2344free_bus_local:
2345 kfree(vfe_bus_local);
2346
2347 *vfe_bus = NULL;
2348
2349 return rc;
2350}
2351