blob: 489689cac2cfa75c3e74a1faaf88fa3b142cccfa [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
848 /* Enable WM */
849 cam_io_w_mb(rsrc_data->en_cfg, common_data->mem_base +
850 rsrc_data->hw_regs->cfg);
851
Harsh Shah23557ae2017-05-13 18:14:34 -0700852 CDBG("WM res %d width = %d, height = %d\n", rsrc_data->index,
Jing Zhoua4e9fbe2017-05-15 14:37:21 -0700853 rsrc_data->width, rsrc_data->height);
Harsh Shah23557ae2017-05-13 18:14:34 -0700854 CDBG("WM res %d pk_fmt = %d\n", rsrc_data->index,
Jing Zhoua4e9fbe2017-05-15 14:37:21 -0700855 rsrc_data->pack_fmt & PACKER_FMT_MAX);
Harsh Shah23557ae2017-05-13 18:14:34 -0700856 CDBG("WM res %d stride = %d, burst len = %d\n",
Jing Zhoua4e9fbe2017-05-15 14:37:21 -0700857 rsrc_data->index, rsrc_data->stride, 0xf);
Harsh Shah23557ae2017-05-13 18:14:34 -0700858 CDBG("enable WM res %d offset 0x%x val 0x%x\n", rsrc_data->index,
Jing Zhoua4e9fbe2017-05-15 14:37:21 -0700859 (uint32_t) rsrc_data->hw_regs->cfg, rsrc_data->en_cfg);
Harsh Shaha1af8822017-05-11 22:06:36 -0700860
861 wm_res->res_state = CAM_ISP_RESOURCE_STATE_STREAMING;
862
863 return rc;
864}
865
866static int cam_vfe_bus_stop_wm(struct cam_isp_resource_node *wm_res)
867{
868 int rc = 0;
869 struct cam_vfe_bus_ver2_wm_resource_data *rsrc_data =
870 wm_res->res_priv;
871 struct cam_vfe_bus_ver2_common_data *common_data =
872 rsrc_data->common_data;
873
874 /* Disble WM */
875 cam_io_w_mb(0x0,
876 common_data->mem_base + rsrc_data->hw_regs->cfg);
877
878 CDBG("irq_enabled %d", rsrc_data->irq_enabled);
879 /* Unsubscribe IRQ */
Harsh Shah19f55812017-06-26 18:58:49 -0700880 if (rsrc_data->irq_enabled)
881 rc = cam_irq_controller_unsubscribe_irq(
882 common_data->bus_irq_controller,
883 wm_res->irq_handle);
Harsh Shaha1af8822017-05-11 22:06:36 -0700884
885 /* Halt & Reset WM */
886 cam_io_w_mb(BIT(rsrc_data->index),
887 common_data->mem_base + common_data->common_reg->sw_reset);
888
889 wm_res->res_state = CAM_ISP_RESOURCE_STATE_RESERVED;
890
891 return rc;
892}
893
894static int cam_vfe_bus_handle_wm_done_top_half(uint32_t evt_id,
895 struct cam_irq_th_payload *th_payload)
896{
Harsh Shah19f55812017-06-26 18:58:49 -0700897 int32_t rc;
898 int i;
899 struct cam_isp_resource_node *wm_res = NULL;
900 struct cam_vfe_bus_ver2_wm_resource_data *rsrc_data = NULL;
901 struct cam_vfe_bus_irq_evt_payload *evt_payload;
902
903 wm_res = th_payload->handler_priv;
904 if (!wm_res) {
905 pr_err_ratelimited("Error! No resource\n");
906 return -ENODEV;
907 }
908
909 rsrc_data = wm_res->res_priv;
910
911 CDBG("IRQ status_0 = %x\n", th_payload->evt_status_arr[0]);
912 CDBG("IRQ status_1 = %x\n", th_payload->evt_status_arr[1]);
913
914 rc = cam_vfe_bus_get_evt_payload(rsrc_data->common_data, &evt_payload);
915 if (rc) {
916 pr_err_ratelimited("No tasklet_cmd is free in queue\n");
917 return rc;
918 }
919
920 cam_isp_hw_get_timestamp(&evt_payload->ts);
921
922 evt_payload->ctx = rsrc_data->ctx;
923 evt_payload->core_index = rsrc_data->common_data->core_index;
924 evt_payload->evt_id = evt_id;
925
926 for (i = 0; i < th_payload->num_registers; i++)
927 evt_payload->irq_reg_val[i] = th_payload->evt_status_arr[i];
928
929 th_payload->evt_payload_priv = evt_payload;
930
931 CDBG("Exit\n");
932 return rc;
Harsh Shaha1af8822017-05-11 22:06:36 -0700933}
934
935static int cam_vfe_bus_handle_wm_done_bottom_half(void *wm_node,
936 void *evt_payload_priv)
937{
938 int rc = CAM_VFE_IRQ_STATUS_ERR;
939 struct cam_isp_resource_node *wm_res = wm_node;
940 struct cam_vfe_bus_irq_evt_payload *evt_payload = evt_payload_priv;
Harsh Shah23557ae2017-05-13 18:14:34 -0700941 struct cam_vfe_bus_ver2_wm_resource_data *rsrc_data =
942 (wm_res == NULL) ? NULL : wm_res->res_priv;
943 uint32_t *cam_ife_irq_regs;
Harsh Shaha1af8822017-05-11 22:06:36 -0700944 uint32_t status_reg;
945
Harsh Shah23557ae2017-05-13 18:14:34 -0700946 if (!evt_payload || !rsrc_data)
947 return rc;
Harsh Shaha1af8822017-05-11 22:06:36 -0700948
Harsh Shah23557ae2017-05-13 18:14:34 -0700949 cam_ife_irq_regs = evt_payload->irq_reg_val;
950 status_reg = cam_ife_irq_regs[CAM_IFE_IRQ_BUS_REG_STATUS1];
951
952 if (status_reg & BIT(rsrc_data->index)) {
953 cam_ife_irq_regs[CAM_IFE_IRQ_BUS_REG_STATUS1] &=
954 ~BIT(rsrc_data->index);
Harsh Shaha1af8822017-05-11 22:06:36 -0700955 rc = CAM_VFE_IRQ_STATUS_SUCCESS;
Harsh Shah23557ae2017-05-13 18:14:34 -0700956 }
Harsh Shah19f55812017-06-26 18:58:49 -0700957 CDBG("status_reg %x rc %d\n", status_reg, rc);
Harsh Shaha1af8822017-05-11 22:06:36 -0700958
959 if (rc == CAM_VFE_IRQ_STATUS_SUCCESS)
Harsh Shah19f55812017-06-26 18:58:49 -0700960 cam_vfe_bus_put_evt_payload(rsrc_data->common_data,
Harsh Shaha1af8822017-05-11 22:06:36 -0700961 &evt_payload);
962
963 return rc;
964}
965
966static int cam_vfe_bus_init_wm_resource(uint32_t index,
967 struct cam_vfe_bus_ver2_priv *ver2_bus_priv,
968 struct cam_vfe_bus_ver2_hw_info *ver2_hw_info,
969 struct cam_isp_resource_node *wm_res)
970{
Harsh Shaha1af8822017-05-11 22:06:36 -0700971 struct cam_vfe_bus_ver2_wm_resource_data *rsrc_data;
972
973 rsrc_data = kzalloc(sizeof(struct cam_vfe_bus_ver2_wm_resource_data),
974 GFP_KERNEL);
975 if (!rsrc_data) {
Harsh Shah545df9a2017-06-16 16:43:17 -0700976 CDBG("Failed to alloc for WM res priv\n");
977 return -ENOMEM;
Harsh Shaha1af8822017-05-11 22:06:36 -0700978 }
979 wm_res->res_priv = rsrc_data;
980
981 rsrc_data->index = index;
982 rsrc_data->hw_regs = &ver2_hw_info->bus_client_reg[index];
983 rsrc_data->common_data = &ver2_bus_priv->common_data;
984
985 wm_res->res_state = CAM_ISP_RESOURCE_STATE_AVAILABLE;
986 INIT_LIST_HEAD(&wm_res->list);
987
988 wm_res->start = cam_vfe_bus_start_wm;
989 wm_res->stop = cam_vfe_bus_stop_wm;
990 wm_res->top_half_handler = cam_vfe_bus_handle_wm_done_top_half;
991 wm_res->bottom_half_handler = cam_vfe_bus_handle_wm_done_bottom_half;
992 wm_res->hw_intf = ver2_bus_priv->common_data.hw_intf;
993
Harsh Shah545df9a2017-06-16 16:43:17 -0700994 return 0;
995}
996
997static int cam_vfe_bus_deinit_wm_resource(
998 struct cam_isp_resource_node *wm_res)
999{
1000 struct cam_vfe_bus_ver2_wm_resource_data *rsrc_data;
1001
1002 wm_res->res_state = CAM_ISP_RESOURCE_STATE_UNAVAILABLE;
1003 INIT_LIST_HEAD(&wm_res->list);
1004
1005 wm_res->start = NULL;
1006 wm_res->stop = NULL;
1007 wm_res->top_half_handler = NULL;
1008 wm_res->bottom_half_handler = NULL;
1009 wm_res->hw_intf = NULL;
1010
1011 rsrc_data = wm_res->res_priv;
1012 wm_res->res_priv = NULL;
1013 if (!rsrc_data) {
1014 pr_err("Error! WM res priv is NULL\n");
1015 return -ENOMEM;
1016 }
1017 kfree(rsrc_data);
1018
1019 return 0;
Harsh Shaha1af8822017-05-11 22:06:36 -07001020}
1021
1022static void cam_vfe_bus_add_wm_to_comp_grp(
1023 struct cam_isp_resource_node *comp_grp,
1024 uint32_t composite_mask)
1025{
1026 struct cam_vfe_bus_ver2_comp_grp_data *rsrc_data = comp_grp->res_priv;
1027
1028 rsrc_data->composite_mask |= composite_mask;
1029}
1030
1031static void cam_vfe_bus_match_comp_grp(
1032 struct cam_vfe_bus_ver2_priv *ver2_bus_priv,
1033 struct cam_isp_resource_node **comp_grp,
1034 uint32_t comp_grp_local_idx,
1035 uint32_t unique_id)
1036{
1037 struct cam_vfe_bus_ver2_comp_grp_data *rsrc_data = NULL;
1038 struct cam_isp_resource_node *comp_grp_local = NULL;
1039
1040 list_for_each_entry(comp_grp_local,
1041 &ver2_bus_priv->used_comp_grp, list) {
1042 rsrc_data = comp_grp_local->res_priv;
1043 if (rsrc_data->comp_grp_local_idx == comp_grp_local_idx &&
1044 rsrc_data->unique_id == unique_id) {
1045 /* Match found */
1046 *comp_grp = comp_grp_local;
1047 return;
1048 }
1049 }
1050
1051 *comp_grp = NULL;
1052}
1053
1054static int cam_vfe_bus_acquire_comp_grp(
1055 struct cam_vfe_bus_ver2_priv *ver2_bus_priv,
1056 struct cam_isp_out_port_info *out_port_info,
Harsh Shah19f55812017-06-26 18:58:49 -07001057 void *tasklet,
1058 void *ctx,
Harsh Shaha1af8822017-05-11 22:06:36 -07001059 uint32_t unique_id,
1060 uint32_t is_dual,
1061 uint32_t is_master,
1062 enum cam_vfe_bus_ver2_vfe_core_id dual_slave_core,
1063 struct cam_isp_resource_node **comp_grp)
1064{
1065 int rc = 0;
1066 struct cam_isp_resource_node *comp_grp_local = NULL;
1067 struct cam_vfe_bus_ver2_comp_grp_data *rsrc_data = NULL;
1068
1069 /* Check if matching comp_grp already acquired */
1070 cam_vfe_bus_match_comp_grp(ver2_bus_priv, &comp_grp_local,
1071 out_port_info->comp_grp_id, unique_id);
1072
1073 if (!comp_grp_local) {
1074 /* First find a free group */
1075 if (is_dual) {
1076 if (list_empty(&ver2_bus_priv->free_dual_comp_grp)) {
1077 pr_err("No Free Composite Group\n");
1078 return -ENODEV;
1079 }
1080 comp_grp_local = list_first_entry(
1081 &ver2_bus_priv->free_dual_comp_grp,
1082 struct cam_isp_resource_node, list);
1083 rsrc_data = comp_grp_local->res_priv;
1084 rc = cam_vfe_bus_ver2_get_intra_client_mask(
1085 dual_slave_core,
1086 comp_grp_local->hw_intf->hw_idx,
1087 &rsrc_data->intra_client_mask);
1088 } else {
1089 if (list_empty(&ver2_bus_priv->free_comp_grp)) {
1090 pr_err("No Free Composite Group\n");
1091 return -ENODEV;
1092 }
1093 comp_grp_local = list_first_entry(
1094 &ver2_bus_priv->free_comp_grp,
1095 struct cam_isp_resource_node, list);
1096 rsrc_data = comp_grp_local->res_priv;
1097 }
1098
1099 list_del(&comp_grp_local->list);
Harsh Shah19f55812017-06-26 18:58:49 -07001100 comp_grp_local->tasklet_info = tasklet;
Harsh Shaha1af8822017-05-11 22:06:36 -07001101 comp_grp_local->res_state = CAM_ISP_RESOURCE_STATE_RESERVED;
1102
1103 rsrc_data->is_master = is_master;
1104 rsrc_data->composite_mask = 0;
1105 rsrc_data->unique_id = unique_id;
1106 rsrc_data->comp_grp_local_idx = out_port_info->comp_grp_id;
1107
1108 list_add_tail(&comp_grp_local->list,
1109 &ver2_bus_priv->used_comp_grp);
1110
1111 } else {
1112 rsrc_data = comp_grp_local->res_priv;
1113 /* Do not support runtime change in composite mask */
1114 if (comp_grp_local->res_state ==
1115 CAM_ISP_RESOURCE_STATE_STREAMING) {
1116 pr_err("Invalid State %d Comp Grp %u\n",
1117 comp_grp_local->res_state,
1118 rsrc_data->comp_grp_type);
1119 return -EBUSY;
1120 }
1121 }
1122
Harsh Shah19f55812017-06-26 18:58:49 -07001123 rsrc_data->ctx = ctx;
Harsh Shaha1af8822017-05-11 22:06:36 -07001124 *comp_grp = comp_grp_local;
1125
1126 return rc;
1127}
1128
1129static int cam_vfe_bus_release_comp_grp(
1130 struct cam_vfe_bus_ver2_priv *ver2_bus_priv,
1131 struct cam_isp_resource_node *in_comp_grp)
1132{
1133 struct cam_isp_resource_node *comp_grp = NULL;
1134 struct cam_vfe_bus_ver2_comp_grp_data *in_rsrc_data = NULL;
1135 int match_found = 0;
1136
1137 if (!in_comp_grp) {
1138 pr_err("Invalid Params Comp Grp %pK\n", in_rsrc_data);
1139 return -EINVAL;
1140 }
1141
1142 if (in_comp_grp->res_state == CAM_ISP_RESOURCE_STATE_AVAILABLE) {
1143 /* Already Released. Do Nothing */
1144 return 0;
1145 }
1146
1147 in_rsrc_data = in_comp_grp->res_priv;
1148
1149 list_for_each_entry(comp_grp, &ver2_bus_priv->used_comp_grp, list) {
1150 if (comp_grp == in_comp_grp) {
1151 match_found = 1;
1152 break;
1153 }
1154 }
1155
1156 if (!match_found) {
1157 pr_err("Could not find matching Comp Grp type %u\n",
1158 in_rsrc_data->comp_grp_type);
1159 return -ENODEV;
1160 }
1161
1162
1163 list_del(&comp_grp->list);
1164 if (in_rsrc_data->comp_grp_type >= CAM_VFE_BUS_VER2_COMP_GRP_DUAL_0 &&
1165 in_rsrc_data->comp_grp_type <= CAM_VFE_BUS_VER2_COMP_GRP_DUAL_5)
1166 list_add_tail(&comp_grp->list,
1167 &ver2_bus_priv->free_dual_comp_grp);
Jing Zhoue71fd4a2017-05-15 19:44:34 -07001168 else if (in_rsrc_data->comp_grp_type >= CAM_VFE_BUS_VER2_COMP_GRP_0
1169 && in_rsrc_data->comp_grp_type <= CAM_VFE_BUS_VER2_COMP_GRP_5)
Harsh Shaha1af8822017-05-11 22:06:36 -07001170 list_add_tail(&comp_grp->list, &ver2_bus_priv->free_comp_grp);
1171
Harsh Shaha1af8822017-05-11 22:06:36 -07001172 in_rsrc_data->unique_id = 0;
1173 in_rsrc_data->comp_grp_local_idx = 0;
1174 in_rsrc_data->composite_mask = 0;
1175 in_rsrc_data->dual_slave_core = CAM_VFE_BUS_VER2_VFE_CORE_MAX;
1176
Harsh Shah19f55812017-06-26 18:58:49 -07001177 comp_grp->tasklet_info = NULL;
Harsh Shaha1af8822017-05-11 22:06:36 -07001178 comp_grp->res_state = CAM_ISP_RESOURCE_STATE_AVAILABLE;
1179
Jing Zhoue71fd4a2017-05-15 19:44:34 -07001180 return 0;
Harsh Shaha1af8822017-05-11 22:06:36 -07001181}
1182
1183static int cam_vfe_bus_start_comp_grp(struct cam_isp_resource_node *comp_grp)
1184{
1185 int rc = 0;
1186 struct cam_vfe_bus_ver2_comp_grp_data *rsrc_data =
1187 comp_grp->res_priv;
1188 struct cam_vfe_bus_ver2_common_data *common_data =
1189 rsrc_data->common_data;
Harsh Shah19f55812017-06-26 18:58:49 -07001190 uint32_t bus_irq_reg_mask[CAM_VFE_BUS_IRQ_MAX] = {0};
Harsh Shaha1af8822017-05-11 22:06:36 -07001191
1192 cam_io_w_mb(rsrc_data->composite_mask, common_data->mem_base +
1193 rsrc_data->hw_regs->comp_mask);
1194
1195 CDBG("composite_mask is 0x%x\n", rsrc_data->composite_mask);
1196 CDBG("composite_mask addr 0x%x\n", rsrc_data->hw_regs->comp_mask);
1197
1198 if (rsrc_data->comp_grp_type >= CAM_VFE_BUS_VER2_COMP_GRP_DUAL_0 &&
1199 rsrc_data->comp_grp_type <= CAM_VFE_BUS_VER2_COMP_GRP_DUAL_5 &&
1200 rsrc_data->is_master) {
1201 int dual_comp_grp = (rsrc_data->comp_grp_type -
1202 CAM_VFE_BUS_VER2_COMP_GRP_DUAL_0);
1203 int intra_client_en = cam_io_r_mb(common_data->mem_base +
1204 common_data->common_reg->dual_master_comp_cfg);
1205
1206 /* 2 Bits per comp_grp. Hence left shift by comp_grp * 2 */
1207 intra_client_en |=
1208 (rsrc_data->intra_client_mask << dual_comp_grp * 2);
1209
1210 cam_io_w_mb(intra_client_en, common_data->mem_base +
1211 common_data->common_reg->dual_master_comp_cfg);
Harsh Shah19f55812017-06-26 18:58:49 -07001212
1213 bus_irq_reg_mask[CAM_VFE_BUS_IRQ_REG2] = (1 << dual_comp_grp);
1214 } else {
1215 /* IRQ bits for COMP GRP start at 5. So add 5 to the shift */
1216 bus_irq_reg_mask[CAM_VFE_BUS_IRQ_REG0] =
1217 (1 << (rsrc_data->comp_grp_type + 5));
1218 }
1219
1220 /* Subscribe IRQ */
1221 CDBG("Subscribe COMP_GRP%d IRQ\n", rsrc_data->comp_grp_type);
1222 comp_grp->irq_handle = cam_irq_controller_subscribe_irq(
1223 common_data->bus_irq_controller, CAM_IRQ_PRIORITY_1,
1224 bus_irq_reg_mask, comp_grp,
1225 comp_grp->top_half_handler,
1226 cam_ife_mgr_do_tasklet_buf_done,
1227 comp_grp->tasklet_info, cam_tasklet_enqueue_cmd);
1228 if (comp_grp->irq_handle < 0) {
1229 pr_err("Subscribe IRQ failed for comp_grp %d\n",
1230 rsrc_data->comp_grp_type);
1231 return -EFAULT;
Harsh Shaha1af8822017-05-11 22:06:36 -07001232 }
1233
1234 comp_grp->res_state = CAM_ISP_RESOURCE_STATE_STREAMING;
Harsh Shah19f55812017-06-26 18:58:49 -07001235
Harsh Shaha1af8822017-05-11 22:06:36 -07001236 return rc;
1237}
1238
1239static int cam_vfe_bus_stop_comp_grp(struct cam_isp_resource_node *comp_grp)
1240{
1241 int rc = 0;
1242 struct cam_vfe_bus_ver2_comp_grp_data *rsrc_data =
1243 comp_grp->res_priv;
1244 struct cam_vfe_bus_ver2_common_data *common_data =
1245 rsrc_data->common_data;
1246
1247 /* Unsubscribe IRQ */
Harsh Shah19f55812017-06-26 18:58:49 -07001248 rc = cam_irq_controller_unsubscribe_irq(
1249 common_data->bus_irq_controller,
1250 comp_grp->irq_handle);
Harsh Shaha1af8822017-05-11 22:06:36 -07001251
1252 cam_io_w_mb(rsrc_data->composite_mask, common_data->mem_base +
1253 rsrc_data->hw_regs->comp_mask);
1254 if (rsrc_data->comp_grp_type >= CAM_VFE_BUS_VER2_COMP_GRP_DUAL_0 &&
1255 rsrc_data->comp_grp_type <= CAM_VFE_BUS_VER2_COMP_GRP_DUAL_5 &&
1256 rsrc_data->is_master) {
1257 int dual_comp_grp = (rsrc_data->comp_grp_type -
1258 CAM_VFE_BUS_VER2_COMP_GRP_DUAL_0);
1259 int intra_client_en = cam_io_r_mb(common_data->mem_base +
1260 common_data->common_reg->dual_master_comp_cfg);
1261
1262 /* 2 Bits per comp_grp. Hence left shift by comp_grp * 2 */
1263 intra_client_en &=
1264 ~(rsrc_data->intra_client_mask << dual_comp_grp * 2);
1265
1266 cam_io_w_mb(intra_client_en, common_data->mem_base +
1267 common_data->common_reg->dual_master_comp_cfg);
1268 }
1269
1270 comp_grp->res_state = CAM_ISP_RESOURCE_STATE_RESERVED;
1271
1272 return rc;
1273}
1274
1275static int cam_vfe_bus_handle_comp_done_top_half(uint32_t evt_id,
1276 struct cam_irq_th_payload *th_payload)
1277{
Harsh Shah19f55812017-06-26 18:58:49 -07001278 int32_t rc;
1279 int i;
1280 struct cam_isp_resource_node *comp_grp = NULL;
1281 struct cam_vfe_bus_ver2_comp_grp_data *rsrc_data = NULL;
1282 struct cam_vfe_bus_irq_evt_payload *evt_payload;
1283
1284 comp_grp = th_payload->handler_priv;
1285 if (!comp_grp) {
1286 pr_err_ratelimited("Error! No resource\n");
1287 return -ENODEV;
1288 }
1289
1290 rsrc_data = comp_grp->res_priv;
1291
1292 CDBG("IRQ status_0 = %x\n", th_payload->evt_status_arr[0]);
1293 CDBG("IRQ status_1 = %x\n", th_payload->evt_status_arr[1]);
1294
1295 rc = cam_vfe_bus_get_evt_payload(rsrc_data->common_data, &evt_payload);
1296 if (rc) {
1297 pr_err_ratelimited("No tasklet_cmd is free in queue\n");
1298 return rc;
1299 }
1300
1301 cam_isp_hw_get_timestamp(&evt_payload->ts);
1302
1303 evt_payload->ctx = rsrc_data->ctx;
1304 evt_payload->core_index = rsrc_data->common_data->core_index;
1305 evt_payload->evt_id = evt_id;
1306
1307 for (i = 0; i < th_payload->num_registers; i++)
1308 evt_payload->irq_reg_val[i] = th_payload->evt_status_arr[i];
1309
1310 th_payload->evt_payload_priv = evt_payload;
1311
1312 CDBG("Exit\n");
1313 return rc;
Harsh Shaha1af8822017-05-11 22:06:36 -07001314}
1315
1316static int cam_vfe_bus_handle_comp_done_bottom_half(
1317 void *handler_priv,
1318 void *evt_payload_priv)
1319{
1320 int rc = CAM_VFE_IRQ_STATUS_ERR;
1321 struct cam_isp_resource_node *comp_grp = handler_priv;
1322 struct cam_vfe_bus_irq_evt_payload *evt_payload = evt_payload_priv;
1323 struct cam_vfe_bus_ver2_comp_grp_data *rsrc_data = comp_grp->res_priv;
Harsh Shah23557ae2017-05-13 18:14:34 -07001324 uint32_t *cam_ife_irq_regs;
1325 uint32_t status_reg;
1326 uint32_t comp_err_reg;
1327 uint32_t comp_grp_id;
1328
Harsh Shah19f55812017-06-26 18:58:49 -07001329 CDBG("comp grp type %d\n", rsrc_data->comp_grp_type);
1330
Harsh Shah23557ae2017-05-13 18:14:34 -07001331 if (!evt_payload)
1332 return rc;
1333
1334 cam_ife_irq_regs = evt_payload->irq_reg_val;
Harsh Shaha1af8822017-05-11 22:06:36 -07001335
Harsh Shaha1af8822017-05-11 22:06:36 -07001336 switch (rsrc_data->comp_grp_type) {
1337 case CAM_VFE_BUS_VER2_COMP_GRP_0:
1338 case CAM_VFE_BUS_VER2_COMP_GRP_1:
1339 case CAM_VFE_BUS_VER2_COMP_GRP_2:
1340 case CAM_VFE_BUS_VER2_COMP_GRP_3:
1341 case CAM_VFE_BUS_VER2_COMP_GRP_4:
1342 case CAM_VFE_BUS_VER2_COMP_GRP_5:
Harsh Shah23557ae2017-05-13 18:14:34 -07001343 comp_grp_id = (rsrc_data->comp_grp_type -
Harsh Shaha1af8822017-05-11 22:06:36 -07001344 CAM_VFE_BUS_VER2_COMP_GRP_0);
1345
1346 /* Check for Regular composite error */
1347 status_reg = cam_ife_irq_regs[CAM_IFE_IRQ_BUS_REG_STATUS0];
1348
1349 comp_err_reg = cam_ife_irq_regs[CAM_IFE_IRQ_BUS_REG_COMP_ERR];
1350 if ((status_reg & BIT(11)) &&
1351 (comp_err_reg & rsrc_data->composite_mask)) {
1352 /* Check for Regular composite error */
1353 rc = CAM_VFE_IRQ_STATUS_ERR_COMP;
1354 break;
1355 }
1356
1357 comp_err_reg = cam_ife_irq_regs[CAM_IFE_IRQ_BUS_REG_COMP_OWRT];
1358 /* Check for Regular composite Overwrite */
1359 if ((status_reg & BIT(12)) &&
1360 (comp_err_reg & rsrc_data->composite_mask)) {
1361 rc = CAM_VFE_IRQ_STATUS_COMP_OWRT;
1362 break;
1363 }
1364
Harsh Shah23557ae2017-05-13 18:14:34 -07001365 /* Regular Composite SUCCESS */
1366 if (status_reg & BIT(comp_grp_id + 5)) {
1367 cam_ife_irq_regs[CAM_IFE_IRQ_BUS_REG_STATUS0] &=
1368 ~BIT(comp_grp_id + 5);
Harsh Shaha1af8822017-05-11 22:06:36 -07001369 rc = CAM_VFE_IRQ_STATUS_SUCCESS;
Harsh Shah23557ae2017-05-13 18:14:34 -07001370 }
Harsh Shaha1af8822017-05-11 22:06:36 -07001371
Harsh Shah19f55812017-06-26 18:58:49 -07001372 CDBG("status reg = 0x%x, bit index = %d rc %d\n",
1373 status_reg, (comp_grp_id + 5), rc);
Harsh Shaha1af8822017-05-11 22:06:36 -07001374 break;
1375
1376 case CAM_VFE_BUS_VER2_COMP_GRP_DUAL_0:
1377 case CAM_VFE_BUS_VER2_COMP_GRP_DUAL_1:
1378 case CAM_VFE_BUS_VER2_COMP_GRP_DUAL_2:
1379 case CAM_VFE_BUS_VER2_COMP_GRP_DUAL_3:
1380 case CAM_VFE_BUS_VER2_COMP_GRP_DUAL_4:
1381 case CAM_VFE_BUS_VER2_COMP_GRP_DUAL_5:
Harsh Shah23557ae2017-05-13 18:14:34 -07001382 comp_grp_id = (rsrc_data->comp_grp_type -
Harsh Shaha1af8822017-05-11 22:06:36 -07001383 CAM_VFE_BUS_VER2_COMP_GRP_DUAL_0);
1384
1385 /* Check for DUAL composite error */
1386 status_reg = cam_ife_irq_regs[CAM_IFE_IRQ_BUS_REG_STATUS2];
1387
1388 comp_err_reg = cam_ife_irq_regs[CAM_IFE_IRQ_BUS_DUAL_COMP_ERR];
1389 if ((status_reg & BIT(6)) &&
1390 (comp_err_reg & rsrc_data->composite_mask)) {
1391 /* Check for DUAL composite error */
1392 rc = CAM_VFE_IRQ_STATUS_ERR_COMP;
1393 break;
1394 }
1395
1396 /* Check for Dual composite Overwrite */
1397 comp_err_reg = cam_ife_irq_regs[CAM_IFE_IRQ_BUS_DUAL_COMP_OWRT];
1398 if ((status_reg & BIT(7)) &&
1399 (comp_err_reg & rsrc_data->composite_mask)) {
1400 rc = CAM_VFE_IRQ_STATUS_COMP_OWRT;
1401 break;
1402 }
1403
Harsh Shah23557ae2017-05-13 18:14:34 -07001404 /* DUAL Composite SUCCESS */
1405 if (status_reg & BIT(comp_grp_id)) {
1406 cam_ife_irq_regs[CAM_IFE_IRQ_BUS_REG_STATUS2] &=
1407 ~BIT(comp_grp_id + 5);
Harsh Shaha1af8822017-05-11 22:06:36 -07001408 rc = CAM_VFE_IRQ_STATUS_SUCCESS;
Harsh Shah23557ae2017-05-13 18:14:34 -07001409 }
Harsh Shaha1af8822017-05-11 22:06:36 -07001410
1411 break;
Harsh Shaha1af8822017-05-11 22:06:36 -07001412 default:
1413 rc = CAM_VFE_IRQ_STATUS_ERR;
Harsh Shah19f55812017-06-26 18:58:49 -07001414 pr_err("Error! Invalid comp_grp_type %u\n",
1415 rsrc_data->comp_grp_type);
Harsh Shaha1af8822017-05-11 22:06:36 -07001416 break;
1417 }
1418
1419 if (rc == CAM_VFE_IRQ_STATUS_SUCCESS)
Harsh Shah19f55812017-06-26 18:58:49 -07001420 cam_vfe_bus_put_evt_payload(rsrc_data->common_data,
Harsh Shaha1af8822017-05-11 22:06:36 -07001421 &evt_payload);
1422
1423 return rc;
1424}
1425
1426static int cam_vfe_bus_init_comp_grp(uint32_t index,
1427 struct cam_vfe_bus_ver2_priv *ver2_bus_priv,
1428 struct cam_vfe_bus_ver2_hw_info *ver2_hw_info,
1429 struct cam_isp_resource_node *comp_grp)
1430{
Harsh Shah545df9a2017-06-16 16:43:17 -07001431 struct cam_vfe_bus_ver2_comp_grp_data *rsrc_data = NULL;
Harsh Shaha1af8822017-05-11 22:06:36 -07001432
1433 rsrc_data = kzalloc(sizeof(struct cam_vfe_bus_ver2_comp_grp_data),
1434 GFP_KERNEL);
1435 if (!rsrc_data) {
1436 CDBG("Failed to alloc for comp_grp_priv\n");
1437 return -ENOMEM;
1438 }
1439 comp_grp->res_priv = rsrc_data;
1440
1441 comp_grp->res_state = CAM_ISP_RESOURCE_STATE_AVAILABLE;
1442 INIT_LIST_HEAD(&comp_grp->list);
1443
1444 rsrc_data->comp_grp_type = index;
1445 rsrc_data->common_data = &ver2_bus_priv->common_data;
1446 rsrc_data->hw_regs = &ver2_hw_info->comp_grp_reg[index];
1447 rsrc_data->dual_slave_core = CAM_VFE_BUS_VER2_VFE_CORE_MAX;
1448
Harsh Shaha1af8822017-05-11 22:06:36 -07001449 if (rsrc_data->comp_grp_type >= CAM_VFE_BUS_VER2_COMP_GRP_DUAL_0 &&
1450 rsrc_data->comp_grp_type <= CAM_VFE_BUS_VER2_COMP_GRP_DUAL_5)
1451 list_add_tail(&comp_grp->list,
1452 &ver2_bus_priv->free_dual_comp_grp);
1453 else if (rsrc_data->comp_grp_type >= CAM_VFE_BUS_VER2_COMP_GRP_0
1454 && rsrc_data->comp_grp_type <= CAM_VFE_BUS_VER2_COMP_GRP_5)
1455 list_add_tail(&comp_grp->list, &ver2_bus_priv->free_comp_grp);
1456
1457 comp_grp->start = cam_vfe_bus_start_comp_grp;
1458 comp_grp->stop = cam_vfe_bus_stop_comp_grp;
1459 comp_grp->top_half_handler = cam_vfe_bus_handle_comp_done_top_half;
1460 comp_grp->bottom_half_handler =
1461 cam_vfe_bus_handle_comp_done_bottom_half;
1462 comp_grp->hw_intf = ver2_bus_priv->common_data.hw_intf;
1463
1464 return 0;
1465}
1466
Harsh Shah545df9a2017-06-16 16:43:17 -07001467static int cam_vfe_bus_deinit_comp_grp(
1468 struct cam_isp_resource_node *comp_grp)
1469{
1470 struct cam_vfe_bus_ver2_comp_grp_data *rsrc_data =
1471 comp_grp->res_priv;
1472
1473 comp_grp->start = NULL;
1474 comp_grp->stop = NULL;
1475 comp_grp->top_half_handler = NULL;
1476 comp_grp->bottom_half_handler = NULL;
1477 comp_grp->hw_intf = NULL;
1478
1479 list_del_init(&comp_grp->list);
1480 comp_grp->res_state = CAM_ISP_RESOURCE_STATE_UNAVAILABLE;
1481
1482 comp_grp->res_priv = NULL;
1483
1484 if (!rsrc_data) {
1485 pr_err("Error! comp_grp_priv is NULL\n");
1486 return -ENODEV;
1487 }
1488 kfree(rsrc_data);
1489
1490 return 0;
1491}
1492
Harsh Shah19f55812017-06-26 18:58:49 -07001493static int cam_vfe_bus_acquire_vfe_out(void *bus_priv, void *acquire_args,
1494 uint32_t args_size)
Harsh Shaha1af8822017-05-11 22:06:36 -07001495{
1496 int rc = -ENODEV;
1497 int i;
1498 enum cam_vfe_bus_ver2_vfe_out_type vfe_out_res_id;
1499 uint32_t format;
1500 uint32_t num_wm;
1501 uint32_t subscribe_irq;
1502 uint32_t client_done_mask;
1503 struct cam_vfe_bus_ver2_priv *ver2_bus_priv = bus_priv;
1504 struct cam_vfe_acquire_args *acq_args = acquire_args;
1505 struct cam_vfe_hw_vfe_out_acquire_args *out_acquire_args;
1506 struct cam_isp_resource_node *rsrc_node = NULL;
1507 struct cam_vfe_bus_ver2_vfe_out_data *rsrc_data = NULL;
1508
1509 if (!bus_priv || !acquire_args) {
1510 pr_err("Invalid Param");
1511 return -EINVAL;
1512 }
1513
1514 out_acquire_args = &acq_args->vfe_out;
1515 format = out_acquire_args->out_port_info->format;
1516
1517 CDBG("Acquiring resource type 0x%x\n",
1518 out_acquire_args->out_port_info->res_type);
1519
1520 vfe_out_res_id = cam_vfe_bus_get_out_res_id(
1521 out_acquire_args->out_port_info->res_type);
1522 if (vfe_out_res_id == CAM_VFE_BUS_VER2_VFE_OUT_MAX)
1523 return -ENODEV;
1524
1525 num_wm = cam_vfe_bus_get_num_wm(vfe_out_res_id, format);
1526 if (num_wm < 1)
1527 return -EINVAL;
1528
1529 rsrc_node = &ver2_bus_priv->vfe_out[vfe_out_res_id];
1530 if (rsrc_node->res_state != CAM_ISP_RESOURCE_STATE_AVAILABLE) {
1531 pr_err("Resource not available: Res_id %d state:%d\n",
1532 vfe_out_res_id, rsrc_node->res_state);
1533 return -EBUSY;
1534 }
1535
1536 rsrc_data = rsrc_node->res_priv;
1537 rsrc_data->num_wm = num_wm;
1538 rsrc_node->res_id = out_acquire_args->out_port_info->res_type;
1539 rsrc_node->tasklet_info = acq_args->tasklet;
1540 rsrc_node->cdm_ops = out_acquire_args->cdm_ops;
1541 rsrc_data->cdm_util_ops = out_acquire_args->cdm_ops;
1542
1543 /* Reserve Composite Group */
1544 if (num_wm > 1 || (out_acquire_args->out_port_info->comp_grp_id >
1545 CAM_ISP_RES_COMP_GROUP_NONE &&
1546 out_acquire_args->out_port_info->comp_grp_id <
1547 CAM_ISP_RES_COMP_GROUP_ID_MAX)) {
1548 rc = cam_vfe_bus_acquire_comp_grp(ver2_bus_priv,
1549 out_acquire_args->out_port_info,
Harsh Shah19f55812017-06-26 18:58:49 -07001550 acq_args->tasklet,
1551 out_acquire_args->ctx,
Harsh Shaha1af8822017-05-11 22:06:36 -07001552 out_acquire_args->unique_id,
1553 out_acquire_args->is_dual,
1554 out_acquire_args->is_master,
1555 out_acquire_args->dual_slave_core,
1556 &rsrc_data->comp_grp);
Harsh Shah19f55812017-06-26 18:58:49 -07001557 if (rc) {
1558 pr_err("VFE%d Comp_Grp acquire failed for Out %d rc=%d\n",
1559 rsrc_data->common_data->core_index,
1560 vfe_out_res_id, rc);
Harsh Shaha1af8822017-05-11 22:06:36 -07001561 return rc;
Harsh Shah19f55812017-06-26 18:58:49 -07001562 }
Harsh Shaha1af8822017-05-11 22:06:36 -07001563
1564 subscribe_irq = 0;
Harsh Shah19f55812017-06-26 18:58:49 -07001565 } else {
Harsh Shaha1af8822017-05-11 22:06:36 -07001566 subscribe_irq = 1;
Harsh Shah19f55812017-06-26 18:58:49 -07001567 }
Harsh Shaha1af8822017-05-11 22:06:36 -07001568
1569 /* Reserve WM */
1570 for (i = 0; i < num_wm; i++) {
1571 rc = cam_vfe_bus_acquire_wm(ver2_bus_priv,
1572 out_acquire_args->out_port_info,
Harsh Shah19f55812017-06-26 18:58:49 -07001573 acq_args->tasklet,
1574 out_acquire_args->ctx,
Harsh Shaha1af8822017-05-11 22:06:36 -07001575 vfe_out_res_id,
1576 i,
1577 out_acquire_args->split_id,
1578 subscribe_irq,
1579 &rsrc_data->wm_res[i],
1580 &client_done_mask);
Harsh Shah19f55812017-06-26 18:58:49 -07001581 if (rc) {
1582 pr_err("VFE%d WM acquire failed for Out %d rc=%d\n",
1583 rsrc_data->common_data->core_index,
1584 vfe_out_res_id, rc);
Harsh Shaha1af8822017-05-11 22:06:36 -07001585 goto release_wm;
Harsh Shah19f55812017-06-26 18:58:49 -07001586 }
Harsh Shaha1af8822017-05-11 22:06:36 -07001587
1588 if (rsrc_data->comp_grp)
1589 cam_vfe_bus_add_wm_to_comp_grp(rsrc_data->comp_grp,
1590 client_done_mask);
1591 }
1592
1593 rsrc_node->res_state = CAM_ISP_RESOURCE_STATE_RESERVED;
1594 out_acquire_args->rsrc_node = rsrc_node;
1595
1596 CDBG("Acquire successful\n");
1597 return rc;
1598
1599release_wm:
1600 for (i--; i >= 0; i--)
1601 cam_vfe_bus_release_wm(ver2_bus_priv, rsrc_data->wm_res[i]);
1602
1603 cam_vfe_bus_release_comp_grp(ver2_bus_priv,
1604 rsrc_data->comp_grp);
1605
1606 return rc;
1607}
1608
Harsh Shah19f55812017-06-26 18:58:49 -07001609static int cam_vfe_bus_release_vfe_out(void *bus_priv, void *release_args,
1610 uint32_t args_size)
Harsh Shaha1af8822017-05-11 22:06:36 -07001611{
Jing Zhoue71fd4a2017-05-15 19:44:34 -07001612 uint32_t i;
Harsh Shah19f55812017-06-26 18:58:49 -07001613 struct cam_isp_resource_node *vfe_out = NULL;
1614 struct cam_vfe_bus_ver2_vfe_out_data *rsrc_data = NULL;
1615
1616 if (!bus_priv || !release_args) {
1617 pr_err("Invalid input bus_priv %pK release_args %pK\n",
1618 bus_priv, release_args);
1619 return -EINVAL;
1620 }
1621
1622 vfe_out = release_args;
1623 rsrc_data = vfe_out->res_priv;
Jing Zhoue71fd4a2017-05-15 19:44:34 -07001624
Harsh Shaha1af8822017-05-11 22:06:36 -07001625 if (vfe_out->res_state != CAM_ISP_RESOURCE_STATE_RESERVED) {
1626 pr_err("Error! Invalid resource state:%d\n",
1627 vfe_out->res_state);
1628 }
1629
Jing Zhoue71fd4a2017-05-15 19:44:34 -07001630 for (i = 0; i < rsrc_data->num_wm; i++)
1631 cam_vfe_bus_release_wm(bus_priv, rsrc_data->wm_res[i]);
1632 rsrc_data->num_wm = 0;
1633
1634 if (rsrc_data->comp_grp)
1635 cam_vfe_bus_release_comp_grp(bus_priv, rsrc_data->comp_grp);
1636 rsrc_data->comp_grp = NULL;
1637
1638 vfe_out->tasklet_info = NULL;
1639 vfe_out->cdm_ops = NULL;
1640 rsrc_data->cdm_util_ops = NULL;
1641
Harsh Shaha1af8822017-05-11 22:06:36 -07001642 if (vfe_out->res_state == CAM_ISP_RESOURCE_STATE_RESERVED)
1643 vfe_out->res_state = CAM_ISP_RESOURCE_STATE_AVAILABLE;
1644
1645 return 0;
1646}
1647
Harsh Shah19f55812017-06-26 18:58:49 -07001648static int cam_vfe_bus_start_vfe_out(
1649 struct cam_isp_resource_node *vfe_out)
Harsh Shaha1af8822017-05-11 22:06:36 -07001650{
1651 int rc = 0, i;
Harsh Shah19f55812017-06-26 18:58:49 -07001652 struct cam_vfe_bus_ver2_vfe_out_data *rsrc_data = NULL;
1653 struct cam_vfe_bus_ver2_common_data *common_data = NULL;
1654
1655 if (!vfe_out) {
1656 pr_err("Invalid input\n");
1657 return -EINVAL;
1658 }
1659
1660 rsrc_data = vfe_out->res_priv;
1661 common_data = rsrc_data->common_data;
Harsh Shaha1af8822017-05-11 22:06:36 -07001662
1663 CDBG("Start resource index %d\n", rsrc_data->out_type);
1664
1665 if (vfe_out->res_state != CAM_ISP_RESOURCE_STATE_RESERVED) {
1666 pr_err("Error! Invalid resource state:%d\n",
1667 vfe_out->res_state);
1668 return -EACCES;
1669 }
1670
1671 for (i = 0; i < rsrc_data->num_wm; i++)
1672 rc = cam_vfe_bus_start_wm(rsrc_data->wm_res[i]);
1673
1674 if (rsrc_data->comp_grp)
1675 rc = cam_vfe_bus_start_comp_grp(rsrc_data->comp_grp);
1676
Harsh Shaha1af8822017-05-11 22:06:36 -07001677 /* BUS_WR_INPUT_IF_ADDR_SYNC_CFG */
1678 cam_io_w_mb(0x0, rsrc_data->common_data->mem_base + 0x0000207C);
1679 /* BUS_WR_INPUT_IF_ADDR_SYNC_FRAME_HEADER */
1680 cam_io_w_mb(0x0, rsrc_data->common_data->mem_base + 0x00002080);
1681 /* BUS_WR_INPUT_IF_ADDR_SYNC_NO_SYNC */
1682 cam_io_w_mb(0xFFFFF, rsrc_data->common_data->mem_base + 0x00002084);
Harsh Shaha1af8822017-05-11 22:06:36 -07001683 /* BUS_WR_INPUT_IF_ADDR_SYNC_0 */
1684 cam_io_w_mb(0x0, rsrc_data->common_data->mem_base + 0x00002088);
1685 cam_io_w_mb(0x0, rsrc_data->common_data->mem_base + 0x0000208c);
1686 cam_io_w_mb(0x0, rsrc_data->common_data->mem_base + 0x00002090);
1687 cam_io_w_mb(0x0, rsrc_data->common_data->mem_base + 0x00002094);
1688 cam_io_w_mb(0x0, rsrc_data->common_data->mem_base + 0x00002098);
1689 cam_io_w_mb(0x0, rsrc_data->common_data->mem_base + 0x0000209c);
1690 cam_io_w_mb(0x0, rsrc_data->common_data->mem_base + 0x000020a0);
1691 cam_io_w_mb(0x0, rsrc_data->common_data->mem_base + 0x000020a4);
1692
Harsh Shah23557ae2017-05-13 18:14:34 -07001693 /* no clock gating at bus input */
1694 cam_io_w_mb(0xFFFFF, rsrc_data->common_data->mem_base + 0x0000200C);
1695
1696 /* BUS_WR_TEST_BUS_CTRL */
1697 cam_io_w_mb(0x0, rsrc_data->common_data->mem_base + 0x0000211C);
1698
Abhishek Kondaveeti157ae882017-07-08 06:56:48 +05301699 vfe_out->res_state = CAM_ISP_RESOURCE_STATE_STREAMING;
Harsh Shaha1af8822017-05-11 22:06:36 -07001700 return rc;
1701}
1702
Harsh Shah19f55812017-06-26 18:58:49 -07001703static int cam_vfe_bus_stop_vfe_out(
1704 struct cam_isp_resource_node *vfe_out)
Harsh Shaha1af8822017-05-11 22:06:36 -07001705{
1706 int rc = 0, i;
Harsh Shah19f55812017-06-26 18:58:49 -07001707 struct cam_vfe_bus_ver2_vfe_out_data *rsrc_data = NULL;
1708
1709 if (!vfe_out) {
1710 pr_err("Invalid input\n");
1711 return -EINVAL;
1712 }
1713
1714 rsrc_data = vfe_out->res_priv;
Harsh Shaha1af8822017-05-11 22:06:36 -07001715
1716 if (vfe_out->res_state == CAM_ISP_RESOURCE_STATE_AVAILABLE ||
1717 vfe_out->res_state == CAM_ISP_RESOURCE_STATE_RESERVED) {
1718 return rc;
1719 }
1720
1721 if (rsrc_data->comp_grp)
1722 rc = cam_vfe_bus_stop_comp_grp(rsrc_data->comp_grp);
1723
1724 for (i = 0; i < rsrc_data->num_wm; i++)
1725 rc = cam_vfe_bus_stop_wm(rsrc_data->wm_res[i]);
1726
Harsh Shaha1af8822017-05-11 22:06:36 -07001727
1728 vfe_out->res_state = CAM_ISP_RESOURCE_STATE_RESERVED;
1729 return rc;
1730}
1731
1732static int cam_vfe_bus_handle_vfe_out_done_top_half(uint32_t evt_id,
1733 struct cam_irq_th_payload *th_payload)
1734{
1735 return -EPERM;
1736}
1737
1738static int cam_vfe_bus_handle_vfe_out_done_bottom_half(
1739 void *handler_priv,
1740 void *evt_payload_priv)
1741{
1742 int rc = -EINVAL;
1743 struct cam_isp_resource_node *vfe_out = handler_priv;
1744 struct cam_vfe_bus_ver2_vfe_out_data *rsrc_data = vfe_out->res_priv;
1745
1746 /*
1747 * If this resource has Composite Group then we only handle
1748 * Composite done. We acquire Composite if number of WM > 1.
1749 * So Else case is only one individual buf_done = WM[0].
1750 */
1751 if (rsrc_data->comp_grp) {
1752 rc = rsrc_data->comp_grp->bottom_half_handler(
1753 rsrc_data->comp_grp, evt_payload_priv);
1754 } else {
1755 rc = rsrc_data->wm_res[0]->bottom_half_handler(
Harsh Shah23557ae2017-05-13 18:14:34 -07001756 rsrc_data->wm_res[0], evt_payload_priv);
Harsh Shaha1af8822017-05-11 22:06:36 -07001757 }
1758
1759 return rc;
1760}
1761
1762static int cam_vfe_bus_init_vfe_out_resource(uint32_t index,
1763 struct cam_vfe_bus_ver2_priv *ver2_bus_priv,
1764 struct cam_vfe_bus_ver2_hw_info *ver2_hw_info,
1765 struct cam_isp_resource_node *vfe_out)
1766{
1767 struct cam_vfe_bus_ver2_vfe_out_data *rsrc_data = NULL;
1768 int rc = 0;
1769
1770 rsrc_data = kzalloc(sizeof(struct cam_vfe_bus_ver2_vfe_out_data),
1771 GFP_KERNEL);
1772 if (!rsrc_data) {
1773 CDBG("Error! Failed to alloc for vfe out priv\n");
1774 rc = -ENOMEM;
1775 return rc;
1776 }
1777 vfe_out->res_priv = rsrc_data;
1778
1779 vfe_out->res_type = CAM_ISP_RESOURCE_VFE_OUT;
1780 vfe_out->res_state = CAM_ISP_RESOURCE_STATE_AVAILABLE;
1781 INIT_LIST_HEAD(&vfe_out->list);
1782
1783 rsrc_data->out_type = index;
1784 rsrc_data->common_data = &ver2_bus_priv->common_data;
1785 rsrc_data->max_width =
1786 ver2_hw_info->vfe_out_hw_info[index].max_width;
1787 rsrc_data->max_height =
1788 ver2_hw_info->vfe_out_hw_info[index].max_height;
1789
1790 vfe_out->start = cam_vfe_bus_start_vfe_out;
1791 vfe_out->stop = cam_vfe_bus_stop_vfe_out;
1792 vfe_out->top_half_handler = cam_vfe_bus_handle_vfe_out_done_top_half;
1793 vfe_out->bottom_half_handler =
1794 cam_vfe_bus_handle_vfe_out_done_bottom_half;
1795 vfe_out->hw_intf = ver2_bus_priv->common_data.hw_intf;
1796
1797 return 0;
1798}
1799
Harsh Shah545df9a2017-06-16 16:43:17 -07001800static int cam_vfe_bus_deinit_vfe_out_resource(
1801 struct cam_isp_resource_node *vfe_out)
1802{
1803 struct cam_vfe_bus_ver2_vfe_out_data *rsrc_data = vfe_out->res_priv;
1804
1805 vfe_out->start = NULL;
1806 vfe_out->stop = NULL;
1807 vfe_out->top_half_handler = NULL;
1808 vfe_out->bottom_half_handler = NULL;
1809 vfe_out->hw_intf = NULL;
1810
1811 vfe_out->res_state = CAM_ISP_RESOURCE_STATE_UNAVAILABLE;
1812 INIT_LIST_HEAD(&vfe_out->list);
1813 vfe_out->res_priv = NULL;
1814
1815 if (!rsrc_data) {
1816 pr_err("Error! vfe out priv is NULL\n");
1817 return -ENOMEM;
1818 }
1819 kfree(rsrc_data);
1820
1821 return 0;
1822}
1823
Harsh Shaha1af8822017-05-11 22:06:36 -07001824static int cam_vfe_bus_ver2_handle_irq(uint32_t evt_id,
1825 struct cam_irq_th_payload *th_payload)
1826{
Harsh Shaha1af8822017-05-11 22:06:36 -07001827 struct cam_vfe_bus_ver2_priv *bus_priv;
Harsh Shaha1af8822017-05-11 22:06:36 -07001828
Harsh Shah19f55812017-06-26 18:58:49 -07001829 bus_priv = th_payload->handler_priv;
Harsh Shaha1af8822017-05-11 22:06:36 -07001830 CDBG("Enter\n");
Harsh Shah19f55812017-06-26 18:58:49 -07001831 return cam_irq_controller_handle_irq(evt_id,
1832 bus_priv->common_data.bus_irq_controller);
Harsh Shaha1af8822017-05-11 22:06:36 -07001833}
1834
1835static int cam_vfe_bus_update_buf(void *priv, void *cmd_args,
1836 uint32_t arg_size)
1837{
1838 struct cam_vfe_bus_ver2_priv *bus_priv;
1839 struct cam_isp_hw_get_buf_update *update_buf;
Jing Zhoua4e9fbe2017-05-15 14:37:21 -07001840 struct cam_buf_io_cfg *io_cfg;
Harsh Shaha1af8822017-05-11 22:06:36 -07001841 struct cam_vfe_bus_ver2_vfe_out_data *vfe_out_data = NULL;
1842 struct cam_vfe_bus_ver2_wm_resource_data *wm_data = NULL;
Jing Zhoua4e9fbe2017-05-15 14:37:21 -07001843 uint32_t *reg_val_pair;
1844 uint32_t i, j, size = 0;
Junzhe Zou193d78c2017-05-16 15:10:54 -07001845 uint32_t frame_inc = 0;
Harsh Shaha1af8822017-05-11 22:06:36 -07001846
1847 /*
1848 * Need the entire buf io config so we can get the stride info
1849 * for the wm.
1850 */
1851
1852 bus_priv = (struct cam_vfe_bus_ver2_priv *) priv;
1853 update_buf = (struct cam_isp_hw_get_buf_update *) cmd_args;
1854
1855 vfe_out_data = (struct cam_vfe_bus_ver2_vfe_out_data *)
1856 update_buf->cdm.res->res_priv;
1857
1858 if (!vfe_out_data || !vfe_out_data->cdm_util_ops) {
1859 pr_err("Failed! Invalid data\n");
1860 return -EINVAL;
1861 }
1862
Jing Zhoua4e9fbe2017-05-15 14:37:21 -07001863 if (update_buf->num_buf != vfe_out_data->num_wm) {
Harsh Shaha1af8822017-05-11 22:06:36 -07001864 pr_err("Failed! Invalid number buffers:%d required:%d\n",
1865 update_buf->num_buf, vfe_out_data->num_wm);
Junzhe Zou193d78c2017-05-16 15:10:54 -07001866 return -EINVAL;
Harsh Shaha1af8822017-05-11 22:06:36 -07001867 }
1868
Jing Zhoua4e9fbe2017-05-15 14:37:21 -07001869 reg_val_pair = &vfe_out_data->common_data->io_buf_update[0];
1870 io_cfg = update_buf->io_cfg;
1871
1872 for (i = 0, j = 0; i < vfe_out_data->num_wm; i++) {
Junzhe Zou193d78c2017-05-16 15:10:54 -07001873 if (j >= (MAX_REG_VAL_PAIR_SIZE - MAX_BUF_UPDATE_REG_NUM * 2)) {
1874 pr_err("reg_val_pair %d exceeds the array limit %lu\n",
1875 j, MAX_REG_VAL_PAIR_SIZE);
1876 return -ENOMEM;
1877 }
1878
Jing Zhoua4e9fbe2017-05-15 14:37:21 -07001879 wm_data = vfe_out_data->wm_res[i]->res_priv;
1880
1881 /* For initial configuration program all bus registers */
1882 if (wm_data->stride != io_cfg->planes[i].plane_stride ||
1883 !wm_data->init_cfg_done) {
1884 CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j,
1885 wm_data->hw_regs->stride,
1886 io_cfg->planes[i].plane_stride);
1887 wm_data->stride = io_cfg->planes[i].plane_stride;
1888 }
1889 CDBG("image stride 0x%x\n", wm_data->stride);
1890
1891 if (wm_data->framedrop_pattern != io_cfg->framedrop_pattern ||
1892 !wm_data->init_cfg_done) {
1893 CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j,
1894 wm_data->hw_regs->framedrop_pattern,
1895 io_cfg->framedrop_pattern);
1896 wm_data->framedrop_pattern = io_cfg->framedrop_pattern;
1897 }
1898 CDBG("framedrop pattern 0x%x\n", wm_data->framedrop_pattern);
1899
1900 if (wm_data->framedrop_period != io_cfg->framedrop_period ||
1901 !wm_data->init_cfg_done) {
1902 CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j,
1903 wm_data->hw_regs->framedrop_period,
1904 io_cfg->framedrop_period);
1905 wm_data->framedrop_period = io_cfg->framedrop_period;
1906 }
1907 CDBG("framedrop period 0x%x\n", wm_data->framedrop_period);
1908
1909 if (wm_data->irq_subsample_period != io_cfg->subsample_period
1910 || !wm_data->init_cfg_done) {
1911 CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j,
1912 wm_data->hw_regs->irq_subsample_period,
1913 io_cfg->subsample_period);
1914 wm_data->irq_subsample_period =
1915 io_cfg->subsample_period;
1916 }
1917 CDBG("irq subsample period 0x%x\n",
1918 wm_data->irq_subsample_period);
1919
1920 if (wm_data->irq_subsample_pattern != io_cfg->subsample_pattern
1921 || !wm_data->init_cfg_done) {
1922 CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j,
1923 wm_data->hw_regs->irq_subsample_pattern,
1924 io_cfg->subsample_pattern);
1925 wm_data->irq_subsample_pattern =
1926 io_cfg->subsample_pattern;
1927 }
1928 CDBG("irq subsample pattern 0x%x\n",
1929 wm_data->irq_subsample_pattern);
1930
1931 if (wm_data->en_ubwc) {
1932 if (!wm_data->hw_regs->ubwc_regs) {
1933 pr_err("%s: No UBWC register to configure.\n",
1934 __func__);
1935 return -EINVAL;
1936 }
1937 if (wm_data->packer_cfg !=
1938 io_cfg->planes[i].packer_config ||
1939 !wm_data->init_cfg_done) {
1940 CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j,
1941 wm_data->hw_regs->packer_cfg,
1942 io_cfg->planes[i].packer_config);
1943 wm_data->packer_cfg =
1944 io_cfg->planes[i].packer_config;
1945 }
1946 CDBG("packer cfg 0x%x\n", wm_data->packer_cfg);
1947
1948 if (wm_data->tile_cfg != io_cfg->planes[i].tile_config
1949 || !wm_data->init_cfg_done) {
1950 CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j,
1951 wm_data->hw_regs->ubwc_regs->tile_cfg,
1952 io_cfg->planes[i].tile_config);
1953 wm_data->tile_cfg =
1954 io_cfg->planes[i].tile_config;
1955 }
1956 CDBG("tile cfg 0x%x\n", wm_data->tile_cfg);
1957
1958 if (wm_data->h_init != io_cfg->planes[i].h_init ||
1959 !wm_data->init_cfg_done) {
1960 CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j,
1961 wm_data->hw_regs->ubwc_regs->h_init,
1962 io_cfg->planes[i].h_init);
1963 wm_data->h_init = io_cfg->planes[i].h_init;
1964 }
1965 CDBG("h_init 0x%x\n", wm_data->h_init);
1966
1967 if (wm_data->v_init != io_cfg->planes[i].v_init ||
1968 !wm_data->init_cfg_done) {
1969 CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j,
1970 wm_data->hw_regs->ubwc_regs->v_init,
1971 io_cfg->planes[i].v_init);
1972 wm_data->v_init = io_cfg->planes[i].v_init;
1973 }
1974 CDBG("v_init 0x%x\n", wm_data->v_init);
1975
1976 if (wm_data->ubwc_meta_stride !=
1977 io_cfg->planes[i].meta_stride ||
1978 !wm_data->init_cfg_done) {
1979 CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j,
1980 wm_data->hw_regs->ubwc_regs->
1981 meta_stride,
1982 io_cfg->planes[i].meta_stride);
1983 wm_data->ubwc_meta_stride =
1984 io_cfg->planes[i].meta_stride;
1985 }
1986 CDBG("meta stride 0x%x\n", wm_data->ubwc_meta_stride);
1987
1988 if (wm_data->ubwc_mode_cfg !=
1989 io_cfg->planes[i].mode_config ||
1990 !wm_data->init_cfg_done) {
1991 CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j,
1992 wm_data->hw_regs->ubwc_regs->mode_cfg,
1993 io_cfg->planes[i].mode_config);
1994 wm_data->ubwc_mode_cfg =
1995 io_cfg->planes[i].mode_config;
1996 }
1997 CDBG("ubwc mode cfg 0x%x\n", wm_data->ubwc_mode_cfg);
1998
1999 if (wm_data->ubwc_meta_offset !=
2000 io_cfg->planes[i].meta_offset ||
2001 !wm_data->init_cfg_done) {
2002 CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j,
2003 wm_data->hw_regs->ubwc_regs->
2004 meta_offset,
2005 io_cfg->planes[i].meta_offset);
2006 wm_data->ubwc_meta_offset =
2007 io_cfg->planes[i].meta_offset;
2008 }
2009 CDBG("ubwc meta offset 0x%x\n",
2010 wm_data->ubwc_meta_offset);
2011
2012 /* UBWC meta address */
2013 CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j,
2014 wm_data->hw_regs->ubwc_regs->meta_addr,
2015 update_buf->image_buf[i]);
2016 CDBG("ubwc meta addr 0x%llx\n",
2017 update_buf->image_buf[i]);
2018 }
2019
2020 /* WM Image address */
2021 if (wm_data->en_ubwc)
2022 CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j,
2023 wm_data->hw_regs->image_addr,
2024 (update_buf->image_buf[i] +
2025 io_cfg->planes[i].meta_size));
2026 else
2027 CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j,
2028 wm_data->hw_regs->image_addr,
2029 update_buf->image_buf[i]);
2030
2031 CDBG("image address 0x%x\n", reg_val_pair[j-1]);
2032
Junzhe Zou193d78c2017-05-16 15:10:54 -07002033 frame_inc = io_cfg->planes[i].plane_stride *
2034 io_cfg->planes[i].slice_height;
2035 CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j,
2036 wm_data->hw_regs->frame_inc, frame_inc);
2037
Jing Zhoua4e9fbe2017-05-15 14:37:21 -07002038 /* enable the WM */
2039 CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j,
2040 wm_data->hw_regs->cfg,
2041 wm_data->en_cfg);
2042
2043 /* set initial configuration done */
2044 if (!wm_data->init_cfg_done)
2045 wm_data->init_cfg_done = 1;
2046 }
2047
2048 size = vfe_out_data->cdm_util_ops->cdm_required_size_reg_random(j/2);
Harsh Shaha1af8822017-05-11 22:06:36 -07002049
2050 /* cdm util returns dwords, need to convert to bytes */
2051 if ((size * 4) > update_buf->cdm.size) {
2052 pr_err("Failed! Buf size:%d insufficient, expected size:%d\n",
2053 update_buf->cdm.size, size);
2054 return -ENOMEM;
2055 }
2056
Harsh Shaha1af8822017-05-11 22:06:36 -07002057 vfe_out_data->cdm_util_ops->cdm_write_regrandom(
Jing Zhoua4e9fbe2017-05-15 14:37:21 -07002058 update_buf->cdm.cmd_buf_addr, j/2, reg_val_pair);
2059
Harsh Shaha1af8822017-05-11 22:06:36 -07002060 /* cdm util returns dwords, need to convert to bytes */
2061 update_buf->cdm.used_bytes = size * 4;
2062
2063 return 0;
2064}
2065
Harsh Shah19f55812017-06-26 18:58:49 -07002066static int cam_vfe_bus_start_hw(void *hw_priv,
2067 void *start_hw_args, uint32_t arg_size)
2068{
2069 return cam_vfe_bus_start_vfe_out(hw_priv);
2070}
2071
2072static int cam_vfe_bus_stop_hw(void *hw_priv,
2073 void *stop_hw_args, uint32_t arg_size)
2074{
2075 return cam_vfe_bus_stop_vfe_out(hw_priv);
2076}
2077
2078static int cam_vfe_bus_init_hw(void *hw_priv,
2079 void *init_hw_args, uint32_t arg_size)
2080{
2081 struct cam_vfe_bus_ver2_priv *bus_priv = hw_priv;
2082 uint32_t top_irq_reg_mask[2] = {0};
2083
2084 if (!bus_priv) {
2085 pr_err("Error! Invalid args\n");
2086 return -EINVAL;
2087 }
2088
2089 top_irq_reg_mask[0] = (1 << 9);
2090
2091 bus_priv->irq_handle = cam_irq_controller_subscribe_irq(
2092 bus_priv->common_data.vfe_irq_controller,
2093 CAM_IRQ_PRIORITY_2,
2094 top_irq_reg_mask,
2095 bus_priv,
2096 cam_vfe_bus_ver2_handle_irq,
2097 NULL,
2098 NULL,
2099 NULL);
2100
2101 if (bus_priv->irq_handle <= 0) {
2102 pr_err("Failed to subscribe BUS IRQ\n");
2103 return -EFAULT;
2104 }
2105
2106 return 0;
2107}
2108
2109static int cam_vfe_bus_deinit_hw(void *hw_priv,
2110 void *deinit_hw_args, uint32_t arg_size)
2111{
2112 struct cam_vfe_bus_ver2_priv *bus_priv = hw_priv;
2113 int rc;
2114
2115 if (!bus_priv || (bus_priv->irq_handle <= 0)) {
2116 pr_err("Error! Invalid args\n");
2117 return -EINVAL;
2118 }
2119
2120 rc = cam_irq_controller_unsubscribe_irq(
2121 bus_priv->common_data.vfe_irq_controller,
2122 bus_priv->irq_handle);
2123 if (rc)
2124 pr_err("Failed to unsubscribe irq rc=%d\n", rc);
2125
2126 return rc;
2127}
2128
Harsh Shaha1af8822017-05-11 22:06:36 -07002129static int cam_vfe_bus_process_cmd(void *priv,
2130 uint32_t cmd_type, void *cmd_args, uint32_t arg_size)
2131{
2132 int rc = -EINVAL;
2133
2134 if (!priv || !cmd_args) {
2135 pr_err_ratelimited("Error! Invalid input arguments\n");
2136 return -EINVAL;
2137 }
2138
2139 switch (cmd_type) {
2140 case CAM_VFE_HW_CMD_GET_BUF_UPDATE:
2141 rc = cam_vfe_bus_update_buf(priv, cmd_args, arg_size);
2142 break;
2143 default:
2144 pr_err_ratelimited("Error! Invalid camif process command:%d\n",
2145 cmd_type);
2146 break;
2147 }
2148
2149 return rc;
2150}
2151
2152int cam_vfe_bus_ver2_init(
Harsh Shah19f55812017-06-26 18:58:49 -07002153 struct cam_hw_soc_info *soc_info,
Harsh Shaha1af8822017-05-11 22:06:36 -07002154 struct cam_hw_intf *hw_intf,
2155 void *bus_hw_info,
2156 void *vfe_irq_controller,
2157 struct cam_vfe_bus **vfe_bus)
2158{
2159 int i, rc = 0;
2160 struct cam_vfe_bus_ver2_priv *bus_priv = NULL;
2161 struct cam_vfe_bus *vfe_bus_local;
2162 struct cam_vfe_bus_ver2_hw_info *ver2_hw_info = bus_hw_info;
2163
2164 CDBG("Enter\n");
2165
Harsh Shah19f55812017-06-26 18:58:49 -07002166 if (!soc_info || !hw_intf || !bus_hw_info || !vfe_irq_controller) {
2167 pr_err("Error! Invalid params soc_info %pK hw_intf %pK hw_info %pK controller %pK\n",
2168 soc_info, hw_intf, bus_hw_info, vfe_irq_controller);
2169 rc = -EINVAL;
2170 goto end;
2171 }
2172
Harsh Shaha1af8822017-05-11 22:06:36 -07002173 vfe_bus_local = kzalloc(sizeof(struct cam_vfe_bus), GFP_KERNEL);
2174 if (!vfe_bus_local) {
2175 CDBG("Failed to alloc for vfe_bus\n");
2176 rc = -ENOMEM;
Harsh Shah545df9a2017-06-16 16:43:17 -07002177 goto end;
Harsh Shaha1af8822017-05-11 22:06:36 -07002178 }
2179
2180 bus_priv = kzalloc(sizeof(struct cam_vfe_bus_ver2_priv),
2181 GFP_KERNEL);
2182 if (!bus_priv) {
2183 CDBG("Failed to alloc for vfe_bus_priv\n");
2184 rc = -ENOMEM;
Harsh Shah545df9a2017-06-16 16:43:17 -07002185 goto free_bus_local;
Harsh Shaha1af8822017-05-11 22:06:36 -07002186 }
2187 vfe_bus_local->bus_priv = bus_priv;
2188
Harsh Shah19f55812017-06-26 18:58:49 -07002189 bus_priv->common_data.core_index = soc_info->index;
2190 bus_priv->common_data.mem_base =
2191 CAM_SOC_GET_REG_MAP_START(soc_info, VFE_CORE_BASE_IDX);
Harsh Shaha1af8822017-05-11 22:06:36 -07002192 bus_priv->common_data.hw_intf = hw_intf;
2193 bus_priv->common_data.vfe_irq_controller = vfe_irq_controller;
2194 bus_priv->common_data.common_reg = &ver2_hw_info->common_reg;
2195
Harsh Shah19f55812017-06-26 18:58:49 -07002196 rc = cam_irq_controller_init(drv_name, bus_priv->common_data.mem_base,
2197 &ver2_hw_info->common_reg.irq_reg_info,
2198 &bus_priv->common_data.bus_irq_controller);
2199 if (rc) {
2200 pr_err("Error! cam_irq_controller_init failed\n");
2201 goto free_bus_priv;
2202 }
2203
Harsh Shaha1af8822017-05-11 22:06:36 -07002204 INIT_LIST_HEAD(&bus_priv->free_comp_grp);
2205 INIT_LIST_HEAD(&bus_priv->free_dual_comp_grp);
2206 INIT_LIST_HEAD(&bus_priv->used_comp_grp);
2207
2208 for (i = 0; i < CAM_VFE_BUS_VER2_MAX_CLIENTS; i++) {
2209 rc = cam_vfe_bus_init_wm_resource(i, bus_priv, bus_hw_info,
2210 &bus_priv->bus_client[i]);
2211 if (rc < 0) {
Harsh Shah545df9a2017-06-16 16:43:17 -07002212 pr_err("Error! Init WM failed rc=%d\n", rc);
2213 goto deinit_wm;
Harsh Shaha1af8822017-05-11 22:06:36 -07002214 }
2215 }
2216
2217 for (i = 0; i < CAM_VFE_BUS_VER2_COMP_GRP_MAX; i++) {
2218 rc = cam_vfe_bus_init_comp_grp(i, bus_priv, bus_hw_info,
2219 &bus_priv->comp_grp[i]);
2220 if (rc < 0) {
Harsh Shah545df9a2017-06-16 16:43:17 -07002221 pr_err("Error! Init Comp Grp failed rc=%d\n", rc);
2222 goto deinit_comp_grp;
Harsh Shaha1af8822017-05-11 22:06:36 -07002223 }
2224 }
2225
2226 for (i = 0; i < CAM_VFE_BUS_VER2_VFE_OUT_MAX; i++) {
2227 rc = cam_vfe_bus_init_vfe_out_resource(i, bus_priv, bus_hw_info,
2228 &bus_priv->vfe_out[i]);
2229 if (rc < 0) {
Harsh Shah545df9a2017-06-16 16:43:17 -07002230 pr_err("Error! Init VFE Out failed rc=%d\n", rc);
2231 goto deinit_vfe_out;
Harsh Shaha1af8822017-05-11 22:06:36 -07002232 }
2233 }
2234
Harsh Shah19f55812017-06-26 18:58:49 -07002235 INIT_LIST_HEAD(&bus_priv->common_data.free_payload_list);
2236 for (i = 0; i < CAM_VFE_BUS_VER2_PAYLOAD_MAX; i++) {
2237 INIT_LIST_HEAD(&bus_priv->common_data.evt_payload[i].list);
2238 list_add_tail(&bus_priv->common_data.evt_payload[i].list,
2239 &bus_priv->common_data.free_payload_list);
Harsh Shaha1af8822017-05-11 22:06:36 -07002240 }
2241
Harsh Shah19f55812017-06-26 18:58:49 -07002242 vfe_bus_local->hw_ops.reserve = cam_vfe_bus_acquire_vfe_out;
2243 vfe_bus_local->hw_ops.release = cam_vfe_bus_release_vfe_out;
2244 vfe_bus_local->hw_ops.start = cam_vfe_bus_start_hw;
2245 vfe_bus_local->hw_ops.stop = cam_vfe_bus_stop_hw;
2246 vfe_bus_local->hw_ops.init = cam_vfe_bus_init_hw;
2247 vfe_bus_local->hw_ops.deinit = cam_vfe_bus_deinit_hw;
2248 vfe_bus_local->top_half_handler = cam_vfe_bus_ver2_handle_irq;
Harsh Shaha1af8822017-05-11 22:06:36 -07002249 vfe_bus_local->bottom_half_handler = NULL;
Harsh Shah19f55812017-06-26 18:58:49 -07002250 vfe_bus_local->hw_ops.process_cmd = cam_vfe_bus_process_cmd;
Harsh Shaha1af8822017-05-11 22:06:36 -07002251
2252 *vfe_bus = vfe_bus_local;
2253
Harsh Shah545df9a2017-06-16 16:43:17 -07002254 CDBG("Exit\n");
Harsh Shaha1af8822017-05-11 22:06:36 -07002255 return rc;
2256
Harsh Shah545df9a2017-06-16 16:43:17 -07002257deinit_vfe_out:
2258 if (i < 0)
2259 i = CAM_VFE_BUS_VER2_VFE_OUT_MAX;
2260 for (--i; i >= 0; i--)
2261 cam_vfe_bus_deinit_vfe_out_resource(&bus_priv->vfe_out[i]);
2262
2263deinit_comp_grp:
2264 if (i < 0)
2265 i = CAM_VFE_BUS_VER2_COMP_GRP_MAX;
2266 for (--i; i >= 0; i--)
2267 cam_vfe_bus_deinit_comp_grp(&bus_priv->comp_grp[i]);
2268
2269deinit_wm:
2270 if (i < 0)
2271 i = CAM_VFE_BUS_VER2_MAX_CLIENTS;
2272 for (--i; i >= 0; i--)
2273 cam_vfe_bus_deinit_wm_resource(&bus_priv->bus_client[i]);
2274
Harsh Shah19f55812017-06-26 18:58:49 -07002275free_bus_priv:
Harsh Shaha1af8822017-05-11 22:06:36 -07002276 kfree(vfe_bus_local->bus_priv);
Harsh Shah545df9a2017-06-16 16:43:17 -07002277
2278free_bus_local:
Harsh Shaha1af8822017-05-11 22:06:36 -07002279 kfree(vfe_bus_local);
Harsh Shah545df9a2017-06-16 16:43:17 -07002280
2281end:
Harsh Shaha1af8822017-05-11 22:06:36 -07002282 return rc;
2283}
Harsh Shah545df9a2017-06-16 16:43:17 -07002284
2285int cam_vfe_bus_ver2_deinit(
2286 struct cam_vfe_bus **vfe_bus)
2287{
2288 int i, rc = 0;
2289 struct cam_vfe_bus_ver2_priv *bus_priv = NULL;
2290 struct cam_vfe_bus *vfe_bus_local;
2291
2292 if (!vfe_bus || !*vfe_bus) {
2293 pr_err("Error! Invalid input\n");
2294 return -EINVAL;
2295 }
2296 vfe_bus_local = *vfe_bus;
2297
2298 bus_priv = vfe_bus_local->bus_priv;
2299 if (!bus_priv) {
2300 pr_err("Error! bus_priv is NULL\n");
2301 rc = -ENODEV;
2302 goto free_bus_local;
2303 }
2304
Harsh Shah19f55812017-06-26 18:58:49 -07002305 INIT_LIST_HEAD(&bus_priv->common_data.free_payload_list);
2306 for (i = 0; i < CAM_VFE_BUS_VER2_PAYLOAD_MAX; i++)
2307 INIT_LIST_HEAD(&bus_priv->common_data.evt_payload[i].list);
Harsh Shah545df9a2017-06-16 16:43:17 -07002308
2309 for (i = 0; i < CAM_VFE_BUS_VER2_MAX_CLIENTS; i++) {
2310 rc = cam_vfe_bus_deinit_wm_resource(&bus_priv->bus_client[i]);
2311 if (rc < 0)
2312 pr_err("Error! Deinit WM failed rc=%d\n", rc);
2313 }
2314
2315 for (i = 0; i < CAM_VFE_BUS_VER2_COMP_GRP_MAX; i++) {
2316 rc = cam_vfe_bus_deinit_comp_grp(&bus_priv->comp_grp[i]);
2317 if (rc < 0)
2318 pr_err("Error! Deinit Comp Grp failed rc=%d\n", rc);
2319 }
2320
2321 for (i = 0; i < CAM_VFE_BUS_VER2_VFE_OUT_MAX; i++) {
2322 rc = cam_vfe_bus_deinit_vfe_out_resource(&bus_priv->vfe_out[i]);
2323 if (rc < 0)
2324 pr_err("Error! Deinit VFE Out failed rc=%d\n", rc);
2325 }
2326
2327 INIT_LIST_HEAD(&bus_priv->free_comp_grp);
2328 INIT_LIST_HEAD(&bus_priv->free_dual_comp_grp);
2329 INIT_LIST_HEAD(&bus_priv->used_comp_grp);
2330
Harsh Shah19f55812017-06-26 18:58:49 -07002331 rc = cam_irq_controller_deinit(
2332 &bus_priv->common_data.bus_irq_controller);
2333 if (rc)
2334 pr_err("Error! Deinit IRQ Controller failed rc=%d\n", rc);
2335
Harsh Shah545df9a2017-06-16 16:43:17 -07002336 kfree(vfe_bus_local->bus_priv);
2337
2338free_bus_local:
2339 kfree(vfe_bus_local);
2340
2341 *vfe_bus = NULL;
2342
2343 return rc;
2344}
2345