blob: ffdf9775c6649fd58a0c1d2f09580bd8bc09ae30 [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
Ravikishore Pampanaad6bc902017-07-12 19:37:06 +053040#define CAM_VFE_RDI_BUS_DEFAULT_WIDTH 0xFF01
41#define CAM_VFE_RDI_BUS_DEFAULT_STRIDE 0xFF01
42
Junzhe Zou193d78c2017-05-16 15:10:54 -070043#define MAX_BUF_UPDATE_REG_NUM \
44 (sizeof(struct cam_vfe_bus_ver2_reg_offset_bus_client)/4)
Jing Zhoua4e9fbe2017-05-15 14:37:21 -070045#define MAX_REG_VAL_PAIR_SIZE \
Harsh Shah19f55812017-06-26 18:58:49 -070046 (MAX_BUF_UPDATE_REG_NUM * 2 * CAM_PACKET_MAX_PLANES)
Jing Zhoua4e9fbe2017-05-15 14:37:21 -070047
48#define CAM_VFE_ADD_REG_VAL_PAIR(buf_array, index, offset, val) \
Harsh Shah19f55812017-06-26 18:58:49 -070049 do { \
50 buf_array[index++] = offset; \
51 buf_array[index++] = val; \
52 } while (0)
Harsh Shaha1af8822017-05-11 22:06:36 -070053
54enum cam_vfe_bus_packer_format {
55 PACKER_FMT_PLAIN_128 = 0x0,
56 PACKER_FMT_PLAIN_8 = 0x1,
57 PACKER_FMT_PLAIN_16_10BPP = 0x2,
58 PACKER_FMT_PLAIN_16_12BPP = 0x3,
59 PACKER_FMT_PLAIN_16_14BPP = 0x4,
60 PACKER_FMT_PLAIN_16_16BPP = 0x5,
61 PACKER_FMT_ARGB_10 = 0x6,
62 PACKER_FMT_ARGB_12 = 0x7,
63 PACKER_FMT_ARGB_14 = 0x8,
64 PACKER_FMT_PLAIN_32_20BPP = 0x9,
65 PACKER_FMT_PLAIN_64 = 0xA,
66 PACKER_FMT_TP_10 = 0xB,
67 PACKER_FMT_PLAIN_32_32BPP = 0xC,
68 PACKER_FMT_PLAIN_8_ODD_EVEN = 0xD,
69 PACKER_FMT_PLAIN_8_LSB_MSB_10 = 0xE,
70 PACKER_FMT_PLAIN_8_LSB_MSB_10_ODD_EVEN = 0xF,
71 PACKER_FMT_MAX = 0xF,
72};
73
74struct cam_vfe_bus_ver2_common_data {
Harsh Shah19f55812017-06-26 18:58:49 -070075 uint32_t core_index;
Harsh Shaha1af8822017-05-11 22:06:36 -070076 void __iomem *mem_base;
77 struct cam_hw_intf *hw_intf;
78 void *bus_irq_controller;
79 void *vfe_irq_controller;
80 struct cam_vfe_bus_ver2_reg_offset_common *common_reg;
Jing Zhoua4e9fbe2017-05-15 14:37:21 -070081 uint32_t io_buf_update[
Harsh Shah19f55812017-06-26 18:58:49 -070082 MAX_REG_VAL_PAIR_SIZE];
83
84 struct cam_vfe_bus_irq_evt_payload evt_payload[
85 CAM_VFE_BUS_VER2_PAYLOAD_MAX];
86 struct list_head free_payload_list;
Harsh Shaha1af8822017-05-11 22:06:36 -070087};
88
89struct cam_vfe_bus_ver2_wm_resource_data {
90 uint32_t index;
91 struct cam_vfe_bus_ver2_common_data *common_data;
92 struct cam_vfe_bus_ver2_reg_offset_bus_client *hw_regs;
Harsh Shah19f55812017-06-26 18:58:49 -070093 void *ctx;
Harsh Shaha1af8822017-05-11 22:06:36 -070094
95 uint32_t irq_enabled;
Jing Zhoua4e9fbe2017-05-15 14:37:21 -070096 uint32_t init_cfg_done;
Harsh Shah19f55812017-06-26 18:58:49 -070097
Harsh Shaha1af8822017-05-11 22:06:36 -070098 uint32_t offset;
99 uint32_t width;
100 uint32_t height;
101 uint32_t stride;
102 uint32_t format;
103 enum cam_vfe_bus_packer_format pack_fmt;
104
105 uint32_t burst_len;
106 uint32_t frame_based;
107
Jing Zhoua4e9fbe2017-05-15 14:37:21 -0700108 uint32_t en_ubwc;
109 uint32_t packer_cfg;
110 uint32_t tile_cfg;
111 uint32_t h_init;
112 uint32_t v_init;
113 uint32_t ubwc_meta_stride;
114 uint32_t ubwc_mode_cfg;
115 uint32_t ubwc_meta_offset;
116
Harsh Shaha1af8822017-05-11 22:06:36 -0700117 uint32_t irq_subsample_period;
118 uint32_t irq_subsample_pattern;
119 uint32_t framedrop_period;
120 uint32_t framedrop_pattern;
Jing Zhoua4e9fbe2017-05-15 14:37:21 -0700121
122 uint32_t en_cfg;
Harsh Shaha1af8822017-05-11 22:06:36 -0700123};
124
125struct cam_vfe_bus_ver2_comp_grp_data {
126 enum cam_vfe_bus_ver2_comp_grp_type comp_grp_type;
127 struct cam_vfe_bus_ver2_common_data *common_data;
128 struct cam_vfe_bus_ver2_reg_offset_comp_grp *hw_regs;
129
130 uint32_t irq_enabled;
131 uint32_t comp_grp_local_idx;
132 uint32_t unique_id;
133
134 uint32_t is_master;
135 uint32_t dual_slave_core;
136 uint32_t intra_client_mask;
137 uint32_t composite_mask;
Harsh Shah19f55812017-06-26 18:58:49 -0700138
139 void *ctx;
Harsh Shaha1af8822017-05-11 22:06:36 -0700140};
141
142struct cam_vfe_bus_ver2_vfe_out_data {
143 uint32_t out_type;
144 struct cam_vfe_bus_ver2_common_data *common_data;
145
146 uint32_t num_wm;
147 struct cam_isp_resource_node *wm_res[PLANE_MAX];
148
149 struct cam_isp_resource_node *comp_grp;
150 enum cam_isp_hw_sync_mode dual_comp_sync_mode;
151 uint32_t dual_hw_alternate_vfe_id;
152 struct list_head vfe_out_list;
153
154 uint32_t format;
155 uint32_t max_width;
156 uint32_t max_height;
157 struct cam_cdm_utils_ops *cdm_util_ops;
158};
159
Harsh Shaha1af8822017-05-11 22:06:36 -0700160struct cam_vfe_bus_ver2_priv {
161 struct cam_vfe_bus_ver2_common_data common_data;
162
163 struct cam_isp_resource_node bus_client[CAM_VFE_BUS_VER2_MAX_CLIENTS];
164 struct cam_isp_resource_node comp_grp[CAM_VFE_BUS_VER2_COMP_GRP_MAX];
165 struct cam_isp_resource_node vfe_out[CAM_VFE_BUS_VER2_VFE_OUT_MAX];
166
167 struct list_head free_comp_grp;
168 struct list_head free_dual_comp_grp;
169 struct list_head used_comp_grp;
170
Harsh Shah19f55812017-06-26 18:58:49 -0700171 uint32_t irq_handle;
Harsh Shaha1af8822017-05-11 22:06:36 -0700172};
173
Harsh Shah19f55812017-06-26 18:58:49 -0700174static int cam_vfe_bus_get_evt_payload(
175 struct cam_vfe_bus_ver2_common_data *common_data,
176 struct cam_vfe_bus_irq_evt_payload **evt_payload)
177{
178 if (list_empty(&common_data->free_payload_list)) {
179 *evt_payload = NULL;
180 pr_err("No free payload\n");
181 return -ENODEV;
182 }
183
184 *evt_payload = list_first_entry(&common_data->free_payload_list,
185 struct cam_vfe_bus_irq_evt_payload, list);
186 list_del_init(&(*evt_payload)->list);
187 return 0;
188}
189
Harsh Shaha1af8822017-05-11 22:06:36 -0700190static int cam_vfe_bus_put_evt_payload(void *core_info,
Harsh Shah19f55812017-06-26 18:58:49 -0700191 struct cam_vfe_bus_irq_evt_payload **evt_payload)
192{
193 struct cam_vfe_bus_ver2_common_data *common_data = NULL;
194 uint32_t *ife_irq_regs = NULL;
195 uint32_t status_reg0, status_reg1, status_reg2;
196
197 if (!core_info) {
198 pr_err("Invalid param core_info NULL");
199 return -EINVAL;
200 }
201 if (*evt_payload == NULL) {
202 pr_err("No payload to put\n");
203 return -EINVAL;
204 }
205
206 ife_irq_regs = (*evt_payload)->irq_reg_val;
207 status_reg0 = ife_irq_regs[CAM_IFE_IRQ_BUS_REG_STATUS0];
208 status_reg1 = ife_irq_regs[CAM_IFE_IRQ_BUS_REG_STATUS1];
209 status_reg2 = ife_irq_regs[CAM_IFE_IRQ_BUS_REG_STATUS2];
210
211 if (status_reg0 || status_reg1 || status_reg2) {
212 CDBG("status0 0x%x status1 0x%x status2 0x%x\n",
213 status_reg0, status_reg1, status_reg2);
214 return 0;
215 }
216
217 common_data = core_info;
218 list_add_tail(&(*evt_payload)->list,
219 &common_data->free_payload_list);
220 *evt_payload = NULL;
221
222 return 0;
223}
Harsh Shaha1af8822017-05-11 22:06:36 -0700224
225static int cam_vfe_bus_ver2_get_intra_client_mask(
226 enum cam_vfe_bus_ver2_vfe_core_id dual_slave_core,
227 enum cam_vfe_bus_ver2_vfe_core_id current_core,
228 uint32_t *intra_client_mask)
229{
230 int rc = 0;
231
232 *intra_client_mask = 0;
233
234 if (dual_slave_core == current_core) {
235 pr_err("Invalid params. Same core as Master and Slave\n");
236 return -EINVAL;
237 }
238
239 switch (current_core) {
240 case CAM_VFE_BUS_VER2_VFE_CORE_0:
241 switch (dual_slave_core) {
242 case CAM_VFE_BUS_VER2_VFE_CORE_1:
243 *intra_client_mask = 0x1;
244 break;
245 case CAM_VFE_BUS_VER2_VFE_CORE_2:
246 *intra_client_mask = 0x2;
247 break;
248 default:
249 pr_err("Invalid value for slave core %u\n",
250 dual_slave_core);
251 rc = -EINVAL;
252 break;
253 }
254 break;
255 case CAM_VFE_BUS_VER2_VFE_CORE_1:
256 switch (dual_slave_core) {
257 case CAM_VFE_BUS_VER2_VFE_CORE_0:
258 *intra_client_mask = 0x1;
259 break;
260 case CAM_VFE_BUS_VER2_VFE_CORE_2:
261 *intra_client_mask = 0x2;
262 break;
263 default:
264 pr_err("Invalid value for slave core %u\n",
265 dual_slave_core);
266 rc = -EINVAL;
267 break;
268 }
269 break;
270 case CAM_VFE_BUS_VER2_VFE_CORE_2:
271 switch (dual_slave_core) {
272 case CAM_VFE_BUS_VER2_VFE_CORE_0:
273 *intra_client_mask = 0x1;
274 break;
275 case CAM_VFE_BUS_VER2_VFE_CORE_1:
276 *intra_client_mask = 0x2;
277 break;
278 default:
279 pr_err("Invalid value for slave core %u\n",
280 dual_slave_core);
281 rc = -EINVAL;
282 break;
283 }
284 break;
285 default:
286 pr_err("Invalid value for master core %u\n", current_core);
287 rc = -EINVAL;
288 break;
289 }
290
291 return rc;
292}
293
294static enum cam_vfe_bus_ver2_vfe_out_type
295 cam_vfe_bus_get_out_res_id(uint32_t res_type)
296{
297 switch (res_type) {
298 case CAM_ISP_IFE_OUT_RES_FULL:
299 return CAM_VFE_BUS_VER2_VFE_OUT_FULL;
300 case CAM_ISP_IFE_OUT_RES_DS4:
301 return CAM_VFE_BUS_VER2_VFE_OUT_DS4;
302 case CAM_ISP_IFE_OUT_RES_DS16:
303 return CAM_VFE_BUS_VER2_VFE_OUT_DS16;
304 case CAM_ISP_IFE_OUT_RES_FD:
305 return CAM_VFE_BUS_VER2_VFE_OUT_FD;
306 case CAM_ISP_IFE_OUT_RES_RAW_DUMP:
307 return CAM_VFE_BUS_VER2_VFE_OUT_RAW_DUMP;
308 case CAM_ISP_IFE_OUT_RES_PDAF:
309 return CAM_VFE_BUS_VER2_VFE_OUT_PDAF;
310 case CAM_ISP_IFE_OUT_RES_RDI_0:
311 return CAM_VFE_BUS_VER2_VFE_OUT_RDI0;
312 case CAM_ISP_IFE_OUT_RES_RDI_1:
313 return CAM_VFE_BUS_VER2_VFE_OUT_RDI1;
314 case CAM_ISP_IFE_OUT_RES_RDI_2:
315 return CAM_VFE_BUS_VER2_VFE_OUT_RDI2;
316 case CAM_ISP_IFE_OUT_RES_STATS_HDR_BE:
317 return CAM_VFE_BUS_VER2_VFE_OUT_STATS_HDR_BE;
318 case CAM_ISP_IFE_OUT_RES_STATS_HDR_BHIST:
319 return CAM_VFE_BUS_VER2_VFE_OUT_STATS_HDR_BHIST;
320 case CAM_ISP_IFE_OUT_RES_STATS_TL_BG:
321 return CAM_VFE_BUS_VER2_VFE_OUT_STATS_TL_BG;
322 case CAM_ISP_IFE_OUT_RES_STATS_BF:
323 return CAM_VFE_BUS_VER2_VFE_OUT_STATS_BF;
324 case CAM_ISP_IFE_OUT_RES_STATS_AWB_BG:
325 return CAM_VFE_BUS_VER2_VFE_OUT_STATS_AWB_BG;
326 case CAM_ISP_IFE_OUT_RES_STATS_BHIST:
327 return CAM_VFE_BUS_VER2_VFE_OUT_STATS_BHIST;
328 case CAM_ISP_IFE_OUT_RES_STATS_RS:
329 return CAM_VFE_BUS_VER2_VFE_OUT_STATS_RS;
330 case CAM_ISP_IFE_OUT_RES_STATS_CS:
331 return CAM_VFE_BUS_VER2_VFE_OUT_STATS_CS;
332 case CAM_ISP_IFE_OUT_RES_STATS_IHIST:
333 return CAM_VFE_BUS_VER2_VFE_OUT_STATS_IHIST;
334 default:
335 return CAM_VFE_BUS_VER2_VFE_OUT_MAX;
336 }
337}
338
339static int cam_vfe_bus_get_num_wm(
340 enum cam_vfe_bus_ver2_vfe_out_type res_type,
341 uint32_t format)
342{
343 switch (res_type) {
344 case CAM_VFE_BUS_VER2_VFE_OUT_RDI0:
345 case CAM_VFE_BUS_VER2_VFE_OUT_RDI1:
346 case CAM_VFE_BUS_VER2_VFE_OUT_RDI2:
347 switch (format) {
348 case CAM_FORMAT_MIPI_RAW_8:
349 case CAM_FORMAT_MIPI_RAW_10:
350 case CAM_FORMAT_MIPI_RAW_12:
351 case CAM_FORMAT_MIPI_RAW_14:
352 case CAM_FORMAT_MIPI_RAW_16:
353 case CAM_FORMAT_MIPI_RAW_20:
Ravikishore Pampanaad6bc902017-07-12 19:37:06 +0530354 case CAM_FORMAT_DPCM_10_6_10:
355 case CAM_FORMAT_DPCM_10_8_10:
356 case CAM_FORMAT_DPCM_12_6_12:
357 case CAM_FORMAT_DPCM_12_8_12:
358 case CAM_FORMAT_DPCM_14_8_14:
359 case CAM_FORMAT_DPCM_14_10_14:
360 case CAM_FORMAT_PLAIN8:
361 case CAM_FORMAT_PLAIN16_8:
362 case CAM_FORMAT_PLAIN16_10:
363 case CAM_FORMAT_PLAIN16_12:
364 case CAM_FORMAT_PLAIN16_14:
365 case CAM_FORMAT_PLAIN16_16:
366 case CAM_FORMAT_PLAIN32_20:
Harsh Shaha1af8822017-05-11 22:06:36 -0700367 case CAM_FORMAT_PLAIN128:
368 return 1;
369 default:
370 break;
371 }
372 break;
373 case CAM_VFE_BUS_VER2_VFE_OUT_FULL:
374 switch (format) {
375 case CAM_FORMAT_NV21:
376 case CAM_FORMAT_NV12:
377 case CAM_FORMAT_MIPI_RAW_8:
378 case CAM_FORMAT_PLAIN8:
379 case CAM_FORMAT_TP10:
380 case CAM_FORMAT_UBWC_NV12:
381 case CAM_FORMAT_UBWC_NV12_4R:
382 case CAM_FORMAT_UBWC_TP10:
383 case CAM_FORMAT_UBWC_P010:
384 return 2;
385 default:
386 break;
387 }
388 break;
389 case CAM_VFE_BUS_VER2_VFE_OUT_FD:
390 switch (format) {
391 case CAM_FORMAT_NV21:
392 case CAM_FORMAT_NV12:
393 case CAM_FORMAT_PLAIN8:
394 case CAM_FORMAT_TP10:
395 case CAM_FORMAT_PLAIN16_10:
396 return 2;
397 default:
398 break;
399 }
400 break;
401 case CAM_VFE_BUS_VER2_VFE_OUT_DS4:
402 case CAM_VFE_BUS_VER2_VFE_OUT_DS16:
403 switch (format) {
404 case CAM_FORMAT_PD8:
405 case CAM_FORMAT_PD10:
406 return 1;
407 default:
408 break;
409 }
410 break;
411 case CAM_VFE_BUS_VER2_VFE_OUT_RAW_DUMP:
412 switch (format) {
413 case CAM_FORMAT_ARGB_14:
414 case CAM_FORMAT_PLAIN8:
415 case CAM_FORMAT_PLAIN16_10:
416 case CAM_FORMAT_PLAIN16_12:
417 case CAM_FORMAT_PLAIN16_14:
418 return 1;
419 default:
420 break;
421 }
422 break;
423 case CAM_VFE_BUS_VER2_VFE_OUT_PDAF:
424 switch (format) {
425 case CAM_FORMAT_PLAIN8:
426 case CAM_FORMAT_PLAIN16_10:
427 case CAM_FORMAT_PLAIN16_12:
428 case CAM_FORMAT_PLAIN16_14:
429 return 1;
430 default:
431 break;
432 }
433 break;
434 case CAM_VFE_BUS_VER2_VFE_OUT_STATS_HDR_BE:
435 case CAM_VFE_BUS_VER2_VFE_OUT_STATS_HDR_BHIST:
436 case CAM_VFE_BUS_VER2_VFE_OUT_STATS_TL_BG:
437 case CAM_VFE_BUS_VER2_VFE_OUT_STATS_BF:
438 case CAM_VFE_BUS_VER2_VFE_OUT_STATS_AWB_BG:
439 case CAM_VFE_BUS_VER2_VFE_OUT_STATS_BHIST:
440 case CAM_VFE_BUS_VER2_VFE_OUT_STATS_CS:
441 switch (format) {
442 case CAM_FORMAT_PLAIN64:
443 return 1;
444 default:
445 break;
446 }
447 break;
448 case CAM_VFE_BUS_VER2_VFE_OUT_STATS_RS:
449 case CAM_VFE_BUS_VER2_VFE_OUT_STATS_IHIST:
450 switch (format) {
451 case CAM_FORMAT_PLAIN16_16:
452 return 1;
453 default:
454 break;
455 }
456 break;
457 default:
458 break;
459 }
460
461 pr_err("Unsupported format %u for resource_type %u", format, res_type);
462
463 return -EINVAL;
464}
465
466static int cam_vfe_bus_get_wm_idx(
467 enum cam_vfe_bus_ver2_vfe_out_type vfe_out_res_id,
468 enum cam_vfe_bus_plane_type plane)
469{
470 int wm_idx = -1;
471
472 switch (vfe_out_res_id) {
473 case CAM_VFE_BUS_VER2_VFE_OUT_FULL:
474 switch (plane) {
475 case PLANE_Y:
476 wm_idx = 3;
477 break;
478 case PLANE_C:
479 wm_idx = 4;
480 break;
481 default:
482 break;
483 }
484 break;
485 case CAM_VFE_BUS_VER2_VFE_OUT_DS4:
486 switch (plane) {
487 case PLANE_Y:
488 wm_idx = 5;
489 break;
490 default:
491 break;
492 }
493 break;
494 case CAM_VFE_BUS_VER2_VFE_OUT_DS16:
495 switch (plane) {
496 case PLANE_Y:
497 wm_idx = 6;
498 break;
499 default:
500 break;
501 }
502 break;
503 case CAM_VFE_BUS_VER2_VFE_OUT_FD:
504 switch (plane) {
505 case PLANE_Y:
506 wm_idx = 7;
507 break;
508 case PLANE_C:
509 wm_idx = 8;
510 break;
511 default:
512 break;
513 }
514 break;
515 case CAM_VFE_BUS_VER2_VFE_OUT_RAW_DUMP:
516 switch (plane) {
517 case PLANE_Y:
518 wm_idx = 9;
519 break;
520 default:
521 break;
522 }
523 break;
524 case CAM_VFE_BUS_VER2_VFE_OUT_PDAF:
525 switch (plane) {
526 case PLANE_Y:
527 wm_idx = 10;
528 break;
529 default:
530 break;
531 }
532 break;
533 case CAM_VFE_BUS_VER2_VFE_OUT_RDI0:
534 switch (plane) {
535 case PLANE_Y:
536 wm_idx = 0;
537 break;
538 default:
539 break;
540 }
541 break;
542 case CAM_VFE_BUS_VER2_VFE_OUT_RDI1:
543 switch (plane) {
544 case PLANE_Y:
545 wm_idx = 1;
546 break;
547 default:
548 break;
549 }
550 break;
551 case CAM_VFE_BUS_VER2_VFE_OUT_RDI2:
552 switch (plane) {
553 case PLANE_Y:
554 wm_idx = 2;
555 break;
556 default:
557 break;
558 }
559 break;
560 case CAM_VFE_BUS_VER2_VFE_OUT_STATS_HDR_BE:
561 switch (plane) {
562 case PLANE_Y:
563 wm_idx = 11;
564 break;
565 default:
566 break;
567 }
568 break;
569 case CAM_VFE_BUS_VER2_VFE_OUT_STATS_HDR_BHIST:
570 switch (plane) {
571 case PLANE_Y:
572 wm_idx = 12;
573 break;
574 default:
575 break;
576 }
577 break;
578 case CAM_VFE_BUS_VER2_VFE_OUT_STATS_TL_BG:
579 switch (plane) {
580 case PLANE_Y:
581 wm_idx = 13;
582 break;
583 default:
584 break;
585 }
586 break;
587 case CAM_VFE_BUS_VER2_VFE_OUT_STATS_BF:
588 switch (plane) {
589 case PLANE_Y:
590 wm_idx = 14;
591 break;
592 default:
593 break;
594 }
595 break;
596 case CAM_VFE_BUS_VER2_VFE_OUT_STATS_AWB_BG:
597 switch (plane) {
598 case PLANE_Y:
599 wm_idx = 15;
600 break;
601 default:
602 break;
603 }
604 break;
605 case CAM_VFE_BUS_VER2_VFE_OUT_STATS_BHIST:
606 switch (plane) {
607 case PLANE_Y:
608 wm_idx = 16;
609 break;
610 default:
611 break;
612 }
613 break;
614 case CAM_VFE_BUS_VER2_VFE_OUT_STATS_RS:
615 switch (plane) {
616 case PLANE_Y:
617 wm_idx = 17;
618 break;
619 default:
620 break;
621 }
622 break;
623 case CAM_VFE_BUS_VER2_VFE_OUT_STATS_CS:
624 switch (plane) {
625 case PLANE_Y:
626 wm_idx = 18;
627 break;
628 default:
629 break;
630 }
631 break;
632 case CAM_VFE_BUS_VER2_VFE_OUT_STATS_IHIST:
633 switch (plane) {
634 case PLANE_Y:
635 wm_idx = 19;
636 break;
637 default:
638 break;
639 }
640 break;
641 default:
642 break;
643 }
644
645 return wm_idx;
646}
647
648static enum cam_vfe_bus_packer_format
649 cam_vfe_bus_get_packer_fmt(uint32_t out_fmt)
650{
651 switch (out_fmt) {
652 case CAM_FORMAT_NV21:
653 case CAM_FORMAT_NV12:
Abhishek Kondaveeti170c8122017-07-06 04:45:12 +0530654 return PACKER_FMT_PLAIN_8_LSB_MSB_10;
Abhishek Kondaveeti170c8122017-07-06 04:45:12 +0530655 case CAM_FORMAT_PLAIN64:
656 return PACKER_FMT_PLAIN_64;
657 case CAM_FORMAT_MIPI_RAW_6:
658 case CAM_FORMAT_MIPI_RAW_8:
659 case CAM_FORMAT_MIPI_RAW_10:
660 case CAM_FORMAT_MIPI_RAW_12:
661 case CAM_FORMAT_MIPI_RAW_14:
662 case CAM_FORMAT_MIPI_RAW_16:
663 case CAM_FORMAT_MIPI_RAW_20:
664 case CAM_FORMAT_QTI_RAW_8:
665 case CAM_FORMAT_QTI_RAW_10:
666 case CAM_FORMAT_QTI_RAW_12:
667 case CAM_FORMAT_QTI_RAW_14:
668 case CAM_FORMAT_PLAIN128:
Ravikishore Pampanaad6bc902017-07-12 19:37:06 +0530669 case CAM_FORMAT_PLAIN8:
670 case CAM_FORMAT_PLAIN16_8:
671 case CAM_FORMAT_PLAIN16_10:
672 case CAM_FORMAT_PLAIN16_12:
673 case CAM_FORMAT_PLAIN16_14:
674 case CAM_FORMAT_PLAIN16_16:
675 case CAM_FORMAT_PLAIN32_20:
Abhishek Kondaveeti170c8122017-07-06 04:45:12 +0530676 case CAM_FORMAT_PD8:
677 case CAM_FORMAT_PD10:
678 return PACKER_FMT_PLAIN_128;
Harsh Shaha1af8822017-05-11 22:06:36 -0700679 default:
680 return PACKER_FMT_MAX;
681 }
682}
683
684static int cam_vfe_bus_acquire_wm(
685 struct cam_vfe_bus_ver2_priv *ver2_bus_priv,
686 struct cam_isp_out_port_info *out_port_info,
Harsh Shah19f55812017-06-26 18:58:49 -0700687 void *tasklet,
688 void *ctx,
Harsh Shaha1af8822017-05-11 22:06:36 -0700689 enum cam_vfe_bus_ver2_vfe_out_type vfe_out_res_id,
690 enum cam_vfe_bus_plane_type plane,
691 enum cam_isp_hw_split_id split_id,
692 uint32_t subscribe_irq,
693 struct cam_isp_resource_node **wm_res,
694 uint32_t *client_done_mask)
695{
696 uint32_t wm_idx = 0;
697 struct cam_isp_resource_node *wm_res_local = NULL;
698 struct cam_vfe_bus_ver2_wm_resource_data *rsrc_data = NULL;
699
700 *wm_res = NULL;
701 *client_done_mask = 0;
702
703 /* No need to allocate for BUS VER2. VFE OUT to WM is fixed. */
704 wm_idx = cam_vfe_bus_get_wm_idx(vfe_out_res_id, plane);
705 if (wm_idx < 0 || wm_idx >= CAM_VFE_BUS_VER2_MAX_CLIENTS) {
706 pr_err("Unsupported VFE out %d plane %d\n",
707 vfe_out_res_id, plane);
708 return -EINVAL;
709 }
710
711 wm_res_local = &ver2_bus_priv->bus_client[wm_idx];
Harsh Shah19f55812017-06-26 18:58:49 -0700712 wm_res_local->tasklet_info = tasklet;
Harsh Shaha1af8822017-05-11 22:06:36 -0700713 wm_res_local->res_state = CAM_ISP_RESOURCE_STATE_RESERVED;
714
715 rsrc_data = wm_res_local->res_priv;
716 rsrc_data->irq_enabled = subscribe_irq;
Harsh Shah19f55812017-06-26 18:58:49 -0700717 rsrc_data->ctx = ctx;
Harsh Shaha1af8822017-05-11 22:06:36 -0700718 rsrc_data->format = out_port_info->format;
719 rsrc_data->pack_fmt = cam_vfe_bus_get_packer_fmt(rsrc_data->format);
720
721 rsrc_data->width = out_port_info->width;
722 rsrc_data->height = out_port_info->height;
Jing Zhoua4e9fbe2017-05-15 14:37:21 -0700723
724 if (rsrc_data->index < 3) {
Ravikishore Pampanaad6bc902017-07-12 19:37:06 +0530725 rsrc_data->width = CAM_VFE_RDI_BUS_DEFAULT_WIDTH;
726 rsrc_data->height = 0;
727 rsrc_data->stride = CAM_VFE_RDI_BUS_DEFAULT_STRIDE;
728 rsrc_data->pack_fmt = 0x0;
Jing Zhoua4e9fbe2017-05-15 14:37:21 -0700729 rsrc_data->en_cfg = 0x3;
Abhishek Kondaveetib31b46c2017-06-23 04:56:24 +0530730 } else if (rsrc_data->index < 5 ||
731 rsrc_data->index == 7 || rsrc_data->index == 8) {
Jing Zhoua4e9fbe2017-05-15 14:37:21 -0700732 switch (plane) {
733 case PLANE_Y:
734 switch (rsrc_data->format) {
735 case CAM_FORMAT_UBWC_NV12:
736 case CAM_FORMAT_UBWC_NV12_4R:
737 case CAM_FORMAT_UBWC_TP10:
738 rsrc_data->en_ubwc = 1;
739 break;
740 default:
741 break;
742 }
743 break;
744 case PLANE_C:
745 switch (rsrc_data->format) {
746 case CAM_FORMAT_NV21:
747 case CAM_FORMAT_NV12:
748 rsrc_data->height /= 2;
749 break;
750 case CAM_FORMAT_UBWC_NV12:
751 case CAM_FORMAT_UBWC_NV12_4R:
752 case CAM_FORMAT_UBWC_TP10:
753 rsrc_data->height /= 2;
754 rsrc_data->en_ubwc = 1;
755 break;
756 default:
757 break;
758 }
Harsh Shaha1af8822017-05-11 22:06:36 -0700759 break;
760 default:
Jing Zhoua4e9fbe2017-05-15 14:37:21 -0700761 pr_err("Invalid plane type %d\n", plane);
762 return -EINVAL;
Harsh Shaha1af8822017-05-11 22:06:36 -0700763 }
Jing Zhoua4e9fbe2017-05-15 14:37:21 -0700764 rsrc_data->en_cfg = 0x1;
Abhishek Kondaveetib31b46c2017-06-23 04:56:24 +0530765 } else if (rsrc_data->index >= 11) {
766 rsrc_data->width = 0;
767 rsrc_data->height = 0;
Abhishek Kondaveetib31b46c2017-06-23 04:56:24 +0530768 rsrc_data->stride = 1;
769 rsrc_data->en_cfg = 0x3;
Jing Zhoua4e9fbe2017-05-15 14:37:21 -0700770 } else {
771 rsrc_data->width = rsrc_data->width * 4;
772 rsrc_data->height = rsrc_data->height / 2;
Jing Zhoua4e9fbe2017-05-15 14:37:21 -0700773 rsrc_data->en_cfg = 0x1;
Harsh Shaha1af8822017-05-11 22:06:36 -0700774 }
775
776 if (vfe_out_res_id >= CAM_ISP_IFE_OUT_RES_RDI_0 &&
777 vfe_out_res_id <= CAM_ISP_IFE_OUT_RES_RDI_3)
778 rsrc_data->frame_based = 1;
779
780 *client_done_mask = (1 << wm_idx);
781 *wm_res = wm_res_local;
782
783 return 0;
784}
785
786static int cam_vfe_bus_release_wm(void *bus_priv,
787 struct cam_isp_resource_node *wm_res)
788{
789 struct cam_vfe_bus_ver2_wm_resource_data *rsrc_data =
790 wm_res->res_priv;
791
792 rsrc_data->irq_enabled = 0;
793 rsrc_data->offset = 0;
794 rsrc_data->width = 0;
795 rsrc_data->height = 0;
796 rsrc_data->stride = 0;
797 rsrc_data->format = 0;
798 rsrc_data->pack_fmt = 0;
799 rsrc_data->burst_len = 0;
800 rsrc_data->frame_based = 0;
801 rsrc_data->irq_subsample_period = 0;
802 rsrc_data->irq_subsample_pattern = 0;
803 rsrc_data->framedrop_period = 0;
804 rsrc_data->framedrop_pattern = 0;
Jing Zhoua4e9fbe2017-05-15 14:37:21 -0700805 rsrc_data->packer_cfg = 0;
806 rsrc_data->en_ubwc = 0;
807 rsrc_data->tile_cfg = 0;
808 rsrc_data->h_init = 0;
809 rsrc_data->v_init = 0;
810 rsrc_data->ubwc_meta_stride = 0;
811 rsrc_data->ubwc_mode_cfg = 0;
812 rsrc_data->ubwc_meta_offset = 0;
813 rsrc_data->init_cfg_done = 0;
814 rsrc_data->en_cfg = 0;
Harsh Shah19f55812017-06-26 18:58:49 -0700815
816 wm_res->tasklet_info = NULL;
Harsh Shaha1af8822017-05-11 22:06:36 -0700817 wm_res->res_state = CAM_ISP_RESOURCE_STATE_AVAILABLE;
818
819 return 0;
820}
821
822static int cam_vfe_bus_start_wm(struct cam_isp_resource_node *wm_res)
823{
824 int rc = 0;
825 struct cam_vfe_bus_ver2_wm_resource_data *rsrc_data =
826 wm_res->res_priv;
827 struct cam_vfe_bus_ver2_common_data *common_data =
828 rsrc_data->common_data;
Harsh Shah19f55812017-06-26 18:58:49 -0700829 uint32_t bus_irq_reg_mask[CAM_VFE_BUS_IRQ_MAX] = {0};
Harsh Shaha1af8822017-05-11 22:06:36 -0700830
Harsh Shah23557ae2017-05-13 18:14:34 -0700831 cam_io_w_mb(0, common_data->mem_base + rsrc_data->hw_regs->header_addr);
832 cam_io_w_mb(0, common_data->mem_base + rsrc_data->hw_regs->header_cfg);
Harsh Shah23557ae2017-05-13 18:14:34 -0700833 cam_io_w(0xf, common_data->mem_base + rsrc_data->hw_regs->burst_limit);
834
Jing Zhoua4e9fbe2017-05-15 14:37:21 -0700835 cam_io_w_mb(rsrc_data->width,
Harsh Shaha1af8822017-05-11 22:06:36 -0700836 common_data->mem_base + rsrc_data->hw_regs->buffer_width_cfg);
Jing Zhoua4e9fbe2017-05-15 14:37:21 -0700837 cam_io_w(rsrc_data->height,
Harsh Shaha1af8822017-05-11 22:06:36 -0700838 common_data->mem_base + rsrc_data->hw_regs->buffer_height_cfg);
Jing Zhoua4e9fbe2017-05-15 14:37:21 -0700839 cam_io_w(rsrc_data->pack_fmt,
Harsh Shaha1af8822017-05-11 22:06:36 -0700840 common_data->mem_base + rsrc_data->hw_regs->packer_cfg);
Harsh Shaha1af8822017-05-11 22:06:36 -0700841
Ravikishore Pampanaad6bc902017-07-12 19:37:06 +0530842 /* Configure stride for RDIs */
843 if (rsrc_data->index < 3)
844 cam_io_w_mb(rsrc_data->stride, (common_data->mem_base +
845 rsrc_data->hw_regs->stride));
Harsh Shaha1af8822017-05-11 22:06:36 -0700846
Harsh Shah19f55812017-06-26 18:58:49 -0700847 /* Subscribe IRQ */
848 if (rsrc_data->irq_enabled) {
849 CDBG("Subscribe WM%d IRQ\n", rsrc_data->index);
850 bus_irq_reg_mask[CAM_VFE_BUS_IRQ_REG1] =
851 (1 << rsrc_data->index);
852 wm_res->irq_handle = cam_irq_controller_subscribe_irq(
853 common_data->bus_irq_controller, CAM_IRQ_PRIORITY_1,
854 bus_irq_reg_mask, wm_res,
855 wm_res->top_half_handler,
856 cam_ife_mgr_do_tasklet_buf_done,
857 wm_res->tasklet_info, cam_tasklet_enqueue_cmd);
858 if (wm_res->irq_handle < 0) {
859 pr_err("Subscribe IRQ failed for WM %d\n",
860 rsrc_data->index);
861 return -EFAULT;
862 }
863 }
864
Junzhe Zou3d292562017-07-12 17:59:58 -0700865 /* enable ubwc if needed*/
866 if (rsrc_data->en_ubwc) {
867 cam_io_w_mb(0x1, common_data->mem_base +
868 rsrc_data->hw_regs->ubwc_regs->mode_cfg);
869 }
870
Harsh Shah19f55812017-06-26 18:58:49 -0700871 /* Enable WM */
872 cam_io_w_mb(rsrc_data->en_cfg, common_data->mem_base +
873 rsrc_data->hw_regs->cfg);
874
Harsh Shah23557ae2017-05-13 18:14:34 -0700875 CDBG("WM res %d width = %d, height = %d\n", rsrc_data->index,
Jing Zhoua4e9fbe2017-05-15 14:37:21 -0700876 rsrc_data->width, rsrc_data->height);
Harsh Shah23557ae2017-05-13 18:14:34 -0700877 CDBG("WM res %d pk_fmt = %d\n", rsrc_data->index,
Jing Zhoua4e9fbe2017-05-15 14:37:21 -0700878 rsrc_data->pack_fmt & PACKER_FMT_MAX);
Harsh Shah23557ae2017-05-13 18:14:34 -0700879 CDBG("WM res %d stride = %d, burst len = %d\n",
Jing Zhoua4e9fbe2017-05-15 14:37:21 -0700880 rsrc_data->index, rsrc_data->stride, 0xf);
Harsh Shah23557ae2017-05-13 18:14:34 -0700881 CDBG("enable WM res %d offset 0x%x val 0x%x\n", rsrc_data->index,
Jing Zhoua4e9fbe2017-05-15 14:37:21 -0700882 (uint32_t) rsrc_data->hw_regs->cfg, rsrc_data->en_cfg);
Harsh Shaha1af8822017-05-11 22:06:36 -0700883
884 wm_res->res_state = CAM_ISP_RESOURCE_STATE_STREAMING;
885
886 return rc;
887}
888
889static int cam_vfe_bus_stop_wm(struct cam_isp_resource_node *wm_res)
890{
891 int rc = 0;
892 struct cam_vfe_bus_ver2_wm_resource_data *rsrc_data =
893 wm_res->res_priv;
894 struct cam_vfe_bus_ver2_common_data *common_data =
895 rsrc_data->common_data;
896
897 /* Disble WM */
898 cam_io_w_mb(0x0,
899 common_data->mem_base + rsrc_data->hw_regs->cfg);
900
901 CDBG("irq_enabled %d", rsrc_data->irq_enabled);
902 /* Unsubscribe IRQ */
Harsh Shah19f55812017-06-26 18:58:49 -0700903 if (rsrc_data->irq_enabled)
904 rc = cam_irq_controller_unsubscribe_irq(
905 common_data->bus_irq_controller,
906 wm_res->irq_handle);
Harsh Shaha1af8822017-05-11 22:06:36 -0700907
908 /* Halt & Reset WM */
909 cam_io_w_mb(BIT(rsrc_data->index),
910 common_data->mem_base + common_data->common_reg->sw_reset);
911
912 wm_res->res_state = CAM_ISP_RESOURCE_STATE_RESERVED;
913
914 return rc;
915}
916
917static int cam_vfe_bus_handle_wm_done_top_half(uint32_t evt_id,
918 struct cam_irq_th_payload *th_payload)
919{
Harsh Shah19f55812017-06-26 18:58:49 -0700920 int32_t rc;
921 int i;
922 struct cam_isp_resource_node *wm_res = NULL;
923 struct cam_vfe_bus_ver2_wm_resource_data *rsrc_data = NULL;
924 struct cam_vfe_bus_irq_evt_payload *evt_payload;
925
926 wm_res = th_payload->handler_priv;
927 if (!wm_res) {
928 pr_err_ratelimited("Error! No resource\n");
929 return -ENODEV;
930 }
931
932 rsrc_data = wm_res->res_priv;
933
934 CDBG("IRQ status_0 = %x\n", th_payload->evt_status_arr[0]);
935 CDBG("IRQ status_1 = %x\n", th_payload->evt_status_arr[1]);
936
937 rc = cam_vfe_bus_get_evt_payload(rsrc_data->common_data, &evt_payload);
938 if (rc) {
939 pr_err_ratelimited("No tasklet_cmd is free in queue\n");
940 return rc;
941 }
942
943 cam_isp_hw_get_timestamp(&evt_payload->ts);
944
945 evt_payload->ctx = rsrc_data->ctx;
946 evt_payload->core_index = rsrc_data->common_data->core_index;
947 evt_payload->evt_id = evt_id;
948
949 for (i = 0; i < th_payload->num_registers; i++)
950 evt_payload->irq_reg_val[i] = th_payload->evt_status_arr[i];
951
952 th_payload->evt_payload_priv = evt_payload;
953
954 CDBG("Exit\n");
955 return rc;
Harsh Shaha1af8822017-05-11 22:06:36 -0700956}
957
958static int cam_vfe_bus_handle_wm_done_bottom_half(void *wm_node,
959 void *evt_payload_priv)
960{
961 int rc = CAM_VFE_IRQ_STATUS_ERR;
962 struct cam_isp_resource_node *wm_res = wm_node;
963 struct cam_vfe_bus_irq_evt_payload *evt_payload = evt_payload_priv;
Harsh Shah23557ae2017-05-13 18:14:34 -0700964 struct cam_vfe_bus_ver2_wm_resource_data *rsrc_data =
965 (wm_res == NULL) ? NULL : wm_res->res_priv;
966 uint32_t *cam_ife_irq_regs;
Harsh Shaha1af8822017-05-11 22:06:36 -0700967 uint32_t status_reg;
968
Harsh Shah23557ae2017-05-13 18:14:34 -0700969 if (!evt_payload || !rsrc_data)
970 return rc;
Harsh Shaha1af8822017-05-11 22:06:36 -0700971
Harsh Shah23557ae2017-05-13 18:14:34 -0700972 cam_ife_irq_regs = evt_payload->irq_reg_val;
973 status_reg = cam_ife_irq_regs[CAM_IFE_IRQ_BUS_REG_STATUS1];
974
975 if (status_reg & BIT(rsrc_data->index)) {
976 cam_ife_irq_regs[CAM_IFE_IRQ_BUS_REG_STATUS1] &=
977 ~BIT(rsrc_data->index);
Harsh Shaha1af8822017-05-11 22:06:36 -0700978 rc = CAM_VFE_IRQ_STATUS_SUCCESS;
Harsh Shah23557ae2017-05-13 18:14:34 -0700979 }
Harsh Shah19f55812017-06-26 18:58:49 -0700980 CDBG("status_reg %x rc %d\n", status_reg, rc);
Harsh Shaha1af8822017-05-11 22:06:36 -0700981
982 if (rc == CAM_VFE_IRQ_STATUS_SUCCESS)
Harsh Shah19f55812017-06-26 18:58:49 -0700983 cam_vfe_bus_put_evt_payload(rsrc_data->common_data,
Harsh Shaha1af8822017-05-11 22:06:36 -0700984 &evt_payload);
985
986 return rc;
987}
988
989static int cam_vfe_bus_init_wm_resource(uint32_t index,
990 struct cam_vfe_bus_ver2_priv *ver2_bus_priv,
991 struct cam_vfe_bus_ver2_hw_info *ver2_hw_info,
992 struct cam_isp_resource_node *wm_res)
993{
Harsh Shaha1af8822017-05-11 22:06:36 -0700994 struct cam_vfe_bus_ver2_wm_resource_data *rsrc_data;
995
996 rsrc_data = kzalloc(sizeof(struct cam_vfe_bus_ver2_wm_resource_data),
997 GFP_KERNEL);
998 if (!rsrc_data) {
Harsh Shah545df9a2017-06-16 16:43:17 -0700999 CDBG("Failed to alloc for WM res priv\n");
1000 return -ENOMEM;
Harsh Shaha1af8822017-05-11 22:06:36 -07001001 }
1002 wm_res->res_priv = rsrc_data;
1003
1004 rsrc_data->index = index;
1005 rsrc_data->hw_regs = &ver2_hw_info->bus_client_reg[index];
1006 rsrc_data->common_data = &ver2_bus_priv->common_data;
1007
1008 wm_res->res_state = CAM_ISP_RESOURCE_STATE_AVAILABLE;
1009 INIT_LIST_HEAD(&wm_res->list);
1010
1011 wm_res->start = cam_vfe_bus_start_wm;
1012 wm_res->stop = cam_vfe_bus_stop_wm;
1013 wm_res->top_half_handler = cam_vfe_bus_handle_wm_done_top_half;
1014 wm_res->bottom_half_handler = cam_vfe_bus_handle_wm_done_bottom_half;
1015 wm_res->hw_intf = ver2_bus_priv->common_data.hw_intf;
1016
Harsh Shah545df9a2017-06-16 16:43:17 -07001017 return 0;
1018}
1019
1020static int cam_vfe_bus_deinit_wm_resource(
1021 struct cam_isp_resource_node *wm_res)
1022{
1023 struct cam_vfe_bus_ver2_wm_resource_data *rsrc_data;
1024
1025 wm_res->res_state = CAM_ISP_RESOURCE_STATE_UNAVAILABLE;
1026 INIT_LIST_HEAD(&wm_res->list);
1027
1028 wm_res->start = NULL;
1029 wm_res->stop = NULL;
1030 wm_res->top_half_handler = NULL;
1031 wm_res->bottom_half_handler = NULL;
1032 wm_res->hw_intf = NULL;
1033
1034 rsrc_data = wm_res->res_priv;
1035 wm_res->res_priv = NULL;
1036 if (!rsrc_data) {
1037 pr_err("Error! WM res priv is NULL\n");
1038 return -ENOMEM;
1039 }
1040 kfree(rsrc_data);
1041
1042 return 0;
Harsh Shaha1af8822017-05-11 22:06:36 -07001043}
1044
1045static void cam_vfe_bus_add_wm_to_comp_grp(
1046 struct cam_isp_resource_node *comp_grp,
1047 uint32_t composite_mask)
1048{
1049 struct cam_vfe_bus_ver2_comp_grp_data *rsrc_data = comp_grp->res_priv;
1050
1051 rsrc_data->composite_mask |= composite_mask;
1052}
1053
1054static void cam_vfe_bus_match_comp_grp(
1055 struct cam_vfe_bus_ver2_priv *ver2_bus_priv,
1056 struct cam_isp_resource_node **comp_grp,
1057 uint32_t comp_grp_local_idx,
1058 uint32_t unique_id)
1059{
1060 struct cam_vfe_bus_ver2_comp_grp_data *rsrc_data = NULL;
1061 struct cam_isp_resource_node *comp_grp_local = NULL;
1062
1063 list_for_each_entry(comp_grp_local,
1064 &ver2_bus_priv->used_comp_grp, list) {
1065 rsrc_data = comp_grp_local->res_priv;
1066 if (rsrc_data->comp_grp_local_idx == comp_grp_local_idx &&
1067 rsrc_data->unique_id == unique_id) {
1068 /* Match found */
1069 *comp_grp = comp_grp_local;
1070 return;
1071 }
1072 }
1073
1074 *comp_grp = NULL;
1075}
1076
1077static int cam_vfe_bus_acquire_comp_grp(
1078 struct cam_vfe_bus_ver2_priv *ver2_bus_priv,
1079 struct cam_isp_out_port_info *out_port_info,
Harsh Shah19f55812017-06-26 18:58:49 -07001080 void *tasklet,
1081 void *ctx,
Harsh Shaha1af8822017-05-11 22:06:36 -07001082 uint32_t unique_id,
1083 uint32_t is_dual,
1084 uint32_t is_master,
1085 enum cam_vfe_bus_ver2_vfe_core_id dual_slave_core,
1086 struct cam_isp_resource_node **comp_grp)
1087{
1088 int rc = 0;
1089 struct cam_isp_resource_node *comp_grp_local = NULL;
1090 struct cam_vfe_bus_ver2_comp_grp_data *rsrc_data = NULL;
1091
1092 /* Check if matching comp_grp already acquired */
1093 cam_vfe_bus_match_comp_grp(ver2_bus_priv, &comp_grp_local,
1094 out_port_info->comp_grp_id, unique_id);
1095
1096 if (!comp_grp_local) {
1097 /* First find a free group */
1098 if (is_dual) {
1099 if (list_empty(&ver2_bus_priv->free_dual_comp_grp)) {
1100 pr_err("No Free Composite Group\n");
1101 return -ENODEV;
1102 }
1103 comp_grp_local = list_first_entry(
1104 &ver2_bus_priv->free_dual_comp_grp,
1105 struct cam_isp_resource_node, list);
1106 rsrc_data = comp_grp_local->res_priv;
1107 rc = cam_vfe_bus_ver2_get_intra_client_mask(
1108 dual_slave_core,
1109 comp_grp_local->hw_intf->hw_idx,
1110 &rsrc_data->intra_client_mask);
1111 } else {
1112 if (list_empty(&ver2_bus_priv->free_comp_grp)) {
1113 pr_err("No Free Composite Group\n");
1114 return -ENODEV;
1115 }
1116 comp_grp_local = list_first_entry(
1117 &ver2_bus_priv->free_comp_grp,
1118 struct cam_isp_resource_node, list);
1119 rsrc_data = comp_grp_local->res_priv;
1120 }
1121
1122 list_del(&comp_grp_local->list);
Harsh Shah19f55812017-06-26 18:58:49 -07001123 comp_grp_local->tasklet_info = tasklet;
Harsh Shaha1af8822017-05-11 22:06:36 -07001124 comp_grp_local->res_state = CAM_ISP_RESOURCE_STATE_RESERVED;
1125
1126 rsrc_data->is_master = is_master;
1127 rsrc_data->composite_mask = 0;
1128 rsrc_data->unique_id = unique_id;
1129 rsrc_data->comp_grp_local_idx = out_port_info->comp_grp_id;
1130
1131 list_add_tail(&comp_grp_local->list,
1132 &ver2_bus_priv->used_comp_grp);
1133
1134 } else {
1135 rsrc_data = comp_grp_local->res_priv;
1136 /* Do not support runtime change in composite mask */
1137 if (comp_grp_local->res_state ==
1138 CAM_ISP_RESOURCE_STATE_STREAMING) {
1139 pr_err("Invalid State %d Comp Grp %u\n",
1140 comp_grp_local->res_state,
1141 rsrc_data->comp_grp_type);
1142 return -EBUSY;
1143 }
1144 }
1145
Harsh Shah19f55812017-06-26 18:58:49 -07001146 rsrc_data->ctx = ctx;
Harsh Shaha1af8822017-05-11 22:06:36 -07001147 *comp_grp = comp_grp_local;
1148
1149 return rc;
1150}
1151
1152static int cam_vfe_bus_release_comp_grp(
1153 struct cam_vfe_bus_ver2_priv *ver2_bus_priv,
1154 struct cam_isp_resource_node *in_comp_grp)
1155{
1156 struct cam_isp_resource_node *comp_grp = NULL;
1157 struct cam_vfe_bus_ver2_comp_grp_data *in_rsrc_data = NULL;
1158 int match_found = 0;
1159
1160 if (!in_comp_grp) {
1161 pr_err("Invalid Params Comp Grp %pK\n", in_rsrc_data);
1162 return -EINVAL;
1163 }
1164
1165 if (in_comp_grp->res_state == CAM_ISP_RESOURCE_STATE_AVAILABLE) {
1166 /* Already Released. Do Nothing */
1167 return 0;
1168 }
1169
1170 in_rsrc_data = in_comp_grp->res_priv;
1171
1172 list_for_each_entry(comp_grp, &ver2_bus_priv->used_comp_grp, list) {
1173 if (comp_grp == in_comp_grp) {
1174 match_found = 1;
1175 break;
1176 }
1177 }
1178
1179 if (!match_found) {
1180 pr_err("Could not find matching Comp Grp type %u\n",
1181 in_rsrc_data->comp_grp_type);
1182 return -ENODEV;
1183 }
1184
1185
1186 list_del(&comp_grp->list);
1187 if (in_rsrc_data->comp_grp_type >= CAM_VFE_BUS_VER2_COMP_GRP_DUAL_0 &&
1188 in_rsrc_data->comp_grp_type <= CAM_VFE_BUS_VER2_COMP_GRP_DUAL_5)
1189 list_add_tail(&comp_grp->list,
1190 &ver2_bus_priv->free_dual_comp_grp);
Jing Zhoue71fd4a2017-05-15 19:44:34 -07001191 else if (in_rsrc_data->comp_grp_type >= CAM_VFE_BUS_VER2_COMP_GRP_0
1192 && in_rsrc_data->comp_grp_type <= CAM_VFE_BUS_VER2_COMP_GRP_5)
Harsh Shaha1af8822017-05-11 22:06:36 -07001193 list_add_tail(&comp_grp->list, &ver2_bus_priv->free_comp_grp);
1194
Harsh Shaha1af8822017-05-11 22:06:36 -07001195 in_rsrc_data->unique_id = 0;
1196 in_rsrc_data->comp_grp_local_idx = 0;
1197 in_rsrc_data->composite_mask = 0;
1198 in_rsrc_data->dual_slave_core = CAM_VFE_BUS_VER2_VFE_CORE_MAX;
1199
Harsh Shah19f55812017-06-26 18:58:49 -07001200 comp_grp->tasklet_info = NULL;
Harsh Shaha1af8822017-05-11 22:06:36 -07001201 comp_grp->res_state = CAM_ISP_RESOURCE_STATE_AVAILABLE;
1202
Jing Zhoue71fd4a2017-05-15 19:44:34 -07001203 return 0;
Harsh Shaha1af8822017-05-11 22:06:36 -07001204}
1205
1206static int cam_vfe_bus_start_comp_grp(struct cam_isp_resource_node *comp_grp)
1207{
1208 int rc = 0;
1209 struct cam_vfe_bus_ver2_comp_grp_data *rsrc_data =
1210 comp_grp->res_priv;
1211 struct cam_vfe_bus_ver2_common_data *common_data =
1212 rsrc_data->common_data;
Harsh Shah19f55812017-06-26 18:58:49 -07001213 uint32_t bus_irq_reg_mask[CAM_VFE_BUS_IRQ_MAX] = {0};
Harsh Shaha1af8822017-05-11 22:06:36 -07001214
1215 cam_io_w_mb(rsrc_data->composite_mask, common_data->mem_base +
1216 rsrc_data->hw_regs->comp_mask);
1217
1218 CDBG("composite_mask is 0x%x\n", rsrc_data->composite_mask);
1219 CDBG("composite_mask addr 0x%x\n", rsrc_data->hw_regs->comp_mask);
1220
1221 if (rsrc_data->comp_grp_type >= CAM_VFE_BUS_VER2_COMP_GRP_DUAL_0 &&
1222 rsrc_data->comp_grp_type <= CAM_VFE_BUS_VER2_COMP_GRP_DUAL_5 &&
1223 rsrc_data->is_master) {
1224 int dual_comp_grp = (rsrc_data->comp_grp_type -
1225 CAM_VFE_BUS_VER2_COMP_GRP_DUAL_0);
1226 int intra_client_en = cam_io_r_mb(common_data->mem_base +
1227 common_data->common_reg->dual_master_comp_cfg);
1228
1229 /* 2 Bits per comp_grp. Hence left shift by comp_grp * 2 */
1230 intra_client_en |=
1231 (rsrc_data->intra_client_mask << dual_comp_grp * 2);
1232
1233 cam_io_w_mb(intra_client_en, common_data->mem_base +
1234 common_data->common_reg->dual_master_comp_cfg);
Harsh Shah19f55812017-06-26 18:58:49 -07001235
1236 bus_irq_reg_mask[CAM_VFE_BUS_IRQ_REG2] = (1 << dual_comp_grp);
1237 } else {
1238 /* IRQ bits for COMP GRP start at 5. So add 5 to the shift */
1239 bus_irq_reg_mask[CAM_VFE_BUS_IRQ_REG0] =
1240 (1 << (rsrc_data->comp_grp_type + 5));
1241 }
1242
1243 /* Subscribe IRQ */
1244 CDBG("Subscribe COMP_GRP%d IRQ\n", rsrc_data->comp_grp_type);
1245 comp_grp->irq_handle = cam_irq_controller_subscribe_irq(
1246 common_data->bus_irq_controller, CAM_IRQ_PRIORITY_1,
1247 bus_irq_reg_mask, comp_grp,
1248 comp_grp->top_half_handler,
1249 cam_ife_mgr_do_tasklet_buf_done,
1250 comp_grp->tasklet_info, cam_tasklet_enqueue_cmd);
1251 if (comp_grp->irq_handle < 0) {
1252 pr_err("Subscribe IRQ failed for comp_grp %d\n",
1253 rsrc_data->comp_grp_type);
1254 return -EFAULT;
Harsh Shaha1af8822017-05-11 22:06:36 -07001255 }
1256
1257 comp_grp->res_state = CAM_ISP_RESOURCE_STATE_STREAMING;
Harsh Shah19f55812017-06-26 18:58:49 -07001258
Harsh Shaha1af8822017-05-11 22:06:36 -07001259 return rc;
1260}
1261
1262static int cam_vfe_bus_stop_comp_grp(struct cam_isp_resource_node *comp_grp)
1263{
1264 int rc = 0;
1265 struct cam_vfe_bus_ver2_comp_grp_data *rsrc_data =
1266 comp_grp->res_priv;
1267 struct cam_vfe_bus_ver2_common_data *common_data =
1268 rsrc_data->common_data;
1269
1270 /* Unsubscribe IRQ */
Harsh Shah19f55812017-06-26 18:58:49 -07001271 rc = cam_irq_controller_unsubscribe_irq(
1272 common_data->bus_irq_controller,
1273 comp_grp->irq_handle);
Harsh Shaha1af8822017-05-11 22:06:36 -07001274
1275 cam_io_w_mb(rsrc_data->composite_mask, common_data->mem_base +
1276 rsrc_data->hw_regs->comp_mask);
1277 if (rsrc_data->comp_grp_type >= CAM_VFE_BUS_VER2_COMP_GRP_DUAL_0 &&
1278 rsrc_data->comp_grp_type <= CAM_VFE_BUS_VER2_COMP_GRP_DUAL_5 &&
1279 rsrc_data->is_master) {
1280 int dual_comp_grp = (rsrc_data->comp_grp_type -
1281 CAM_VFE_BUS_VER2_COMP_GRP_DUAL_0);
1282 int intra_client_en = cam_io_r_mb(common_data->mem_base +
1283 common_data->common_reg->dual_master_comp_cfg);
1284
1285 /* 2 Bits per comp_grp. Hence left shift by comp_grp * 2 */
1286 intra_client_en &=
1287 ~(rsrc_data->intra_client_mask << dual_comp_grp * 2);
1288
1289 cam_io_w_mb(intra_client_en, common_data->mem_base +
1290 common_data->common_reg->dual_master_comp_cfg);
1291 }
1292
1293 comp_grp->res_state = CAM_ISP_RESOURCE_STATE_RESERVED;
1294
1295 return rc;
1296}
1297
1298static int cam_vfe_bus_handle_comp_done_top_half(uint32_t evt_id,
1299 struct cam_irq_th_payload *th_payload)
1300{
Harsh Shah19f55812017-06-26 18:58:49 -07001301 int32_t rc;
1302 int i;
1303 struct cam_isp_resource_node *comp_grp = NULL;
1304 struct cam_vfe_bus_ver2_comp_grp_data *rsrc_data = NULL;
1305 struct cam_vfe_bus_irq_evt_payload *evt_payload;
1306
1307 comp_grp = th_payload->handler_priv;
1308 if (!comp_grp) {
1309 pr_err_ratelimited("Error! No resource\n");
1310 return -ENODEV;
1311 }
1312
1313 rsrc_data = comp_grp->res_priv;
1314
1315 CDBG("IRQ status_0 = %x\n", th_payload->evt_status_arr[0]);
1316 CDBG("IRQ status_1 = %x\n", th_payload->evt_status_arr[1]);
1317
1318 rc = cam_vfe_bus_get_evt_payload(rsrc_data->common_data, &evt_payload);
1319 if (rc) {
1320 pr_err_ratelimited("No tasklet_cmd is free in queue\n");
1321 return rc;
1322 }
1323
1324 cam_isp_hw_get_timestamp(&evt_payload->ts);
1325
1326 evt_payload->ctx = rsrc_data->ctx;
1327 evt_payload->core_index = rsrc_data->common_data->core_index;
1328 evt_payload->evt_id = evt_id;
1329
1330 for (i = 0; i < th_payload->num_registers; i++)
1331 evt_payload->irq_reg_val[i] = th_payload->evt_status_arr[i];
1332
1333 th_payload->evt_payload_priv = evt_payload;
1334
1335 CDBG("Exit\n");
1336 return rc;
Harsh Shaha1af8822017-05-11 22:06:36 -07001337}
1338
1339static int cam_vfe_bus_handle_comp_done_bottom_half(
1340 void *handler_priv,
1341 void *evt_payload_priv)
1342{
1343 int rc = CAM_VFE_IRQ_STATUS_ERR;
1344 struct cam_isp_resource_node *comp_grp = handler_priv;
1345 struct cam_vfe_bus_irq_evt_payload *evt_payload = evt_payload_priv;
1346 struct cam_vfe_bus_ver2_comp_grp_data *rsrc_data = comp_grp->res_priv;
Harsh Shah23557ae2017-05-13 18:14:34 -07001347 uint32_t *cam_ife_irq_regs;
1348 uint32_t status_reg;
1349 uint32_t comp_err_reg;
1350 uint32_t comp_grp_id;
1351
Harsh Shah19f55812017-06-26 18:58:49 -07001352 CDBG("comp grp type %d\n", rsrc_data->comp_grp_type);
1353
Harsh Shah23557ae2017-05-13 18:14:34 -07001354 if (!evt_payload)
1355 return rc;
1356
1357 cam_ife_irq_regs = evt_payload->irq_reg_val;
Harsh Shaha1af8822017-05-11 22:06:36 -07001358
Harsh Shaha1af8822017-05-11 22:06:36 -07001359 switch (rsrc_data->comp_grp_type) {
1360 case CAM_VFE_BUS_VER2_COMP_GRP_0:
1361 case CAM_VFE_BUS_VER2_COMP_GRP_1:
1362 case CAM_VFE_BUS_VER2_COMP_GRP_2:
1363 case CAM_VFE_BUS_VER2_COMP_GRP_3:
1364 case CAM_VFE_BUS_VER2_COMP_GRP_4:
1365 case CAM_VFE_BUS_VER2_COMP_GRP_5:
Harsh Shah23557ae2017-05-13 18:14:34 -07001366 comp_grp_id = (rsrc_data->comp_grp_type -
Harsh Shaha1af8822017-05-11 22:06:36 -07001367 CAM_VFE_BUS_VER2_COMP_GRP_0);
1368
1369 /* Check for Regular composite error */
1370 status_reg = cam_ife_irq_regs[CAM_IFE_IRQ_BUS_REG_STATUS0];
1371
1372 comp_err_reg = cam_ife_irq_regs[CAM_IFE_IRQ_BUS_REG_COMP_ERR];
1373 if ((status_reg & BIT(11)) &&
1374 (comp_err_reg & rsrc_data->composite_mask)) {
1375 /* Check for Regular composite error */
1376 rc = CAM_VFE_IRQ_STATUS_ERR_COMP;
1377 break;
1378 }
1379
1380 comp_err_reg = cam_ife_irq_regs[CAM_IFE_IRQ_BUS_REG_COMP_OWRT];
1381 /* Check for Regular composite Overwrite */
1382 if ((status_reg & BIT(12)) &&
1383 (comp_err_reg & rsrc_data->composite_mask)) {
1384 rc = CAM_VFE_IRQ_STATUS_COMP_OWRT;
1385 break;
1386 }
1387
Harsh Shah23557ae2017-05-13 18:14:34 -07001388 /* Regular Composite SUCCESS */
1389 if (status_reg & BIT(comp_grp_id + 5)) {
1390 cam_ife_irq_regs[CAM_IFE_IRQ_BUS_REG_STATUS0] &=
1391 ~BIT(comp_grp_id + 5);
Harsh Shaha1af8822017-05-11 22:06:36 -07001392 rc = CAM_VFE_IRQ_STATUS_SUCCESS;
Harsh Shah23557ae2017-05-13 18:14:34 -07001393 }
Harsh Shaha1af8822017-05-11 22:06:36 -07001394
Harsh Shah19f55812017-06-26 18:58:49 -07001395 CDBG("status reg = 0x%x, bit index = %d rc %d\n",
1396 status_reg, (comp_grp_id + 5), rc);
Harsh Shaha1af8822017-05-11 22:06:36 -07001397 break;
1398
1399 case CAM_VFE_BUS_VER2_COMP_GRP_DUAL_0:
1400 case CAM_VFE_BUS_VER2_COMP_GRP_DUAL_1:
1401 case CAM_VFE_BUS_VER2_COMP_GRP_DUAL_2:
1402 case CAM_VFE_BUS_VER2_COMP_GRP_DUAL_3:
1403 case CAM_VFE_BUS_VER2_COMP_GRP_DUAL_4:
1404 case CAM_VFE_BUS_VER2_COMP_GRP_DUAL_5:
Harsh Shah23557ae2017-05-13 18:14:34 -07001405 comp_grp_id = (rsrc_data->comp_grp_type -
Harsh Shaha1af8822017-05-11 22:06:36 -07001406 CAM_VFE_BUS_VER2_COMP_GRP_DUAL_0);
1407
1408 /* Check for DUAL composite error */
1409 status_reg = cam_ife_irq_regs[CAM_IFE_IRQ_BUS_REG_STATUS2];
1410
1411 comp_err_reg = cam_ife_irq_regs[CAM_IFE_IRQ_BUS_DUAL_COMP_ERR];
1412 if ((status_reg & BIT(6)) &&
1413 (comp_err_reg & rsrc_data->composite_mask)) {
1414 /* Check for DUAL composite error */
1415 rc = CAM_VFE_IRQ_STATUS_ERR_COMP;
1416 break;
1417 }
1418
1419 /* Check for Dual composite Overwrite */
1420 comp_err_reg = cam_ife_irq_regs[CAM_IFE_IRQ_BUS_DUAL_COMP_OWRT];
1421 if ((status_reg & BIT(7)) &&
1422 (comp_err_reg & rsrc_data->composite_mask)) {
1423 rc = CAM_VFE_IRQ_STATUS_COMP_OWRT;
1424 break;
1425 }
1426
Harsh Shah23557ae2017-05-13 18:14:34 -07001427 /* DUAL Composite SUCCESS */
1428 if (status_reg & BIT(comp_grp_id)) {
1429 cam_ife_irq_regs[CAM_IFE_IRQ_BUS_REG_STATUS2] &=
1430 ~BIT(comp_grp_id + 5);
Harsh Shaha1af8822017-05-11 22:06:36 -07001431 rc = CAM_VFE_IRQ_STATUS_SUCCESS;
Harsh Shah23557ae2017-05-13 18:14:34 -07001432 }
Harsh Shaha1af8822017-05-11 22:06:36 -07001433
1434 break;
Harsh Shaha1af8822017-05-11 22:06:36 -07001435 default:
1436 rc = CAM_VFE_IRQ_STATUS_ERR;
Harsh Shah19f55812017-06-26 18:58:49 -07001437 pr_err("Error! Invalid comp_grp_type %u\n",
1438 rsrc_data->comp_grp_type);
Harsh Shaha1af8822017-05-11 22:06:36 -07001439 break;
1440 }
1441
1442 if (rc == CAM_VFE_IRQ_STATUS_SUCCESS)
Harsh Shah19f55812017-06-26 18:58:49 -07001443 cam_vfe_bus_put_evt_payload(rsrc_data->common_data,
Harsh Shaha1af8822017-05-11 22:06:36 -07001444 &evt_payload);
1445
1446 return rc;
1447}
1448
1449static int cam_vfe_bus_init_comp_grp(uint32_t index,
1450 struct cam_vfe_bus_ver2_priv *ver2_bus_priv,
1451 struct cam_vfe_bus_ver2_hw_info *ver2_hw_info,
1452 struct cam_isp_resource_node *comp_grp)
1453{
Harsh Shah545df9a2017-06-16 16:43:17 -07001454 struct cam_vfe_bus_ver2_comp_grp_data *rsrc_data = NULL;
Harsh Shaha1af8822017-05-11 22:06:36 -07001455
1456 rsrc_data = kzalloc(sizeof(struct cam_vfe_bus_ver2_comp_grp_data),
1457 GFP_KERNEL);
1458 if (!rsrc_data) {
1459 CDBG("Failed to alloc for comp_grp_priv\n");
1460 return -ENOMEM;
1461 }
1462 comp_grp->res_priv = rsrc_data;
1463
1464 comp_grp->res_state = CAM_ISP_RESOURCE_STATE_AVAILABLE;
1465 INIT_LIST_HEAD(&comp_grp->list);
1466
1467 rsrc_data->comp_grp_type = index;
1468 rsrc_data->common_data = &ver2_bus_priv->common_data;
1469 rsrc_data->hw_regs = &ver2_hw_info->comp_grp_reg[index];
1470 rsrc_data->dual_slave_core = CAM_VFE_BUS_VER2_VFE_CORE_MAX;
1471
Harsh Shaha1af8822017-05-11 22:06:36 -07001472 if (rsrc_data->comp_grp_type >= CAM_VFE_BUS_VER2_COMP_GRP_DUAL_0 &&
1473 rsrc_data->comp_grp_type <= CAM_VFE_BUS_VER2_COMP_GRP_DUAL_5)
1474 list_add_tail(&comp_grp->list,
1475 &ver2_bus_priv->free_dual_comp_grp);
1476 else if (rsrc_data->comp_grp_type >= CAM_VFE_BUS_VER2_COMP_GRP_0
1477 && rsrc_data->comp_grp_type <= CAM_VFE_BUS_VER2_COMP_GRP_5)
1478 list_add_tail(&comp_grp->list, &ver2_bus_priv->free_comp_grp);
1479
1480 comp_grp->start = cam_vfe_bus_start_comp_grp;
1481 comp_grp->stop = cam_vfe_bus_stop_comp_grp;
1482 comp_grp->top_half_handler = cam_vfe_bus_handle_comp_done_top_half;
1483 comp_grp->bottom_half_handler =
1484 cam_vfe_bus_handle_comp_done_bottom_half;
1485 comp_grp->hw_intf = ver2_bus_priv->common_data.hw_intf;
1486
1487 return 0;
1488}
1489
Harsh Shah545df9a2017-06-16 16:43:17 -07001490static int cam_vfe_bus_deinit_comp_grp(
1491 struct cam_isp_resource_node *comp_grp)
1492{
1493 struct cam_vfe_bus_ver2_comp_grp_data *rsrc_data =
1494 comp_grp->res_priv;
1495
1496 comp_grp->start = NULL;
1497 comp_grp->stop = NULL;
1498 comp_grp->top_half_handler = NULL;
1499 comp_grp->bottom_half_handler = NULL;
1500 comp_grp->hw_intf = NULL;
1501
1502 list_del_init(&comp_grp->list);
1503 comp_grp->res_state = CAM_ISP_RESOURCE_STATE_UNAVAILABLE;
1504
1505 comp_grp->res_priv = NULL;
1506
1507 if (!rsrc_data) {
1508 pr_err("Error! comp_grp_priv is NULL\n");
1509 return -ENODEV;
1510 }
1511 kfree(rsrc_data);
1512
1513 return 0;
1514}
1515
Harsh Shah19f55812017-06-26 18:58:49 -07001516static int cam_vfe_bus_acquire_vfe_out(void *bus_priv, void *acquire_args,
1517 uint32_t args_size)
Harsh Shaha1af8822017-05-11 22:06:36 -07001518{
1519 int rc = -ENODEV;
1520 int i;
1521 enum cam_vfe_bus_ver2_vfe_out_type vfe_out_res_id;
1522 uint32_t format;
1523 uint32_t num_wm;
1524 uint32_t subscribe_irq;
1525 uint32_t client_done_mask;
1526 struct cam_vfe_bus_ver2_priv *ver2_bus_priv = bus_priv;
1527 struct cam_vfe_acquire_args *acq_args = acquire_args;
1528 struct cam_vfe_hw_vfe_out_acquire_args *out_acquire_args;
1529 struct cam_isp_resource_node *rsrc_node = NULL;
1530 struct cam_vfe_bus_ver2_vfe_out_data *rsrc_data = NULL;
1531
1532 if (!bus_priv || !acquire_args) {
1533 pr_err("Invalid Param");
1534 return -EINVAL;
1535 }
1536
1537 out_acquire_args = &acq_args->vfe_out;
1538 format = out_acquire_args->out_port_info->format;
1539
1540 CDBG("Acquiring resource type 0x%x\n",
1541 out_acquire_args->out_port_info->res_type);
1542
1543 vfe_out_res_id = cam_vfe_bus_get_out_res_id(
1544 out_acquire_args->out_port_info->res_type);
1545 if (vfe_out_res_id == CAM_VFE_BUS_VER2_VFE_OUT_MAX)
1546 return -ENODEV;
1547
1548 num_wm = cam_vfe_bus_get_num_wm(vfe_out_res_id, format);
1549 if (num_wm < 1)
1550 return -EINVAL;
1551
1552 rsrc_node = &ver2_bus_priv->vfe_out[vfe_out_res_id];
1553 if (rsrc_node->res_state != CAM_ISP_RESOURCE_STATE_AVAILABLE) {
1554 pr_err("Resource not available: Res_id %d state:%d\n",
1555 vfe_out_res_id, rsrc_node->res_state);
1556 return -EBUSY;
1557 }
1558
1559 rsrc_data = rsrc_node->res_priv;
1560 rsrc_data->num_wm = num_wm;
1561 rsrc_node->res_id = out_acquire_args->out_port_info->res_type;
1562 rsrc_node->tasklet_info = acq_args->tasklet;
1563 rsrc_node->cdm_ops = out_acquire_args->cdm_ops;
1564 rsrc_data->cdm_util_ops = out_acquire_args->cdm_ops;
1565
1566 /* Reserve Composite Group */
1567 if (num_wm > 1 || (out_acquire_args->out_port_info->comp_grp_id >
1568 CAM_ISP_RES_COMP_GROUP_NONE &&
1569 out_acquire_args->out_port_info->comp_grp_id <
1570 CAM_ISP_RES_COMP_GROUP_ID_MAX)) {
1571 rc = cam_vfe_bus_acquire_comp_grp(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 out_acquire_args->unique_id,
1576 out_acquire_args->is_dual,
1577 out_acquire_args->is_master,
1578 out_acquire_args->dual_slave_core,
1579 &rsrc_data->comp_grp);
Harsh Shah19f55812017-06-26 18:58:49 -07001580 if (rc) {
1581 pr_err("VFE%d Comp_Grp acquire failed for Out %d rc=%d\n",
1582 rsrc_data->common_data->core_index,
1583 vfe_out_res_id, rc);
Harsh Shaha1af8822017-05-11 22:06:36 -07001584 return rc;
Harsh Shah19f55812017-06-26 18:58:49 -07001585 }
Harsh Shaha1af8822017-05-11 22:06:36 -07001586
1587 subscribe_irq = 0;
Harsh Shah19f55812017-06-26 18:58:49 -07001588 } else {
Harsh Shaha1af8822017-05-11 22:06:36 -07001589 subscribe_irq = 1;
Harsh Shah19f55812017-06-26 18:58:49 -07001590 }
Harsh Shaha1af8822017-05-11 22:06:36 -07001591
1592 /* Reserve WM */
1593 for (i = 0; i < num_wm; i++) {
1594 rc = cam_vfe_bus_acquire_wm(ver2_bus_priv,
1595 out_acquire_args->out_port_info,
Harsh Shah19f55812017-06-26 18:58:49 -07001596 acq_args->tasklet,
1597 out_acquire_args->ctx,
Harsh Shaha1af8822017-05-11 22:06:36 -07001598 vfe_out_res_id,
1599 i,
1600 out_acquire_args->split_id,
1601 subscribe_irq,
1602 &rsrc_data->wm_res[i],
1603 &client_done_mask);
Harsh Shah19f55812017-06-26 18:58:49 -07001604 if (rc) {
1605 pr_err("VFE%d WM acquire failed for Out %d rc=%d\n",
1606 rsrc_data->common_data->core_index,
1607 vfe_out_res_id, rc);
Harsh Shaha1af8822017-05-11 22:06:36 -07001608 goto release_wm;
Harsh Shah19f55812017-06-26 18:58:49 -07001609 }
Harsh Shaha1af8822017-05-11 22:06:36 -07001610
1611 if (rsrc_data->comp_grp)
1612 cam_vfe_bus_add_wm_to_comp_grp(rsrc_data->comp_grp,
1613 client_done_mask);
1614 }
1615
1616 rsrc_node->res_state = CAM_ISP_RESOURCE_STATE_RESERVED;
1617 out_acquire_args->rsrc_node = rsrc_node;
1618
1619 CDBG("Acquire successful\n");
1620 return rc;
1621
1622release_wm:
1623 for (i--; i >= 0; i--)
1624 cam_vfe_bus_release_wm(ver2_bus_priv, rsrc_data->wm_res[i]);
1625
1626 cam_vfe_bus_release_comp_grp(ver2_bus_priv,
1627 rsrc_data->comp_grp);
1628
1629 return rc;
1630}
1631
Harsh Shah19f55812017-06-26 18:58:49 -07001632static int cam_vfe_bus_release_vfe_out(void *bus_priv, void *release_args,
1633 uint32_t args_size)
Harsh Shaha1af8822017-05-11 22:06:36 -07001634{
Jing Zhoue71fd4a2017-05-15 19:44:34 -07001635 uint32_t i;
Harsh Shah19f55812017-06-26 18:58:49 -07001636 struct cam_isp_resource_node *vfe_out = NULL;
1637 struct cam_vfe_bus_ver2_vfe_out_data *rsrc_data = NULL;
1638
1639 if (!bus_priv || !release_args) {
1640 pr_err("Invalid input bus_priv %pK release_args %pK\n",
1641 bus_priv, release_args);
1642 return -EINVAL;
1643 }
1644
1645 vfe_out = release_args;
1646 rsrc_data = vfe_out->res_priv;
Jing Zhoue71fd4a2017-05-15 19:44:34 -07001647
Harsh Shaha1af8822017-05-11 22:06:36 -07001648 if (vfe_out->res_state != CAM_ISP_RESOURCE_STATE_RESERVED) {
1649 pr_err("Error! Invalid resource state:%d\n",
1650 vfe_out->res_state);
1651 }
1652
Jing Zhoue71fd4a2017-05-15 19:44:34 -07001653 for (i = 0; i < rsrc_data->num_wm; i++)
1654 cam_vfe_bus_release_wm(bus_priv, rsrc_data->wm_res[i]);
1655 rsrc_data->num_wm = 0;
1656
1657 if (rsrc_data->comp_grp)
1658 cam_vfe_bus_release_comp_grp(bus_priv, rsrc_data->comp_grp);
1659 rsrc_data->comp_grp = NULL;
1660
1661 vfe_out->tasklet_info = NULL;
1662 vfe_out->cdm_ops = NULL;
1663 rsrc_data->cdm_util_ops = NULL;
1664
Harsh Shaha1af8822017-05-11 22:06:36 -07001665 if (vfe_out->res_state == CAM_ISP_RESOURCE_STATE_RESERVED)
1666 vfe_out->res_state = CAM_ISP_RESOURCE_STATE_AVAILABLE;
1667
1668 return 0;
1669}
1670
Harsh Shah19f55812017-06-26 18:58:49 -07001671static int cam_vfe_bus_start_vfe_out(
1672 struct cam_isp_resource_node *vfe_out)
Harsh Shaha1af8822017-05-11 22:06:36 -07001673{
1674 int rc = 0, i;
Harsh Shah19f55812017-06-26 18:58:49 -07001675 struct cam_vfe_bus_ver2_vfe_out_data *rsrc_data = NULL;
1676 struct cam_vfe_bus_ver2_common_data *common_data = NULL;
1677
1678 if (!vfe_out) {
1679 pr_err("Invalid input\n");
1680 return -EINVAL;
1681 }
1682
1683 rsrc_data = vfe_out->res_priv;
1684 common_data = rsrc_data->common_data;
Harsh Shaha1af8822017-05-11 22:06:36 -07001685
1686 CDBG("Start resource index %d\n", rsrc_data->out_type);
1687
1688 if (vfe_out->res_state != CAM_ISP_RESOURCE_STATE_RESERVED) {
1689 pr_err("Error! Invalid resource state:%d\n",
1690 vfe_out->res_state);
1691 return -EACCES;
1692 }
1693
1694 for (i = 0; i < rsrc_data->num_wm; i++)
1695 rc = cam_vfe_bus_start_wm(rsrc_data->wm_res[i]);
1696
1697 if (rsrc_data->comp_grp)
1698 rc = cam_vfe_bus_start_comp_grp(rsrc_data->comp_grp);
1699
Harsh Shaha1af8822017-05-11 22:06:36 -07001700 /* BUS_WR_INPUT_IF_ADDR_SYNC_CFG */
1701 cam_io_w_mb(0x0, rsrc_data->common_data->mem_base + 0x0000207C);
1702 /* BUS_WR_INPUT_IF_ADDR_SYNC_FRAME_HEADER */
1703 cam_io_w_mb(0x0, rsrc_data->common_data->mem_base + 0x00002080);
1704 /* BUS_WR_INPUT_IF_ADDR_SYNC_NO_SYNC */
1705 cam_io_w_mb(0xFFFFF, rsrc_data->common_data->mem_base + 0x00002084);
Harsh Shaha1af8822017-05-11 22:06:36 -07001706 /* BUS_WR_INPUT_IF_ADDR_SYNC_0 */
1707 cam_io_w_mb(0x0, rsrc_data->common_data->mem_base + 0x00002088);
1708 cam_io_w_mb(0x0, rsrc_data->common_data->mem_base + 0x0000208c);
1709 cam_io_w_mb(0x0, rsrc_data->common_data->mem_base + 0x00002090);
1710 cam_io_w_mb(0x0, rsrc_data->common_data->mem_base + 0x00002094);
1711 cam_io_w_mb(0x0, rsrc_data->common_data->mem_base + 0x00002098);
1712 cam_io_w_mb(0x0, rsrc_data->common_data->mem_base + 0x0000209c);
1713 cam_io_w_mb(0x0, rsrc_data->common_data->mem_base + 0x000020a0);
1714 cam_io_w_mb(0x0, rsrc_data->common_data->mem_base + 0x000020a4);
1715
Harsh Shah23557ae2017-05-13 18:14:34 -07001716 /* no clock gating at bus input */
1717 cam_io_w_mb(0xFFFFF, rsrc_data->common_data->mem_base + 0x0000200C);
1718
1719 /* BUS_WR_TEST_BUS_CTRL */
1720 cam_io_w_mb(0x0, rsrc_data->common_data->mem_base + 0x0000211C);
1721
Abhishek Kondaveeti157ae882017-07-08 06:56:48 +05301722 vfe_out->res_state = CAM_ISP_RESOURCE_STATE_STREAMING;
Harsh Shaha1af8822017-05-11 22:06:36 -07001723 return rc;
1724}
1725
Harsh Shah19f55812017-06-26 18:58:49 -07001726static int cam_vfe_bus_stop_vfe_out(
1727 struct cam_isp_resource_node *vfe_out)
Harsh Shaha1af8822017-05-11 22:06:36 -07001728{
1729 int rc = 0, i;
Harsh Shah19f55812017-06-26 18:58:49 -07001730 struct cam_vfe_bus_ver2_vfe_out_data *rsrc_data = NULL;
1731
1732 if (!vfe_out) {
1733 pr_err("Invalid input\n");
1734 return -EINVAL;
1735 }
1736
1737 rsrc_data = vfe_out->res_priv;
Harsh Shaha1af8822017-05-11 22:06:36 -07001738
1739 if (vfe_out->res_state == CAM_ISP_RESOURCE_STATE_AVAILABLE ||
1740 vfe_out->res_state == CAM_ISP_RESOURCE_STATE_RESERVED) {
1741 return rc;
1742 }
1743
1744 if (rsrc_data->comp_grp)
1745 rc = cam_vfe_bus_stop_comp_grp(rsrc_data->comp_grp);
1746
1747 for (i = 0; i < rsrc_data->num_wm; i++)
1748 rc = cam_vfe_bus_stop_wm(rsrc_data->wm_res[i]);
1749
Harsh Shaha1af8822017-05-11 22:06:36 -07001750
1751 vfe_out->res_state = CAM_ISP_RESOURCE_STATE_RESERVED;
1752 return rc;
1753}
1754
1755static int cam_vfe_bus_handle_vfe_out_done_top_half(uint32_t evt_id,
1756 struct cam_irq_th_payload *th_payload)
1757{
1758 return -EPERM;
1759}
1760
1761static int cam_vfe_bus_handle_vfe_out_done_bottom_half(
1762 void *handler_priv,
1763 void *evt_payload_priv)
1764{
1765 int rc = -EINVAL;
1766 struct cam_isp_resource_node *vfe_out = handler_priv;
1767 struct cam_vfe_bus_ver2_vfe_out_data *rsrc_data = vfe_out->res_priv;
1768
1769 /*
1770 * If this resource has Composite Group then we only handle
1771 * Composite done. We acquire Composite if number of WM > 1.
1772 * So Else case is only one individual buf_done = WM[0].
1773 */
1774 if (rsrc_data->comp_grp) {
1775 rc = rsrc_data->comp_grp->bottom_half_handler(
1776 rsrc_data->comp_grp, evt_payload_priv);
1777 } else {
1778 rc = rsrc_data->wm_res[0]->bottom_half_handler(
Harsh Shah23557ae2017-05-13 18:14:34 -07001779 rsrc_data->wm_res[0], evt_payload_priv);
Harsh Shaha1af8822017-05-11 22:06:36 -07001780 }
1781
1782 return rc;
1783}
1784
1785static int cam_vfe_bus_init_vfe_out_resource(uint32_t index,
1786 struct cam_vfe_bus_ver2_priv *ver2_bus_priv,
1787 struct cam_vfe_bus_ver2_hw_info *ver2_hw_info,
1788 struct cam_isp_resource_node *vfe_out)
1789{
1790 struct cam_vfe_bus_ver2_vfe_out_data *rsrc_data = NULL;
1791 int rc = 0;
1792
1793 rsrc_data = kzalloc(sizeof(struct cam_vfe_bus_ver2_vfe_out_data),
1794 GFP_KERNEL);
1795 if (!rsrc_data) {
1796 CDBG("Error! Failed to alloc for vfe out priv\n");
1797 rc = -ENOMEM;
1798 return rc;
1799 }
1800 vfe_out->res_priv = rsrc_data;
1801
1802 vfe_out->res_type = CAM_ISP_RESOURCE_VFE_OUT;
1803 vfe_out->res_state = CAM_ISP_RESOURCE_STATE_AVAILABLE;
1804 INIT_LIST_HEAD(&vfe_out->list);
1805
1806 rsrc_data->out_type = index;
1807 rsrc_data->common_data = &ver2_bus_priv->common_data;
1808 rsrc_data->max_width =
1809 ver2_hw_info->vfe_out_hw_info[index].max_width;
1810 rsrc_data->max_height =
1811 ver2_hw_info->vfe_out_hw_info[index].max_height;
1812
1813 vfe_out->start = cam_vfe_bus_start_vfe_out;
1814 vfe_out->stop = cam_vfe_bus_stop_vfe_out;
1815 vfe_out->top_half_handler = cam_vfe_bus_handle_vfe_out_done_top_half;
1816 vfe_out->bottom_half_handler =
1817 cam_vfe_bus_handle_vfe_out_done_bottom_half;
1818 vfe_out->hw_intf = ver2_bus_priv->common_data.hw_intf;
1819
1820 return 0;
1821}
1822
Harsh Shah545df9a2017-06-16 16:43:17 -07001823static int cam_vfe_bus_deinit_vfe_out_resource(
1824 struct cam_isp_resource_node *vfe_out)
1825{
1826 struct cam_vfe_bus_ver2_vfe_out_data *rsrc_data = vfe_out->res_priv;
1827
1828 vfe_out->start = NULL;
1829 vfe_out->stop = NULL;
1830 vfe_out->top_half_handler = NULL;
1831 vfe_out->bottom_half_handler = NULL;
1832 vfe_out->hw_intf = NULL;
1833
1834 vfe_out->res_state = CAM_ISP_RESOURCE_STATE_UNAVAILABLE;
1835 INIT_LIST_HEAD(&vfe_out->list);
1836 vfe_out->res_priv = NULL;
1837
1838 if (!rsrc_data) {
1839 pr_err("Error! vfe out priv is NULL\n");
1840 return -ENOMEM;
1841 }
1842 kfree(rsrc_data);
1843
1844 return 0;
1845}
1846
Harsh Shaha1af8822017-05-11 22:06:36 -07001847static int cam_vfe_bus_ver2_handle_irq(uint32_t evt_id,
1848 struct cam_irq_th_payload *th_payload)
1849{
Harsh Shaha1af8822017-05-11 22:06:36 -07001850 struct cam_vfe_bus_ver2_priv *bus_priv;
Harsh Shaha1af8822017-05-11 22:06:36 -07001851
Harsh Shah19f55812017-06-26 18:58:49 -07001852 bus_priv = th_payload->handler_priv;
Harsh Shaha1af8822017-05-11 22:06:36 -07001853 CDBG("Enter\n");
Harsh Shah19f55812017-06-26 18:58:49 -07001854 return cam_irq_controller_handle_irq(evt_id,
1855 bus_priv->common_data.bus_irq_controller);
Harsh Shaha1af8822017-05-11 22:06:36 -07001856}
1857
1858static int cam_vfe_bus_update_buf(void *priv, void *cmd_args,
1859 uint32_t arg_size)
1860{
1861 struct cam_vfe_bus_ver2_priv *bus_priv;
1862 struct cam_isp_hw_get_buf_update *update_buf;
Jing Zhoua4e9fbe2017-05-15 14:37:21 -07001863 struct cam_buf_io_cfg *io_cfg;
Harsh Shaha1af8822017-05-11 22:06:36 -07001864 struct cam_vfe_bus_ver2_vfe_out_data *vfe_out_data = NULL;
1865 struct cam_vfe_bus_ver2_wm_resource_data *wm_data = NULL;
Jing Zhoua4e9fbe2017-05-15 14:37:21 -07001866 uint32_t *reg_val_pair;
1867 uint32_t i, j, size = 0;
Junzhe Zou193d78c2017-05-16 15:10:54 -07001868 uint32_t frame_inc = 0;
Harsh Shaha1af8822017-05-11 22:06:36 -07001869
1870 /*
1871 * Need the entire buf io config so we can get the stride info
1872 * for the wm.
1873 */
1874
1875 bus_priv = (struct cam_vfe_bus_ver2_priv *) priv;
1876 update_buf = (struct cam_isp_hw_get_buf_update *) cmd_args;
1877
1878 vfe_out_data = (struct cam_vfe_bus_ver2_vfe_out_data *)
1879 update_buf->cdm.res->res_priv;
1880
1881 if (!vfe_out_data || !vfe_out_data->cdm_util_ops) {
1882 pr_err("Failed! Invalid data\n");
1883 return -EINVAL;
1884 }
1885
Jing Zhoua4e9fbe2017-05-15 14:37:21 -07001886 if (update_buf->num_buf != vfe_out_data->num_wm) {
Harsh Shaha1af8822017-05-11 22:06:36 -07001887 pr_err("Failed! Invalid number buffers:%d required:%d\n",
1888 update_buf->num_buf, vfe_out_data->num_wm);
Junzhe Zou193d78c2017-05-16 15:10:54 -07001889 return -EINVAL;
Harsh Shaha1af8822017-05-11 22:06:36 -07001890 }
1891
Jing Zhoua4e9fbe2017-05-15 14:37:21 -07001892 reg_val_pair = &vfe_out_data->common_data->io_buf_update[0];
1893 io_cfg = update_buf->io_cfg;
1894
1895 for (i = 0, j = 0; i < vfe_out_data->num_wm; i++) {
Junzhe Zou193d78c2017-05-16 15:10:54 -07001896 if (j >= (MAX_REG_VAL_PAIR_SIZE - MAX_BUF_UPDATE_REG_NUM * 2)) {
1897 pr_err("reg_val_pair %d exceeds the array limit %lu\n",
1898 j, MAX_REG_VAL_PAIR_SIZE);
1899 return -ENOMEM;
1900 }
1901
Jing Zhoua4e9fbe2017-05-15 14:37:21 -07001902 wm_data = vfe_out_data->wm_res[i]->res_priv;
1903
1904 /* For initial configuration program all bus registers */
Ravikishore Pampanaad6bc902017-07-12 19:37:06 +05301905 if ((wm_data->stride != io_cfg->planes[i].plane_stride ||
1906 !wm_data->init_cfg_done) && (wm_data->index >= 3)) {
Jing Zhoua4e9fbe2017-05-15 14:37:21 -07001907 CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j,
1908 wm_data->hw_regs->stride,
1909 io_cfg->planes[i].plane_stride);
1910 wm_data->stride = io_cfg->planes[i].plane_stride;
1911 }
1912 CDBG("image stride 0x%x\n", wm_data->stride);
1913
1914 if (wm_data->framedrop_pattern != io_cfg->framedrop_pattern ||
1915 !wm_data->init_cfg_done) {
1916 CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j,
1917 wm_data->hw_regs->framedrop_pattern,
1918 io_cfg->framedrop_pattern);
1919 wm_data->framedrop_pattern = io_cfg->framedrop_pattern;
1920 }
1921 CDBG("framedrop pattern 0x%x\n", wm_data->framedrop_pattern);
1922
1923 if (wm_data->framedrop_period != io_cfg->framedrop_period ||
1924 !wm_data->init_cfg_done) {
1925 CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j,
1926 wm_data->hw_regs->framedrop_period,
1927 io_cfg->framedrop_period);
1928 wm_data->framedrop_period = io_cfg->framedrop_period;
1929 }
1930 CDBG("framedrop period 0x%x\n", wm_data->framedrop_period);
1931
1932 if (wm_data->irq_subsample_period != io_cfg->subsample_period
1933 || !wm_data->init_cfg_done) {
1934 CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j,
1935 wm_data->hw_regs->irq_subsample_period,
1936 io_cfg->subsample_period);
1937 wm_data->irq_subsample_period =
1938 io_cfg->subsample_period;
1939 }
1940 CDBG("irq subsample period 0x%x\n",
1941 wm_data->irq_subsample_period);
1942
1943 if (wm_data->irq_subsample_pattern != io_cfg->subsample_pattern
1944 || !wm_data->init_cfg_done) {
1945 CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j,
1946 wm_data->hw_regs->irq_subsample_pattern,
1947 io_cfg->subsample_pattern);
1948 wm_data->irq_subsample_pattern =
1949 io_cfg->subsample_pattern;
1950 }
1951 CDBG("irq subsample pattern 0x%x\n",
1952 wm_data->irq_subsample_pattern);
1953
1954 if (wm_data->en_ubwc) {
1955 if (!wm_data->hw_regs->ubwc_regs) {
1956 pr_err("%s: No UBWC register to configure.\n",
1957 __func__);
1958 return -EINVAL;
1959 }
1960 if (wm_data->packer_cfg !=
1961 io_cfg->planes[i].packer_config ||
1962 !wm_data->init_cfg_done) {
1963 CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j,
1964 wm_data->hw_regs->packer_cfg,
1965 io_cfg->planes[i].packer_config);
1966 wm_data->packer_cfg =
1967 io_cfg->planes[i].packer_config;
1968 }
1969 CDBG("packer cfg 0x%x\n", wm_data->packer_cfg);
1970
1971 if (wm_data->tile_cfg != io_cfg->planes[i].tile_config
1972 || !wm_data->init_cfg_done) {
1973 CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j,
1974 wm_data->hw_regs->ubwc_regs->tile_cfg,
1975 io_cfg->planes[i].tile_config);
1976 wm_data->tile_cfg =
1977 io_cfg->planes[i].tile_config;
1978 }
1979 CDBG("tile cfg 0x%x\n", wm_data->tile_cfg);
1980
1981 if (wm_data->h_init != io_cfg->planes[i].h_init ||
1982 !wm_data->init_cfg_done) {
1983 CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j,
1984 wm_data->hw_regs->ubwc_regs->h_init,
1985 io_cfg->planes[i].h_init);
1986 wm_data->h_init = io_cfg->planes[i].h_init;
1987 }
1988 CDBG("h_init 0x%x\n", wm_data->h_init);
1989
1990 if (wm_data->v_init != io_cfg->planes[i].v_init ||
1991 !wm_data->init_cfg_done) {
1992 CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j,
1993 wm_data->hw_regs->ubwc_regs->v_init,
1994 io_cfg->planes[i].v_init);
1995 wm_data->v_init = io_cfg->planes[i].v_init;
1996 }
1997 CDBG("v_init 0x%x\n", wm_data->v_init);
1998
1999 if (wm_data->ubwc_meta_stride !=
2000 io_cfg->planes[i].meta_stride ||
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_stride,
2005 io_cfg->planes[i].meta_stride);
2006 wm_data->ubwc_meta_stride =
2007 io_cfg->planes[i].meta_stride;
2008 }
2009 CDBG("meta stride 0x%x\n", wm_data->ubwc_meta_stride);
2010
2011 if (wm_data->ubwc_mode_cfg !=
2012 io_cfg->planes[i].mode_config ||
2013 !wm_data->init_cfg_done) {
2014 CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j,
2015 wm_data->hw_regs->ubwc_regs->mode_cfg,
2016 io_cfg->planes[i].mode_config);
2017 wm_data->ubwc_mode_cfg =
2018 io_cfg->planes[i].mode_config;
2019 }
2020 CDBG("ubwc mode cfg 0x%x\n", wm_data->ubwc_mode_cfg);
2021
2022 if (wm_data->ubwc_meta_offset !=
2023 io_cfg->planes[i].meta_offset ||
2024 !wm_data->init_cfg_done) {
2025 CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j,
2026 wm_data->hw_regs->ubwc_regs->
2027 meta_offset,
2028 io_cfg->planes[i].meta_offset);
2029 wm_data->ubwc_meta_offset =
2030 io_cfg->planes[i].meta_offset;
2031 }
2032 CDBG("ubwc meta offset 0x%x\n",
2033 wm_data->ubwc_meta_offset);
2034
2035 /* UBWC meta address */
2036 CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j,
2037 wm_data->hw_regs->ubwc_regs->meta_addr,
2038 update_buf->image_buf[i]);
2039 CDBG("ubwc meta addr 0x%llx\n",
2040 update_buf->image_buf[i]);
2041 }
2042
2043 /* WM Image address */
2044 if (wm_data->en_ubwc)
2045 CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j,
2046 wm_data->hw_regs->image_addr,
2047 (update_buf->image_buf[i] +
2048 io_cfg->planes[i].meta_size));
2049 else
2050 CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j,
2051 wm_data->hw_regs->image_addr,
2052 update_buf->image_buf[i]);
2053
2054 CDBG("image address 0x%x\n", reg_val_pair[j-1]);
2055
Junzhe Zou193d78c2017-05-16 15:10:54 -07002056 frame_inc = io_cfg->planes[i].plane_stride *
2057 io_cfg->planes[i].slice_height;
2058 CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j,
2059 wm_data->hw_regs->frame_inc, frame_inc);
2060
Jing Zhoua4e9fbe2017-05-15 14:37:21 -07002061 /* enable the WM */
2062 CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j,
2063 wm_data->hw_regs->cfg,
2064 wm_data->en_cfg);
2065
2066 /* set initial configuration done */
2067 if (!wm_data->init_cfg_done)
2068 wm_data->init_cfg_done = 1;
2069 }
2070
2071 size = vfe_out_data->cdm_util_ops->cdm_required_size_reg_random(j/2);
Harsh Shaha1af8822017-05-11 22:06:36 -07002072
2073 /* cdm util returns dwords, need to convert to bytes */
2074 if ((size * 4) > update_buf->cdm.size) {
2075 pr_err("Failed! Buf size:%d insufficient, expected size:%d\n",
2076 update_buf->cdm.size, size);
2077 return -ENOMEM;
2078 }
2079
Harsh Shaha1af8822017-05-11 22:06:36 -07002080 vfe_out_data->cdm_util_ops->cdm_write_regrandom(
Jing Zhoua4e9fbe2017-05-15 14:37:21 -07002081 update_buf->cdm.cmd_buf_addr, j/2, reg_val_pair);
2082
Harsh Shaha1af8822017-05-11 22:06:36 -07002083 /* cdm util returns dwords, need to convert to bytes */
2084 update_buf->cdm.used_bytes = size * 4;
2085
2086 return 0;
2087}
2088
Harsh Shah19f55812017-06-26 18:58:49 -07002089static int cam_vfe_bus_start_hw(void *hw_priv,
2090 void *start_hw_args, uint32_t arg_size)
2091{
2092 return cam_vfe_bus_start_vfe_out(hw_priv);
2093}
2094
2095static int cam_vfe_bus_stop_hw(void *hw_priv,
2096 void *stop_hw_args, uint32_t arg_size)
2097{
2098 return cam_vfe_bus_stop_vfe_out(hw_priv);
2099}
2100
2101static int cam_vfe_bus_init_hw(void *hw_priv,
2102 void *init_hw_args, uint32_t arg_size)
2103{
2104 struct cam_vfe_bus_ver2_priv *bus_priv = hw_priv;
2105 uint32_t top_irq_reg_mask[2] = {0};
2106
2107 if (!bus_priv) {
2108 pr_err("Error! Invalid args\n");
2109 return -EINVAL;
2110 }
2111
2112 top_irq_reg_mask[0] = (1 << 9);
2113
2114 bus_priv->irq_handle = cam_irq_controller_subscribe_irq(
2115 bus_priv->common_data.vfe_irq_controller,
2116 CAM_IRQ_PRIORITY_2,
2117 top_irq_reg_mask,
2118 bus_priv,
2119 cam_vfe_bus_ver2_handle_irq,
2120 NULL,
2121 NULL,
2122 NULL);
2123
2124 if (bus_priv->irq_handle <= 0) {
2125 pr_err("Failed to subscribe BUS IRQ\n");
2126 return -EFAULT;
2127 }
2128
2129 return 0;
2130}
2131
2132static int cam_vfe_bus_deinit_hw(void *hw_priv,
2133 void *deinit_hw_args, uint32_t arg_size)
2134{
2135 struct cam_vfe_bus_ver2_priv *bus_priv = hw_priv;
2136 int rc;
2137
2138 if (!bus_priv || (bus_priv->irq_handle <= 0)) {
2139 pr_err("Error! Invalid args\n");
2140 return -EINVAL;
2141 }
2142
2143 rc = cam_irq_controller_unsubscribe_irq(
2144 bus_priv->common_data.vfe_irq_controller,
2145 bus_priv->irq_handle);
2146 if (rc)
2147 pr_err("Failed to unsubscribe irq rc=%d\n", rc);
2148
2149 return rc;
2150}
2151
Harsh Shaha1af8822017-05-11 22:06:36 -07002152static int cam_vfe_bus_process_cmd(void *priv,
2153 uint32_t cmd_type, void *cmd_args, uint32_t arg_size)
2154{
2155 int rc = -EINVAL;
2156
2157 if (!priv || !cmd_args) {
2158 pr_err_ratelimited("Error! Invalid input arguments\n");
2159 return -EINVAL;
2160 }
2161
2162 switch (cmd_type) {
2163 case CAM_VFE_HW_CMD_GET_BUF_UPDATE:
2164 rc = cam_vfe_bus_update_buf(priv, cmd_args, arg_size);
2165 break;
2166 default:
2167 pr_err_ratelimited("Error! Invalid camif process command:%d\n",
2168 cmd_type);
2169 break;
2170 }
2171
2172 return rc;
2173}
2174
2175int cam_vfe_bus_ver2_init(
Harsh Shah19f55812017-06-26 18:58:49 -07002176 struct cam_hw_soc_info *soc_info,
Harsh Shaha1af8822017-05-11 22:06:36 -07002177 struct cam_hw_intf *hw_intf,
2178 void *bus_hw_info,
2179 void *vfe_irq_controller,
2180 struct cam_vfe_bus **vfe_bus)
2181{
2182 int i, rc = 0;
2183 struct cam_vfe_bus_ver2_priv *bus_priv = NULL;
2184 struct cam_vfe_bus *vfe_bus_local;
2185 struct cam_vfe_bus_ver2_hw_info *ver2_hw_info = bus_hw_info;
2186
2187 CDBG("Enter\n");
2188
Harsh Shah19f55812017-06-26 18:58:49 -07002189 if (!soc_info || !hw_intf || !bus_hw_info || !vfe_irq_controller) {
2190 pr_err("Error! Invalid params soc_info %pK hw_intf %pK hw_info %pK controller %pK\n",
2191 soc_info, hw_intf, bus_hw_info, vfe_irq_controller);
2192 rc = -EINVAL;
2193 goto end;
2194 }
2195
Harsh Shaha1af8822017-05-11 22:06:36 -07002196 vfe_bus_local = kzalloc(sizeof(struct cam_vfe_bus), GFP_KERNEL);
2197 if (!vfe_bus_local) {
2198 CDBG("Failed to alloc for vfe_bus\n");
2199 rc = -ENOMEM;
Harsh Shah545df9a2017-06-16 16:43:17 -07002200 goto end;
Harsh Shaha1af8822017-05-11 22:06:36 -07002201 }
2202
2203 bus_priv = kzalloc(sizeof(struct cam_vfe_bus_ver2_priv),
2204 GFP_KERNEL);
2205 if (!bus_priv) {
2206 CDBG("Failed to alloc for vfe_bus_priv\n");
2207 rc = -ENOMEM;
Harsh Shah545df9a2017-06-16 16:43:17 -07002208 goto free_bus_local;
Harsh Shaha1af8822017-05-11 22:06:36 -07002209 }
2210 vfe_bus_local->bus_priv = bus_priv;
2211
Harsh Shah19f55812017-06-26 18:58:49 -07002212 bus_priv->common_data.core_index = soc_info->index;
2213 bus_priv->common_data.mem_base =
2214 CAM_SOC_GET_REG_MAP_START(soc_info, VFE_CORE_BASE_IDX);
Harsh Shaha1af8822017-05-11 22:06:36 -07002215 bus_priv->common_data.hw_intf = hw_intf;
2216 bus_priv->common_data.vfe_irq_controller = vfe_irq_controller;
2217 bus_priv->common_data.common_reg = &ver2_hw_info->common_reg;
2218
Harsh Shah19f55812017-06-26 18:58:49 -07002219 rc = cam_irq_controller_init(drv_name, bus_priv->common_data.mem_base,
2220 &ver2_hw_info->common_reg.irq_reg_info,
2221 &bus_priv->common_data.bus_irq_controller);
2222 if (rc) {
2223 pr_err("Error! cam_irq_controller_init failed\n");
2224 goto free_bus_priv;
2225 }
2226
Harsh Shaha1af8822017-05-11 22:06:36 -07002227 INIT_LIST_HEAD(&bus_priv->free_comp_grp);
2228 INIT_LIST_HEAD(&bus_priv->free_dual_comp_grp);
2229 INIT_LIST_HEAD(&bus_priv->used_comp_grp);
2230
2231 for (i = 0; i < CAM_VFE_BUS_VER2_MAX_CLIENTS; i++) {
2232 rc = cam_vfe_bus_init_wm_resource(i, bus_priv, bus_hw_info,
2233 &bus_priv->bus_client[i]);
2234 if (rc < 0) {
Harsh Shah545df9a2017-06-16 16:43:17 -07002235 pr_err("Error! Init WM failed rc=%d\n", rc);
2236 goto deinit_wm;
Harsh Shaha1af8822017-05-11 22:06:36 -07002237 }
2238 }
2239
2240 for (i = 0; i < CAM_VFE_BUS_VER2_COMP_GRP_MAX; i++) {
2241 rc = cam_vfe_bus_init_comp_grp(i, bus_priv, bus_hw_info,
2242 &bus_priv->comp_grp[i]);
2243 if (rc < 0) {
Harsh Shah545df9a2017-06-16 16:43:17 -07002244 pr_err("Error! Init Comp Grp failed rc=%d\n", rc);
2245 goto deinit_comp_grp;
Harsh Shaha1af8822017-05-11 22:06:36 -07002246 }
2247 }
2248
2249 for (i = 0; i < CAM_VFE_BUS_VER2_VFE_OUT_MAX; i++) {
2250 rc = cam_vfe_bus_init_vfe_out_resource(i, bus_priv, bus_hw_info,
2251 &bus_priv->vfe_out[i]);
2252 if (rc < 0) {
Harsh Shah545df9a2017-06-16 16:43:17 -07002253 pr_err("Error! Init VFE Out failed rc=%d\n", rc);
2254 goto deinit_vfe_out;
Harsh Shaha1af8822017-05-11 22:06:36 -07002255 }
2256 }
2257
Harsh Shah19f55812017-06-26 18:58:49 -07002258 INIT_LIST_HEAD(&bus_priv->common_data.free_payload_list);
2259 for (i = 0; i < CAM_VFE_BUS_VER2_PAYLOAD_MAX; i++) {
2260 INIT_LIST_HEAD(&bus_priv->common_data.evt_payload[i].list);
2261 list_add_tail(&bus_priv->common_data.evt_payload[i].list,
2262 &bus_priv->common_data.free_payload_list);
Harsh Shaha1af8822017-05-11 22:06:36 -07002263 }
2264
Harsh Shah19f55812017-06-26 18:58:49 -07002265 vfe_bus_local->hw_ops.reserve = cam_vfe_bus_acquire_vfe_out;
2266 vfe_bus_local->hw_ops.release = cam_vfe_bus_release_vfe_out;
2267 vfe_bus_local->hw_ops.start = cam_vfe_bus_start_hw;
2268 vfe_bus_local->hw_ops.stop = cam_vfe_bus_stop_hw;
2269 vfe_bus_local->hw_ops.init = cam_vfe_bus_init_hw;
2270 vfe_bus_local->hw_ops.deinit = cam_vfe_bus_deinit_hw;
2271 vfe_bus_local->top_half_handler = cam_vfe_bus_ver2_handle_irq;
Harsh Shaha1af8822017-05-11 22:06:36 -07002272 vfe_bus_local->bottom_half_handler = NULL;
Harsh Shah19f55812017-06-26 18:58:49 -07002273 vfe_bus_local->hw_ops.process_cmd = cam_vfe_bus_process_cmd;
Harsh Shaha1af8822017-05-11 22:06:36 -07002274
2275 *vfe_bus = vfe_bus_local;
2276
Harsh Shah545df9a2017-06-16 16:43:17 -07002277 CDBG("Exit\n");
Harsh Shaha1af8822017-05-11 22:06:36 -07002278 return rc;
2279
Harsh Shah545df9a2017-06-16 16:43:17 -07002280deinit_vfe_out:
2281 if (i < 0)
2282 i = CAM_VFE_BUS_VER2_VFE_OUT_MAX;
2283 for (--i; i >= 0; i--)
2284 cam_vfe_bus_deinit_vfe_out_resource(&bus_priv->vfe_out[i]);
2285
2286deinit_comp_grp:
2287 if (i < 0)
2288 i = CAM_VFE_BUS_VER2_COMP_GRP_MAX;
2289 for (--i; i >= 0; i--)
2290 cam_vfe_bus_deinit_comp_grp(&bus_priv->comp_grp[i]);
2291
2292deinit_wm:
2293 if (i < 0)
2294 i = CAM_VFE_BUS_VER2_MAX_CLIENTS;
2295 for (--i; i >= 0; i--)
2296 cam_vfe_bus_deinit_wm_resource(&bus_priv->bus_client[i]);
2297
Harsh Shah19f55812017-06-26 18:58:49 -07002298free_bus_priv:
Harsh Shaha1af8822017-05-11 22:06:36 -07002299 kfree(vfe_bus_local->bus_priv);
Harsh Shah545df9a2017-06-16 16:43:17 -07002300
2301free_bus_local:
Harsh Shaha1af8822017-05-11 22:06:36 -07002302 kfree(vfe_bus_local);
Harsh Shah545df9a2017-06-16 16:43:17 -07002303
2304end:
Harsh Shaha1af8822017-05-11 22:06:36 -07002305 return rc;
2306}
Harsh Shah545df9a2017-06-16 16:43:17 -07002307
2308int cam_vfe_bus_ver2_deinit(
2309 struct cam_vfe_bus **vfe_bus)
2310{
2311 int i, rc = 0;
2312 struct cam_vfe_bus_ver2_priv *bus_priv = NULL;
2313 struct cam_vfe_bus *vfe_bus_local;
2314
2315 if (!vfe_bus || !*vfe_bus) {
2316 pr_err("Error! Invalid input\n");
2317 return -EINVAL;
2318 }
2319 vfe_bus_local = *vfe_bus;
2320
2321 bus_priv = vfe_bus_local->bus_priv;
2322 if (!bus_priv) {
2323 pr_err("Error! bus_priv is NULL\n");
2324 rc = -ENODEV;
2325 goto free_bus_local;
2326 }
2327
Harsh Shah19f55812017-06-26 18:58:49 -07002328 INIT_LIST_HEAD(&bus_priv->common_data.free_payload_list);
2329 for (i = 0; i < CAM_VFE_BUS_VER2_PAYLOAD_MAX; i++)
2330 INIT_LIST_HEAD(&bus_priv->common_data.evt_payload[i].list);
Harsh Shah545df9a2017-06-16 16:43:17 -07002331
2332 for (i = 0; i < CAM_VFE_BUS_VER2_MAX_CLIENTS; i++) {
2333 rc = cam_vfe_bus_deinit_wm_resource(&bus_priv->bus_client[i]);
2334 if (rc < 0)
2335 pr_err("Error! Deinit WM failed rc=%d\n", rc);
2336 }
2337
2338 for (i = 0; i < CAM_VFE_BUS_VER2_COMP_GRP_MAX; i++) {
2339 rc = cam_vfe_bus_deinit_comp_grp(&bus_priv->comp_grp[i]);
2340 if (rc < 0)
2341 pr_err("Error! Deinit Comp Grp failed rc=%d\n", rc);
2342 }
2343
2344 for (i = 0; i < CAM_VFE_BUS_VER2_VFE_OUT_MAX; i++) {
2345 rc = cam_vfe_bus_deinit_vfe_out_resource(&bus_priv->vfe_out[i]);
2346 if (rc < 0)
2347 pr_err("Error! Deinit VFE Out failed rc=%d\n", rc);
2348 }
2349
2350 INIT_LIST_HEAD(&bus_priv->free_comp_grp);
2351 INIT_LIST_HEAD(&bus_priv->free_dual_comp_grp);
2352 INIT_LIST_HEAD(&bus_priv->used_comp_grp);
2353
Harsh Shah19f55812017-06-26 18:58:49 -07002354 rc = cam_irq_controller_deinit(
2355 &bus_priv->common_data.bus_irq_controller);
2356 if (rc)
2357 pr_err("Error! Deinit IRQ Controller failed rc=%d\n", rc);
2358
Harsh Shah545df9a2017-06-16 16:43:17 -07002359 kfree(vfe_bus_local->bus_priv);
2360
2361free_bus_local:
2362 kfree(vfe_bus_local);
2363
2364 *vfe_bus = NULL;
2365
2366 return rc;
2367}
2368