blob: 07a76125149ffea0bca220e6538e77e0a797bc58 [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:
Abhishek Kondaveetib31b46c2017-06-23 04:56:24 +0530427 case CAM_FORMAT_PLAIN128:
Harsh Shaha1af8822017-05-11 22:06:36 -0700428 return 1;
429 default:
430 break;
431 }
432 break;
433 case CAM_VFE_BUS_VER2_VFE_OUT_STATS_RS:
434 case CAM_VFE_BUS_VER2_VFE_OUT_STATS_IHIST:
435 switch (format) {
436 case CAM_FORMAT_PLAIN16_16:
437 return 1;
438 default:
439 break;
440 }
441 break;
442 default:
443 break;
444 }
445
446 pr_err("Unsupported format %u for resource_type %u", format, res_type);
447
448 return -EINVAL;
449}
450
451static int cam_vfe_bus_get_wm_idx(
452 enum cam_vfe_bus_ver2_vfe_out_type vfe_out_res_id,
453 enum cam_vfe_bus_plane_type plane)
454{
455 int wm_idx = -1;
456
457 switch (vfe_out_res_id) {
458 case CAM_VFE_BUS_VER2_VFE_OUT_FULL:
459 switch (plane) {
460 case PLANE_Y:
461 wm_idx = 3;
462 break;
463 case PLANE_C:
464 wm_idx = 4;
465 break;
466 default:
467 break;
468 }
469 break;
470 case CAM_VFE_BUS_VER2_VFE_OUT_DS4:
471 switch (plane) {
472 case PLANE_Y:
473 wm_idx = 5;
474 break;
475 default:
476 break;
477 }
478 break;
479 case CAM_VFE_BUS_VER2_VFE_OUT_DS16:
480 switch (plane) {
481 case PLANE_Y:
482 wm_idx = 6;
483 break;
484 default:
485 break;
486 }
487 break;
488 case CAM_VFE_BUS_VER2_VFE_OUT_FD:
489 switch (plane) {
490 case PLANE_Y:
491 wm_idx = 7;
492 break;
493 case PLANE_C:
494 wm_idx = 8;
495 break;
496 default:
497 break;
498 }
499 break;
500 case CAM_VFE_BUS_VER2_VFE_OUT_RAW_DUMP:
501 switch (plane) {
502 case PLANE_Y:
503 wm_idx = 9;
504 break;
505 default:
506 break;
507 }
508 break;
509 case CAM_VFE_BUS_VER2_VFE_OUT_PDAF:
510 switch (plane) {
511 case PLANE_Y:
512 wm_idx = 10;
513 break;
514 default:
515 break;
516 }
517 break;
518 case CAM_VFE_BUS_VER2_VFE_OUT_RDI0:
519 switch (plane) {
520 case PLANE_Y:
521 wm_idx = 0;
522 break;
523 default:
524 break;
525 }
526 break;
527 case CAM_VFE_BUS_VER2_VFE_OUT_RDI1:
528 switch (plane) {
529 case PLANE_Y:
530 wm_idx = 1;
531 break;
532 default:
533 break;
534 }
535 break;
536 case CAM_VFE_BUS_VER2_VFE_OUT_RDI2:
537 switch (plane) {
538 case PLANE_Y:
539 wm_idx = 2;
540 break;
541 default:
542 break;
543 }
544 break;
545 case CAM_VFE_BUS_VER2_VFE_OUT_STATS_HDR_BE:
546 switch (plane) {
547 case PLANE_Y:
548 wm_idx = 11;
549 break;
550 default:
551 break;
552 }
553 break;
554 case CAM_VFE_BUS_VER2_VFE_OUT_STATS_HDR_BHIST:
555 switch (plane) {
556 case PLANE_Y:
557 wm_idx = 12;
558 break;
559 default:
560 break;
561 }
562 break;
563 case CAM_VFE_BUS_VER2_VFE_OUT_STATS_TL_BG:
564 switch (plane) {
565 case PLANE_Y:
566 wm_idx = 13;
567 break;
568 default:
569 break;
570 }
571 break;
572 case CAM_VFE_BUS_VER2_VFE_OUT_STATS_BF:
573 switch (plane) {
574 case PLANE_Y:
575 wm_idx = 14;
576 break;
577 default:
578 break;
579 }
580 break;
581 case CAM_VFE_BUS_VER2_VFE_OUT_STATS_AWB_BG:
582 switch (plane) {
583 case PLANE_Y:
584 wm_idx = 15;
585 break;
586 default:
587 break;
588 }
589 break;
590 case CAM_VFE_BUS_VER2_VFE_OUT_STATS_BHIST:
591 switch (plane) {
592 case PLANE_Y:
593 wm_idx = 16;
594 break;
595 default:
596 break;
597 }
598 break;
599 case CAM_VFE_BUS_VER2_VFE_OUT_STATS_RS:
600 switch (plane) {
601 case PLANE_Y:
602 wm_idx = 17;
603 break;
604 default:
605 break;
606 }
607 break;
608 case CAM_VFE_BUS_VER2_VFE_OUT_STATS_CS:
609 switch (plane) {
610 case PLANE_Y:
611 wm_idx = 18;
612 break;
613 default:
614 break;
615 }
616 break;
617 case CAM_VFE_BUS_VER2_VFE_OUT_STATS_IHIST:
618 switch (plane) {
619 case PLANE_Y:
620 wm_idx = 19;
621 break;
622 default:
623 break;
624 }
625 break;
626 default:
627 break;
628 }
629
630 return wm_idx;
631}
632
633static enum cam_vfe_bus_packer_format
634 cam_vfe_bus_get_packer_fmt(uint32_t out_fmt)
635{
636 switch (out_fmt) {
637 case CAM_FORMAT_NV21:
638 case CAM_FORMAT_NV12:
639 return PACKER_FMT_PLAIN_8;
640 default:
641 return PACKER_FMT_MAX;
642 }
643}
644
645static int cam_vfe_bus_acquire_wm(
646 struct cam_vfe_bus_ver2_priv *ver2_bus_priv,
647 struct cam_isp_out_port_info *out_port_info,
Harsh Shah19f55812017-06-26 18:58:49 -0700648 void *tasklet,
649 void *ctx,
Harsh Shaha1af8822017-05-11 22:06:36 -0700650 enum cam_vfe_bus_ver2_vfe_out_type vfe_out_res_id,
651 enum cam_vfe_bus_plane_type plane,
652 enum cam_isp_hw_split_id split_id,
653 uint32_t subscribe_irq,
654 struct cam_isp_resource_node **wm_res,
655 uint32_t *client_done_mask)
656{
657 uint32_t wm_idx = 0;
658 struct cam_isp_resource_node *wm_res_local = NULL;
659 struct cam_vfe_bus_ver2_wm_resource_data *rsrc_data = NULL;
660
661 *wm_res = NULL;
662 *client_done_mask = 0;
663
664 /* No need to allocate for BUS VER2. VFE OUT to WM is fixed. */
665 wm_idx = cam_vfe_bus_get_wm_idx(vfe_out_res_id, plane);
666 if (wm_idx < 0 || wm_idx >= CAM_VFE_BUS_VER2_MAX_CLIENTS) {
667 pr_err("Unsupported VFE out %d plane %d\n",
668 vfe_out_res_id, plane);
669 return -EINVAL;
670 }
671
672 wm_res_local = &ver2_bus_priv->bus_client[wm_idx];
Harsh Shah19f55812017-06-26 18:58:49 -0700673 wm_res_local->tasklet_info = tasklet;
Harsh Shaha1af8822017-05-11 22:06:36 -0700674 wm_res_local->res_state = CAM_ISP_RESOURCE_STATE_RESERVED;
675
676 rsrc_data = wm_res_local->res_priv;
677 rsrc_data->irq_enabled = subscribe_irq;
Harsh Shah19f55812017-06-26 18:58:49 -0700678 rsrc_data->ctx = ctx;
Harsh Shaha1af8822017-05-11 22:06:36 -0700679 rsrc_data->format = out_port_info->format;
680 rsrc_data->pack_fmt = cam_vfe_bus_get_packer_fmt(rsrc_data->format);
681
682 rsrc_data->width = out_port_info->width;
683 rsrc_data->height = out_port_info->height;
Jing Zhoua4e9fbe2017-05-15 14:37:21 -0700684
685 if (rsrc_data->index < 3) {
686 rsrc_data->width = rsrc_data->width * 5/4 * rsrc_data->height;
687 rsrc_data->height = 1;
688 rsrc_data->pack_fmt = 0x0;
689 rsrc_data->en_cfg = 0x3;
Abhishek Kondaveetib31b46c2017-06-23 04:56:24 +0530690 } else if (rsrc_data->index < 5 ||
691 rsrc_data->index == 7 || rsrc_data->index == 8) {
Jing Zhoua4e9fbe2017-05-15 14:37:21 -0700692 switch (plane) {
693 case PLANE_Y:
694 switch (rsrc_data->format) {
695 case CAM_FORMAT_UBWC_NV12:
696 case CAM_FORMAT_UBWC_NV12_4R:
697 case CAM_FORMAT_UBWC_TP10:
698 rsrc_data->en_ubwc = 1;
699 break;
700 default:
701 break;
702 }
703 break;
704 case PLANE_C:
705 switch (rsrc_data->format) {
706 case CAM_FORMAT_NV21:
707 case CAM_FORMAT_NV12:
708 rsrc_data->height /= 2;
709 break;
710 case CAM_FORMAT_UBWC_NV12:
711 case CAM_FORMAT_UBWC_NV12_4R:
712 case CAM_FORMAT_UBWC_TP10:
713 rsrc_data->height /= 2;
714 rsrc_data->en_ubwc = 1;
715 break;
716 default:
717 break;
718 }
Harsh Shaha1af8822017-05-11 22:06:36 -0700719 break;
720 default:
Jing Zhoua4e9fbe2017-05-15 14:37:21 -0700721 pr_err("Invalid plane type %d\n", plane);
722 return -EINVAL;
Harsh Shaha1af8822017-05-11 22:06:36 -0700723 }
Jing Zhoua4e9fbe2017-05-15 14:37:21 -0700724 rsrc_data->pack_fmt = 0xE;
725 rsrc_data->en_cfg = 0x1;
Abhishek Kondaveetib31b46c2017-06-23 04:56:24 +0530726 } else if (rsrc_data->index >= 11) {
727 rsrc_data->width = 0;
728 rsrc_data->height = 0;
729 rsrc_data->pack_fmt = 0x0;
730 rsrc_data->stride = 1;
731 rsrc_data->en_cfg = 0x3;
Jing Zhoua4e9fbe2017-05-15 14:37:21 -0700732 } else {
733 rsrc_data->width = rsrc_data->width * 4;
734 rsrc_data->height = rsrc_data->height / 2;
735 rsrc_data->pack_fmt = 0x0;
736 rsrc_data->en_cfg = 0x1;
Harsh Shaha1af8822017-05-11 22:06:36 -0700737 }
738
739 if (vfe_out_res_id >= CAM_ISP_IFE_OUT_RES_RDI_0 &&
740 vfe_out_res_id <= CAM_ISP_IFE_OUT_RES_RDI_3)
741 rsrc_data->frame_based = 1;
742
743 *client_done_mask = (1 << wm_idx);
744 *wm_res = wm_res_local;
745
746 return 0;
747}
748
749static int cam_vfe_bus_release_wm(void *bus_priv,
750 struct cam_isp_resource_node *wm_res)
751{
752 struct cam_vfe_bus_ver2_wm_resource_data *rsrc_data =
753 wm_res->res_priv;
754
755 rsrc_data->irq_enabled = 0;
756 rsrc_data->offset = 0;
757 rsrc_data->width = 0;
758 rsrc_data->height = 0;
759 rsrc_data->stride = 0;
760 rsrc_data->format = 0;
761 rsrc_data->pack_fmt = 0;
762 rsrc_data->burst_len = 0;
763 rsrc_data->frame_based = 0;
764 rsrc_data->irq_subsample_period = 0;
765 rsrc_data->irq_subsample_pattern = 0;
766 rsrc_data->framedrop_period = 0;
767 rsrc_data->framedrop_pattern = 0;
Jing Zhoua4e9fbe2017-05-15 14:37:21 -0700768 rsrc_data->packer_cfg = 0;
769 rsrc_data->en_ubwc = 0;
770 rsrc_data->tile_cfg = 0;
771 rsrc_data->h_init = 0;
772 rsrc_data->v_init = 0;
773 rsrc_data->ubwc_meta_stride = 0;
774 rsrc_data->ubwc_mode_cfg = 0;
775 rsrc_data->ubwc_meta_offset = 0;
776 rsrc_data->init_cfg_done = 0;
777 rsrc_data->en_cfg = 0;
Harsh Shah19f55812017-06-26 18:58:49 -0700778
779 wm_res->tasklet_info = NULL;
Harsh Shaha1af8822017-05-11 22:06:36 -0700780 wm_res->res_state = CAM_ISP_RESOURCE_STATE_AVAILABLE;
781
782 return 0;
783}
784
785static int cam_vfe_bus_start_wm(struct cam_isp_resource_node *wm_res)
786{
787 int rc = 0;
788 struct cam_vfe_bus_ver2_wm_resource_data *rsrc_data =
789 wm_res->res_priv;
790 struct cam_vfe_bus_ver2_common_data *common_data =
791 rsrc_data->common_data;
Harsh Shah19f55812017-06-26 18:58:49 -0700792 uint32_t bus_irq_reg_mask[CAM_VFE_BUS_IRQ_MAX] = {0};
Harsh Shaha1af8822017-05-11 22:06:36 -0700793
Harsh Shah23557ae2017-05-13 18:14:34 -0700794 cam_io_w_mb(0, common_data->mem_base + rsrc_data->hw_regs->header_addr);
795 cam_io_w_mb(0, common_data->mem_base + rsrc_data->hw_regs->header_cfg);
796 cam_io_w_mb(0, common_data->mem_base + rsrc_data->hw_regs->frame_inc);
797 cam_io_w(0xf, common_data->mem_base + rsrc_data->hw_regs->burst_limit);
798
Jing Zhoua4e9fbe2017-05-15 14:37:21 -0700799 cam_io_w_mb(rsrc_data->width,
Harsh Shaha1af8822017-05-11 22:06:36 -0700800 common_data->mem_base + rsrc_data->hw_regs->buffer_width_cfg);
Jing Zhoua4e9fbe2017-05-15 14:37:21 -0700801 cam_io_w(rsrc_data->height,
Harsh Shaha1af8822017-05-11 22:06:36 -0700802 common_data->mem_base + rsrc_data->hw_regs->buffer_height_cfg);
Jing Zhoua4e9fbe2017-05-15 14:37:21 -0700803 cam_io_w(rsrc_data->pack_fmt,
Harsh Shaha1af8822017-05-11 22:06:36 -0700804 common_data->mem_base + rsrc_data->hw_regs->packer_cfg);
Harsh Shaha1af8822017-05-11 22:06:36 -0700805
806 cam_io_w(0xFFFFFFFF, common_data->mem_base +
807 rsrc_data->hw_regs->irq_subsample_pattern);
808 cam_io_w(0x0, common_data->mem_base +
809 rsrc_data->hw_regs->irq_subsample_period);
810
811 cam_io_w(0xFFFFFFFF,
Harsh Shah23557ae2017-05-13 18:14:34 -0700812 common_data->mem_base + rsrc_data->hw_regs->framedrop_pattern);
Harsh Shaha1af8822017-05-11 22:06:36 -0700813 cam_io_w(0x0,
Harsh Shah23557ae2017-05-13 18:14:34 -0700814 common_data->mem_base + rsrc_data->hw_regs->framedrop_period);
Harsh Shaha1af8822017-05-11 22:06:36 -0700815
Harsh Shah19f55812017-06-26 18:58:49 -0700816 /* Subscribe IRQ */
817 if (rsrc_data->irq_enabled) {
818 CDBG("Subscribe WM%d IRQ\n", rsrc_data->index);
819 bus_irq_reg_mask[CAM_VFE_BUS_IRQ_REG1] =
820 (1 << rsrc_data->index);
821 wm_res->irq_handle = cam_irq_controller_subscribe_irq(
822 common_data->bus_irq_controller, CAM_IRQ_PRIORITY_1,
823 bus_irq_reg_mask, wm_res,
824 wm_res->top_half_handler,
825 cam_ife_mgr_do_tasklet_buf_done,
826 wm_res->tasklet_info, cam_tasklet_enqueue_cmd);
827 if (wm_res->irq_handle < 0) {
828 pr_err("Subscribe IRQ failed for WM %d\n",
829 rsrc_data->index);
830 return -EFAULT;
831 }
832 }
833
834 /* Enable WM */
835 cam_io_w_mb(rsrc_data->en_cfg, common_data->mem_base +
836 rsrc_data->hw_regs->cfg);
837
Harsh Shah23557ae2017-05-13 18:14:34 -0700838 CDBG("WM res %d width = %d, height = %d\n", rsrc_data->index,
Jing Zhoua4e9fbe2017-05-15 14:37:21 -0700839 rsrc_data->width, rsrc_data->height);
Harsh Shah23557ae2017-05-13 18:14:34 -0700840 CDBG("WM res %d pk_fmt = %d\n", rsrc_data->index,
Jing Zhoua4e9fbe2017-05-15 14:37:21 -0700841 rsrc_data->pack_fmt & PACKER_FMT_MAX);
Harsh Shah23557ae2017-05-13 18:14:34 -0700842 CDBG("WM res %d stride = %d, burst len = %d\n",
Jing Zhoua4e9fbe2017-05-15 14:37:21 -0700843 rsrc_data->index, rsrc_data->stride, 0xf);
Harsh Shah23557ae2017-05-13 18:14:34 -0700844 CDBG("enable WM res %d offset 0x%x val 0x%x\n", rsrc_data->index,
Jing Zhoua4e9fbe2017-05-15 14:37:21 -0700845 (uint32_t) rsrc_data->hw_regs->cfg, rsrc_data->en_cfg);
Harsh Shaha1af8822017-05-11 22:06:36 -0700846
847 wm_res->res_state = CAM_ISP_RESOURCE_STATE_STREAMING;
848
849 return rc;
850}
851
852static int cam_vfe_bus_stop_wm(struct cam_isp_resource_node *wm_res)
853{
854 int rc = 0;
855 struct cam_vfe_bus_ver2_wm_resource_data *rsrc_data =
856 wm_res->res_priv;
857 struct cam_vfe_bus_ver2_common_data *common_data =
858 rsrc_data->common_data;
859
860 /* Disble WM */
861 cam_io_w_mb(0x0,
862 common_data->mem_base + rsrc_data->hw_regs->cfg);
863
864 CDBG("irq_enabled %d", rsrc_data->irq_enabled);
865 /* Unsubscribe IRQ */
Harsh Shah19f55812017-06-26 18:58:49 -0700866 if (rsrc_data->irq_enabled)
867 rc = cam_irq_controller_unsubscribe_irq(
868 common_data->bus_irq_controller,
869 wm_res->irq_handle);
Harsh Shaha1af8822017-05-11 22:06:36 -0700870
871 /* Halt & Reset WM */
872 cam_io_w_mb(BIT(rsrc_data->index),
873 common_data->mem_base + common_data->common_reg->sw_reset);
874
875 wm_res->res_state = CAM_ISP_RESOURCE_STATE_RESERVED;
876
877 return rc;
878}
879
880static int cam_vfe_bus_handle_wm_done_top_half(uint32_t evt_id,
881 struct cam_irq_th_payload *th_payload)
882{
Harsh Shah19f55812017-06-26 18:58:49 -0700883 int32_t rc;
884 int i;
885 struct cam_isp_resource_node *wm_res = NULL;
886 struct cam_vfe_bus_ver2_wm_resource_data *rsrc_data = NULL;
887 struct cam_vfe_bus_irq_evt_payload *evt_payload;
888
889 wm_res = th_payload->handler_priv;
890 if (!wm_res) {
891 pr_err_ratelimited("Error! No resource\n");
892 return -ENODEV;
893 }
894
895 rsrc_data = wm_res->res_priv;
896
897 CDBG("IRQ status_0 = %x\n", th_payload->evt_status_arr[0]);
898 CDBG("IRQ status_1 = %x\n", th_payload->evt_status_arr[1]);
899
900 rc = cam_vfe_bus_get_evt_payload(rsrc_data->common_data, &evt_payload);
901 if (rc) {
902 pr_err_ratelimited("No tasklet_cmd is free in queue\n");
903 return rc;
904 }
905
906 cam_isp_hw_get_timestamp(&evt_payload->ts);
907
908 evt_payload->ctx = rsrc_data->ctx;
909 evt_payload->core_index = rsrc_data->common_data->core_index;
910 evt_payload->evt_id = evt_id;
911
912 for (i = 0; i < th_payload->num_registers; i++)
913 evt_payload->irq_reg_val[i] = th_payload->evt_status_arr[i];
914
915 th_payload->evt_payload_priv = evt_payload;
916
917 CDBG("Exit\n");
918 return rc;
Harsh Shaha1af8822017-05-11 22:06:36 -0700919}
920
921static int cam_vfe_bus_handle_wm_done_bottom_half(void *wm_node,
922 void *evt_payload_priv)
923{
924 int rc = CAM_VFE_IRQ_STATUS_ERR;
925 struct cam_isp_resource_node *wm_res = wm_node;
926 struct cam_vfe_bus_irq_evt_payload *evt_payload = evt_payload_priv;
Harsh Shah23557ae2017-05-13 18:14:34 -0700927 struct cam_vfe_bus_ver2_wm_resource_data *rsrc_data =
928 (wm_res == NULL) ? NULL : wm_res->res_priv;
929 uint32_t *cam_ife_irq_regs;
Harsh Shaha1af8822017-05-11 22:06:36 -0700930 uint32_t status_reg;
931
Harsh Shah23557ae2017-05-13 18:14:34 -0700932 if (!evt_payload || !rsrc_data)
933 return rc;
Harsh Shaha1af8822017-05-11 22:06:36 -0700934
Harsh Shah23557ae2017-05-13 18:14:34 -0700935 cam_ife_irq_regs = evt_payload->irq_reg_val;
936 status_reg = cam_ife_irq_regs[CAM_IFE_IRQ_BUS_REG_STATUS1];
937
938 if (status_reg & BIT(rsrc_data->index)) {
939 cam_ife_irq_regs[CAM_IFE_IRQ_BUS_REG_STATUS1] &=
940 ~BIT(rsrc_data->index);
Harsh Shaha1af8822017-05-11 22:06:36 -0700941 rc = CAM_VFE_IRQ_STATUS_SUCCESS;
Harsh Shah23557ae2017-05-13 18:14:34 -0700942 }
Harsh Shah19f55812017-06-26 18:58:49 -0700943 CDBG("status_reg %x rc %d\n", status_reg, rc);
Harsh Shaha1af8822017-05-11 22:06:36 -0700944
945 if (rc == CAM_VFE_IRQ_STATUS_SUCCESS)
Harsh Shah19f55812017-06-26 18:58:49 -0700946 cam_vfe_bus_put_evt_payload(rsrc_data->common_data,
Harsh Shaha1af8822017-05-11 22:06:36 -0700947 &evt_payload);
948
949 return rc;
950}
951
952static int cam_vfe_bus_init_wm_resource(uint32_t index,
953 struct cam_vfe_bus_ver2_priv *ver2_bus_priv,
954 struct cam_vfe_bus_ver2_hw_info *ver2_hw_info,
955 struct cam_isp_resource_node *wm_res)
956{
Harsh Shaha1af8822017-05-11 22:06:36 -0700957 struct cam_vfe_bus_ver2_wm_resource_data *rsrc_data;
958
959 rsrc_data = kzalloc(sizeof(struct cam_vfe_bus_ver2_wm_resource_data),
960 GFP_KERNEL);
961 if (!rsrc_data) {
Harsh Shah545df9a2017-06-16 16:43:17 -0700962 CDBG("Failed to alloc for WM res priv\n");
963 return -ENOMEM;
Harsh Shaha1af8822017-05-11 22:06:36 -0700964 }
965 wm_res->res_priv = rsrc_data;
966
967 rsrc_data->index = index;
968 rsrc_data->hw_regs = &ver2_hw_info->bus_client_reg[index];
969 rsrc_data->common_data = &ver2_bus_priv->common_data;
970
971 wm_res->res_state = CAM_ISP_RESOURCE_STATE_AVAILABLE;
972 INIT_LIST_HEAD(&wm_res->list);
973
974 wm_res->start = cam_vfe_bus_start_wm;
975 wm_res->stop = cam_vfe_bus_stop_wm;
976 wm_res->top_half_handler = cam_vfe_bus_handle_wm_done_top_half;
977 wm_res->bottom_half_handler = cam_vfe_bus_handle_wm_done_bottom_half;
978 wm_res->hw_intf = ver2_bus_priv->common_data.hw_intf;
979
Harsh Shah545df9a2017-06-16 16:43:17 -0700980 return 0;
981}
982
983static int cam_vfe_bus_deinit_wm_resource(
984 struct cam_isp_resource_node *wm_res)
985{
986 struct cam_vfe_bus_ver2_wm_resource_data *rsrc_data;
987
988 wm_res->res_state = CAM_ISP_RESOURCE_STATE_UNAVAILABLE;
989 INIT_LIST_HEAD(&wm_res->list);
990
991 wm_res->start = NULL;
992 wm_res->stop = NULL;
993 wm_res->top_half_handler = NULL;
994 wm_res->bottom_half_handler = NULL;
995 wm_res->hw_intf = NULL;
996
997 rsrc_data = wm_res->res_priv;
998 wm_res->res_priv = NULL;
999 if (!rsrc_data) {
1000 pr_err("Error! WM res priv is NULL\n");
1001 return -ENOMEM;
1002 }
1003 kfree(rsrc_data);
1004
1005 return 0;
Harsh Shaha1af8822017-05-11 22:06:36 -07001006}
1007
1008static void cam_vfe_bus_add_wm_to_comp_grp(
1009 struct cam_isp_resource_node *comp_grp,
1010 uint32_t composite_mask)
1011{
1012 struct cam_vfe_bus_ver2_comp_grp_data *rsrc_data = comp_grp->res_priv;
1013
1014 rsrc_data->composite_mask |= composite_mask;
1015}
1016
1017static void cam_vfe_bus_match_comp_grp(
1018 struct cam_vfe_bus_ver2_priv *ver2_bus_priv,
1019 struct cam_isp_resource_node **comp_grp,
1020 uint32_t comp_grp_local_idx,
1021 uint32_t unique_id)
1022{
1023 struct cam_vfe_bus_ver2_comp_grp_data *rsrc_data = NULL;
1024 struct cam_isp_resource_node *comp_grp_local = NULL;
1025
1026 list_for_each_entry(comp_grp_local,
1027 &ver2_bus_priv->used_comp_grp, list) {
1028 rsrc_data = comp_grp_local->res_priv;
1029 if (rsrc_data->comp_grp_local_idx == comp_grp_local_idx &&
1030 rsrc_data->unique_id == unique_id) {
1031 /* Match found */
1032 *comp_grp = comp_grp_local;
1033 return;
1034 }
1035 }
1036
1037 *comp_grp = NULL;
1038}
1039
1040static int cam_vfe_bus_acquire_comp_grp(
1041 struct cam_vfe_bus_ver2_priv *ver2_bus_priv,
1042 struct cam_isp_out_port_info *out_port_info,
Harsh Shah19f55812017-06-26 18:58:49 -07001043 void *tasklet,
1044 void *ctx,
Harsh Shaha1af8822017-05-11 22:06:36 -07001045 uint32_t unique_id,
1046 uint32_t is_dual,
1047 uint32_t is_master,
1048 enum cam_vfe_bus_ver2_vfe_core_id dual_slave_core,
1049 struct cam_isp_resource_node **comp_grp)
1050{
1051 int rc = 0;
1052 struct cam_isp_resource_node *comp_grp_local = NULL;
1053 struct cam_vfe_bus_ver2_comp_grp_data *rsrc_data = NULL;
1054
1055 /* Check if matching comp_grp already acquired */
1056 cam_vfe_bus_match_comp_grp(ver2_bus_priv, &comp_grp_local,
1057 out_port_info->comp_grp_id, unique_id);
1058
1059 if (!comp_grp_local) {
1060 /* First find a free group */
1061 if (is_dual) {
1062 if (list_empty(&ver2_bus_priv->free_dual_comp_grp)) {
1063 pr_err("No Free Composite Group\n");
1064 return -ENODEV;
1065 }
1066 comp_grp_local = list_first_entry(
1067 &ver2_bus_priv->free_dual_comp_grp,
1068 struct cam_isp_resource_node, list);
1069 rsrc_data = comp_grp_local->res_priv;
1070 rc = cam_vfe_bus_ver2_get_intra_client_mask(
1071 dual_slave_core,
1072 comp_grp_local->hw_intf->hw_idx,
1073 &rsrc_data->intra_client_mask);
1074 } else {
1075 if (list_empty(&ver2_bus_priv->free_comp_grp)) {
1076 pr_err("No Free Composite Group\n");
1077 return -ENODEV;
1078 }
1079 comp_grp_local = list_first_entry(
1080 &ver2_bus_priv->free_comp_grp,
1081 struct cam_isp_resource_node, list);
1082 rsrc_data = comp_grp_local->res_priv;
1083 }
1084
1085 list_del(&comp_grp_local->list);
Harsh Shah19f55812017-06-26 18:58:49 -07001086 comp_grp_local->tasklet_info = tasklet;
Harsh Shaha1af8822017-05-11 22:06:36 -07001087 comp_grp_local->res_state = CAM_ISP_RESOURCE_STATE_RESERVED;
1088
1089 rsrc_data->is_master = is_master;
1090 rsrc_data->composite_mask = 0;
1091 rsrc_data->unique_id = unique_id;
1092 rsrc_data->comp_grp_local_idx = out_port_info->comp_grp_id;
1093
1094 list_add_tail(&comp_grp_local->list,
1095 &ver2_bus_priv->used_comp_grp);
1096
1097 } else {
1098 rsrc_data = comp_grp_local->res_priv;
1099 /* Do not support runtime change in composite mask */
1100 if (comp_grp_local->res_state ==
1101 CAM_ISP_RESOURCE_STATE_STREAMING) {
1102 pr_err("Invalid State %d Comp Grp %u\n",
1103 comp_grp_local->res_state,
1104 rsrc_data->comp_grp_type);
1105 return -EBUSY;
1106 }
1107 }
1108
Harsh Shah19f55812017-06-26 18:58:49 -07001109 rsrc_data->ctx = ctx;
Harsh Shaha1af8822017-05-11 22:06:36 -07001110 *comp_grp = comp_grp_local;
1111
1112 return rc;
1113}
1114
1115static int cam_vfe_bus_release_comp_grp(
1116 struct cam_vfe_bus_ver2_priv *ver2_bus_priv,
1117 struct cam_isp_resource_node *in_comp_grp)
1118{
1119 struct cam_isp_resource_node *comp_grp = NULL;
1120 struct cam_vfe_bus_ver2_comp_grp_data *in_rsrc_data = NULL;
1121 int match_found = 0;
1122
1123 if (!in_comp_grp) {
1124 pr_err("Invalid Params Comp Grp %pK\n", in_rsrc_data);
1125 return -EINVAL;
1126 }
1127
1128 if (in_comp_grp->res_state == CAM_ISP_RESOURCE_STATE_AVAILABLE) {
1129 /* Already Released. Do Nothing */
1130 return 0;
1131 }
1132
1133 in_rsrc_data = in_comp_grp->res_priv;
1134
1135 list_for_each_entry(comp_grp, &ver2_bus_priv->used_comp_grp, list) {
1136 if (comp_grp == in_comp_grp) {
1137 match_found = 1;
1138 break;
1139 }
1140 }
1141
1142 if (!match_found) {
1143 pr_err("Could not find matching Comp Grp type %u\n",
1144 in_rsrc_data->comp_grp_type);
1145 return -ENODEV;
1146 }
1147
1148
1149 list_del(&comp_grp->list);
1150 if (in_rsrc_data->comp_grp_type >= CAM_VFE_BUS_VER2_COMP_GRP_DUAL_0 &&
1151 in_rsrc_data->comp_grp_type <= CAM_VFE_BUS_VER2_COMP_GRP_DUAL_5)
1152 list_add_tail(&comp_grp->list,
1153 &ver2_bus_priv->free_dual_comp_grp);
Jing Zhoue71fd4a2017-05-15 19:44:34 -07001154 else if (in_rsrc_data->comp_grp_type >= CAM_VFE_BUS_VER2_COMP_GRP_0
1155 && in_rsrc_data->comp_grp_type <= CAM_VFE_BUS_VER2_COMP_GRP_5)
Harsh Shaha1af8822017-05-11 22:06:36 -07001156 list_add_tail(&comp_grp->list, &ver2_bus_priv->free_comp_grp);
1157
Harsh Shaha1af8822017-05-11 22:06:36 -07001158 in_rsrc_data->unique_id = 0;
1159 in_rsrc_data->comp_grp_local_idx = 0;
1160 in_rsrc_data->composite_mask = 0;
1161 in_rsrc_data->dual_slave_core = CAM_VFE_BUS_VER2_VFE_CORE_MAX;
1162
Harsh Shah19f55812017-06-26 18:58:49 -07001163 comp_grp->tasklet_info = NULL;
Harsh Shaha1af8822017-05-11 22:06:36 -07001164 comp_grp->res_state = CAM_ISP_RESOURCE_STATE_AVAILABLE;
1165
Jing Zhoue71fd4a2017-05-15 19:44:34 -07001166 return 0;
Harsh Shaha1af8822017-05-11 22:06:36 -07001167}
1168
1169static int cam_vfe_bus_start_comp_grp(struct cam_isp_resource_node *comp_grp)
1170{
1171 int rc = 0;
1172 struct cam_vfe_bus_ver2_comp_grp_data *rsrc_data =
1173 comp_grp->res_priv;
1174 struct cam_vfe_bus_ver2_common_data *common_data =
1175 rsrc_data->common_data;
Harsh Shah19f55812017-06-26 18:58:49 -07001176 uint32_t bus_irq_reg_mask[CAM_VFE_BUS_IRQ_MAX] = {0};
Harsh Shaha1af8822017-05-11 22:06:36 -07001177
1178 cam_io_w_mb(rsrc_data->composite_mask, common_data->mem_base +
1179 rsrc_data->hw_regs->comp_mask);
1180
1181 CDBG("composite_mask is 0x%x\n", rsrc_data->composite_mask);
1182 CDBG("composite_mask addr 0x%x\n", rsrc_data->hw_regs->comp_mask);
1183
1184 if (rsrc_data->comp_grp_type >= CAM_VFE_BUS_VER2_COMP_GRP_DUAL_0 &&
1185 rsrc_data->comp_grp_type <= CAM_VFE_BUS_VER2_COMP_GRP_DUAL_5 &&
1186 rsrc_data->is_master) {
1187 int dual_comp_grp = (rsrc_data->comp_grp_type -
1188 CAM_VFE_BUS_VER2_COMP_GRP_DUAL_0);
1189 int intra_client_en = cam_io_r_mb(common_data->mem_base +
1190 common_data->common_reg->dual_master_comp_cfg);
1191
1192 /* 2 Bits per comp_grp. Hence left shift by comp_grp * 2 */
1193 intra_client_en |=
1194 (rsrc_data->intra_client_mask << dual_comp_grp * 2);
1195
1196 cam_io_w_mb(intra_client_en, common_data->mem_base +
1197 common_data->common_reg->dual_master_comp_cfg);
Harsh Shah19f55812017-06-26 18:58:49 -07001198
1199 bus_irq_reg_mask[CAM_VFE_BUS_IRQ_REG2] = (1 << dual_comp_grp);
1200 } else {
1201 /* IRQ bits for COMP GRP start at 5. So add 5 to the shift */
1202 bus_irq_reg_mask[CAM_VFE_BUS_IRQ_REG0] =
1203 (1 << (rsrc_data->comp_grp_type + 5));
1204 }
1205
1206 /* Subscribe IRQ */
1207 CDBG("Subscribe COMP_GRP%d IRQ\n", rsrc_data->comp_grp_type);
1208 comp_grp->irq_handle = cam_irq_controller_subscribe_irq(
1209 common_data->bus_irq_controller, CAM_IRQ_PRIORITY_1,
1210 bus_irq_reg_mask, comp_grp,
1211 comp_grp->top_half_handler,
1212 cam_ife_mgr_do_tasklet_buf_done,
1213 comp_grp->tasklet_info, cam_tasklet_enqueue_cmd);
1214 if (comp_grp->irq_handle < 0) {
1215 pr_err("Subscribe IRQ failed for comp_grp %d\n",
1216 rsrc_data->comp_grp_type);
1217 return -EFAULT;
Harsh Shaha1af8822017-05-11 22:06:36 -07001218 }
1219
1220 comp_grp->res_state = CAM_ISP_RESOURCE_STATE_STREAMING;
Harsh Shah19f55812017-06-26 18:58:49 -07001221
Harsh Shaha1af8822017-05-11 22:06:36 -07001222 return rc;
1223}
1224
1225static int cam_vfe_bus_stop_comp_grp(struct cam_isp_resource_node *comp_grp)
1226{
1227 int rc = 0;
1228 struct cam_vfe_bus_ver2_comp_grp_data *rsrc_data =
1229 comp_grp->res_priv;
1230 struct cam_vfe_bus_ver2_common_data *common_data =
1231 rsrc_data->common_data;
1232
1233 /* Unsubscribe IRQ */
Harsh Shah19f55812017-06-26 18:58:49 -07001234 rc = cam_irq_controller_unsubscribe_irq(
1235 common_data->bus_irq_controller,
1236 comp_grp->irq_handle);
Harsh Shaha1af8822017-05-11 22:06:36 -07001237
1238 cam_io_w_mb(rsrc_data->composite_mask, common_data->mem_base +
1239 rsrc_data->hw_regs->comp_mask);
1240 if (rsrc_data->comp_grp_type >= CAM_VFE_BUS_VER2_COMP_GRP_DUAL_0 &&
1241 rsrc_data->comp_grp_type <= CAM_VFE_BUS_VER2_COMP_GRP_DUAL_5 &&
1242 rsrc_data->is_master) {
1243 int dual_comp_grp = (rsrc_data->comp_grp_type -
1244 CAM_VFE_BUS_VER2_COMP_GRP_DUAL_0);
1245 int intra_client_en = cam_io_r_mb(common_data->mem_base +
1246 common_data->common_reg->dual_master_comp_cfg);
1247
1248 /* 2 Bits per comp_grp. Hence left shift by comp_grp * 2 */
1249 intra_client_en &=
1250 ~(rsrc_data->intra_client_mask << dual_comp_grp * 2);
1251
1252 cam_io_w_mb(intra_client_en, common_data->mem_base +
1253 common_data->common_reg->dual_master_comp_cfg);
1254 }
1255
1256 comp_grp->res_state = CAM_ISP_RESOURCE_STATE_RESERVED;
1257
1258 return rc;
1259}
1260
1261static int cam_vfe_bus_handle_comp_done_top_half(uint32_t evt_id,
1262 struct cam_irq_th_payload *th_payload)
1263{
Harsh Shah19f55812017-06-26 18:58:49 -07001264 int32_t rc;
1265 int i;
1266 struct cam_isp_resource_node *comp_grp = NULL;
1267 struct cam_vfe_bus_ver2_comp_grp_data *rsrc_data = NULL;
1268 struct cam_vfe_bus_irq_evt_payload *evt_payload;
1269
1270 comp_grp = th_payload->handler_priv;
1271 if (!comp_grp) {
1272 pr_err_ratelimited("Error! No resource\n");
1273 return -ENODEV;
1274 }
1275
1276 rsrc_data = comp_grp->res_priv;
1277
1278 CDBG("IRQ status_0 = %x\n", th_payload->evt_status_arr[0]);
1279 CDBG("IRQ status_1 = %x\n", th_payload->evt_status_arr[1]);
1280
1281 rc = cam_vfe_bus_get_evt_payload(rsrc_data->common_data, &evt_payload);
1282 if (rc) {
1283 pr_err_ratelimited("No tasklet_cmd is free in queue\n");
1284 return rc;
1285 }
1286
1287 cam_isp_hw_get_timestamp(&evt_payload->ts);
1288
1289 evt_payload->ctx = rsrc_data->ctx;
1290 evt_payload->core_index = rsrc_data->common_data->core_index;
1291 evt_payload->evt_id = evt_id;
1292
1293 for (i = 0; i < th_payload->num_registers; i++)
1294 evt_payload->irq_reg_val[i] = th_payload->evt_status_arr[i];
1295
1296 th_payload->evt_payload_priv = evt_payload;
1297
1298 CDBG("Exit\n");
1299 return rc;
Harsh Shaha1af8822017-05-11 22:06:36 -07001300}
1301
1302static int cam_vfe_bus_handle_comp_done_bottom_half(
1303 void *handler_priv,
1304 void *evt_payload_priv)
1305{
1306 int rc = CAM_VFE_IRQ_STATUS_ERR;
1307 struct cam_isp_resource_node *comp_grp = handler_priv;
1308 struct cam_vfe_bus_irq_evt_payload *evt_payload = evt_payload_priv;
1309 struct cam_vfe_bus_ver2_comp_grp_data *rsrc_data = comp_grp->res_priv;
Harsh Shah23557ae2017-05-13 18:14:34 -07001310 uint32_t *cam_ife_irq_regs;
1311 uint32_t status_reg;
1312 uint32_t comp_err_reg;
1313 uint32_t comp_grp_id;
1314
Harsh Shah19f55812017-06-26 18:58:49 -07001315 CDBG("comp grp type %d\n", rsrc_data->comp_grp_type);
1316
Harsh Shah23557ae2017-05-13 18:14:34 -07001317 if (!evt_payload)
1318 return rc;
1319
1320 cam_ife_irq_regs = evt_payload->irq_reg_val;
Harsh Shaha1af8822017-05-11 22:06:36 -07001321
Harsh Shaha1af8822017-05-11 22:06:36 -07001322 switch (rsrc_data->comp_grp_type) {
1323 case CAM_VFE_BUS_VER2_COMP_GRP_0:
1324 case CAM_VFE_BUS_VER2_COMP_GRP_1:
1325 case CAM_VFE_BUS_VER2_COMP_GRP_2:
1326 case CAM_VFE_BUS_VER2_COMP_GRP_3:
1327 case CAM_VFE_BUS_VER2_COMP_GRP_4:
1328 case CAM_VFE_BUS_VER2_COMP_GRP_5:
Harsh Shah23557ae2017-05-13 18:14:34 -07001329 comp_grp_id = (rsrc_data->comp_grp_type -
Harsh Shaha1af8822017-05-11 22:06:36 -07001330 CAM_VFE_BUS_VER2_COMP_GRP_0);
1331
1332 /* Check for Regular composite error */
1333 status_reg = cam_ife_irq_regs[CAM_IFE_IRQ_BUS_REG_STATUS0];
1334
1335 comp_err_reg = cam_ife_irq_regs[CAM_IFE_IRQ_BUS_REG_COMP_ERR];
1336 if ((status_reg & BIT(11)) &&
1337 (comp_err_reg & rsrc_data->composite_mask)) {
1338 /* Check for Regular composite error */
1339 rc = CAM_VFE_IRQ_STATUS_ERR_COMP;
1340 break;
1341 }
1342
1343 comp_err_reg = cam_ife_irq_regs[CAM_IFE_IRQ_BUS_REG_COMP_OWRT];
1344 /* Check for Regular composite Overwrite */
1345 if ((status_reg & BIT(12)) &&
1346 (comp_err_reg & rsrc_data->composite_mask)) {
1347 rc = CAM_VFE_IRQ_STATUS_COMP_OWRT;
1348 break;
1349 }
1350
Harsh Shah23557ae2017-05-13 18:14:34 -07001351 /* Regular Composite SUCCESS */
1352 if (status_reg & BIT(comp_grp_id + 5)) {
1353 cam_ife_irq_regs[CAM_IFE_IRQ_BUS_REG_STATUS0] &=
1354 ~BIT(comp_grp_id + 5);
Harsh Shaha1af8822017-05-11 22:06:36 -07001355 rc = CAM_VFE_IRQ_STATUS_SUCCESS;
Harsh Shah23557ae2017-05-13 18:14:34 -07001356 }
Harsh Shaha1af8822017-05-11 22:06:36 -07001357
Harsh Shah19f55812017-06-26 18:58:49 -07001358 CDBG("status reg = 0x%x, bit index = %d rc %d\n",
1359 status_reg, (comp_grp_id + 5), rc);
Harsh Shaha1af8822017-05-11 22:06:36 -07001360 break;
1361
1362 case CAM_VFE_BUS_VER2_COMP_GRP_DUAL_0:
1363 case CAM_VFE_BUS_VER2_COMP_GRP_DUAL_1:
1364 case CAM_VFE_BUS_VER2_COMP_GRP_DUAL_2:
1365 case CAM_VFE_BUS_VER2_COMP_GRP_DUAL_3:
1366 case CAM_VFE_BUS_VER2_COMP_GRP_DUAL_4:
1367 case CAM_VFE_BUS_VER2_COMP_GRP_DUAL_5:
Harsh Shah23557ae2017-05-13 18:14:34 -07001368 comp_grp_id = (rsrc_data->comp_grp_type -
Harsh Shaha1af8822017-05-11 22:06:36 -07001369 CAM_VFE_BUS_VER2_COMP_GRP_DUAL_0);
1370
1371 /* Check for DUAL composite error */
1372 status_reg = cam_ife_irq_regs[CAM_IFE_IRQ_BUS_REG_STATUS2];
1373
1374 comp_err_reg = cam_ife_irq_regs[CAM_IFE_IRQ_BUS_DUAL_COMP_ERR];
1375 if ((status_reg & BIT(6)) &&
1376 (comp_err_reg & rsrc_data->composite_mask)) {
1377 /* Check for DUAL composite error */
1378 rc = CAM_VFE_IRQ_STATUS_ERR_COMP;
1379 break;
1380 }
1381
1382 /* Check for Dual composite Overwrite */
1383 comp_err_reg = cam_ife_irq_regs[CAM_IFE_IRQ_BUS_DUAL_COMP_OWRT];
1384 if ((status_reg & BIT(7)) &&
1385 (comp_err_reg & rsrc_data->composite_mask)) {
1386 rc = CAM_VFE_IRQ_STATUS_COMP_OWRT;
1387 break;
1388 }
1389
Harsh Shah23557ae2017-05-13 18:14:34 -07001390 /* DUAL Composite SUCCESS */
1391 if (status_reg & BIT(comp_grp_id)) {
1392 cam_ife_irq_regs[CAM_IFE_IRQ_BUS_REG_STATUS2] &=
1393 ~BIT(comp_grp_id + 5);
Harsh Shaha1af8822017-05-11 22:06:36 -07001394 rc = CAM_VFE_IRQ_STATUS_SUCCESS;
Harsh Shah23557ae2017-05-13 18:14:34 -07001395 }
Harsh Shaha1af8822017-05-11 22:06:36 -07001396
1397 break;
Harsh Shaha1af8822017-05-11 22:06:36 -07001398 default:
1399 rc = CAM_VFE_IRQ_STATUS_ERR;
Harsh Shah19f55812017-06-26 18:58:49 -07001400 pr_err("Error! Invalid comp_grp_type %u\n",
1401 rsrc_data->comp_grp_type);
Harsh Shaha1af8822017-05-11 22:06:36 -07001402 break;
1403 }
1404
1405 if (rc == CAM_VFE_IRQ_STATUS_SUCCESS)
Harsh Shah19f55812017-06-26 18:58:49 -07001406 cam_vfe_bus_put_evt_payload(rsrc_data->common_data,
Harsh Shaha1af8822017-05-11 22:06:36 -07001407 &evt_payload);
1408
1409 return rc;
1410}
1411
1412static int cam_vfe_bus_init_comp_grp(uint32_t index,
1413 struct cam_vfe_bus_ver2_priv *ver2_bus_priv,
1414 struct cam_vfe_bus_ver2_hw_info *ver2_hw_info,
1415 struct cam_isp_resource_node *comp_grp)
1416{
Harsh Shah545df9a2017-06-16 16:43:17 -07001417 struct cam_vfe_bus_ver2_comp_grp_data *rsrc_data = NULL;
Harsh Shaha1af8822017-05-11 22:06:36 -07001418
1419 rsrc_data = kzalloc(sizeof(struct cam_vfe_bus_ver2_comp_grp_data),
1420 GFP_KERNEL);
1421 if (!rsrc_data) {
1422 CDBG("Failed to alloc for comp_grp_priv\n");
1423 return -ENOMEM;
1424 }
1425 comp_grp->res_priv = rsrc_data;
1426
1427 comp_grp->res_state = CAM_ISP_RESOURCE_STATE_AVAILABLE;
1428 INIT_LIST_HEAD(&comp_grp->list);
1429
1430 rsrc_data->comp_grp_type = index;
1431 rsrc_data->common_data = &ver2_bus_priv->common_data;
1432 rsrc_data->hw_regs = &ver2_hw_info->comp_grp_reg[index];
1433 rsrc_data->dual_slave_core = CAM_VFE_BUS_VER2_VFE_CORE_MAX;
1434
Harsh Shaha1af8822017-05-11 22:06:36 -07001435 if (rsrc_data->comp_grp_type >= CAM_VFE_BUS_VER2_COMP_GRP_DUAL_0 &&
1436 rsrc_data->comp_grp_type <= CAM_VFE_BUS_VER2_COMP_GRP_DUAL_5)
1437 list_add_tail(&comp_grp->list,
1438 &ver2_bus_priv->free_dual_comp_grp);
1439 else if (rsrc_data->comp_grp_type >= CAM_VFE_BUS_VER2_COMP_GRP_0
1440 && rsrc_data->comp_grp_type <= CAM_VFE_BUS_VER2_COMP_GRP_5)
1441 list_add_tail(&comp_grp->list, &ver2_bus_priv->free_comp_grp);
1442
1443 comp_grp->start = cam_vfe_bus_start_comp_grp;
1444 comp_grp->stop = cam_vfe_bus_stop_comp_grp;
1445 comp_grp->top_half_handler = cam_vfe_bus_handle_comp_done_top_half;
1446 comp_grp->bottom_half_handler =
1447 cam_vfe_bus_handle_comp_done_bottom_half;
1448 comp_grp->hw_intf = ver2_bus_priv->common_data.hw_intf;
1449
1450 return 0;
1451}
1452
Harsh Shah545df9a2017-06-16 16:43:17 -07001453static int cam_vfe_bus_deinit_comp_grp(
1454 struct cam_isp_resource_node *comp_grp)
1455{
1456 struct cam_vfe_bus_ver2_comp_grp_data *rsrc_data =
1457 comp_grp->res_priv;
1458
1459 comp_grp->start = NULL;
1460 comp_grp->stop = NULL;
1461 comp_grp->top_half_handler = NULL;
1462 comp_grp->bottom_half_handler = NULL;
1463 comp_grp->hw_intf = NULL;
1464
1465 list_del_init(&comp_grp->list);
1466 comp_grp->res_state = CAM_ISP_RESOURCE_STATE_UNAVAILABLE;
1467
1468 comp_grp->res_priv = NULL;
1469
1470 if (!rsrc_data) {
1471 pr_err("Error! comp_grp_priv is NULL\n");
1472 return -ENODEV;
1473 }
1474 kfree(rsrc_data);
1475
1476 return 0;
1477}
1478
Harsh Shah19f55812017-06-26 18:58:49 -07001479static int cam_vfe_bus_acquire_vfe_out(void *bus_priv, void *acquire_args,
1480 uint32_t args_size)
Harsh Shaha1af8822017-05-11 22:06:36 -07001481{
1482 int rc = -ENODEV;
1483 int i;
1484 enum cam_vfe_bus_ver2_vfe_out_type vfe_out_res_id;
1485 uint32_t format;
1486 uint32_t num_wm;
1487 uint32_t subscribe_irq;
1488 uint32_t client_done_mask;
1489 struct cam_vfe_bus_ver2_priv *ver2_bus_priv = bus_priv;
1490 struct cam_vfe_acquire_args *acq_args = acquire_args;
1491 struct cam_vfe_hw_vfe_out_acquire_args *out_acquire_args;
1492 struct cam_isp_resource_node *rsrc_node = NULL;
1493 struct cam_vfe_bus_ver2_vfe_out_data *rsrc_data = NULL;
1494
1495 if (!bus_priv || !acquire_args) {
1496 pr_err("Invalid Param");
1497 return -EINVAL;
1498 }
1499
1500 out_acquire_args = &acq_args->vfe_out;
1501 format = out_acquire_args->out_port_info->format;
1502
1503 CDBG("Acquiring resource type 0x%x\n",
1504 out_acquire_args->out_port_info->res_type);
1505
1506 vfe_out_res_id = cam_vfe_bus_get_out_res_id(
1507 out_acquire_args->out_port_info->res_type);
1508 if (vfe_out_res_id == CAM_VFE_BUS_VER2_VFE_OUT_MAX)
1509 return -ENODEV;
1510
1511 num_wm = cam_vfe_bus_get_num_wm(vfe_out_res_id, format);
1512 if (num_wm < 1)
1513 return -EINVAL;
1514
1515 rsrc_node = &ver2_bus_priv->vfe_out[vfe_out_res_id];
1516 if (rsrc_node->res_state != CAM_ISP_RESOURCE_STATE_AVAILABLE) {
1517 pr_err("Resource not available: Res_id %d state:%d\n",
1518 vfe_out_res_id, rsrc_node->res_state);
1519 return -EBUSY;
1520 }
1521
1522 rsrc_data = rsrc_node->res_priv;
1523 rsrc_data->num_wm = num_wm;
1524 rsrc_node->res_id = out_acquire_args->out_port_info->res_type;
1525 rsrc_node->tasklet_info = acq_args->tasklet;
1526 rsrc_node->cdm_ops = out_acquire_args->cdm_ops;
1527 rsrc_data->cdm_util_ops = out_acquire_args->cdm_ops;
1528
1529 /* Reserve Composite Group */
1530 if (num_wm > 1 || (out_acquire_args->out_port_info->comp_grp_id >
1531 CAM_ISP_RES_COMP_GROUP_NONE &&
1532 out_acquire_args->out_port_info->comp_grp_id <
1533 CAM_ISP_RES_COMP_GROUP_ID_MAX)) {
1534 rc = cam_vfe_bus_acquire_comp_grp(ver2_bus_priv,
1535 out_acquire_args->out_port_info,
Harsh Shah19f55812017-06-26 18:58:49 -07001536 acq_args->tasklet,
1537 out_acquire_args->ctx,
Harsh Shaha1af8822017-05-11 22:06:36 -07001538 out_acquire_args->unique_id,
1539 out_acquire_args->is_dual,
1540 out_acquire_args->is_master,
1541 out_acquire_args->dual_slave_core,
1542 &rsrc_data->comp_grp);
Harsh Shah19f55812017-06-26 18:58:49 -07001543 if (rc) {
1544 pr_err("VFE%d Comp_Grp acquire failed for Out %d rc=%d\n",
1545 rsrc_data->common_data->core_index,
1546 vfe_out_res_id, rc);
Harsh Shaha1af8822017-05-11 22:06:36 -07001547 return rc;
Harsh Shah19f55812017-06-26 18:58:49 -07001548 }
Harsh Shaha1af8822017-05-11 22:06:36 -07001549
1550 subscribe_irq = 0;
Harsh Shah19f55812017-06-26 18:58:49 -07001551 } else {
Harsh Shaha1af8822017-05-11 22:06:36 -07001552 subscribe_irq = 1;
Harsh Shah19f55812017-06-26 18:58:49 -07001553 }
Harsh Shaha1af8822017-05-11 22:06:36 -07001554
1555 /* Reserve WM */
1556 for (i = 0; i < num_wm; i++) {
1557 rc = cam_vfe_bus_acquire_wm(ver2_bus_priv,
1558 out_acquire_args->out_port_info,
Harsh Shah19f55812017-06-26 18:58:49 -07001559 acq_args->tasklet,
1560 out_acquire_args->ctx,
Harsh Shaha1af8822017-05-11 22:06:36 -07001561 vfe_out_res_id,
1562 i,
1563 out_acquire_args->split_id,
1564 subscribe_irq,
1565 &rsrc_data->wm_res[i],
1566 &client_done_mask);
Harsh Shah19f55812017-06-26 18:58:49 -07001567 if (rc) {
1568 pr_err("VFE%d WM acquire failed for Out %d rc=%d\n",
1569 rsrc_data->common_data->core_index,
1570 vfe_out_res_id, rc);
Harsh Shaha1af8822017-05-11 22:06:36 -07001571 goto release_wm;
Harsh Shah19f55812017-06-26 18:58:49 -07001572 }
Harsh Shaha1af8822017-05-11 22:06:36 -07001573
1574 if (rsrc_data->comp_grp)
1575 cam_vfe_bus_add_wm_to_comp_grp(rsrc_data->comp_grp,
1576 client_done_mask);
1577 }
1578
1579 rsrc_node->res_state = CAM_ISP_RESOURCE_STATE_RESERVED;
1580 out_acquire_args->rsrc_node = rsrc_node;
1581
1582 CDBG("Acquire successful\n");
1583 return rc;
1584
1585release_wm:
1586 for (i--; i >= 0; i--)
1587 cam_vfe_bus_release_wm(ver2_bus_priv, rsrc_data->wm_res[i]);
1588
1589 cam_vfe_bus_release_comp_grp(ver2_bus_priv,
1590 rsrc_data->comp_grp);
1591
1592 return rc;
1593}
1594
Harsh Shah19f55812017-06-26 18:58:49 -07001595static int cam_vfe_bus_release_vfe_out(void *bus_priv, void *release_args,
1596 uint32_t args_size)
Harsh Shaha1af8822017-05-11 22:06:36 -07001597{
Jing Zhoue71fd4a2017-05-15 19:44:34 -07001598 uint32_t i;
Harsh Shah19f55812017-06-26 18:58:49 -07001599 struct cam_isp_resource_node *vfe_out = NULL;
1600 struct cam_vfe_bus_ver2_vfe_out_data *rsrc_data = NULL;
1601
1602 if (!bus_priv || !release_args) {
1603 pr_err("Invalid input bus_priv %pK release_args %pK\n",
1604 bus_priv, release_args);
1605 return -EINVAL;
1606 }
1607
1608 vfe_out = release_args;
1609 rsrc_data = vfe_out->res_priv;
Jing Zhoue71fd4a2017-05-15 19:44:34 -07001610
Harsh Shaha1af8822017-05-11 22:06:36 -07001611 if (vfe_out->res_state != CAM_ISP_RESOURCE_STATE_RESERVED) {
1612 pr_err("Error! Invalid resource state:%d\n",
1613 vfe_out->res_state);
1614 }
1615
Jing Zhoue71fd4a2017-05-15 19:44:34 -07001616 for (i = 0; i < rsrc_data->num_wm; i++)
1617 cam_vfe_bus_release_wm(bus_priv, rsrc_data->wm_res[i]);
1618 rsrc_data->num_wm = 0;
1619
1620 if (rsrc_data->comp_grp)
1621 cam_vfe_bus_release_comp_grp(bus_priv, rsrc_data->comp_grp);
1622 rsrc_data->comp_grp = NULL;
1623
1624 vfe_out->tasklet_info = NULL;
1625 vfe_out->cdm_ops = NULL;
1626 rsrc_data->cdm_util_ops = NULL;
1627
Harsh Shaha1af8822017-05-11 22:06:36 -07001628 if (vfe_out->res_state == CAM_ISP_RESOURCE_STATE_RESERVED)
1629 vfe_out->res_state = CAM_ISP_RESOURCE_STATE_AVAILABLE;
1630
1631 return 0;
1632}
1633
Harsh Shah19f55812017-06-26 18:58:49 -07001634static int cam_vfe_bus_start_vfe_out(
1635 struct cam_isp_resource_node *vfe_out)
Harsh Shaha1af8822017-05-11 22:06:36 -07001636{
1637 int rc = 0, i;
Harsh Shah19f55812017-06-26 18:58:49 -07001638 struct cam_vfe_bus_ver2_vfe_out_data *rsrc_data = NULL;
1639 struct cam_vfe_bus_ver2_common_data *common_data = NULL;
1640
1641 if (!vfe_out) {
1642 pr_err("Invalid input\n");
1643 return -EINVAL;
1644 }
1645
1646 rsrc_data = vfe_out->res_priv;
1647 common_data = rsrc_data->common_data;
Harsh Shaha1af8822017-05-11 22:06:36 -07001648
1649 CDBG("Start resource index %d\n", rsrc_data->out_type);
1650
1651 if (vfe_out->res_state != CAM_ISP_RESOURCE_STATE_RESERVED) {
1652 pr_err("Error! Invalid resource state:%d\n",
1653 vfe_out->res_state);
1654 return -EACCES;
1655 }
1656
1657 for (i = 0; i < rsrc_data->num_wm; i++)
1658 rc = cam_vfe_bus_start_wm(rsrc_data->wm_res[i]);
1659
1660 if (rsrc_data->comp_grp)
1661 rc = cam_vfe_bus_start_comp_grp(rsrc_data->comp_grp);
1662
Harsh Shaha1af8822017-05-11 22:06:36 -07001663 /* BUS_WR_INPUT_IF_ADDR_SYNC_CFG */
1664 cam_io_w_mb(0x0, rsrc_data->common_data->mem_base + 0x0000207C);
1665 /* BUS_WR_INPUT_IF_ADDR_SYNC_FRAME_HEADER */
1666 cam_io_w_mb(0x0, rsrc_data->common_data->mem_base + 0x00002080);
1667 /* BUS_WR_INPUT_IF_ADDR_SYNC_NO_SYNC */
1668 cam_io_w_mb(0xFFFFF, rsrc_data->common_data->mem_base + 0x00002084);
Harsh Shaha1af8822017-05-11 22:06:36 -07001669 /* BUS_WR_INPUT_IF_ADDR_SYNC_0 */
1670 cam_io_w_mb(0x0, rsrc_data->common_data->mem_base + 0x00002088);
1671 cam_io_w_mb(0x0, rsrc_data->common_data->mem_base + 0x0000208c);
1672 cam_io_w_mb(0x0, rsrc_data->common_data->mem_base + 0x00002090);
1673 cam_io_w_mb(0x0, rsrc_data->common_data->mem_base + 0x00002094);
1674 cam_io_w_mb(0x0, rsrc_data->common_data->mem_base + 0x00002098);
1675 cam_io_w_mb(0x0, rsrc_data->common_data->mem_base + 0x0000209c);
1676 cam_io_w_mb(0x0, rsrc_data->common_data->mem_base + 0x000020a0);
1677 cam_io_w_mb(0x0, rsrc_data->common_data->mem_base + 0x000020a4);
1678
Harsh Shah23557ae2017-05-13 18:14:34 -07001679 /* no clock gating at bus input */
1680 cam_io_w_mb(0xFFFFF, rsrc_data->common_data->mem_base + 0x0000200C);
1681
1682 /* BUS_WR_TEST_BUS_CTRL */
1683 cam_io_w_mb(0x0, rsrc_data->common_data->mem_base + 0x0000211C);
1684
Harsh Shaha1af8822017-05-11 22:06:36 -07001685 return rc;
1686}
1687
Harsh Shah19f55812017-06-26 18:58:49 -07001688static int cam_vfe_bus_stop_vfe_out(
1689 struct cam_isp_resource_node *vfe_out)
Harsh Shaha1af8822017-05-11 22:06:36 -07001690{
1691 int rc = 0, i;
Harsh Shah19f55812017-06-26 18:58:49 -07001692 struct cam_vfe_bus_ver2_vfe_out_data *rsrc_data = NULL;
1693
1694 if (!vfe_out) {
1695 pr_err("Invalid input\n");
1696 return -EINVAL;
1697 }
1698
1699 rsrc_data = vfe_out->res_priv;
Harsh Shaha1af8822017-05-11 22:06:36 -07001700
1701 if (vfe_out->res_state == CAM_ISP_RESOURCE_STATE_AVAILABLE ||
1702 vfe_out->res_state == CAM_ISP_RESOURCE_STATE_RESERVED) {
1703 return rc;
1704 }
1705
1706 if (rsrc_data->comp_grp)
1707 rc = cam_vfe_bus_stop_comp_grp(rsrc_data->comp_grp);
1708
1709 for (i = 0; i < rsrc_data->num_wm; i++)
1710 rc = cam_vfe_bus_stop_wm(rsrc_data->wm_res[i]);
1711
1712 vfe_out->res_state = CAM_ISP_RESOURCE_STATE_STREAMING;
1713
1714 vfe_out->res_state = CAM_ISP_RESOURCE_STATE_RESERVED;
1715 return rc;
1716}
1717
1718static int cam_vfe_bus_handle_vfe_out_done_top_half(uint32_t evt_id,
1719 struct cam_irq_th_payload *th_payload)
1720{
1721 return -EPERM;
1722}
1723
1724static int cam_vfe_bus_handle_vfe_out_done_bottom_half(
1725 void *handler_priv,
1726 void *evt_payload_priv)
1727{
1728 int rc = -EINVAL;
1729 struct cam_isp_resource_node *vfe_out = handler_priv;
1730 struct cam_vfe_bus_ver2_vfe_out_data *rsrc_data = vfe_out->res_priv;
1731
1732 /*
1733 * If this resource has Composite Group then we only handle
1734 * Composite done. We acquire Composite if number of WM > 1.
1735 * So Else case is only one individual buf_done = WM[0].
1736 */
1737 if (rsrc_data->comp_grp) {
1738 rc = rsrc_data->comp_grp->bottom_half_handler(
1739 rsrc_data->comp_grp, evt_payload_priv);
1740 } else {
1741 rc = rsrc_data->wm_res[0]->bottom_half_handler(
Harsh Shah23557ae2017-05-13 18:14:34 -07001742 rsrc_data->wm_res[0], evt_payload_priv);
Harsh Shaha1af8822017-05-11 22:06:36 -07001743 }
1744
1745 return rc;
1746}
1747
1748static int cam_vfe_bus_init_vfe_out_resource(uint32_t index,
1749 struct cam_vfe_bus_ver2_priv *ver2_bus_priv,
1750 struct cam_vfe_bus_ver2_hw_info *ver2_hw_info,
1751 struct cam_isp_resource_node *vfe_out)
1752{
1753 struct cam_vfe_bus_ver2_vfe_out_data *rsrc_data = NULL;
1754 int rc = 0;
1755
1756 rsrc_data = kzalloc(sizeof(struct cam_vfe_bus_ver2_vfe_out_data),
1757 GFP_KERNEL);
1758 if (!rsrc_data) {
1759 CDBG("Error! Failed to alloc for vfe out priv\n");
1760 rc = -ENOMEM;
1761 return rc;
1762 }
1763 vfe_out->res_priv = rsrc_data;
1764
1765 vfe_out->res_type = CAM_ISP_RESOURCE_VFE_OUT;
1766 vfe_out->res_state = CAM_ISP_RESOURCE_STATE_AVAILABLE;
1767 INIT_LIST_HEAD(&vfe_out->list);
1768
1769 rsrc_data->out_type = index;
1770 rsrc_data->common_data = &ver2_bus_priv->common_data;
1771 rsrc_data->max_width =
1772 ver2_hw_info->vfe_out_hw_info[index].max_width;
1773 rsrc_data->max_height =
1774 ver2_hw_info->vfe_out_hw_info[index].max_height;
1775
1776 vfe_out->start = cam_vfe_bus_start_vfe_out;
1777 vfe_out->stop = cam_vfe_bus_stop_vfe_out;
1778 vfe_out->top_half_handler = cam_vfe_bus_handle_vfe_out_done_top_half;
1779 vfe_out->bottom_half_handler =
1780 cam_vfe_bus_handle_vfe_out_done_bottom_half;
1781 vfe_out->hw_intf = ver2_bus_priv->common_data.hw_intf;
1782
1783 return 0;
1784}
1785
Harsh Shah545df9a2017-06-16 16:43:17 -07001786static int cam_vfe_bus_deinit_vfe_out_resource(
1787 struct cam_isp_resource_node *vfe_out)
1788{
1789 struct cam_vfe_bus_ver2_vfe_out_data *rsrc_data = vfe_out->res_priv;
1790
1791 vfe_out->start = NULL;
1792 vfe_out->stop = NULL;
1793 vfe_out->top_half_handler = NULL;
1794 vfe_out->bottom_half_handler = NULL;
1795 vfe_out->hw_intf = NULL;
1796
1797 vfe_out->res_state = CAM_ISP_RESOURCE_STATE_UNAVAILABLE;
1798 INIT_LIST_HEAD(&vfe_out->list);
1799 vfe_out->res_priv = NULL;
1800
1801 if (!rsrc_data) {
1802 pr_err("Error! vfe out priv is NULL\n");
1803 return -ENOMEM;
1804 }
1805 kfree(rsrc_data);
1806
1807 return 0;
1808}
1809
Harsh Shaha1af8822017-05-11 22:06:36 -07001810static int cam_vfe_bus_ver2_handle_irq(uint32_t evt_id,
1811 struct cam_irq_th_payload *th_payload)
1812{
Harsh Shaha1af8822017-05-11 22:06:36 -07001813 struct cam_vfe_bus_ver2_priv *bus_priv;
Harsh Shaha1af8822017-05-11 22:06:36 -07001814
Harsh Shah19f55812017-06-26 18:58:49 -07001815 bus_priv = th_payload->handler_priv;
Harsh Shaha1af8822017-05-11 22:06:36 -07001816 CDBG("Enter\n");
Harsh Shah19f55812017-06-26 18:58:49 -07001817 return cam_irq_controller_handle_irq(evt_id,
1818 bus_priv->common_data.bus_irq_controller);
Harsh Shaha1af8822017-05-11 22:06:36 -07001819}
1820
1821static int cam_vfe_bus_update_buf(void *priv, void *cmd_args,
1822 uint32_t arg_size)
1823{
1824 struct cam_vfe_bus_ver2_priv *bus_priv;
1825 struct cam_isp_hw_get_buf_update *update_buf;
Jing Zhoua4e9fbe2017-05-15 14:37:21 -07001826 struct cam_buf_io_cfg *io_cfg;
Harsh Shaha1af8822017-05-11 22:06:36 -07001827 struct cam_vfe_bus_ver2_vfe_out_data *vfe_out_data = NULL;
1828 struct cam_vfe_bus_ver2_wm_resource_data *wm_data = NULL;
Jing Zhoua4e9fbe2017-05-15 14:37:21 -07001829 uint32_t *reg_val_pair;
1830 uint32_t i, j, size = 0;
Junzhe Zou193d78c2017-05-16 15:10:54 -07001831 uint32_t frame_inc = 0;
Harsh Shaha1af8822017-05-11 22:06:36 -07001832
1833 /*
1834 * Need the entire buf io config so we can get the stride info
1835 * for the wm.
1836 */
1837
1838 bus_priv = (struct cam_vfe_bus_ver2_priv *) priv;
1839 update_buf = (struct cam_isp_hw_get_buf_update *) cmd_args;
1840
1841 vfe_out_data = (struct cam_vfe_bus_ver2_vfe_out_data *)
1842 update_buf->cdm.res->res_priv;
1843
1844 if (!vfe_out_data || !vfe_out_data->cdm_util_ops) {
1845 pr_err("Failed! Invalid data\n");
1846 return -EINVAL;
1847 }
1848
Jing Zhoua4e9fbe2017-05-15 14:37:21 -07001849 if (update_buf->num_buf != vfe_out_data->num_wm) {
Harsh Shaha1af8822017-05-11 22:06:36 -07001850 pr_err("Failed! Invalid number buffers:%d required:%d\n",
1851 update_buf->num_buf, vfe_out_data->num_wm);
Junzhe Zou193d78c2017-05-16 15:10:54 -07001852 return -EINVAL;
Harsh Shaha1af8822017-05-11 22:06:36 -07001853 }
1854
Jing Zhoua4e9fbe2017-05-15 14:37:21 -07001855 reg_val_pair = &vfe_out_data->common_data->io_buf_update[0];
1856 io_cfg = update_buf->io_cfg;
1857
1858 for (i = 0, j = 0; i < vfe_out_data->num_wm; i++) {
Junzhe Zou193d78c2017-05-16 15:10:54 -07001859 if (j >= (MAX_REG_VAL_PAIR_SIZE - MAX_BUF_UPDATE_REG_NUM * 2)) {
1860 pr_err("reg_val_pair %d exceeds the array limit %lu\n",
1861 j, MAX_REG_VAL_PAIR_SIZE);
1862 return -ENOMEM;
1863 }
1864
Jing Zhoua4e9fbe2017-05-15 14:37:21 -07001865 wm_data = vfe_out_data->wm_res[i]->res_priv;
1866
1867 /* For initial configuration program all bus registers */
1868 if (wm_data->stride != io_cfg->planes[i].plane_stride ||
1869 !wm_data->init_cfg_done) {
1870 CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j,
1871 wm_data->hw_regs->stride,
1872 io_cfg->planes[i].plane_stride);
1873 wm_data->stride = io_cfg->planes[i].plane_stride;
1874 }
1875 CDBG("image stride 0x%x\n", wm_data->stride);
1876
1877 if (wm_data->framedrop_pattern != io_cfg->framedrop_pattern ||
1878 !wm_data->init_cfg_done) {
1879 CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j,
1880 wm_data->hw_regs->framedrop_pattern,
1881 io_cfg->framedrop_pattern);
1882 wm_data->framedrop_pattern = io_cfg->framedrop_pattern;
1883 }
1884 CDBG("framedrop pattern 0x%x\n", wm_data->framedrop_pattern);
1885
1886 if (wm_data->framedrop_period != io_cfg->framedrop_period ||
1887 !wm_data->init_cfg_done) {
1888 CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j,
1889 wm_data->hw_regs->framedrop_period,
1890 io_cfg->framedrop_period);
1891 wm_data->framedrop_period = io_cfg->framedrop_period;
1892 }
1893 CDBG("framedrop period 0x%x\n", wm_data->framedrop_period);
1894
1895 if (wm_data->irq_subsample_period != io_cfg->subsample_period
1896 || !wm_data->init_cfg_done) {
1897 CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j,
1898 wm_data->hw_regs->irq_subsample_period,
1899 io_cfg->subsample_period);
1900 wm_data->irq_subsample_period =
1901 io_cfg->subsample_period;
1902 }
1903 CDBG("irq subsample period 0x%x\n",
1904 wm_data->irq_subsample_period);
1905
1906 if (wm_data->irq_subsample_pattern != io_cfg->subsample_pattern
1907 || !wm_data->init_cfg_done) {
1908 CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j,
1909 wm_data->hw_regs->irq_subsample_pattern,
1910 io_cfg->subsample_pattern);
1911 wm_data->irq_subsample_pattern =
1912 io_cfg->subsample_pattern;
1913 }
1914 CDBG("irq subsample pattern 0x%x\n",
1915 wm_data->irq_subsample_pattern);
1916
1917 if (wm_data->en_ubwc) {
1918 if (!wm_data->hw_regs->ubwc_regs) {
1919 pr_err("%s: No UBWC register to configure.\n",
1920 __func__);
1921 return -EINVAL;
1922 }
1923 if (wm_data->packer_cfg !=
1924 io_cfg->planes[i].packer_config ||
1925 !wm_data->init_cfg_done) {
1926 CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j,
1927 wm_data->hw_regs->packer_cfg,
1928 io_cfg->planes[i].packer_config);
1929 wm_data->packer_cfg =
1930 io_cfg->planes[i].packer_config;
1931 }
1932 CDBG("packer cfg 0x%x\n", wm_data->packer_cfg);
1933
1934 if (wm_data->tile_cfg != io_cfg->planes[i].tile_config
1935 || !wm_data->init_cfg_done) {
1936 CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j,
1937 wm_data->hw_regs->ubwc_regs->tile_cfg,
1938 io_cfg->planes[i].tile_config);
1939 wm_data->tile_cfg =
1940 io_cfg->planes[i].tile_config;
1941 }
1942 CDBG("tile cfg 0x%x\n", wm_data->tile_cfg);
1943
1944 if (wm_data->h_init != io_cfg->planes[i].h_init ||
1945 !wm_data->init_cfg_done) {
1946 CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j,
1947 wm_data->hw_regs->ubwc_regs->h_init,
1948 io_cfg->planes[i].h_init);
1949 wm_data->h_init = io_cfg->planes[i].h_init;
1950 }
1951 CDBG("h_init 0x%x\n", wm_data->h_init);
1952
1953 if (wm_data->v_init != io_cfg->planes[i].v_init ||
1954 !wm_data->init_cfg_done) {
1955 CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j,
1956 wm_data->hw_regs->ubwc_regs->v_init,
1957 io_cfg->planes[i].v_init);
1958 wm_data->v_init = io_cfg->planes[i].v_init;
1959 }
1960 CDBG("v_init 0x%x\n", wm_data->v_init);
1961
1962 if (wm_data->ubwc_meta_stride !=
1963 io_cfg->planes[i].meta_stride ||
1964 !wm_data->init_cfg_done) {
1965 CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j,
1966 wm_data->hw_regs->ubwc_regs->
1967 meta_stride,
1968 io_cfg->planes[i].meta_stride);
1969 wm_data->ubwc_meta_stride =
1970 io_cfg->planes[i].meta_stride;
1971 }
1972 CDBG("meta stride 0x%x\n", wm_data->ubwc_meta_stride);
1973
1974 if (wm_data->ubwc_mode_cfg !=
1975 io_cfg->planes[i].mode_config ||
1976 !wm_data->init_cfg_done) {
1977 CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j,
1978 wm_data->hw_regs->ubwc_regs->mode_cfg,
1979 io_cfg->planes[i].mode_config);
1980 wm_data->ubwc_mode_cfg =
1981 io_cfg->planes[i].mode_config;
1982 }
1983 CDBG("ubwc mode cfg 0x%x\n", wm_data->ubwc_mode_cfg);
1984
1985 if (wm_data->ubwc_meta_offset !=
1986 io_cfg->planes[i].meta_offset ||
1987 !wm_data->init_cfg_done) {
1988 CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j,
1989 wm_data->hw_regs->ubwc_regs->
1990 meta_offset,
1991 io_cfg->planes[i].meta_offset);
1992 wm_data->ubwc_meta_offset =
1993 io_cfg->planes[i].meta_offset;
1994 }
1995 CDBG("ubwc meta offset 0x%x\n",
1996 wm_data->ubwc_meta_offset);
1997
1998 /* UBWC meta address */
1999 CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j,
2000 wm_data->hw_regs->ubwc_regs->meta_addr,
2001 update_buf->image_buf[i]);
2002 CDBG("ubwc meta addr 0x%llx\n",
2003 update_buf->image_buf[i]);
2004 }
2005
2006 /* WM Image address */
2007 if (wm_data->en_ubwc)
2008 CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j,
2009 wm_data->hw_regs->image_addr,
2010 (update_buf->image_buf[i] +
2011 io_cfg->planes[i].meta_size));
2012 else
2013 CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j,
2014 wm_data->hw_regs->image_addr,
2015 update_buf->image_buf[i]);
2016
2017 CDBG("image address 0x%x\n", reg_val_pair[j-1]);
2018
Junzhe Zou193d78c2017-05-16 15:10:54 -07002019 frame_inc = io_cfg->planes[i].plane_stride *
2020 io_cfg->planes[i].slice_height;
2021 CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j,
2022 wm_data->hw_regs->frame_inc, frame_inc);
2023
Jing Zhoua4e9fbe2017-05-15 14:37:21 -07002024 /* enable the WM */
2025 CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j,
2026 wm_data->hw_regs->cfg,
2027 wm_data->en_cfg);
2028
2029 /* set initial configuration done */
2030 if (!wm_data->init_cfg_done)
2031 wm_data->init_cfg_done = 1;
2032 }
2033
2034 size = vfe_out_data->cdm_util_ops->cdm_required_size_reg_random(j/2);
Harsh Shaha1af8822017-05-11 22:06:36 -07002035
2036 /* cdm util returns dwords, need to convert to bytes */
2037 if ((size * 4) > update_buf->cdm.size) {
2038 pr_err("Failed! Buf size:%d insufficient, expected size:%d\n",
2039 update_buf->cdm.size, size);
2040 return -ENOMEM;
2041 }
2042
Harsh Shaha1af8822017-05-11 22:06:36 -07002043 vfe_out_data->cdm_util_ops->cdm_write_regrandom(
Jing Zhoua4e9fbe2017-05-15 14:37:21 -07002044 update_buf->cdm.cmd_buf_addr, j/2, reg_val_pair);
2045
Harsh Shaha1af8822017-05-11 22:06:36 -07002046 /* cdm util returns dwords, need to convert to bytes */
2047 update_buf->cdm.used_bytes = size * 4;
2048
2049 return 0;
2050}
2051
Harsh Shah19f55812017-06-26 18:58:49 -07002052static int cam_vfe_bus_start_hw(void *hw_priv,
2053 void *start_hw_args, uint32_t arg_size)
2054{
2055 return cam_vfe_bus_start_vfe_out(hw_priv);
2056}
2057
2058static int cam_vfe_bus_stop_hw(void *hw_priv,
2059 void *stop_hw_args, uint32_t arg_size)
2060{
2061 return cam_vfe_bus_stop_vfe_out(hw_priv);
2062}
2063
2064static int cam_vfe_bus_init_hw(void *hw_priv,
2065 void *init_hw_args, uint32_t arg_size)
2066{
2067 struct cam_vfe_bus_ver2_priv *bus_priv = hw_priv;
2068 uint32_t top_irq_reg_mask[2] = {0};
2069
2070 if (!bus_priv) {
2071 pr_err("Error! Invalid args\n");
2072 return -EINVAL;
2073 }
2074
2075 top_irq_reg_mask[0] = (1 << 9);
2076
2077 bus_priv->irq_handle = cam_irq_controller_subscribe_irq(
2078 bus_priv->common_data.vfe_irq_controller,
2079 CAM_IRQ_PRIORITY_2,
2080 top_irq_reg_mask,
2081 bus_priv,
2082 cam_vfe_bus_ver2_handle_irq,
2083 NULL,
2084 NULL,
2085 NULL);
2086
2087 if (bus_priv->irq_handle <= 0) {
2088 pr_err("Failed to subscribe BUS IRQ\n");
2089 return -EFAULT;
2090 }
2091
2092 return 0;
2093}
2094
2095static int cam_vfe_bus_deinit_hw(void *hw_priv,
2096 void *deinit_hw_args, uint32_t arg_size)
2097{
2098 struct cam_vfe_bus_ver2_priv *bus_priv = hw_priv;
2099 int rc;
2100
2101 if (!bus_priv || (bus_priv->irq_handle <= 0)) {
2102 pr_err("Error! Invalid args\n");
2103 return -EINVAL;
2104 }
2105
2106 rc = cam_irq_controller_unsubscribe_irq(
2107 bus_priv->common_data.vfe_irq_controller,
2108 bus_priv->irq_handle);
2109 if (rc)
2110 pr_err("Failed to unsubscribe irq rc=%d\n", rc);
2111
2112 return rc;
2113}
2114
Harsh Shaha1af8822017-05-11 22:06:36 -07002115static int cam_vfe_bus_process_cmd(void *priv,
2116 uint32_t cmd_type, void *cmd_args, uint32_t arg_size)
2117{
2118 int rc = -EINVAL;
2119
2120 if (!priv || !cmd_args) {
2121 pr_err_ratelimited("Error! Invalid input arguments\n");
2122 return -EINVAL;
2123 }
2124
2125 switch (cmd_type) {
2126 case CAM_VFE_HW_CMD_GET_BUF_UPDATE:
2127 rc = cam_vfe_bus_update_buf(priv, cmd_args, arg_size);
2128 break;
2129 default:
2130 pr_err_ratelimited("Error! Invalid camif process command:%d\n",
2131 cmd_type);
2132 break;
2133 }
2134
2135 return rc;
2136}
2137
2138int cam_vfe_bus_ver2_init(
Harsh Shah19f55812017-06-26 18:58:49 -07002139 struct cam_hw_soc_info *soc_info,
Harsh Shaha1af8822017-05-11 22:06:36 -07002140 struct cam_hw_intf *hw_intf,
2141 void *bus_hw_info,
2142 void *vfe_irq_controller,
2143 struct cam_vfe_bus **vfe_bus)
2144{
2145 int i, rc = 0;
2146 struct cam_vfe_bus_ver2_priv *bus_priv = NULL;
2147 struct cam_vfe_bus *vfe_bus_local;
2148 struct cam_vfe_bus_ver2_hw_info *ver2_hw_info = bus_hw_info;
2149
2150 CDBG("Enter\n");
2151
Harsh Shah19f55812017-06-26 18:58:49 -07002152 if (!soc_info || !hw_intf || !bus_hw_info || !vfe_irq_controller) {
2153 pr_err("Error! Invalid params soc_info %pK hw_intf %pK hw_info %pK controller %pK\n",
2154 soc_info, hw_intf, bus_hw_info, vfe_irq_controller);
2155 rc = -EINVAL;
2156 goto end;
2157 }
2158
Harsh Shaha1af8822017-05-11 22:06:36 -07002159 vfe_bus_local = kzalloc(sizeof(struct cam_vfe_bus), GFP_KERNEL);
2160 if (!vfe_bus_local) {
2161 CDBG("Failed to alloc for vfe_bus\n");
2162 rc = -ENOMEM;
Harsh Shah545df9a2017-06-16 16:43:17 -07002163 goto end;
Harsh Shaha1af8822017-05-11 22:06:36 -07002164 }
2165
2166 bus_priv = kzalloc(sizeof(struct cam_vfe_bus_ver2_priv),
2167 GFP_KERNEL);
2168 if (!bus_priv) {
2169 CDBG("Failed to alloc for vfe_bus_priv\n");
2170 rc = -ENOMEM;
Harsh Shah545df9a2017-06-16 16:43:17 -07002171 goto free_bus_local;
Harsh Shaha1af8822017-05-11 22:06:36 -07002172 }
2173 vfe_bus_local->bus_priv = bus_priv;
2174
Harsh Shah19f55812017-06-26 18:58:49 -07002175 bus_priv->common_data.core_index = soc_info->index;
2176 bus_priv->common_data.mem_base =
2177 CAM_SOC_GET_REG_MAP_START(soc_info, VFE_CORE_BASE_IDX);
Harsh Shaha1af8822017-05-11 22:06:36 -07002178 bus_priv->common_data.hw_intf = hw_intf;
2179 bus_priv->common_data.vfe_irq_controller = vfe_irq_controller;
2180 bus_priv->common_data.common_reg = &ver2_hw_info->common_reg;
2181
Harsh Shah19f55812017-06-26 18:58:49 -07002182 rc = cam_irq_controller_init(drv_name, bus_priv->common_data.mem_base,
2183 &ver2_hw_info->common_reg.irq_reg_info,
2184 &bus_priv->common_data.bus_irq_controller);
2185 if (rc) {
2186 pr_err("Error! cam_irq_controller_init failed\n");
2187 goto free_bus_priv;
2188 }
2189
Harsh Shaha1af8822017-05-11 22:06:36 -07002190 INIT_LIST_HEAD(&bus_priv->free_comp_grp);
2191 INIT_LIST_HEAD(&bus_priv->free_dual_comp_grp);
2192 INIT_LIST_HEAD(&bus_priv->used_comp_grp);
2193
2194 for (i = 0; i < CAM_VFE_BUS_VER2_MAX_CLIENTS; i++) {
2195 rc = cam_vfe_bus_init_wm_resource(i, bus_priv, bus_hw_info,
2196 &bus_priv->bus_client[i]);
2197 if (rc < 0) {
Harsh Shah545df9a2017-06-16 16:43:17 -07002198 pr_err("Error! Init WM failed rc=%d\n", rc);
2199 goto deinit_wm;
Harsh Shaha1af8822017-05-11 22:06:36 -07002200 }
2201 }
2202
2203 for (i = 0; i < CAM_VFE_BUS_VER2_COMP_GRP_MAX; i++) {
2204 rc = cam_vfe_bus_init_comp_grp(i, bus_priv, bus_hw_info,
2205 &bus_priv->comp_grp[i]);
2206 if (rc < 0) {
Harsh Shah545df9a2017-06-16 16:43:17 -07002207 pr_err("Error! Init Comp Grp failed rc=%d\n", rc);
2208 goto deinit_comp_grp;
Harsh Shaha1af8822017-05-11 22:06:36 -07002209 }
2210 }
2211
2212 for (i = 0; i < CAM_VFE_BUS_VER2_VFE_OUT_MAX; i++) {
2213 rc = cam_vfe_bus_init_vfe_out_resource(i, bus_priv, bus_hw_info,
2214 &bus_priv->vfe_out[i]);
2215 if (rc < 0) {
Harsh Shah545df9a2017-06-16 16:43:17 -07002216 pr_err("Error! Init VFE Out failed rc=%d\n", rc);
2217 goto deinit_vfe_out;
Harsh Shaha1af8822017-05-11 22:06:36 -07002218 }
2219 }
2220
Harsh Shah19f55812017-06-26 18:58:49 -07002221 INIT_LIST_HEAD(&bus_priv->common_data.free_payload_list);
2222 for (i = 0; i < CAM_VFE_BUS_VER2_PAYLOAD_MAX; i++) {
2223 INIT_LIST_HEAD(&bus_priv->common_data.evt_payload[i].list);
2224 list_add_tail(&bus_priv->common_data.evt_payload[i].list,
2225 &bus_priv->common_data.free_payload_list);
Harsh Shaha1af8822017-05-11 22:06:36 -07002226 }
2227
Harsh Shah19f55812017-06-26 18:58:49 -07002228 vfe_bus_local->hw_ops.reserve = cam_vfe_bus_acquire_vfe_out;
2229 vfe_bus_local->hw_ops.release = cam_vfe_bus_release_vfe_out;
2230 vfe_bus_local->hw_ops.start = cam_vfe_bus_start_hw;
2231 vfe_bus_local->hw_ops.stop = cam_vfe_bus_stop_hw;
2232 vfe_bus_local->hw_ops.init = cam_vfe_bus_init_hw;
2233 vfe_bus_local->hw_ops.deinit = cam_vfe_bus_deinit_hw;
2234 vfe_bus_local->top_half_handler = cam_vfe_bus_ver2_handle_irq;
Harsh Shaha1af8822017-05-11 22:06:36 -07002235 vfe_bus_local->bottom_half_handler = NULL;
Harsh Shah19f55812017-06-26 18:58:49 -07002236 vfe_bus_local->hw_ops.process_cmd = cam_vfe_bus_process_cmd;
Harsh Shaha1af8822017-05-11 22:06:36 -07002237
2238 *vfe_bus = vfe_bus_local;
2239
Harsh Shah545df9a2017-06-16 16:43:17 -07002240 CDBG("Exit\n");
Harsh Shaha1af8822017-05-11 22:06:36 -07002241 return rc;
2242
Harsh Shah545df9a2017-06-16 16:43:17 -07002243deinit_vfe_out:
2244 if (i < 0)
2245 i = CAM_VFE_BUS_VER2_VFE_OUT_MAX;
2246 for (--i; i >= 0; i--)
2247 cam_vfe_bus_deinit_vfe_out_resource(&bus_priv->vfe_out[i]);
2248
2249deinit_comp_grp:
2250 if (i < 0)
2251 i = CAM_VFE_BUS_VER2_COMP_GRP_MAX;
2252 for (--i; i >= 0; i--)
2253 cam_vfe_bus_deinit_comp_grp(&bus_priv->comp_grp[i]);
2254
2255deinit_wm:
2256 if (i < 0)
2257 i = CAM_VFE_BUS_VER2_MAX_CLIENTS;
2258 for (--i; i >= 0; i--)
2259 cam_vfe_bus_deinit_wm_resource(&bus_priv->bus_client[i]);
2260
Harsh Shah19f55812017-06-26 18:58:49 -07002261free_bus_priv:
Harsh Shaha1af8822017-05-11 22:06:36 -07002262 kfree(vfe_bus_local->bus_priv);
Harsh Shah545df9a2017-06-16 16:43:17 -07002263
2264free_bus_local:
Harsh Shaha1af8822017-05-11 22:06:36 -07002265 kfree(vfe_bus_local);
Harsh Shah545df9a2017-06-16 16:43:17 -07002266
2267end:
Harsh Shaha1af8822017-05-11 22:06:36 -07002268 return rc;
2269}
Harsh Shah545df9a2017-06-16 16:43:17 -07002270
2271int cam_vfe_bus_ver2_deinit(
2272 struct cam_vfe_bus **vfe_bus)
2273{
2274 int i, rc = 0;
2275 struct cam_vfe_bus_ver2_priv *bus_priv = NULL;
2276 struct cam_vfe_bus *vfe_bus_local;
2277
2278 if (!vfe_bus || !*vfe_bus) {
2279 pr_err("Error! Invalid input\n");
2280 return -EINVAL;
2281 }
2282 vfe_bus_local = *vfe_bus;
2283
2284 bus_priv = vfe_bus_local->bus_priv;
2285 if (!bus_priv) {
2286 pr_err("Error! bus_priv is NULL\n");
2287 rc = -ENODEV;
2288 goto free_bus_local;
2289 }
2290
Harsh Shah19f55812017-06-26 18:58:49 -07002291 INIT_LIST_HEAD(&bus_priv->common_data.free_payload_list);
2292 for (i = 0; i < CAM_VFE_BUS_VER2_PAYLOAD_MAX; i++)
2293 INIT_LIST_HEAD(&bus_priv->common_data.evt_payload[i].list);
Harsh Shah545df9a2017-06-16 16:43:17 -07002294
2295 for (i = 0; i < CAM_VFE_BUS_VER2_MAX_CLIENTS; i++) {
2296 rc = cam_vfe_bus_deinit_wm_resource(&bus_priv->bus_client[i]);
2297 if (rc < 0)
2298 pr_err("Error! Deinit WM failed rc=%d\n", rc);
2299 }
2300
2301 for (i = 0; i < CAM_VFE_BUS_VER2_COMP_GRP_MAX; i++) {
2302 rc = cam_vfe_bus_deinit_comp_grp(&bus_priv->comp_grp[i]);
2303 if (rc < 0)
2304 pr_err("Error! Deinit Comp Grp failed rc=%d\n", rc);
2305 }
2306
2307 for (i = 0; i < CAM_VFE_BUS_VER2_VFE_OUT_MAX; i++) {
2308 rc = cam_vfe_bus_deinit_vfe_out_resource(&bus_priv->vfe_out[i]);
2309 if (rc < 0)
2310 pr_err("Error! Deinit VFE Out failed rc=%d\n", rc);
2311 }
2312
2313 INIT_LIST_HEAD(&bus_priv->free_comp_grp);
2314 INIT_LIST_HEAD(&bus_priv->free_dual_comp_grp);
2315 INIT_LIST_HEAD(&bus_priv->used_comp_grp);
2316
Harsh Shah19f55812017-06-26 18:58:49 -07002317 rc = cam_irq_controller_deinit(
2318 &bus_priv->common_data.bus_irq_controller);
2319 if (rc)
2320 pr_err("Error! Deinit IRQ Controller failed rc=%d\n", rc);
2321
Harsh Shah545df9a2017-06-16 16:43:17 -07002322 kfree(vfe_bus_local->bus_priv);
2323
2324free_bus_local:
2325 kfree(vfe_bus_local);
2326
2327 *vfe_bus = NULL;
2328
2329 return rc;
2330}
2331