blob: 03c5eb3c1963f48e3b471284c713cc6e43ce40c8 [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
Harsh Shaha1af8822017-05-11 22:06:36 -070013#include <linux/ratelimit.h>
14#include <linux/slab.h>
15#include "cam_io_util.h"
Harsh Shahf7136392017-08-29 12:42:52 -070016#include "cam_debug_util.h"
Harsh Shaha1af8822017-05-11 22:06:36 -070017#include "cam_cdm_util.h"
18#include "cam_hw_intf.h"
Harsh Shah19f55812017-06-26 18:58:49 -070019#include "cam_ife_hw_mgr.h"
Harsh Shaha1af8822017-05-11 22:06:36 -070020#include "cam_vfe_hw_intf.h"
21#include "cam_irq_controller.h"
Harsh Shah19f55812017-06-26 18:58:49 -070022#include "cam_tasklet_util.h"
Harsh Shaha1af8822017-05-11 22:06:36 -070023#include "cam_vfe_bus.h"
24#include "cam_vfe_bus_ver2.h"
25#include "cam_vfe_core.h"
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -070026#include "cam_debug_util.h"
Harsh Shaha1af8822017-05-11 22:06:36 -070027
Harsh Shah19f55812017-06-26 18:58:49 -070028static const char drv_name[] = "vfe_bus";
29
30#define CAM_VFE_BUS_IRQ_REG0 0
31#define CAM_VFE_BUS_IRQ_REG1 1
32#define CAM_VFE_BUS_IRQ_REG2 2
33#define CAM_VFE_BUS_IRQ_MAX 3
34
35#define CAM_VFE_BUS_VER2_PAYLOAD_MAX 256
Harsh Shah23557ae2017-05-13 18:14:34 -070036
Ravikishore Pampanaad6bc902017-07-12 19:37:06 +053037#define CAM_VFE_RDI_BUS_DEFAULT_WIDTH 0xFF01
38#define CAM_VFE_RDI_BUS_DEFAULT_STRIDE 0xFF01
39
Krishnankutty Kolathappilly06406e52017-08-17 00:50:21 -070040#define ALIGNUP(value, alignment) \
41 ((value + alignment - 1) / alignment * alignment)
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;
Pavan Kumar Chilamkurthi649cdf92017-08-15 01:40:57 -070096 bool init_cfg_done;
97 bool hfr_cfg_done;
Harsh Shah19f55812017-06-26 18:58:49 -070098
Harsh Shaha1af8822017-05-11 22:06:36 -070099 uint32_t offset;
100 uint32_t width;
101 uint32_t height;
102 uint32_t stride;
103 uint32_t format;
104 enum cam_vfe_bus_packer_format pack_fmt;
105
106 uint32_t burst_len;
Harsh Shaha1af8822017-05-11 22:06:36 -0700107
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;
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -0700180 CAM_ERR(CAM_ISP, "No free payload");
Harsh Shah19f55812017-06-26 18:58:49 -0700181 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) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -0700198 CAM_ERR(CAM_ISP, "Invalid param core_info NULL");
Harsh Shah19f55812017-06-26 18:58:49 -0700199 return -EINVAL;
200 }
201 if (*evt_payload == NULL) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -0700202 CAM_ERR(CAM_ISP, "No payload to put");
Harsh Shah19f55812017-06-26 18:58:49 -0700203 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) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -0700212 CAM_DBG(CAM_ISP, "status0 0x%x status1 0x%x status2 0x%x",
Harsh Shah19f55812017-06-26 18:58:49 -0700213 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) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -0700235 CAM_ERR(CAM_ISP,
236 "Invalid params. Same core as Master and Slave");
Harsh Shaha1af8822017-05-11 22:06:36 -0700237 return -EINVAL;
238 }
239
240 switch (current_core) {
241 case CAM_VFE_BUS_VER2_VFE_CORE_0:
242 switch (dual_slave_core) {
243 case CAM_VFE_BUS_VER2_VFE_CORE_1:
244 *intra_client_mask = 0x1;
245 break;
246 case CAM_VFE_BUS_VER2_VFE_CORE_2:
247 *intra_client_mask = 0x2;
248 break;
249 default:
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -0700250 CAM_ERR(CAM_ISP, "Invalid value for slave core %u",
Harsh Shaha1af8822017-05-11 22:06:36 -0700251 dual_slave_core);
252 rc = -EINVAL;
253 break;
254 }
255 break;
256 case CAM_VFE_BUS_VER2_VFE_CORE_1:
257 switch (dual_slave_core) {
258 case CAM_VFE_BUS_VER2_VFE_CORE_0:
259 *intra_client_mask = 0x1;
260 break;
261 case CAM_VFE_BUS_VER2_VFE_CORE_2:
262 *intra_client_mask = 0x2;
263 break;
264 default:
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -0700265 CAM_ERR(CAM_ISP, "Invalid value for slave core %u",
Harsh Shaha1af8822017-05-11 22:06:36 -0700266 dual_slave_core);
267 rc = -EINVAL;
268 break;
269 }
270 break;
271 case CAM_VFE_BUS_VER2_VFE_CORE_2:
272 switch (dual_slave_core) {
273 case CAM_VFE_BUS_VER2_VFE_CORE_0:
274 *intra_client_mask = 0x1;
275 break;
276 case CAM_VFE_BUS_VER2_VFE_CORE_1:
277 *intra_client_mask = 0x2;
278 break;
279 default:
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -0700280 CAM_ERR(CAM_ISP, "Invalid value for slave core %u",
Harsh Shaha1af8822017-05-11 22:06:36 -0700281 dual_slave_core);
282 rc = -EINVAL;
283 break;
284 }
285 break;
286 default:
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -0700287 CAM_ERR(CAM_ISP,
288 "Invalid value for master core %u", current_core);
Harsh Shaha1af8822017-05-11 22:06:36 -0700289 rc = -EINVAL;
290 break;
291 }
292
293 return rc;
294}
295
296static enum cam_vfe_bus_ver2_vfe_out_type
297 cam_vfe_bus_get_out_res_id(uint32_t res_type)
298{
299 switch (res_type) {
300 case CAM_ISP_IFE_OUT_RES_FULL:
301 return CAM_VFE_BUS_VER2_VFE_OUT_FULL;
302 case CAM_ISP_IFE_OUT_RES_DS4:
303 return CAM_VFE_BUS_VER2_VFE_OUT_DS4;
304 case CAM_ISP_IFE_OUT_RES_DS16:
305 return CAM_VFE_BUS_VER2_VFE_OUT_DS16;
306 case CAM_ISP_IFE_OUT_RES_FD:
307 return CAM_VFE_BUS_VER2_VFE_OUT_FD;
308 case CAM_ISP_IFE_OUT_RES_RAW_DUMP:
309 return CAM_VFE_BUS_VER2_VFE_OUT_RAW_DUMP;
310 case CAM_ISP_IFE_OUT_RES_PDAF:
311 return CAM_VFE_BUS_VER2_VFE_OUT_PDAF;
312 case CAM_ISP_IFE_OUT_RES_RDI_0:
313 return CAM_VFE_BUS_VER2_VFE_OUT_RDI0;
314 case CAM_ISP_IFE_OUT_RES_RDI_1:
315 return CAM_VFE_BUS_VER2_VFE_OUT_RDI1;
316 case CAM_ISP_IFE_OUT_RES_RDI_2:
317 return CAM_VFE_BUS_VER2_VFE_OUT_RDI2;
318 case CAM_ISP_IFE_OUT_RES_STATS_HDR_BE:
319 return CAM_VFE_BUS_VER2_VFE_OUT_STATS_HDR_BE;
320 case CAM_ISP_IFE_OUT_RES_STATS_HDR_BHIST:
321 return CAM_VFE_BUS_VER2_VFE_OUT_STATS_HDR_BHIST;
322 case CAM_ISP_IFE_OUT_RES_STATS_TL_BG:
323 return CAM_VFE_BUS_VER2_VFE_OUT_STATS_TL_BG;
324 case CAM_ISP_IFE_OUT_RES_STATS_BF:
325 return CAM_VFE_BUS_VER2_VFE_OUT_STATS_BF;
326 case CAM_ISP_IFE_OUT_RES_STATS_AWB_BG:
327 return CAM_VFE_BUS_VER2_VFE_OUT_STATS_AWB_BG;
328 case CAM_ISP_IFE_OUT_RES_STATS_BHIST:
329 return CAM_VFE_BUS_VER2_VFE_OUT_STATS_BHIST;
330 case CAM_ISP_IFE_OUT_RES_STATS_RS:
331 return CAM_VFE_BUS_VER2_VFE_OUT_STATS_RS;
332 case CAM_ISP_IFE_OUT_RES_STATS_CS:
333 return CAM_VFE_BUS_VER2_VFE_OUT_STATS_CS;
334 case CAM_ISP_IFE_OUT_RES_STATS_IHIST:
335 return CAM_VFE_BUS_VER2_VFE_OUT_STATS_IHIST;
336 default:
337 return CAM_VFE_BUS_VER2_VFE_OUT_MAX;
338 }
339}
340
341static int cam_vfe_bus_get_num_wm(
342 enum cam_vfe_bus_ver2_vfe_out_type res_type,
343 uint32_t format)
344{
345 switch (res_type) {
346 case CAM_VFE_BUS_VER2_VFE_OUT_RDI0:
347 case CAM_VFE_BUS_VER2_VFE_OUT_RDI1:
348 case CAM_VFE_BUS_VER2_VFE_OUT_RDI2:
349 switch (format) {
350 case CAM_FORMAT_MIPI_RAW_8:
351 case CAM_FORMAT_MIPI_RAW_10:
352 case CAM_FORMAT_MIPI_RAW_12:
353 case CAM_FORMAT_MIPI_RAW_14:
354 case CAM_FORMAT_MIPI_RAW_16:
355 case CAM_FORMAT_MIPI_RAW_20:
Ravikishore Pampanaad6bc902017-07-12 19:37:06 +0530356 case CAM_FORMAT_DPCM_10_6_10:
357 case CAM_FORMAT_DPCM_10_8_10:
358 case CAM_FORMAT_DPCM_12_6_12:
359 case CAM_FORMAT_DPCM_12_8_12:
360 case CAM_FORMAT_DPCM_14_8_14:
361 case CAM_FORMAT_DPCM_14_10_14:
362 case CAM_FORMAT_PLAIN8:
Ravikishore Pampanaad6bc902017-07-12 19:37:06 +0530363 case CAM_FORMAT_PLAIN16_10:
364 case CAM_FORMAT_PLAIN16_12:
365 case CAM_FORMAT_PLAIN16_14:
366 case CAM_FORMAT_PLAIN16_16:
367 case CAM_FORMAT_PLAIN32_20:
Harsh Shaha1af8822017-05-11 22:06:36 -0700368 case CAM_FORMAT_PLAIN128:
369 return 1;
370 default:
371 break;
372 }
373 break;
374 case CAM_VFE_BUS_VER2_VFE_OUT_FULL:
375 switch (format) {
376 case CAM_FORMAT_NV21:
377 case CAM_FORMAT_NV12:
378 case CAM_FORMAT_MIPI_RAW_8:
379 case CAM_FORMAT_PLAIN8:
380 case CAM_FORMAT_TP10:
381 case CAM_FORMAT_UBWC_NV12:
382 case CAM_FORMAT_UBWC_NV12_4R:
383 case CAM_FORMAT_UBWC_TP10:
384 case CAM_FORMAT_UBWC_P010:
385 return 2;
386 default:
387 break;
388 }
389 break;
390 case CAM_VFE_BUS_VER2_VFE_OUT_FD:
391 switch (format) {
392 case CAM_FORMAT_NV21:
393 case CAM_FORMAT_NV12:
394 case CAM_FORMAT_PLAIN8:
395 case CAM_FORMAT_TP10:
396 case CAM_FORMAT_PLAIN16_10:
397 return 2;
398 default:
399 break;
400 }
401 break;
402 case CAM_VFE_BUS_VER2_VFE_OUT_DS4:
403 case CAM_VFE_BUS_VER2_VFE_OUT_DS16:
404 switch (format) {
405 case CAM_FORMAT_PD8:
406 case CAM_FORMAT_PD10:
407 return 1;
408 default:
409 break;
410 }
411 break;
412 case CAM_VFE_BUS_VER2_VFE_OUT_RAW_DUMP:
413 switch (format) {
414 case CAM_FORMAT_ARGB_14:
415 case CAM_FORMAT_PLAIN8:
416 case CAM_FORMAT_PLAIN16_10:
417 case CAM_FORMAT_PLAIN16_12:
418 case CAM_FORMAT_PLAIN16_14:
419 return 1;
420 default:
421 break;
422 }
423 break;
424 case CAM_VFE_BUS_VER2_VFE_OUT_PDAF:
425 switch (format) {
426 case CAM_FORMAT_PLAIN8:
427 case CAM_FORMAT_PLAIN16_10:
428 case CAM_FORMAT_PLAIN16_12:
429 case CAM_FORMAT_PLAIN16_14:
430 return 1;
431 default:
432 break;
433 }
434 break;
435 case CAM_VFE_BUS_VER2_VFE_OUT_STATS_HDR_BE:
436 case CAM_VFE_BUS_VER2_VFE_OUT_STATS_HDR_BHIST:
437 case CAM_VFE_BUS_VER2_VFE_OUT_STATS_TL_BG:
438 case CAM_VFE_BUS_VER2_VFE_OUT_STATS_BF:
439 case CAM_VFE_BUS_VER2_VFE_OUT_STATS_AWB_BG:
440 case CAM_VFE_BUS_VER2_VFE_OUT_STATS_BHIST:
441 case CAM_VFE_BUS_VER2_VFE_OUT_STATS_CS:
442 switch (format) {
443 case CAM_FORMAT_PLAIN64:
444 return 1;
445 default:
446 break;
447 }
448 break;
449 case CAM_VFE_BUS_VER2_VFE_OUT_STATS_RS:
450 case CAM_VFE_BUS_VER2_VFE_OUT_STATS_IHIST:
451 switch (format) {
452 case CAM_FORMAT_PLAIN16_16:
453 return 1;
454 default:
455 break;
456 }
457 break;
458 default:
459 break;
460 }
461
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -0700462 CAM_ERR(CAM_ISP, "Unsupported format %u for resource_type %u",
463 format, res_type);
Harsh Shaha1af8822017-05-11 22:06:36 -0700464
465 return -EINVAL;
466}
467
468static int cam_vfe_bus_get_wm_idx(
469 enum cam_vfe_bus_ver2_vfe_out_type vfe_out_res_id,
470 enum cam_vfe_bus_plane_type plane)
471{
472 int wm_idx = -1;
473
474 switch (vfe_out_res_id) {
475 case CAM_VFE_BUS_VER2_VFE_OUT_FULL:
476 switch (plane) {
477 case PLANE_Y:
478 wm_idx = 3;
479 break;
480 case PLANE_C:
481 wm_idx = 4;
482 break;
483 default:
484 break;
485 }
486 break;
487 case CAM_VFE_BUS_VER2_VFE_OUT_DS4:
488 switch (plane) {
489 case PLANE_Y:
490 wm_idx = 5;
491 break;
492 default:
493 break;
494 }
495 break;
496 case CAM_VFE_BUS_VER2_VFE_OUT_DS16:
497 switch (plane) {
498 case PLANE_Y:
499 wm_idx = 6;
500 break;
501 default:
502 break;
503 }
504 break;
505 case CAM_VFE_BUS_VER2_VFE_OUT_FD:
506 switch (plane) {
507 case PLANE_Y:
508 wm_idx = 7;
509 break;
510 case PLANE_C:
511 wm_idx = 8;
512 break;
513 default:
514 break;
515 }
516 break;
517 case CAM_VFE_BUS_VER2_VFE_OUT_RAW_DUMP:
518 switch (plane) {
519 case PLANE_Y:
520 wm_idx = 9;
521 break;
522 default:
523 break;
524 }
525 break;
526 case CAM_VFE_BUS_VER2_VFE_OUT_PDAF:
527 switch (plane) {
528 case PLANE_Y:
529 wm_idx = 10;
530 break;
531 default:
532 break;
533 }
534 break;
535 case CAM_VFE_BUS_VER2_VFE_OUT_RDI0:
536 switch (plane) {
537 case PLANE_Y:
538 wm_idx = 0;
539 break;
540 default:
541 break;
542 }
543 break;
544 case CAM_VFE_BUS_VER2_VFE_OUT_RDI1:
545 switch (plane) {
546 case PLANE_Y:
547 wm_idx = 1;
548 break;
549 default:
550 break;
551 }
552 break;
553 case CAM_VFE_BUS_VER2_VFE_OUT_RDI2:
554 switch (plane) {
555 case PLANE_Y:
556 wm_idx = 2;
557 break;
558 default:
559 break;
560 }
561 break;
562 case CAM_VFE_BUS_VER2_VFE_OUT_STATS_HDR_BE:
563 switch (plane) {
564 case PLANE_Y:
565 wm_idx = 11;
566 break;
567 default:
568 break;
569 }
570 break;
571 case CAM_VFE_BUS_VER2_VFE_OUT_STATS_HDR_BHIST:
572 switch (plane) {
573 case PLANE_Y:
574 wm_idx = 12;
575 break;
576 default:
577 break;
578 }
579 break;
580 case CAM_VFE_BUS_VER2_VFE_OUT_STATS_TL_BG:
581 switch (plane) {
582 case PLANE_Y:
583 wm_idx = 13;
584 break;
585 default:
586 break;
587 }
588 break;
589 case CAM_VFE_BUS_VER2_VFE_OUT_STATS_BF:
590 switch (plane) {
591 case PLANE_Y:
592 wm_idx = 14;
593 break;
594 default:
595 break;
596 }
597 break;
598 case CAM_VFE_BUS_VER2_VFE_OUT_STATS_AWB_BG:
599 switch (plane) {
600 case PLANE_Y:
601 wm_idx = 15;
602 break;
603 default:
604 break;
605 }
606 break;
607 case CAM_VFE_BUS_VER2_VFE_OUT_STATS_BHIST:
608 switch (plane) {
609 case PLANE_Y:
610 wm_idx = 16;
611 break;
612 default:
613 break;
614 }
615 break;
616 case CAM_VFE_BUS_VER2_VFE_OUT_STATS_RS:
617 switch (plane) {
618 case PLANE_Y:
619 wm_idx = 17;
620 break;
621 default:
622 break;
623 }
624 break;
625 case CAM_VFE_BUS_VER2_VFE_OUT_STATS_CS:
626 switch (plane) {
627 case PLANE_Y:
628 wm_idx = 18;
629 break;
630 default:
631 break;
632 }
633 break;
634 case CAM_VFE_BUS_VER2_VFE_OUT_STATS_IHIST:
635 switch (plane) {
636 case PLANE_Y:
637 wm_idx = 19;
638 break;
639 default:
640 break;
641 }
642 break;
643 default:
644 break;
645 }
646
647 return wm_idx;
648}
649
650static enum cam_vfe_bus_packer_format
651 cam_vfe_bus_get_packer_fmt(uint32_t out_fmt)
652{
653 switch (out_fmt) {
654 case CAM_FORMAT_NV21:
655 case CAM_FORMAT_NV12:
Krishnankutty Kolathappillyf39e6412017-07-18 15:58:22 -0700656 case CAM_FORMAT_UBWC_NV12:
657 case CAM_FORMAT_UBWC_NV12_4R:
Abhishek Kondaveeti170c8122017-07-06 04:45:12 +0530658 return PACKER_FMT_PLAIN_8_LSB_MSB_10;
Ravikishore Pampana5286dba2017-08-31 16:19:18 +0530659 case CAM_FORMAT_PLAIN16_16:
660 return PACKER_FMT_PLAIN_16_16BPP;
Abhishek Kondaveeti170c8122017-07-06 04:45:12 +0530661 case CAM_FORMAT_PLAIN64:
662 return PACKER_FMT_PLAIN_64;
Ravikishore Pampana5286dba2017-08-31 16:19:18 +0530663 case CAM_FORMAT_PLAIN8:
664 return PACKER_FMT_PLAIN_8;
665 case CAM_FORMAT_PLAIN16_10:
666 return PACKER_FMT_PLAIN_16_10BPP;
667 case CAM_FORMAT_PLAIN16_12:
668 return PACKER_FMT_PLAIN_16_12BPP;
669 case CAM_FORMAT_PLAIN16_14:
670 return PACKER_FMT_PLAIN_16_14BPP;
671 case CAM_FORMAT_PLAIN32_20:
672 return PACKER_FMT_PLAIN_32_20BPP;
Abhishek Kondaveeti170c8122017-07-06 04:45:12 +0530673 case CAM_FORMAT_MIPI_RAW_6:
674 case CAM_FORMAT_MIPI_RAW_8:
675 case CAM_FORMAT_MIPI_RAW_10:
676 case CAM_FORMAT_MIPI_RAW_12:
677 case CAM_FORMAT_MIPI_RAW_14:
678 case CAM_FORMAT_MIPI_RAW_16:
679 case CAM_FORMAT_MIPI_RAW_20:
Ravikishore Pampanaad6bc902017-07-12 19:37:06 +0530680 case CAM_FORMAT_PLAIN16_8:
Ravikishore Pampana5286dba2017-08-31 16:19:18 +0530681 case CAM_FORMAT_PLAIN128:
Abhishek Kondaveeti170c8122017-07-06 04:45:12 +0530682 case CAM_FORMAT_PD8:
683 case CAM_FORMAT_PD10:
684 return PACKER_FMT_PLAIN_128;
Krishnankutty Kolathappillyf39e6412017-07-18 15:58:22 -0700685 case CAM_FORMAT_UBWC_TP10:
686 case CAM_FORMAT_TP10:
687 return PACKER_FMT_TP_10;
Harsh Shaha1af8822017-05-11 22:06:36 -0700688 default:
689 return PACKER_FMT_MAX;
690 }
691}
692
693static int cam_vfe_bus_acquire_wm(
694 struct cam_vfe_bus_ver2_priv *ver2_bus_priv,
695 struct cam_isp_out_port_info *out_port_info,
Harsh Shah19f55812017-06-26 18:58:49 -0700696 void *tasklet,
697 void *ctx,
Harsh Shaha1af8822017-05-11 22:06:36 -0700698 enum cam_vfe_bus_ver2_vfe_out_type vfe_out_res_id,
699 enum cam_vfe_bus_plane_type plane,
700 enum cam_isp_hw_split_id split_id,
701 uint32_t subscribe_irq,
702 struct cam_isp_resource_node **wm_res,
703 uint32_t *client_done_mask)
704{
705 uint32_t wm_idx = 0;
706 struct cam_isp_resource_node *wm_res_local = NULL;
707 struct cam_vfe_bus_ver2_wm_resource_data *rsrc_data = NULL;
708
709 *wm_res = NULL;
710 *client_done_mask = 0;
711
712 /* No need to allocate for BUS VER2. VFE OUT to WM is fixed. */
713 wm_idx = cam_vfe_bus_get_wm_idx(vfe_out_res_id, plane);
714 if (wm_idx < 0 || wm_idx >= CAM_VFE_BUS_VER2_MAX_CLIENTS) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -0700715 CAM_ERR(CAM_ISP, "Unsupported VFE out %d plane %d",
Harsh Shaha1af8822017-05-11 22:06:36 -0700716 vfe_out_res_id, plane);
717 return -EINVAL;
718 }
719
720 wm_res_local = &ver2_bus_priv->bus_client[wm_idx];
Harsh Shah19f55812017-06-26 18:58:49 -0700721 wm_res_local->tasklet_info = tasklet;
Harsh Shaha1af8822017-05-11 22:06:36 -0700722 wm_res_local->res_state = CAM_ISP_RESOURCE_STATE_RESERVED;
723
724 rsrc_data = wm_res_local->res_priv;
725 rsrc_data->irq_enabled = subscribe_irq;
Harsh Shah19f55812017-06-26 18:58:49 -0700726 rsrc_data->ctx = ctx;
Harsh Shaha1af8822017-05-11 22:06:36 -0700727 rsrc_data->format = out_port_info->format;
728 rsrc_data->pack_fmt = cam_vfe_bus_get_packer_fmt(rsrc_data->format);
729
730 rsrc_data->width = out_port_info->width;
731 rsrc_data->height = out_port_info->height;
Harsh Shahf7136392017-08-29 12:42:52 -0700732 CAM_DBG(CAM_ISP, "WM %d width %d height %d", rsrc_data->index,
733 rsrc_data->width, rsrc_data->height);
Jing Zhoua4e9fbe2017-05-15 14:37:21 -0700734
735 if (rsrc_data->index < 3) {
Krishnankutty Kolathappillyf39e6412017-07-18 15:58:22 -0700736 /* Write master 0-2 refers to RDI 0/ RDI 1/RDI 2 */
Harsh Shahf7136392017-08-29 12:42:52 -0700737 switch (rsrc_data->format) {
738 case CAM_FORMAT_MIPI_RAW_6:
739 case CAM_FORMAT_MIPI_RAW_8:
740 case CAM_FORMAT_MIPI_RAW_10:
741 case CAM_FORMAT_MIPI_RAW_12:
742 case CAM_FORMAT_MIPI_RAW_14:
743 case CAM_FORMAT_MIPI_RAW_16:
744 case CAM_FORMAT_MIPI_RAW_20:
745 rsrc_data->width = CAM_VFE_RDI_BUS_DEFAULT_WIDTH;
746 rsrc_data->height = 0;
747 rsrc_data->stride = CAM_VFE_RDI_BUS_DEFAULT_STRIDE;
748 rsrc_data->pack_fmt = 0x0;
749 rsrc_data->en_cfg = 0x3;
750 break;
751 case CAM_FORMAT_PLAIN8:
752 rsrc_data->en_cfg = 0x1;
753 rsrc_data->pack_fmt = 0x1;
754 rsrc_data->width = rsrc_data->width * 2;
755 rsrc_data->stride = rsrc_data->width;
756 break;
757 case CAM_FORMAT_PLAIN16_10:
758 rsrc_data->en_cfg = 0x1;
759 rsrc_data->pack_fmt = 0x2;
760 rsrc_data->width = rsrc_data->width * 2;
761 rsrc_data->stride = rsrc_data->width;
762 break;
763 case CAM_FORMAT_PLAIN16_12:
764 rsrc_data->en_cfg = 0x1;
765 rsrc_data->pack_fmt = 0x3;
766 rsrc_data->width = rsrc_data->width * 2;
767 rsrc_data->stride = rsrc_data->width;
768 break;
769 case CAM_FORMAT_PLAIN16_14:
770 rsrc_data->en_cfg = 0x1;
771 rsrc_data->pack_fmt = 0x4;
772 rsrc_data->width = rsrc_data->width * 2;
773 rsrc_data->stride = rsrc_data->width;
774 break;
775 case CAM_FORMAT_PLAIN16_16:
776 rsrc_data->en_cfg = 0x1;
777 rsrc_data->pack_fmt = 0x5;
778 rsrc_data->width = rsrc_data->width * 2;
779 rsrc_data->stride = rsrc_data->width;
780 break;
781 case CAM_FORMAT_PLAIN32_20:
782 rsrc_data->en_cfg = 0x1;
783 rsrc_data->pack_fmt = 0x9;
784 break;
785 case CAM_FORMAT_PLAIN64:
786 rsrc_data->en_cfg = 0x1;
787 rsrc_data->pack_fmt = 0xA;
788 break;
789 case CAM_FORMAT_PLAIN128:
790 rsrc_data->en_cfg = 0x1;
791 rsrc_data->pack_fmt = 0x0;
792 break;
793 default:
794 CAM_ERR(CAM_ISP, "Unsupported RDI format %d",
795 rsrc_data->format);
796 return -EINVAL;
797 }
Abhishek Kondaveetib31b46c2017-06-23 04:56:24 +0530798 } else if (rsrc_data->index < 5 ||
799 rsrc_data->index == 7 || rsrc_data->index == 8) {
Krishnankutty Kolathappillyf39e6412017-07-18 15:58:22 -0700800 /* Write master 3, 4 - for Full OUT , 7-8 FD OUT */
801 switch (rsrc_data->format) {
Krishnankutty Kolathappillyf39e6412017-07-18 15:58:22 -0700802 case CAM_FORMAT_UBWC_NV12_4R:
803 rsrc_data->en_ubwc = 1;
Krishnankutty Kolathappilly06406e52017-08-17 00:50:21 -0700804 rsrc_data->width = ALIGNUP(rsrc_data->width, 64);
805 switch (plane) {
806 case PLANE_C:
807 rsrc_data->height /= 2;
808 break;
809 case PLANE_Y:
810 break;
811 default:
812 CAM_ERR(CAM_ISP, "Invalid plane %d\n", plane);
813 return -EINVAL;
814 }
815 break;
816 case CAM_FORMAT_UBWC_NV12:
817 rsrc_data->en_ubwc = 1;
Krishnankutty Kolathappillyf39e6412017-07-18 15:58:22 -0700818 /* Fall through for NV12 */
819 case CAM_FORMAT_NV21:
820 case CAM_FORMAT_NV12:
821 switch (plane) {
822 case PLANE_C:
823 rsrc_data->height /= 2;
824 break;
825 case PLANE_Y:
Jing Zhoua4e9fbe2017-05-15 14:37:21 -0700826 break;
827 default:
Krishnankutty Kolathappillyf39e6412017-07-18 15:58:22 -0700828 CAM_ERR(CAM_ISP, "Invalid plane %d\n", plane);
829 return -EINVAL;
Jing Zhoua4e9fbe2017-05-15 14:37:21 -0700830 }
831 break;
Krishnankutty Kolathappillyf39e6412017-07-18 15:58:22 -0700832 case CAM_FORMAT_UBWC_TP10:
833 rsrc_data->en_ubwc = 1;
Krishnankutty Kolathappilly06406e52017-08-17 00:50:21 -0700834 rsrc_data->width =
835 ALIGNUP(rsrc_data->width, 48) * 4 / 3;
836 switch (plane) {
837 case PLANE_C:
838 rsrc_data->height /= 2;
839 break;
840 case PLANE_Y:
841 break;
842 default:
843 CAM_ERR(CAM_ISP, "Invalid plane %d\n", plane);
844 return -EINVAL;
845 }
846 break;
Krishnankutty Kolathappillyf39e6412017-07-18 15:58:22 -0700847 case CAM_FORMAT_TP10:
Krishnankutty Kolathappilly06406e52017-08-17 00:50:21 -0700848 rsrc_data->width =
849 ALIGNUP(rsrc_data->width, 3) * 4 / 3;
Krishnankutty Kolathappillyf39e6412017-07-18 15:58:22 -0700850 switch (plane) {
851 case PLANE_C:
Jing Zhoua4e9fbe2017-05-15 14:37:21 -0700852 rsrc_data->height /= 2;
853 break;
Krishnankutty Kolathappillyf39e6412017-07-18 15:58:22 -0700854 case PLANE_Y:
Jing Zhoua4e9fbe2017-05-15 14:37:21 -0700855 break;
856 default:
Krishnankutty Kolathappillyf39e6412017-07-18 15:58:22 -0700857 CAM_ERR(CAM_ISP, "Invalid plane %d\n", plane);
858 return -EINVAL;
Jing Zhoua4e9fbe2017-05-15 14:37:21 -0700859 }
Harsh Shaha1af8822017-05-11 22:06:36 -0700860 break;
861 default:
Krishnankutty Kolathappillyf39e6412017-07-18 15:58:22 -0700862 CAM_ERR(CAM_ISP, "Invalid format %d\n",
863 rsrc_data->format);
Jing Zhoua4e9fbe2017-05-15 14:37:21 -0700864 return -EINVAL;
Harsh Shaha1af8822017-05-11 22:06:36 -0700865 }
Jing Zhoua4e9fbe2017-05-15 14:37:21 -0700866 rsrc_data->en_cfg = 0x1;
Abhishek Kondaveetib31b46c2017-06-23 04:56:24 +0530867 } else if (rsrc_data->index >= 11) {
Krishnankutty Kolathappillyf39e6412017-07-18 15:58:22 -0700868 /* Write master 11-19 stats */
Abhishek Kondaveetib31b46c2017-06-23 04:56:24 +0530869 rsrc_data->width = 0;
870 rsrc_data->height = 0;
Abhishek Kondaveetib31b46c2017-06-23 04:56:24 +0530871 rsrc_data->stride = 1;
872 rsrc_data->en_cfg = 0x3;
Jing Zhoua4e9fbe2017-05-15 14:37:21 -0700873 } else {
Krishnankutty Kolathappillyf39e6412017-07-18 15:58:22 -0700874 /* Write master 5-6 DS ports , 9 - Raw dump , 10 PDAF */
Jing Zhoua4e9fbe2017-05-15 14:37:21 -0700875 rsrc_data->width = rsrc_data->width * 4;
876 rsrc_data->height = rsrc_data->height / 2;
Jing Zhoua4e9fbe2017-05-15 14:37:21 -0700877 rsrc_data->en_cfg = 0x1;
Harsh Shaha1af8822017-05-11 22:06:36 -0700878 }
Harsh Shaha1af8822017-05-11 22:06:36 -0700879
880 *client_done_mask = (1 << wm_idx);
881 *wm_res = wm_res_local;
882
883 return 0;
884}
885
886static int cam_vfe_bus_release_wm(void *bus_priv,
887 struct cam_isp_resource_node *wm_res)
888{
889 struct cam_vfe_bus_ver2_wm_resource_data *rsrc_data =
890 wm_res->res_priv;
891
892 rsrc_data->irq_enabled = 0;
893 rsrc_data->offset = 0;
894 rsrc_data->width = 0;
895 rsrc_data->height = 0;
896 rsrc_data->stride = 0;
897 rsrc_data->format = 0;
898 rsrc_data->pack_fmt = 0;
899 rsrc_data->burst_len = 0;
Harsh Shaha1af8822017-05-11 22:06:36 -0700900 rsrc_data->irq_subsample_period = 0;
901 rsrc_data->irq_subsample_pattern = 0;
902 rsrc_data->framedrop_period = 0;
903 rsrc_data->framedrop_pattern = 0;
Jing Zhoua4e9fbe2017-05-15 14:37:21 -0700904 rsrc_data->packer_cfg = 0;
905 rsrc_data->en_ubwc = 0;
906 rsrc_data->tile_cfg = 0;
907 rsrc_data->h_init = 0;
908 rsrc_data->v_init = 0;
909 rsrc_data->ubwc_meta_stride = 0;
910 rsrc_data->ubwc_mode_cfg = 0;
911 rsrc_data->ubwc_meta_offset = 0;
Pavan Kumar Chilamkurthi649cdf92017-08-15 01:40:57 -0700912 rsrc_data->init_cfg_done = false;
913 rsrc_data->hfr_cfg_done = false;
Jing Zhoua4e9fbe2017-05-15 14:37:21 -0700914 rsrc_data->en_cfg = 0;
Harsh Shah19f55812017-06-26 18:58:49 -0700915
916 wm_res->tasklet_info = NULL;
Harsh Shaha1af8822017-05-11 22:06:36 -0700917 wm_res->res_state = CAM_ISP_RESOURCE_STATE_AVAILABLE;
918
919 return 0;
920}
921
922static int cam_vfe_bus_start_wm(struct cam_isp_resource_node *wm_res)
923{
924 int rc = 0;
925 struct cam_vfe_bus_ver2_wm_resource_data *rsrc_data =
926 wm_res->res_priv;
927 struct cam_vfe_bus_ver2_common_data *common_data =
928 rsrc_data->common_data;
Harsh Shah19f55812017-06-26 18:58:49 -0700929 uint32_t bus_irq_reg_mask[CAM_VFE_BUS_IRQ_MAX] = {0};
Harsh Shaha1af8822017-05-11 22:06:36 -0700930
Harsh Shah23557ae2017-05-13 18:14:34 -0700931 cam_io_w_mb(0, common_data->mem_base + rsrc_data->hw_regs->header_addr);
932 cam_io_w_mb(0, common_data->mem_base + rsrc_data->hw_regs->header_cfg);
Harsh Shah23557ae2017-05-13 18:14:34 -0700933 cam_io_w(0xf, common_data->mem_base + rsrc_data->hw_regs->burst_limit);
934
Jing Zhoua4e9fbe2017-05-15 14:37:21 -0700935 cam_io_w_mb(rsrc_data->width,
Harsh Shaha1af8822017-05-11 22:06:36 -0700936 common_data->mem_base + rsrc_data->hw_regs->buffer_width_cfg);
Jing Zhoua4e9fbe2017-05-15 14:37:21 -0700937 cam_io_w(rsrc_data->height,
Harsh Shaha1af8822017-05-11 22:06:36 -0700938 common_data->mem_base + rsrc_data->hw_regs->buffer_height_cfg);
Jing Zhoua4e9fbe2017-05-15 14:37:21 -0700939 cam_io_w(rsrc_data->pack_fmt,
Harsh Shaha1af8822017-05-11 22:06:36 -0700940 common_data->mem_base + rsrc_data->hw_regs->packer_cfg);
Harsh Shaha1af8822017-05-11 22:06:36 -0700941
Ravikishore Pampanaad6bc902017-07-12 19:37:06 +0530942 /* Configure stride for RDIs */
943 if (rsrc_data->index < 3)
944 cam_io_w_mb(rsrc_data->stride, (common_data->mem_base +
945 rsrc_data->hw_regs->stride));
Harsh Shaha1af8822017-05-11 22:06:36 -0700946
Harsh Shah19f55812017-06-26 18:58:49 -0700947 /* Subscribe IRQ */
948 if (rsrc_data->irq_enabled) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -0700949 CAM_DBG(CAM_ISP, "Subscribe WM%d IRQ", rsrc_data->index);
Harsh Shah19f55812017-06-26 18:58:49 -0700950 bus_irq_reg_mask[CAM_VFE_BUS_IRQ_REG1] =
951 (1 << rsrc_data->index);
952 wm_res->irq_handle = cam_irq_controller_subscribe_irq(
953 common_data->bus_irq_controller, CAM_IRQ_PRIORITY_1,
954 bus_irq_reg_mask, wm_res,
955 wm_res->top_half_handler,
956 cam_ife_mgr_do_tasklet_buf_done,
957 wm_res->tasklet_info, cam_tasklet_enqueue_cmd);
958 if (wm_res->irq_handle < 0) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -0700959 CAM_ERR(CAM_ISP, "Subscribe IRQ failed for WM %d",
Harsh Shah19f55812017-06-26 18:58:49 -0700960 rsrc_data->index);
961 return -EFAULT;
962 }
963 }
964
Junzhe Zou3d292562017-07-12 17:59:58 -0700965 /* enable ubwc if needed*/
966 if (rsrc_data->en_ubwc) {
967 cam_io_w_mb(0x1, common_data->mem_base +
968 rsrc_data->hw_regs->ubwc_regs->mode_cfg);
969 }
970
Harsh Shah19f55812017-06-26 18:58:49 -0700971 /* Enable WM */
972 cam_io_w_mb(rsrc_data->en_cfg, common_data->mem_base +
973 rsrc_data->hw_regs->cfg);
974
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -0700975 CAM_DBG(CAM_ISP, "WM res %d width = %d, height = %d", rsrc_data->index,
Jing Zhoua4e9fbe2017-05-15 14:37:21 -0700976 rsrc_data->width, rsrc_data->height);
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -0700977 CAM_DBG(CAM_ISP, "WM res %d pk_fmt = %d", rsrc_data->index,
Jing Zhoua4e9fbe2017-05-15 14:37:21 -0700978 rsrc_data->pack_fmt & PACKER_FMT_MAX);
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -0700979 CAM_DBG(CAM_ISP, "WM res %d stride = %d, burst len = %d",
Jing Zhoua4e9fbe2017-05-15 14:37:21 -0700980 rsrc_data->index, rsrc_data->stride, 0xf);
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -0700981 CAM_DBG(CAM_ISP, "enable WM res %d offset 0x%x val 0x%x",
982 rsrc_data->index, (uint32_t) rsrc_data->hw_regs->cfg,
983 rsrc_data->en_cfg);
Harsh Shaha1af8822017-05-11 22:06:36 -0700984
985 wm_res->res_state = CAM_ISP_RESOURCE_STATE_STREAMING;
986
987 return rc;
988}
989
990static int cam_vfe_bus_stop_wm(struct cam_isp_resource_node *wm_res)
991{
992 int rc = 0;
993 struct cam_vfe_bus_ver2_wm_resource_data *rsrc_data =
994 wm_res->res_priv;
995 struct cam_vfe_bus_ver2_common_data *common_data =
996 rsrc_data->common_data;
997
998 /* Disble WM */
999 cam_io_w_mb(0x0,
1000 common_data->mem_base + rsrc_data->hw_regs->cfg);
1001
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07001002 CAM_DBG(CAM_ISP, "irq_enabled %d", rsrc_data->irq_enabled);
Harsh Shaha1af8822017-05-11 22:06:36 -07001003 /* Unsubscribe IRQ */
Harsh Shah19f55812017-06-26 18:58:49 -07001004 if (rsrc_data->irq_enabled)
1005 rc = cam_irq_controller_unsubscribe_irq(
1006 common_data->bus_irq_controller,
1007 wm_res->irq_handle);
Harsh Shaha1af8822017-05-11 22:06:36 -07001008
1009 /* Halt & Reset WM */
1010 cam_io_w_mb(BIT(rsrc_data->index),
1011 common_data->mem_base + common_data->common_reg->sw_reset);
1012
1013 wm_res->res_state = CAM_ISP_RESOURCE_STATE_RESERVED;
1014
1015 return rc;
1016}
1017
1018static int cam_vfe_bus_handle_wm_done_top_half(uint32_t evt_id,
1019 struct cam_irq_th_payload *th_payload)
1020{
Harsh Shah19f55812017-06-26 18:58:49 -07001021 int32_t rc;
1022 int i;
1023 struct cam_isp_resource_node *wm_res = NULL;
1024 struct cam_vfe_bus_ver2_wm_resource_data *rsrc_data = NULL;
1025 struct cam_vfe_bus_irq_evt_payload *evt_payload;
1026
1027 wm_res = th_payload->handler_priv;
1028 if (!wm_res) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07001029 CAM_ERR_RATE_LIMIT(CAM_ISP, "Error! No resource\n");
Harsh Shah19f55812017-06-26 18:58:49 -07001030 return -ENODEV;
1031 }
1032
1033 rsrc_data = wm_res->res_priv;
1034
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07001035 CAM_DBG(CAM_ISP, "IRQ status_0 = %x", th_payload->evt_status_arr[0]);
1036 CAM_DBG(CAM_ISP, "IRQ status_1 = %x", th_payload->evt_status_arr[1]);
Harsh Shah19f55812017-06-26 18:58:49 -07001037
1038 rc = cam_vfe_bus_get_evt_payload(rsrc_data->common_data, &evt_payload);
1039 if (rc) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07001040 CAM_ERR_RATE_LIMIT(CAM_ISP,
1041 "No tasklet_cmd is free in queue\n");
Harsh Shah19f55812017-06-26 18:58:49 -07001042 return rc;
1043 }
1044
1045 cam_isp_hw_get_timestamp(&evt_payload->ts);
1046
1047 evt_payload->ctx = rsrc_data->ctx;
1048 evt_payload->core_index = rsrc_data->common_data->core_index;
1049 evt_payload->evt_id = evt_id;
1050
1051 for (i = 0; i < th_payload->num_registers; i++)
1052 evt_payload->irq_reg_val[i] = th_payload->evt_status_arr[i];
1053
1054 th_payload->evt_payload_priv = evt_payload;
1055
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07001056 CAM_DBG(CAM_ISP, "Exit");
Harsh Shah19f55812017-06-26 18:58:49 -07001057 return rc;
Harsh Shaha1af8822017-05-11 22:06:36 -07001058}
1059
1060static int cam_vfe_bus_handle_wm_done_bottom_half(void *wm_node,
1061 void *evt_payload_priv)
1062{
1063 int rc = CAM_VFE_IRQ_STATUS_ERR;
1064 struct cam_isp_resource_node *wm_res = wm_node;
1065 struct cam_vfe_bus_irq_evt_payload *evt_payload = evt_payload_priv;
Harsh Shah23557ae2017-05-13 18:14:34 -07001066 struct cam_vfe_bus_ver2_wm_resource_data *rsrc_data =
1067 (wm_res == NULL) ? NULL : wm_res->res_priv;
1068 uint32_t *cam_ife_irq_regs;
Harsh Shaha1af8822017-05-11 22:06:36 -07001069 uint32_t status_reg;
1070
Harsh Shah23557ae2017-05-13 18:14:34 -07001071 if (!evt_payload || !rsrc_data)
1072 return rc;
Harsh Shaha1af8822017-05-11 22:06:36 -07001073
Harsh Shah23557ae2017-05-13 18:14:34 -07001074 cam_ife_irq_regs = evt_payload->irq_reg_val;
1075 status_reg = cam_ife_irq_regs[CAM_IFE_IRQ_BUS_REG_STATUS1];
1076
1077 if (status_reg & BIT(rsrc_data->index)) {
1078 cam_ife_irq_regs[CAM_IFE_IRQ_BUS_REG_STATUS1] &=
1079 ~BIT(rsrc_data->index);
Harsh Shaha1af8822017-05-11 22:06:36 -07001080 rc = CAM_VFE_IRQ_STATUS_SUCCESS;
Harsh Shah23557ae2017-05-13 18:14:34 -07001081 }
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07001082 CAM_DBG(CAM_ISP, "status_reg %x rc %d", status_reg, rc);
Harsh Shaha1af8822017-05-11 22:06:36 -07001083
1084 if (rc == CAM_VFE_IRQ_STATUS_SUCCESS)
Harsh Shah19f55812017-06-26 18:58:49 -07001085 cam_vfe_bus_put_evt_payload(rsrc_data->common_data,
Harsh Shaha1af8822017-05-11 22:06:36 -07001086 &evt_payload);
1087
1088 return rc;
1089}
1090
1091static int cam_vfe_bus_init_wm_resource(uint32_t index,
1092 struct cam_vfe_bus_ver2_priv *ver2_bus_priv,
1093 struct cam_vfe_bus_ver2_hw_info *ver2_hw_info,
1094 struct cam_isp_resource_node *wm_res)
1095{
Harsh Shaha1af8822017-05-11 22:06:36 -07001096 struct cam_vfe_bus_ver2_wm_resource_data *rsrc_data;
1097
1098 rsrc_data = kzalloc(sizeof(struct cam_vfe_bus_ver2_wm_resource_data),
1099 GFP_KERNEL);
1100 if (!rsrc_data) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07001101 CAM_DBG(CAM_ISP, "Failed to alloc for WM res priv");
Harsh Shah545df9a2017-06-16 16:43:17 -07001102 return -ENOMEM;
Harsh Shaha1af8822017-05-11 22:06:36 -07001103 }
1104 wm_res->res_priv = rsrc_data;
1105
1106 rsrc_data->index = index;
1107 rsrc_data->hw_regs = &ver2_hw_info->bus_client_reg[index];
1108 rsrc_data->common_data = &ver2_bus_priv->common_data;
1109
1110 wm_res->res_state = CAM_ISP_RESOURCE_STATE_AVAILABLE;
1111 INIT_LIST_HEAD(&wm_res->list);
1112
1113 wm_res->start = cam_vfe_bus_start_wm;
1114 wm_res->stop = cam_vfe_bus_stop_wm;
1115 wm_res->top_half_handler = cam_vfe_bus_handle_wm_done_top_half;
1116 wm_res->bottom_half_handler = cam_vfe_bus_handle_wm_done_bottom_half;
1117 wm_res->hw_intf = ver2_bus_priv->common_data.hw_intf;
1118
Harsh Shah545df9a2017-06-16 16:43:17 -07001119 return 0;
1120}
1121
1122static int cam_vfe_bus_deinit_wm_resource(
1123 struct cam_isp_resource_node *wm_res)
1124{
1125 struct cam_vfe_bus_ver2_wm_resource_data *rsrc_data;
1126
1127 wm_res->res_state = CAM_ISP_RESOURCE_STATE_UNAVAILABLE;
1128 INIT_LIST_HEAD(&wm_res->list);
1129
1130 wm_res->start = NULL;
1131 wm_res->stop = NULL;
1132 wm_res->top_half_handler = NULL;
1133 wm_res->bottom_half_handler = NULL;
1134 wm_res->hw_intf = NULL;
1135
1136 rsrc_data = wm_res->res_priv;
1137 wm_res->res_priv = NULL;
1138 if (!rsrc_data) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07001139 CAM_ERR(CAM_ISP, "Error! WM res priv is NULL");
Harsh Shah545df9a2017-06-16 16:43:17 -07001140 return -ENOMEM;
1141 }
1142 kfree(rsrc_data);
1143
1144 return 0;
Harsh Shaha1af8822017-05-11 22:06:36 -07001145}
1146
1147static void cam_vfe_bus_add_wm_to_comp_grp(
1148 struct cam_isp_resource_node *comp_grp,
1149 uint32_t composite_mask)
1150{
1151 struct cam_vfe_bus_ver2_comp_grp_data *rsrc_data = comp_grp->res_priv;
1152
1153 rsrc_data->composite_mask |= composite_mask;
1154}
1155
1156static void cam_vfe_bus_match_comp_grp(
1157 struct cam_vfe_bus_ver2_priv *ver2_bus_priv,
1158 struct cam_isp_resource_node **comp_grp,
1159 uint32_t comp_grp_local_idx,
1160 uint32_t unique_id)
1161{
1162 struct cam_vfe_bus_ver2_comp_grp_data *rsrc_data = NULL;
1163 struct cam_isp_resource_node *comp_grp_local = NULL;
1164
1165 list_for_each_entry(comp_grp_local,
1166 &ver2_bus_priv->used_comp_grp, list) {
1167 rsrc_data = comp_grp_local->res_priv;
1168 if (rsrc_data->comp_grp_local_idx == comp_grp_local_idx &&
1169 rsrc_data->unique_id == unique_id) {
1170 /* Match found */
1171 *comp_grp = comp_grp_local;
1172 return;
1173 }
1174 }
1175
1176 *comp_grp = NULL;
1177}
1178
1179static int cam_vfe_bus_acquire_comp_grp(
1180 struct cam_vfe_bus_ver2_priv *ver2_bus_priv,
1181 struct cam_isp_out_port_info *out_port_info,
Harsh Shah19f55812017-06-26 18:58:49 -07001182 void *tasklet,
1183 void *ctx,
Harsh Shaha1af8822017-05-11 22:06:36 -07001184 uint32_t unique_id,
1185 uint32_t is_dual,
1186 uint32_t is_master,
1187 enum cam_vfe_bus_ver2_vfe_core_id dual_slave_core,
1188 struct cam_isp_resource_node **comp_grp)
1189{
1190 int rc = 0;
1191 struct cam_isp_resource_node *comp_grp_local = NULL;
1192 struct cam_vfe_bus_ver2_comp_grp_data *rsrc_data = NULL;
1193
1194 /* Check if matching comp_grp already acquired */
1195 cam_vfe_bus_match_comp_grp(ver2_bus_priv, &comp_grp_local,
1196 out_port_info->comp_grp_id, unique_id);
1197
1198 if (!comp_grp_local) {
1199 /* First find a free group */
1200 if (is_dual) {
1201 if (list_empty(&ver2_bus_priv->free_dual_comp_grp)) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07001202 CAM_ERR(CAM_ISP, "No Free Composite Group");
Harsh Shaha1af8822017-05-11 22:06:36 -07001203 return -ENODEV;
1204 }
1205 comp_grp_local = list_first_entry(
1206 &ver2_bus_priv->free_dual_comp_grp,
1207 struct cam_isp_resource_node, list);
1208 rsrc_data = comp_grp_local->res_priv;
1209 rc = cam_vfe_bus_ver2_get_intra_client_mask(
1210 dual_slave_core,
1211 comp_grp_local->hw_intf->hw_idx,
1212 &rsrc_data->intra_client_mask);
1213 } else {
1214 if (list_empty(&ver2_bus_priv->free_comp_grp)) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07001215 CAM_ERR(CAM_ISP, "No Free Composite Group");
Harsh Shaha1af8822017-05-11 22:06:36 -07001216 return -ENODEV;
1217 }
1218 comp_grp_local = list_first_entry(
1219 &ver2_bus_priv->free_comp_grp,
1220 struct cam_isp_resource_node, list);
1221 rsrc_data = comp_grp_local->res_priv;
1222 }
1223
1224 list_del(&comp_grp_local->list);
Harsh Shah19f55812017-06-26 18:58:49 -07001225 comp_grp_local->tasklet_info = tasklet;
Harsh Shaha1af8822017-05-11 22:06:36 -07001226 comp_grp_local->res_state = CAM_ISP_RESOURCE_STATE_RESERVED;
1227
1228 rsrc_data->is_master = is_master;
1229 rsrc_data->composite_mask = 0;
1230 rsrc_data->unique_id = unique_id;
1231 rsrc_data->comp_grp_local_idx = out_port_info->comp_grp_id;
1232
1233 list_add_tail(&comp_grp_local->list,
1234 &ver2_bus_priv->used_comp_grp);
1235
1236 } else {
1237 rsrc_data = comp_grp_local->res_priv;
1238 /* Do not support runtime change in composite mask */
1239 if (comp_grp_local->res_state ==
1240 CAM_ISP_RESOURCE_STATE_STREAMING) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07001241 CAM_ERR(CAM_ISP, "Invalid State %d Comp Grp %u",
Harsh Shaha1af8822017-05-11 22:06:36 -07001242 comp_grp_local->res_state,
1243 rsrc_data->comp_grp_type);
1244 return -EBUSY;
1245 }
1246 }
1247
Harsh Shah19f55812017-06-26 18:58:49 -07001248 rsrc_data->ctx = ctx;
Harsh Shaha1af8822017-05-11 22:06:36 -07001249 *comp_grp = comp_grp_local;
1250
1251 return rc;
1252}
1253
1254static int cam_vfe_bus_release_comp_grp(
1255 struct cam_vfe_bus_ver2_priv *ver2_bus_priv,
1256 struct cam_isp_resource_node *in_comp_grp)
1257{
1258 struct cam_isp_resource_node *comp_grp = NULL;
1259 struct cam_vfe_bus_ver2_comp_grp_data *in_rsrc_data = NULL;
1260 int match_found = 0;
1261
1262 if (!in_comp_grp) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07001263 CAM_ERR(CAM_ISP, "Invalid Params Comp Grp %pK", in_rsrc_data);
Harsh Shaha1af8822017-05-11 22:06:36 -07001264 return -EINVAL;
1265 }
1266
1267 if (in_comp_grp->res_state == CAM_ISP_RESOURCE_STATE_AVAILABLE) {
1268 /* Already Released. Do Nothing */
1269 return 0;
1270 }
1271
1272 in_rsrc_data = in_comp_grp->res_priv;
1273
1274 list_for_each_entry(comp_grp, &ver2_bus_priv->used_comp_grp, list) {
1275 if (comp_grp == in_comp_grp) {
1276 match_found = 1;
1277 break;
1278 }
1279 }
1280
1281 if (!match_found) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07001282 CAM_ERR(CAM_ISP, "Could not find matching Comp Grp type %u",
Harsh Shaha1af8822017-05-11 22:06:36 -07001283 in_rsrc_data->comp_grp_type);
1284 return -ENODEV;
1285 }
1286
1287
1288 list_del(&comp_grp->list);
1289 if (in_rsrc_data->comp_grp_type >= CAM_VFE_BUS_VER2_COMP_GRP_DUAL_0 &&
1290 in_rsrc_data->comp_grp_type <= CAM_VFE_BUS_VER2_COMP_GRP_DUAL_5)
1291 list_add_tail(&comp_grp->list,
1292 &ver2_bus_priv->free_dual_comp_grp);
Jing Zhoue71fd4a2017-05-15 19:44:34 -07001293 else if (in_rsrc_data->comp_grp_type >= CAM_VFE_BUS_VER2_COMP_GRP_0
1294 && in_rsrc_data->comp_grp_type <= CAM_VFE_BUS_VER2_COMP_GRP_5)
Harsh Shaha1af8822017-05-11 22:06:36 -07001295 list_add_tail(&comp_grp->list, &ver2_bus_priv->free_comp_grp);
1296
Harsh Shaha1af8822017-05-11 22:06:36 -07001297 in_rsrc_data->unique_id = 0;
1298 in_rsrc_data->comp_grp_local_idx = 0;
1299 in_rsrc_data->composite_mask = 0;
1300 in_rsrc_data->dual_slave_core = CAM_VFE_BUS_VER2_VFE_CORE_MAX;
1301
Harsh Shah19f55812017-06-26 18:58:49 -07001302 comp_grp->tasklet_info = NULL;
Harsh Shaha1af8822017-05-11 22:06:36 -07001303 comp_grp->res_state = CAM_ISP_RESOURCE_STATE_AVAILABLE;
1304
Jing Zhoue71fd4a2017-05-15 19:44:34 -07001305 return 0;
Harsh Shaha1af8822017-05-11 22:06:36 -07001306}
1307
1308static int cam_vfe_bus_start_comp_grp(struct cam_isp_resource_node *comp_grp)
1309{
1310 int rc = 0;
1311 struct cam_vfe_bus_ver2_comp_grp_data *rsrc_data =
1312 comp_grp->res_priv;
1313 struct cam_vfe_bus_ver2_common_data *common_data =
1314 rsrc_data->common_data;
Harsh Shah19f55812017-06-26 18:58:49 -07001315 uint32_t bus_irq_reg_mask[CAM_VFE_BUS_IRQ_MAX] = {0};
Harsh Shaha1af8822017-05-11 22:06:36 -07001316
1317 cam_io_w_mb(rsrc_data->composite_mask, common_data->mem_base +
1318 rsrc_data->hw_regs->comp_mask);
1319
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07001320 CAM_DBG(CAM_ISP, "composite_mask is 0x%x", rsrc_data->composite_mask);
1321 CAM_DBG(CAM_ISP, "composite_mask addr 0x%x",
1322 rsrc_data->hw_regs->comp_mask);
Harsh Shaha1af8822017-05-11 22:06:36 -07001323
1324 if (rsrc_data->comp_grp_type >= CAM_VFE_BUS_VER2_COMP_GRP_DUAL_0 &&
1325 rsrc_data->comp_grp_type <= CAM_VFE_BUS_VER2_COMP_GRP_DUAL_5 &&
1326 rsrc_data->is_master) {
1327 int dual_comp_grp = (rsrc_data->comp_grp_type -
1328 CAM_VFE_BUS_VER2_COMP_GRP_DUAL_0);
1329 int intra_client_en = cam_io_r_mb(common_data->mem_base +
1330 common_data->common_reg->dual_master_comp_cfg);
1331
1332 /* 2 Bits per comp_grp. Hence left shift by comp_grp * 2 */
1333 intra_client_en |=
1334 (rsrc_data->intra_client_mask << dual_comp_grp * 2);
1335
1336 cam_io_w_mb(intra_client_en, common_data->mem_base +
1337 common_data->common_reg->dual_master_comp_cfg);
Harsh Shah19f55812017-06-26 18:58:49 -07001338
1339 bus_irq_reg_mask[CAM_VFE_BUS_IRQ_REG2] = (1 << dual_comp_grp);
1340 } else {
1341 /* IRQ bits for COMP GRP start at 5. So add 5 to the shift */
1342 bus_irq_reg_mask[CAM_VFE_BUS_IRQ_REG0] =
1343 (1 << (rsrc_data->comp_grp_type + 5));
1344 }
1345
1346 /* Subscribe IRQ */
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07001347 CAM_DBG(CAM_ISP, "Subscribe COMP_GRP%d IRQ", rsrc_data->comp_grp_type);
Harsh Shah19f55812017-06-26 18:58:49 -07001348 comp_grp->irq_handle = cam_irq_controller_subscribe_irq(
1349 common_data->bus_irq_controller, CAM_IRQ_PRIORITY_1,
1350 bus_irq_reg_mask, comp_grp,
1351 comp_grp->top_half_handler,
1352 cam_ife_mgr_do_tasklet_buf_done,
1353 comp_grp->tasklet_info, cam_tasklet_enqueue_cmd);
1354 if (comp_grp->irq_handle < 0) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07001355 CAM_ERR(CAM_ISP, "Subscribe IRQ failed for comp_grp %d",
Harsh Shah19f55812017-06-26 18:58:49 -07001356 rsrc_data->comp_grp_type);
1357 return -EFAULT;
Harsh Shaha1af8822017-05-11 22:06:36 -07001358 }
1359
1360 comp_grp->res_state = CAM_ISP_RESOURCE_STATE_STREAMING;
Harsh Shah19f55812017-06-26 18:58:49 -07001361
Harsh Shaha1af8822017-05-11 22:06:36 -07001362 return rc;
1363}
1364
1365static int cam_vfe_bus_stop_comp_grp(struct cam_isp_resource_node *comp_grp)
1366{
1367 int rc = 0;
1368 struct cam_vfe_bus_ver2_comp_grp_data *rsrc_data =
1369 comp_grp->res_priv;
1370 struct cam_vfe_bus_ver2_common_data *common_data =
1371 rsrc_data->common_data;
1372
1373 /* Unsubscribe IRQ */
Harsh Shah19f55812017-06-26 18:58:49 -07001374 rc = cam_irq_controller_unsubscribe_irq(
1375 common_data->bus_irq_controller,
1376 comp_grp->irq_handle);
Harsh Shaha1af8822017-05-11 22:06:36 -07001377
1378 cam_io_w_mb(rsrc_data->composite_mask, common_data->mem_base +
1379 rsrc_data->hw_regs->comp_mask);
1380 if (rsrc_data->comp_grp_type >= CAM_VFE_BUS_VER2_COMP_GRP_DUAL_0 &&
1381 rsrc_data->comp_grp_type <= CAM_VFE_BUS_VER2_COMP_GRP_DUAL_5 &&
1382 rsrc_data->is_master) {
1383 int dual_comp_grp = (rsrc_data->comp_grp_type -
1384 CAM_VFE_BUS_VER2_COMP_GRP_DUAL_0);
1385 int intra_client_en = cam_io_r_mb(common_data->mem_base +
1386 common_data->common_reg->dual_master_comp_cfg);
1387
1388 /* 2 Bits per comp_grp. Hence left shift by comp_grp * 2 */
1389 intra_client_en &=
1390 ~(rsrc_data->intra_client_mask << dual_comp_grp * 2);
1391
1392 cam_io_w_mb(intra_client_en, common_data->mem_base +
1393 common_data->common_reg->dual_master_comp_cfg);
1394 }
1395
1396 comp_grp->res_state = CAM_ISP_RESOURCE_STATE_RESERVED;
1397
1398 return rc;
1399}
1400
1401static int cam_vfe_bus_handle_comp_done_top_half(uint32_t evt_id,
1402 struct cam_irq_th_payload *th_payload)
1403{
Harsh Shah19f55812017-06-26 18:58:49 -07001404 int32_t rc;
1405 int i;
1406 struct cam_isp_resource_node *comp_grp = NULL;
1407 struct cam_vfe_bus_ver2_comp_grp_data *rsrc_data = NULL;
1408 struct cam_vfe_bus_irq_evt_payload *evt_payload;
1409
1410 comp_grp = th_payload->handler_priv;
1411 if (!comp_grp) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07001412 CAM_ERR_RATE_LIMIT(CAM_ISP, "Error! No resource\n");
Harsh Shah19f55812017-06-26 18:58:49 -07001413 return -ENODEV;
1414 }
1415
1416 rsrc_data = comp_grp->res_priv;
1417
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07001418 CAM_DBG(CAM_ISP, "IRQ status_0 = %x", th_payload->evt_status_arr[0]);
1419 CAM_DBG(CAM_ISP, "IRQ status_1 = %x", th_payload->evt_status_arr[1]);
Harsh Shah19f55812017-06-26 18:58:49 -07001420
1421 rc = cam_vfe_bus_get_evt_payload(rsrc_data->common_data, &evt_payload);
1422 if (rc) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07001423 CAM_ERR_RATE_LIMIT(CAM_ISP,
1424 "No tasklet_cmd is free in queue\n");
Harsh Shah19f55812017-06-26 18:58:49 -07001425 return rc;
1426 }
1427
1428 cam_isp_hw_get_timestamp(&evt_payload->ts);
1429
1430 evt_payload->ctx = rsrc_data->ctx;
1431 evt_payload->core_index = rsrc_data->common_data->core_index;
1432 evt_payload->evt_id = evt_id;
1433
1434 for (i = 0; i < th_payload->num_registers; i++)
1435 evt_payload->irq_reg_val[i] = th_payload->evt_status_arr[i];
1436
1437 th_payload->evt_payload_priv = evt_payload;
1438
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07001439 CAM_DBG(CAM_ISP, "Exit");
Harsh Shah19f55812017-06-26 18:58:49 -07001440 return rc;
Harsh Shaha1af8822017-05-11 22:06:36 -07001441}
1442
1443static int cam_vfe_bus_handle_comp_done_bottom_half(
1444 void *handler_priv,
1445 void *evt_payload_priv)
1446{
1447 int rc = CAM_VFE_IRQ_STATUS_ERR;
1448 struct cam_isp_resource_node *comp_grp = handler_priv;
1449 struct cam_vfe_bus_irq_evt_payload *evt_payload = evt_payload_priv;
1450 struct cam_vfe_bus_ver2_comp_grp_data *rsrc_data = comp_grp->res_priv;
Harsh Shah23557ae2017-05-13 18:14:34 -07001451 uint32_t *cam_ife_irq_regs;
1452 uint32_t status_reg;
1453 uint32_t comp_err_reg;
1454 uint32_t comp_grp_id;
1455
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07001456 CAM_DBG(CAM_ISP, "comp grp type %d", rsrc_data->comp_grp_type);
Harsh Shah19f55812017-06-26 18:58:49 -07001457
Harsh Shah23557ae2017-05-13 18:14:34 -07001458 if (!evt_payload)
1459 return rc;
1460
1461 cam_ife_irq_regs = evt_payload->irq_reg_val;
Harsh Shaha1af8822017-05-11 22:06:36 -07001462
Harsh Shaha1af8822017-05-11 22:06:36 -07001463 switch (rsrc_data->comp_grp_type) {
1464 case CAM_VFE_BUS_VER2_COMP_GRP_0:
1465 case CAM_VFE_BUS_VER2_COMP_GRP_1:
1466 case CAM_VFE_BUS_VER2_COMP_GRP_2:
1467 case CAM_VFE_BUS_VER2_COMP_GRP_3:
1468 case CAM_VFE_BUS_VER2_COMP_GRP_4:
1469 case CAM_VFE_BUS_VER2_COMP_GRP_5:
Harsh Shah23557ae2017-05-13 18:14:34 -07001470 comp_grp_id = (rsrc_data->comp_grp_type -
Harsh Shaha1af8822017-05-11 22:06:36 -07001471 CAM_VFE_BUS_VER2_COMP_GRP_0);
1472
1473 /* Check for Regular composite error */
1474 status_reg = cam_ife_irq_regs[CAM_IFE_IRQ_BUS_REG_STATUS0];
1475
1476 comp_err_reg = cam_ife_irq_regs[CAM_IFE_IRQ_BUS_REG_COMP_ERR];
1477 if ((status_reg & BIT(11)) &&
1478 (comp_err_reg & rsrc_data->composite_mask)) {
1479 /* Check for Regular composite error */
1480 rc = CAM_VFE_IRQ_STATUS_ERR_COMP;
1481 break;
1482 }
1483
1484 comp_err_reg = cam_ife_irq_regs[CAM_IFE_IRQ_BUS_REG_COMP_OWRT];
1485 /* Check for Regular composite Overwrite */
1486 if ((status_reg & BIT(12)) &&
1487 (comp_err_reg & rsrc_data->composite_mask)) {
1488 rc = CAM_VFE_IRQ_STATUS_COMP_OWRT;
1489 break;
1490 }
1491
Harsh Shah23557ae2017-05-13 18:14:34 -07001492 /* Regular Composite SUCCESS */
1493 if (status_reg & BIT(comp_grp_id + 5)) {
1494 cam_ife_irq_regs[CAM_IFE_IRQ_BUS_REG_STATUS0] &=
1495 ~BIT(comp_grp_id + 5);
Harsh Shaha1af8822017-05-11 22:06:36 -07001496 rc = CAM_VFE_IRQ_STATUS_SUCCESS;
Harsh Shah23557ae2017-05-13 18:14:34 -07001497 }
Harsh Shaha1af8822017-05-11 22:06:36 -07001498
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07001499 CAM_DBG(CAM_ISP, "status reg = 0x%x, bit index = %d rc %d",
Harsh Shah19f55812017-06-26 18:58:49 -07001500 status_reg, (comp_grp_id + 5), rc);
Harsh Shaha1af8822017-05-11 22:06:36 -07001501 break;
1502
1503 case CAM_VFE_BUS_VER2_COMP_GRP_DUAL_0:
1504 case CAM_VFE_BUS_VER2_COMP_GRP_DUAL_1:
1505 case CAM_VFE_BUS_VER2_COMP_GRP_DUAL_2:
1506 case CAM_VFE_BUS_VER2_COMP_GRP_DUAL_3:
1507 case CAM_VFE_BUS_VER2_COMP_GRP_DUAL_4:
1508 case CAM_VFE_BUS_VER2_COMP_GRP_DUAL_5:
Harsh Shah23557ae2017-05-13 18:14:34 -07001509 comp_grp_id = (rsrc_data->comp_grp_type -
Harsh Shaha1af8822017-05-11 22:06:36 -07001510 CAM_VFE_BUS_VER2_COMP_GRP_DUAL_0);
1511
1512 /* Check for DUAL composite error */
1513 status_reg = cam_ife_irq_regs[CAM_IFE_IRQ_BUS_REG_STATUS2];
1514
1515 comp_err_reg = cam_ife_irq_regs[CAM_IFE_IRQ_BUS_DUAL_COMP_ERR];
1516 if ((status_reg & BIT(6)) &&
1517 (comp_err_reg & rsrc_data->composite_mask)) {
1518 /* Check for DUAL composite error */
1519 rc = CAM_VFE_IRQ_STATUS_ERR_COMP;
1520 break;
1521 }
1522
1523 /* Check for Dual composite Overwrite */
1524 comp_err_reg = cam_ife_irq_regs[CAM_IFE_IRQ_BUS_DUAL_COMP_OWRT];
1525 if ((status_reg & BIT(7)) &&
1526 (comp_err_reg & rsrc_data->composite_mask)) {
1527 rc = CAM_VFE_IRQ_STATUS_COMP_OWRT;
1528 break;
1529 }
1530
Harsh Shah23557ae2017-05-13 18:14:34 -07001531 /* DUAL Composite SUCCESS */
1532 if (status_reg & BIT(comp_grp_id)) {
1533 cam_ife_irq_regs[CAM_IFE_IRQ_BUS_REG_STATUS2] &=
1534 ~BIT(comp_grp_id + 5);
Harsh Shaha1af8822017-05-11 22:06:36 -07001535 rc = CAM_VFE_IRQ_STATUS_SUCCESS;
Harsh Shah23557ae2017-05-13 18:14:34 -07001536 }
Harsh Shaha1af8822017-05-11 22:06:36 -07001537
1538 break;
Harsh Shaha1af8822017-05-11 22:06:36 -07001539 default:
1540 rc = CAM_VFE_IRQ_STATUS_ERR;
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07001541 CAM_ERR(CAM_ISP, "Error! Invalid comp_grp_type %u",
Harsh Shah19f55812017-06-26 18:58:49 -07001542 rsrc_data->comp_grp_type);
Harsh Shaha1af8822017-05-11 22:06:36 -07001543 break;
1544 }
1545
1546 if (rc == CAM_VFE_IRQ_STATUS_SUCCESS)
Harsh Shah19f55812017-06-26 18:58:49 -07001547 cam_vfe_bus_put_evt_payload(rsrc_data->common_data,
Harsh Shaha1af8822017-05-11 22:06:36 -07001548 &evt_payload);
1549
1550 return rc;
1551}
1552
1553static int cam_vfe_bus_init_comp_grp(uint32_t index,
1554 struct cam_vfe_bus_ver2_priv *ver2_bus_priv,
1555 struct cam_vfe_bus_ver2_hw_info *ver2_hw_info,
1556 struct cam_isp_resource_node *comp_grp)
1557{
Harsh Shah545df9a2017-06-16 16:43:17 -07001558 struct cam_vfe_bus_ver2_comp_grp_data *rsrc_data = NULL;
Harsh Shaha1af8822017-05-11 22:06:36 -07001559
1560 rsrc_data = kzalloc(sizeof(struct cam_vfe_bus_ver2_comp_grp_data),
1561 GFP_KERNEL);
1562 if (!rsrc_data) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07001563 CAM_DBG(CAM_ISP, "Failed to alloc for comp_grp_priv");
Harsh Shaha1af8822017-05-11 22:06:36 -07001564 return -ENOMEM;
1565 }
1566 comp_grp->res_priv = rsrc_data;
1567
1568 comp_grp->res_state = CAM_ISP_RESOURCE_STATE_AVAILABLE;
1569 INIT_LIST_HEAD(&comp_grp->list);
1570
1571 rsrc_data->comp_grp_type = index;
1572 rsrc_data->common_data = &ver2_bus_priv->common_data;
1573 rsrc_data->hw_regs = &ver2_hw_info->comp_grp_reg[index];
1574 rsrc_data->dual_slave_core = CAM_VFE_BUS_VER2_VFE_CORE_MAX;
1575
Harsh Shaha1af8822017-05-11 22:06:36 -07001576 if (rsrc_data->comp_grp_type >= CAM_VFE_BUS_VER2_COMP_GRP_DUAL_0 &&
1577 rsrc_data->comp_grp_type <= CAM_VFE_BUS_VER2_COMP_GRP_DUAL_5)
1578 list_add_tail(&comp_grp->list,
1579 &ver2_bus_priv->free_dual_comp_grp);
1580 else if (rsrc_data->comp_grp_type >= CAM_VFE_BUS_VER2_COMP_GRP_0
1581 && rsrc_data->comp_grp_type <= CAM_VFE_BUS_VER2_COMP_GRP_5)
1582 list_add_tail(&comp_grp->list, &ver2_bus_priv->free_comp_grp);
1583
1584 comp_grp->start = cam_vfe_bus_start_comp_grp;
1585 comp_grp->stop = cam_vfe_bus_stop_comp_grp;
1586 comp_grp->top_half_handler = cam_vfe_bus_handle_comp_done_top_half;
1587 comp_grp->bottom_half_handler =
1588 cam_vfe_bus_handle_comp_done_bottom_half;
1589 comp_grp->hw_intf = ver2_bus_priv->common_data.hw_intf;
1590
1591 return 0;
1592}
1593
Harsh Shah545df9a2017-06-16 16:43:17 -07001594static int cam_vfe_bus_deinit_comp_grp(
1595 struct cam_isp_resource_node *comp_grp)
1596{
1597 struct cam_vfe_bus_ver2_comp_grp_data *rsrc_data =
1598 comp_grp->res_priv;
1599
1600 comp_grp->start = NULL;
1601 comp_grp->stop = NULL;
1602 comp_grp->top_half_handler = NULL;
1603 comp_grp->bottom_half_handler = NULL;
1604 comp_grp->hw_intf = NULL;
1605
1606 list_del_init(&comp_grp->list);
1607 comp_grp->res_state = CAM_ISP_RESOURCE_STATE_UNAVAILABLE;
1608
1609 comp_grp->res_priv = NULL;
1610
1611 if (!rsrc_data) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07001612 CAM_ERR(CAM_ISP, "Error! comp_grp_priv is NULL");
Harsh Shah545df9a2017-06-16 16:43:17 -07001613 return -ENODEV;
1614 }
1615 kfree(rsrc_data);
1616
1617 return 0;
1618}
1619
Harsh Shah19f55812017-06-26 18:58:49 -07001620static int cam_vfe_bus_acquire_vfe_out(void *bus_priv, void *acquire_args,
1621 uint32_t args_size)
Harsh Shaha1af8822017-05-11 22:06:36 -07001622{
1623 int rc = -ENODEV;
1624 int i;
1625 enum cam_vfe_bus_ver2_vfe_out_type vfe_out_res_id;
1626 uint32_t format;
1627 uint32_t num_wm;
1628 uint32_t subscribe_irq;
1629 uint32_t client_done_mask;
1630 struct cam_vfe_bus_ver2_priv *ver2_bus_priv = bus_priv;
1631 struct cam_vfe_acquire_args *acq_args = acquire_args;
1632 struct cam_vfe_hw_vfe_out_acquire_args *out_acquire_args;
1633 struct cam_isp_resource_node *rsrc_node = NULL;
1634 struct cam_vfe_bus_ver2_vfe_out_data *rsrc_data = NULL;
1635
1636 if (!bus_priv || !acquire_args) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07001637 CAM_ERR(CAM_ISP, "Invalid Param");
Harsh Shaha1af8822017-05-11 22:06:36 -07001638 return -EINVAL;
1639 }
1640
1641 out_acquire_args = &acq_args->vfe_out;
1642 format = out_acquire_args->out_port_info->format;
1643
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07001644 CAM_DBG(CAM_ISP, "Acquiring resource type 0x%x",
Harsh Shaha1af8822017-05-11 22:06:36 -07001645 out_acquire_args->out_port_info->res_type);
1646
1647 vfe_out_res_id = cam_vfe_bus_get_out_res_id(
1648 out_acquire_args->out_port_info->res_type);
1649 if (vfe_out_res_id == CAM_VFE_BUS_VER2_VFE_OUT_MAX)
1650 return -ENODEV;
1651
1652 num_wm = cam_vfe_bus_get_num_wm(vfe_out_res_id, format);
1653 if (num_wm < 1)
1654 return -EINVAL;
1655
1656 rsrc_node = &ver2_bus_priv->vfe_out[vfe_out_res_id];
1657 if (rsrc_node->res_state != CAM_ISP_RESOURCE_STATE_AVAILABLE) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07001658 CAM_ERR(CAM_ISP, "Resource not available: Res_id %d state:%d",
Harsh Shaha1af8822017-05-11 22:06:36 -07001659 vfe_out_res_id, rsrc_node->res_state);
1660 return -EBUSY;
1661 }
1662
1663 rsrc_data = rsrc_node->res_priv;
1664 rsrc_data->num_wm = num_wm;
1665 rsrc_node->res_id = out_acquire_args->out_port_info->res_type;
1666 rsrc_node->tasklet_info = acq_args->tasklet;
1667 rsrc_node->cdm_ops = out_acquire_args->cdm_ops;
1668 rsrc_data->cdm_util_ops = out_acquire_args->cdm_ops;
1669
1670 /* Reserve Composite Group */
1671 if (num_wm > 1 || (out_acquire_args->out_port_info->comp_grp_id >
1672 CAM_ISP_RES_COMP_GROUP_NONE &&
1673 out_acquire_args->out_port_info->comp_grp_id <
1674 CAM_ISP_RES_COMP_GROUP_ID_MAX)) {
1675 rc = cam_vfe_bus_acquire_comp_grp(ver2_bus_priv,
1676 out_acquire_args->out_port_info,
Harsh Shah19f55812017-06-26 18:58:49 -07001677 acq_args->tasklet,
1678 out_acquire_args->ctx,
Harsh Shaha1af8822017-05-11 22:06:36 -07001679 out_acquire_args->unique_id,
1680 out_acquire_args->is_dual,
1681 out_acquire_args->is_master,
1682 out_acquire_args->dual_slave_core,
1683 &rsrc_data->comp_grp);
Harsh Shah19f55812017-06-26 18:58:49 -07001684 if (rc) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07001685 CAM_ERR(CAM_ISP,
1686 "VFE%d Comp_Grp acquire fail for Out %d rc=%d",
Harsh Shah19f55812017-06-26 18:58:49 -07001687 rsrc_data->common_data->core_index,
1688 vfe_out_res_id, rc);
Harsh Shaha1af8822017-05-11 22:06:36 -07001689 return rc;
Harsh Shah19f55812017-06-26 18:58:49 -07001690 }
Harsh Shaha1af8822017-05-11 22:06:36 -07001691
1692 subscribe_irq = 0;
Harsh Shah19f55812017-06-26 18:58:49 -07001693 } else {
Harsh Shaha1af8822017-05-11 22:06:36 -07001694 subscribe_irq = 1;
Harsh Shah19f55812017-06-26 18:58:49 -07001695 }
Harsh Shaha1af8822017-05-11 22:06:36 -07001696
1697 /* Reserve WM */
1698 for (i = 0; i < num_wm; i++) {
1699 rc = cam_vfe_bus_acquire_wm(ver2_bus_priv,
1700 out_acquire_args->out_port_info,
Harsh Shah19f55812017-06-26 18:58:49 -07001701 acq_args->tasklet,
1702 out_acquire_args->ctx,
Harsh Shaha1af8822017-05-11 22:06:36 -07001703 vfe_out_res_id,
1704 i,
1705 out_acquire_args->split_id,
1706 subscribe_irq,
1707 &rsrc_data->wm_res[i],
1708 &client_done_mask);
Harsh Shah19f55812017-06-26 18:58:49 -07001709 if (rc) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07001710 CAM_ERR(CAM_ISP,
1711 "VFE%d WM acquire failed for Out %d rc=%d",
Harsh Shah19f55812017-06-26 18:58:49 -07001712 rsrc_data->common_data->core_index,
1713 vfe_out_res_id, rc);
Harsh Shaha1af8822017-05-11 22:06:36 -07001714 goto release_wm;
Harsh Shah19f55812017-06-26 18:58:49 -07001715 }
Harsh Shaha1af8822017-05-11 22:06:36 -07001716
1717 if (rsrc_data->comp_grp)
1718 cam_vfe_bus_add_wm_to_comp_grp(rsrc_data->comp_grp,
1719 client_done_mask);
1720 }
1721
1722 rsrc_node->res_state = CAM_ISP_RESOURCE_STATE_RESERVED;
1723 out_acquire_args->rsrc_node = rsrc_node;
1724
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07001725 CAM_DBG(CAM_ISP, "Acquire successful");
Harsh Shaha1af8822017-05-11 22:06:36 -07001726 return rc;
1727
1728release_wm:
1729 for (i--; i >= 0; i--)
1730 cam_vfe_bus_release_wm(ver2_bus_priv, rsrc_data->wm_res[i]);
1731
1732 cam_vfe_bus_release_comp_grp(ver2_bus_priv,
1733 rsrc_data->comp_grp);
1734
1735 return rc;
1736}
1737
Harsh Shah19f55812017-06-26 18:58:49 -07001738static int cam_vfe_bus_release_vfe_out(void *bus_priv, void *release_args,
1739 uint32_t args_size)
Harsh Shaha1af8822017-05-11 22:06:36 -07001740{
Jing Zhoue71fd4a2017-05-15 19:44:34 -07001741 uint32_t i;
Harsh Shah19f55812017-06-26 18:58:49 -07001742 struct cam_isp_resource_node *vfe_out = NULL;
1743 struct cam_vfe_bus_ver2_vfe_out_data *rsrc_data = NULL;
1744
1745 if (!bus_priv || !release_args) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07001746 CAM_ERR(CAM_ISP, "Invalid input bus_priv %pK release_args %pK",
Harsh Shah19f55812017-06-26 18:58:49 -07001747 bus_priv, release_args);
1748 return -EINVAL;
1749 }
1750
1751 vfe_out = release_args;
1752 rsrc_data = vfe_out->res_priv;
Jing Zhoue71fd4a2017-05-15 19:44:34 -07001753
Harsh Shaha1af8822017-05-11 22:06:36 -07001754 if (vfe_out->res_state != CAM_ISP_RESOURCE_STATE_RESERVED) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07001755 CAM_ERR(CAM_ISP, "Error! Invalid resource state:%d",
Harsh Shaha1af8822017-05-11 22:06:36 -07001756 vfe_out->res_state);
1757 }
1758
Jing Zhoue71fd4a2017-05-15 19:44:34 -07001759 for (i = 0; i < rsrc_data->num_wm; i++)
1760 cam_vfe_bus_release_wm(bus_priv, rsrc_data->wm_res[i]);
1761 rsrc_data->num_wm = 0;
1762
1763 if (rsrc_data->comp_grp)
1764 cam_vfe_bus_release_comp_grp(bus_priv, rsrc_data->comp_grp);
1765 rsrc_data->comp_grp = NULL;
1766
1767 vfe_out->tasklet_info = NULL;
1768 vfe_out->cdm_ops = NULL;
1769 rsrc_data->cdm_util_ops = NULL;
1770
Harsh Shaha1af8822017-05-11 22:06:36 -07001771 if (vfe_out->res_state == CAM_ISP_RESOURCE_STATE_RESERVED)
1772 vfe_out->res_state = CAM_ISP_RESOURCE_STATE_AVAILABLE;
1773
1774 return 0;
1775}
1776
Harsh Shah19f55812017-06-26 18:58:49 -07001777static int cam_vfe_bus_start_vfe_out(
1778 struct cam_isp_resource_node *vfe_out)
Harsh Shaha1af8822017-05-11 22:06:36 -07001779{
1780 int rc = 0, i;
Harsh Shah19f55812017-06-26 18:58:49 -07001781 struct cam_vfe_bus_ver2_vfe_out_data *rsrc_data = NULL;
1782 struct cam_vfe_bus_ver2_common_data *common_data = NULL;
1783
1784 if (!vfe_out) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07001785 CAM_ERR(CAM_ISP, "Invalid input");
Harsh Shah19f55812017-06-26 18:58:49 -07001786 return -EINVAL;
1787 }
1788
1789 rsrc_data = vfe_out->res_priv;
1790 common_data = rsrc_data->common_data;
Harsh Shaha1af8822017-05-11 22:06:36 -07001791
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07001792 CAM_DBG(CAM_ISP, "Start resource index %d", rsrc_data->out_type);
Harsh Shaha1af8822017-05-11 22:06:36 -07001793
1794 if (vfe_out->res_state != CAM_ISP_RESOURCE_STATE_RESERVED) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07001795 CAM_ERR(CAM_ISP, "Error! Invalid resource state:%d",
Harsh Shaha1af8822017-05-11 22:06:36 -07001796 vfe_out->res_state);
1797 return -EACCES;
1798 }
1799
1800 for (i = 0; i < rsrc_data->num_wm; i++)
1801 rc = cam_vfe_bus_start_wm(rsrc_data->wm_res[i]);
1802
1803 if (rsrc_data->comp_grp)
1804 rc = cam_vfe_bus_start_comp_grp(rsrc_data->comp_grp);
1805
Harsh Shaha1af8822017-05-11 22:06:36 -07001806 /* BUS_WR_INPUT_IF_ADDR_SYNC_CFG */
1807 cam_io_w_mb(0x0, rsrc_data->common_data->mem_base + 0x0000207C);
1808 /* BUS_WR_INPUT_IF_ADDR_SYNC_FRAME_HEADER */
1809 cam_io_w_mb(0x0, rsrc_data->common_data->mem_base + 0x00002080);
1810 /* BUS_WR_INPUT_IF_ADDR_SYNC_NO_SYNC */
1811 cam_io_w_mb(0xFFFFF, rsrc_data->common_data->mem_base + 0x00002084);
Harsh Shaha1af8822017-05-11 22:06:36 -07001812 /* BUS_WR_INPUT_IF_ADDR_SYNC_0 */
1813 cam_io_w_mb(0x0, rsrc_data->common_data->mem_base + 0x00002088);
1814 cam_io_w_mb(0x0, rsrc_data->common_data->mem_base + 0x0000208c);
1815 cam_io_w_mb(0x0, rsrc_data->common_data->mem_base + 0x00002090);
1816 cam_io_w_mb(0x0, rsrc_data->common_data->mem_base + 0x00002094);
1817 cam_io_w_mb(0x0, rsrc_data->common_data->mem_base + 0x00002098);
1818 cam_io_w_mb(0x0, rsrc_data->common_data->mem_base + 0x0000209c);
1819 cam_io_w_mb(0x0, rsrc_data->common_data->mem_base + 0x000020a0);
1820 cam_io_w_mb(0x0, rsrc_data->common_data->mem_base + 0x000020a4);
1821
Harsh Shah23557ae2017-05-13 18:14:34 -07001822 /* no clock gating at bus input */
1823 cam_io_w_mb(0xFFFFF, rsrc_data->common_data->mem_base + 0x0000200C);
1824
1825 /* BUS_WR_TEST_BUS_CTRL */
1826 cam_io_w_mb(0x0, rsrc_data->common_data->mem_base + 0x0000211C);
1827
Abhishek Kondaveeti157ae882017-07-08 06:56:48 +05301828 vfe_out->res_state = CAM_ISP_RESOURCE_STATE_STREAMING;
Harsh Shaha1af8822017-05-11 22:06:36 -07001829 return rc;
1830}
1831
Harsh Shah19f55812017-06-26 18:58:49 -07001832static int cam_vfe_bus_stop_vfe_out(
1833 struct cam_isp_resource_node *vfe_out)
Harsh Shaha1af8822017-05-11 22:06:36 -07001834{
1835 int rc = 0, i;
Harsh Shah19f55812017-06-26 18:58:49 -07001836 struct cam_vfe_bus_ver2_vfe_out_data *rsrc_data = NULL;
1837
1838 if (!vfe_out) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07001839 CAM_ERR(CAM_ISP, "Invalid input");
Harsh Shah19f55812017-06-26 18:58:49 -07001840 return -EINVAL;
1841 }
1842
1843 rsrc_data = vfe_out->res_priv;
Harsh Shaha1af8822017-05-11 22:06:36 -07001844
1845 if (vfe_out->res_state == CAM_ISP_RESOURCE_STATE_AVAILABLE ||
1846 vfe_out->res_state == CAM_ISP_RESOURCE_STATE_RESERVED) {
1847 return rc;
1848 }
1849
1850 if (rsrc_data->comp_grp)
1851 rc = cam_vfe_bus_stop_comp_grp(rsrc_data->comp_grp);
1852
1853 for (i = 0; i < rsrc_data->num_wm; i++)
1854 rc = cam_vfe_bus_stop_wm(rsrc_data->wm_res[i]);
1855
Harsh Shaha1af8822017-05-11 22:06:36 -07001856
1857 vfe_out->res_state = CAM_ISP_RESOURCE_STATE_RESERVED;
1858 return rc;
1859}
1860
1861static int cam_vfe_bus_handle_vfe_out_done_top_half(uint32_t evt_id,
1862 struct cam_irq_th_payload *th_payload)
1863{
1864 return -EPERM;
1865}
1866
1867static int cam_vfe_bus_handle_vfe_out_done_bottom_half(
1868 void *handler_priv,
1869 void *evt_payload_priv)
1870{
1871 int rc = -EINVAL;
1872 struct cam_isp_resource_node *vfe_out = handler_priv;
1873 struct cam_vfe_bus_ver2_vfe_out_data *rsrc_data = vfe_out->res_priv;
1874
1875 /*
1876 * If this resource has Composite Group then we only handle
1877 * Composite done. We acquire Composite if number of WM > 1.
1878 * So Else case is only one individual buf_done = WM[0].
1879 */
1880 if (rsrc_data->comp_grp) {
1881 rc = rsrc_data->comp_grp->bottom_half_handler(
1882 rsrc_data->comp_grp, evt_payload_priv);
1883 } else {
1884 rc = rsrc_data->wm_res[0]->bottom_half_handler(
Harsh Shah23557ae2017-05-13 18:14:34 -07001885 rsrc_data->wm_res[0], evt_payload_priv);
Harsh Shaha1af8822017-05-11 22:06:36 -07001886 }
1887
1888 return rc;
1889}
1890
1891static int cam_vfe_bus_init_vfe_out_resource(uint32_t index,
1892 struct cam_vfe_bus_ver2_priv *ver2_bus_priv,
1893 struct cam_vfe_bus_ver2_hw_info *ver2_hw_info,
1894 struct cam_isp_resource_node *vfe_out)
1895{
1896 struct cam_vfe_bus_ver2_vfe_out_data *rsrc_data = NULL;
1897 int rc = 0;
1898
1899 rsrc_data = kzalloc(sizeof(struct cam_vfe_bus_ver2_vfe_out_data),
1900 GFP_KERNEL);
1901 if (!rsrc_data) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07001902 CAM_DBG(CAM_ISP, "Error! Failed to alloc for vfe out priv");
Harsh Shaha1af8822017-05-11 22:06:36 -07001903 rc = -ENOMEM;
1904 return rc;
1905 }
1906 vfe_out->res_priv = rsrc_data;
1907
1908 vfe_out->res_type = CAM_ISP_RESOURCE_VFE_OUT;
1909 vfe_out->res_state = CAM_ISP_RESOURCE_STATE_AVAILABLE;
1910 INIT_LIST_HEAD(&vfe_out->list);
1911
1912 rsrc_data->out_type = index;
1913 rsrc_data->common_data = &ver2_bus_priv->common_data;
1914 rsrc_data->max_width =
1915 ver2_hw_info->vfe_out_hw_info[index].max_width;
1916 rsrc_data->max_height =
1917 ver2_hw_info->vfe_out_hw_info[index].max_height;
1918
1919 vfe_out->start = cam_vfe_bus_start_vfe_out;
1920 vfe_out->stop = cam_vfe_bus_stop_vfe_out;
1921 vfe_out->top_half_handler = cam_vfe_bus_handle_vfe_out_done_top_half;
1922 vfe_out->bottom_half_handler =
1923 cam_vfe_bus_handle_vfe_out_done_bottom_half;
1924 vfe_out->hw_intf = ver2_bus_priv->common_data.hw_intf;
1925
1926 return 0;
1927}
1928
Harsh Shah545df9a2017-06-16 16:43:17 -07001929static int cam_vfe_bus_deinit_vfe_out_resource(
1930 struct cam_isp_resource_node *vfe_out)
1931{
1932 struct cam_vfe_bus_ver2_vfe_out_data *rsrc_data = vfe_out->res_priv;
1933
1934 vfe_out->start = NULL;
1935 vfe_out->stop = NULL;
1936 vfe_out->top_half_handler = NULL;
1937 vfe_out->bottom_half_handler = NULL;
1938 vfe_out->hw_intf = NULL;
1939
1940 vfe_out->res_state = CAM_ISP_RESOURCE_STATE_UNAVAILABLE;
1941 INIT_LIST_HEAD(&vfe_out->list);
1942 vfe_out->res_priv = NULL;
1943
1944 if (!rsrc_data) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07001945 CAM_ERR(CAM_ISP, "Error! vfe out priv is NULL");
Harsh Shah545df9a2017-06-16 16:43:17 -07001946 return -ENOMEM;
1947 }
1948 kfree(rsrc_data);
1949
1950 return 0;
1951}
1952
Harsh Shaha1af8822017-05-11 22:06:36 -07001953static int cam_vfe_bus_ver2_handle_irq(uint32_t evt_id,
1954 struct cam_irq_th_payload *th_payload)
1955{
Harsh Shaha1af8822017-05-11 22:06:36 -07001956 struct cam_vfe_bus_ver2_priv *bus_priv;
Harsh Shaha1af8822017-05-11 22:06:36 -07001957
Harsh Shah19f55812017-06-26 18:58:49 -07001958 bus_priv = th_payload->handler_priv;
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07001959 CAM_DBG(CAM_ISP, "Enter");
Harsh Shah19f55812017-06-26 18:58:49 -07001960 return cam_irq_controller_handle_irq(evt_id,
1961 bus_priv->common_data.bus_irq_controller);
Harsh Shaha1af8822017-05-11 22:06:36 -07001962}
1963
1964static int cam_vfe_bus_update_buf(void *priv, void *cmd_args,
1965 uint32_t arg_size)
1966{
1967 struct cam_vfe_bus_ver2_priv *bus_priv;
1968 struct cam_isp_hw_get_buf_update *update_buf;
Jing Zhoua4e9fbe2017-05-15 14:37:21 -07001969 struct cam_buf_io_cfg *io_cfg;
Harsh Shaha1af8822017-05-11 22:06:36 -07001970 struct cam_vfe_bus_ver2_vfe_out_data *vfe_out_data = NULL;
1971 struct cam_vfe_bus_ver2_wm_resource_data *wm_data = NULL;
Jing Zhoua4e9fbe2017-05-15 14:37:21 -07001972 uint32_t *reg_val_pair;
1973 uint32_t i, j, size = 0;
Junzhe Zou193d78c2017-05-16 15:10:54 -07001974 uint32_t frame_inc = 0;
Harsh Shaha1af8822017-05-11 22:06:36 -07001975
1976 /*
1977 * Need the entire buf io config so we can get the stride info
1978 * for the wm.
1979 */
1980
1981 bus_priv = (struct cam_vfe_bus_ver2_priv *) priv;
1982 update_buf = (struct cam_isp_hw_get_buf_update *) cmd_args;
1983
1984 vfe_out_data = (struct cam_vfe_bus_ver2_vfe_out_data *)
1985 update_buf->cdm.res->res_priv;
1986
1987 if (!vfe_out_data || !vfe_out_data->cdm_util_ops) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07001988 CAM_ERR(CAM_ISP, "Failed! Invalid data");
Harsh Shaha1af8822017-05-11 22:06:36 -07001989 return -EINVAL;
1990 }
1991
Jing Zhoua4e9fbe2017-05-15 14:37:21 -07001992 if (update_buf->num_buf != vfe_out_data->num_wm) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07001993 CAM_ERR(CAM_ISP,
1994 "Failed! Invalid number buffers:%d required:%d",
Harsh Shaha1af8822017-05-11 22:06:36 -07001995 update_buf->num_buf, vfe_out_data->num_wm);
Junzhe Zou193d78c2017-05-16 15:10:54 -07001996 return -EINVAL;
Harsh Shaha1af8822017-05-11 22:06:36 -07001997 }
1998
Jing Zhoua4e9fbe2017-05-15 14:37:21 -07001999 reg_val_pair = &vfe_out_data->common_data->io_buf_update[0];
2000 io_cfg = update_buf->io_cfg;
2001
2002 for (i = 0, j = 0; i < vfe_out_data->num_wm; i++) {
Junzhe Zou193d78c2017-05-16 15:10:54 -07002003 if (j >= (MAX_REG_VAL_PAIR_SIZE - MAX_BUF_UPDATE_REG_NUM * 2)) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07002004 CAM_ERR(CAM_ISP,
2005 "reg_val_pair %d exceeds the array limit %lu",
Junzhe Zou193d78c2017-05-16 15:10:54 -07002006 j, MAX_REG_VAL_PAIR_SIZE);
2007 return -ENOMEM;
2008 }
2009
Jing Zhoua4e9fbe2017-05-15 14:37:21 -07002010 wm_data = vfe_out_data->wm_res[i]->res_priv;
2011
2012 /* For initial configuration program all bus registers */
Ravikishore Pampanaad6bc902017-07-12 19:37:06 +05302013 if ((wm_data->stride != io_cfg->planes[i].plane_stride ||
2014 !wm_data->init_cfg_done) && (wm_data->index >= 3)) {
Jing Zhoua4e9fbe2017-05-15 14:37:21 -07002015 CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j,
2016 wm_data->hw_regs->stride,
2017 io_cfg->planes[i].plane_stride);
2018 wm_data->stride = io_cfg->planes[i].plane_stride;
2019 }
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07002020 CAM_DBG(CAM_ISP, "image stride 0x%x", wm_data->stride);
Jing Zhoua4e9fbe2017-05-15 14:37:21 -07002021
2022 if (wm_data->framedrop_pattern != io_cfg->framedrop_pattern ||
Pavan Kumar Chilamkurthi649cdf92017-08-15 01:40:57 -07002023 !wm_data->hfr_cfg_done) {
Jing Zhoua4e9fbe2017-05-15 14:37:21 -07002024 CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j,
2025 wm_data->hw_regs->framedrop_pattern,
2026 io_cfg->framedrop_pattern);
2027 wm_data->framedrop_pattern = io_cfg->framedrop_pattern;
2028 }
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07002029 CAM_DBG(CAM_ISP, "framedrop pattern 0x%x",
2030 wm_data->framedrop_pattern);
Jing Zhoua4e9fbe2017-05-15 14:37:21 -07002031
2032 if (wm_data->framedrop_period != io_cfg->framedrop_period ||
Pavan Kumar Chilamkurthi649cdf92017-08-15 01:40:57 -07002033 !wm_data->hfr_cfg_done) {
Jing Zhoua4e9fbe2017-05-15 14:37:21 -07002034 CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j,
2035 wm_data->hw_regs->framedrop_period,
2036 io_cfg->framedrop_period);
2037 wm_data->framedrop_period = io_cfg->framedrop_period;
2038 }
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07002039 CAM_DBG(CAM_ISP, "framedrop period 0x%x",
2040 wm_data->framedrop_period);
Jing Zhoua4e9fbe2017-05-15 14:37:21 -07002041
2042 if (wm_data->irq_subsample_period != io_cfg->subsample_period
Pavan Kumar Chilamkurthi649cdf92017-08-15 01:40:57 -07002043 || !wm_data->hfr_cfg_done) {
Jing Zhoua4e9fbe2017-05-15 14:37:21 -07002044 CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j,
2045 wm_data->hw_regs->irq_subsample_period,
2046 io_cfg->subsample_period);
2047 wm_data->irq_subsample_period =
2048 io_cfg->subsample_period;
2049 }
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07002050 CAM_DBG(CAM_ISP, "irq subsample period 0x%x",
Jing Zhoua4e9fbe2017-05-15 14:37:21 -07002051 wm_data->irq_subsample_period);
2052
2053 if (wm_data->irq_subsample_pattern != io_cfg->subsample_pattern
Pavan Kumar Chilamkurthi649cdf92017-08-15 01:40:57 -07002054 || !wm_data->hfr_cfg_done) {
Jing Zhoua4e9fbe2017-05-15 14:37:21 -07002055 CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j,
2056 wm_data->hw_regs->irq_subsample_pattern,
2057 io_cfg->subsample_pattern);
2058 wm_data->irq_subsample_pattern =
2059 io_cfg->subsample_pattern;
2060 }
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07002061 CAM_DBG(CAM_ISP, "irq subsample pattern 0x%x",
Jing Zhoua4e9fbe2017-05-15 14:37:21 -07002062 wm_data->irq_subsample_pattern);
2063
2064 if (wm_data->en_ubwc) {
2065 if (!wm_data->hw_regs->ubwc_regs) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07002066 CAM_ERR(CAM_ISP,
2067 "No UBWC register to configure.");
Jing Zhoua4e9fbe2017-05-15 14:37:21 -07002068 return -EINVAL;
2069 }
2070 if (wm_data->packer_cfg !=
2071 io_cfg->planes[i].packer_config ||
2072 !wm_data->init_cfg_done) {
2073 CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j,
2074 wm_data->hw_regs->packer_cfg,
2075 io_cfg->planes[i].packer_config);
2076 wm_data->packer_cfg =
2077 io_cfg->planes[i].packer_config;
2078 }
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07002079 CAM_DBG(CAM_ISP, "packer cfg 0x%x",
2080 wm_data->packer_cfg);
Jing Zhoua4e9fbe2017-05-15 14:37:21 -07002081
2082 if (wm_data->tile_cfg != io_cfg->planes[i].tile_config
2083 || !wm_data->init_cfg_done) {
2084 CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j,
2085 wm_data->hw_regs->ubwc_regs->tile_cfg,
2086 io_cfg->planes[i].tile_config);
2087 wm_data->tile_cfg =
2088 io_cfg->planes[i].tile_config;
2089 }
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07002090 CAM_DBG(CAM_ISP, "tile cfg 0x%x", wm_data->tile_cfg);
Jing Zhoua4e9fbe2017-05-15 14:37:21 -07002091
2092 if (wm_data->h_init != io_cfg->planes[i].h_init ||
2093 !wm_data->init_cfg_done) {
2094 CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j,
2095 wm_data->hw_regs->ubwc_regs->h_init,
2096 io_cfg->planes[i].h_init);
2097 wm_data->h_init = io_cfg->planes[i].h_init;
2098 }
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07002099 CAM_DBG(CAM_ISP, "h_init 0x%x", wm_data->h_init);
Jing Zhoua4e9fbe2017-05-15 14:37:21 -07002100
2101 if (wm_data->v_init != io_cfg->planes[i].v_init ||
2102 !wm_data->init_cfg_done) {
2103 CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j,
2104 wm_data->hw_regs->ubwc_regs->v_init,
2105 io_cfg->planes[i].v_init);
2106 wm_data->v_init = io_cfg->planes[i].v_init;
2107 }
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07002108 CAM_DBG(CAM_ISP, "v_init 0x%x", wm_data->v_init);
Jing Zhoua4e9fbe2017-05-15 14:37:21 -07002109
2110 if (wm_data->ubwc_meta_stride !=
2111 io_cfg->planes[i].meta_stride ||
2112 !wm_data->init_cfg_done) {
2113 CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j,
2114 wm_data->hw_regs->ubwc_regs->
2115 meta_stride,
2116 io_cfg->planes[i].meta_stride);
2117 wm_data->ubwc_meta_stride =
2118 io_cfg->planes[i].meta_stride;
2119 }
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07002120 CAM_DBG(CAM_ISP, "meta stride 0x%x",
2121 wm_data->ubwc_meta_stride);
Jing Zhoua4e9fbe2017-05-15 14:37:21 -07002122
2123 if (wm_data->ubwc_mode_cfg !=
2124 io_cfg->planes[i].mode_config ||
2125 !wm_data->init_cfg_done) {
2126 CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j,
2127 wm_data->hw_regs->ubwc_regs->mode_cfg,
2128 io_cfg->planes[i].mode_config);
2129 wm_data->ubwc_mode_cfg =
2130 io_cfg->planes[i].mode_config;
2131 }
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07002132 CAM_DBG(CAM_ISP, "ubwc mode cfg 0x%x",
2133 wm_data->ubwc_mode_cfg);
Jing Zhoua4e9fbe2017-05-15 14:37:21 -07002134
2135 if (wm_data->ubwc_meta_offset !=
2136 io_cfg->planes[i].meta_offset ||
2137 !wm_data->init_cfg_done) {
2138 CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j,
2139 wm_data->hw_regs->ubwc_regs->
2140 meta_offset,
2141 io_cfg->planes[i].meta_offset);
2142 wm_data->ubwc_meta_offset =
2143 io_cfg->planes[i].meta_offset;
2144 }
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07002145 CAM_DBG(CAM_ISP, "ubwc meta offset 0x%x",
Jing Zhoua4e9fbe2017-05-15 14:37:21 -07002146 wm_data->ubwc_meta_offset);
2147
2148 /* UBWC meta address */
2149 CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j,
2150 wm_data->hw_regs->ubwc_regs->meta_addr,
2151 update_buf->image_buf[i]);
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07002152 CAM_DBG(CAM_ISP, "ubwc meta addr 0x%llx",
Jing Zhoua4e9fbe2017-05-15 14:37:21 -07002153 update_buf->image_buf[i]);
2154 }
2155
2156 /* WM Image address */
2157 if (wm_data->en_ubwc)
2158 CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j,
2159 wm_data->hw_regs->image_addr,
2160 (update_buf->image_buf[i] +
2161 io_cfg->planes[i].meta_size));
2162 else
2163 CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j,
2164 wm_data->hw_regs->image_addr,
2165 update_buf->image_buf[i]);
2166
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07002167 CAM_DBG(CAM_ISP, "image address 0x%x", reg_val_pair[j-1]);
Jing Zhoua4e9fbe2017-05-15 14:37:21 -07002168
Junzhe Zou193d78c2017-05-16 15:10:54 -07002169 frame_inc = io_cfg->planes[i].plane_stride *
2170 io_cfg->planes[i].slice_height;
2171 CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j,
2172 wm_data->hw_regs->frame_inc, frame_inc);
2173
Jing Zhoua4e9fbe2017-05-15 14:37:21 -07002174 /* enable the WM */
2175 CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j,
2176 wm_data->hw_regs->cfg,
2177 wm_data->en_cfg);
2178
2179 /* set initial configuration done */
2180 if (!wm_data->init_cfg_done)
Pavan Kumar Chilamkurthi649cdf92017-08-15 01:40:57 -07002181 wm_data->init_cfg_done = true;
Jing Zhoua4e9fbe2017-05-15 14:37:21 -07002182 }
2183
2184 size = vfe_out_data->cdm_util_ops->cdm_required_size_reg_random(j/2);
Harsh Shaha1af8822017-05-11 22:06:36 -07002185
2186 /* cdm util returns dwords, need to convert to bytes */
2187 if ((size * 4) > update_buf->cdm.size) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07002188 CAM_ERR(CAM_ISP,
2189 "Failed! Buf size:%d insufficient, expected size:%d",
Harsh Shaha1af8822017-05-11 22:06:36 -07002190 update_buf->cdm.size, size);
2191 return -ENOMEM;
2192 }
2193
Harsh Shaha1af8822017-05-11 22:06:36 -07002194 vfe_out_data->cdm_util_ops->cdm_write_regrandom(
Jing Zhoua4e9fbe2017-05-15 14:37:21 -07002195 update_buf->cdm.cmd_buf_addr, j/2, reg_val_pair);
2196
Harsh Shaha1af8822017-05-11 22:06:36 -07002197 /* cdm util returns dwords, need to convert to bytes */
2198 update_buf->cdm.used_bytes = size * 4;
2199
2200 return 0;
2201}
2202
Pavan Kumar Chilamkurthi649cdf92017-08-15 01:40:57 -07002203static int cam_vfe_bus_update_hfr(void *priv, void *cmd_args,
2204 uint32_t arg_size)
2205{
2206 struct cam_vfe_bus_ver2_priv *bus_priv;
2207 struct cam_isp_hw_get_hfr_update *update_hfr;
2208 struct cam_vfe_bus_ver2_vfe_out_data *vfe_out_data = NULL;
2209 struct cam_vfe_bus_ver2_wm_resource_data *wm_data = NULL;
2210 struct cam_isp_port_hfr_config *hfr_cfg = NULL;
2211 uint32_t *reg_val_pair;
2212 uint32_t i, j, size = 0;
2213
2214 bus_priv = (struct cam_vfe_bus_ver2_priv *) priv;
2215 update_hfr = (struct cam_isp_hw_get_hfr_update *) cmd_args;
2216
2217 vfe_out_data = (struct cam_vfe_bus_ver2_vfe_out_data *)
2218 update_hfr->cdm.res->res_priv;
2219
2220 if (!vfe_out_data || !vfe_out_data->cdm_util_ops) {
2221 CAM_ERR(CAM_ISP, "Failed! Invalid data");
2222 return -EINVAL;
2223 }
2224
2225 reg_val_pair = &vfe_out_data->common_data->io_buf_update[0];
2226 hfr_cfg = update_hfr->io_hfr_cfg;
2227
2228 for (i = 0, j = 0; i < vfe_out_data->num_wm; i++) {
2229 if (j >= (MAX_REG_VAL_PAIR_SIZE - MAX_BUF_UPDATE_REG_NUM * 2)) {
2230 CAM_ERR(CAM_ISP,
2231 "reg_val_pair %d exceeds the array limit %lu",
2232 j, MAX_REG_VAL_PAIR_SIZE);
2233 return -ENOMEM;
2234 }
2235
2236 wm_data = vfe_out_data->wm_res[i]->res_priv;
2237
2238 if ((wm_data->framedrop_pattern !=
2239 hfr_cfg->framedrop_pattern) ||
2240 !wm_data->hfr_cfg_done) {
2241 CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j,
2242 wm_data->hw_regs->framedrop_pattern,
2243 hfr_cfg->framedrop_pattern);
2244 wm_data->framedrop_pattern = hfr_cfg->framedrop_pattern;
2245 }
2246 CAM_DBG(CAM_ISP, "framedrop pattern 0x%x",
2247 wm_data->framedrop_pattern);
2248
2249 if (wm_data->framedrop_period != hfr_cfg->framedrop_period ||
2250 !wm_data->hfr_cfg_done) {
2251 CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j,
2252 wm_data->hw_regs->framedrop_period,
2253 hfr_cfg->framedrop_period);
2254 wm_data->framedrop_period = hfr_cfg->framedrop_period;
2255 }
2256 CAM_DBG(CAM_ISP, "framedrop period 0x%x",
2257 wm_data->framedrop_period);
2258
2259 if (wm_data->irq_subsample_period != hfr_cfg->subsample_period
2260 || !wm_data->hfr_cfg_done) {
2261 CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j,
2262 wm_data->hw_regs->irq_subsample_period,
2263 hfr_cfg->subsample_period);
2264 wm_data->irq_subsample_period =
2265 hfr_cfg->subsample_period;
2266 }
2267 CAM_DBG(CAM_ISP, "irq subsample period 0x%x",
2268 wm_data->irq_subsample_period);
2269
2270 if (wm_data->irq_subsample_pattern != hfr_cfg->subsample_pattern
2271 || !wm_data->hfr_cfg_done) {
2272 CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j,
2273 wm_data->hw_regs->irq_subsample_pattern,
2274 hfr_cfg->subsample_pattern);
2275 wm_data->irq_subsample_pattern =
2276 hfr_cfg->subsample_pattern;
2277 }
2278 CAM_DBG(CAM_ISP, "irq subsample pattern 0x%x",
2279 wm_data->irq_subsample_pattern);
2280
2281 /* set initial configuration done */
2282 if (!wm_data->hfr_cfg_done)
2283 wm_data->hfr_cfg_done = true;
2284 }
2285
2286 size = vfe_out_data->cdm_util_ops->cdm_required_size_reg_random(j/2);
2287
2288 /* cdm util returns dwords, need to convert to bytes */
2289 if ((size * 4) > update_hfr->cdm.size) {
2290 CAM_ERR(CAM_ISP,
2291 "Failed! Buf size:%d insufficient, expected size:%d",
2292 update_hfr->cdm.size, size);
2293 return -ENOMEM;
2294 }
2295
2296 vfe_out_data->cdm_util_ops->cdm_write_regrandom(
2297 update_hfr->cdm.cmd_buf_addr, j/2, reg_val_pair);
2298
2299 /* cdm util returns dwords, need to convert to bytes */
2300 update_hfr->cdm.used_bytes = size * 4;
2301
2302 return 0;
2303}
2304
Harsh Shah19f55812017-06-26 18:58:49 -07002305static int cam_vfe_bus_start_hw(void *hw_priv,
2306 void *start_hw_args, uint32_t arg_size)
2307{
2308 return cam_vfe_bus_start_vfe_out(hw_priv);
2309}
2310
2311static int cam_vfe_bus_stop_hw(void *hw_priv,
2312 void *stop_hw_args, uint32_t arg_size)
2313{
2314 return cam_vfe_bus_stop_vfe_out(hw_priv);
2315}
2316
2317static int cam_vfe_bus_init_hw(void *hw_priv,
2318 void *init_hw_args, uint32_t arg_size)
2319{
2320 struct cam_vfe_bus_ver2_priv *bus_priv = hw_priv;
2321 uint32_t top_irq_reg_mask[2] = {0};
2322
2323 if (!bus_priv) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07002324 CAM_ERR(CAM_ISP, "Error! Invalid args");
Harsh Shah19f55812017-06-26 18:58:49 -07002325 return -EINVAL;
2326 }
2327
2328 top_irq_reg_mask[0] = (1 << 9);
2329
2330 bus_priv->irq_handle = cam_irq_controller_subscribe_irq(
2331 bus_priv->common_data.vfe_irq_controller,
2332 CAM_IRQ_PRIORITY_2,
2333 top_irq_reg_mask,
2334 bus_priv,
2335 cam_vfe_bus_ver2_handle_irq,
2336 NULL,
2337 NULL,
2338 NULL);
2339
2340 if (bus_priv->irq_handle <= 0) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07002341 CAM_ERR(CAM_ISP, "Failed to subscribe BUS IRQ");
Harsh Shah19f55812017-06-26 18:58:49 -07002342 return -EFAULT;
2343 }
2344
2345 return 0;
2346}
2347
2348static int cam_vfe_bus_deinit_hw(void *hw_priv,
2349 void *deinit_hw_args, uint32_t arg_size)
2350{
2351 struct cam_vfe_bus_ver2_priv *bus_priv = hw_priv;
2352 int rc;
2353
2354 if (!bus_priv || (bus_priv->irq_handle <= 0)) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07002355 CAM_ERR(CAM_ISP, "Error! Invalid args");
Harsh Shah19f55812017-06-26 18:58:49 -07002356 return -EINVAL;
2357 }
2358
2359 rc = cam_irq_controller_unsubscribe_irq(
2360 bus_priv->common_data.vfe_irq_controller,
2361 bus_priv->irq_handle);
2362 if (rc)
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07002363 CAM_ERR(CAM_ISP, "Failed to unsubscribe irq rc=%d", rc);
Harsh Shah19f55812017-06-26 18:58:49 -07002364
2365 return rc;
2366}
2367
Harsh Shaha1af8822017-05-11 22:06:36 -07002368static int cam_vfe_bus_process_cmd(void *priv,
2369 uint32_t cmd_type, void *cmd_args, uint32_t arg_size)
2370{
2371 int rc = -EINVAL;
2372
2373 if (!priv || !cmd_args) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07002374 CAM_ERR_RATE_LIMIT(CAM_ISP, "Error! Invalid input arguments\n");
Harsh Shaha1af8822017-05-11 22:06:36 -07002375 return -EINVAL;
2376 }
2377
2378 switch (cmd_type) {
2379 case CAM_VFE_HW_CMD_GET_BUF_UPDATE:
2380 rc = cam_vfe_bus_update_buf(priv, cmd_args, arg_size);
2381 break;
Pavan Kumar Chilamkurthi649cdf92017-08-15 01:40:57 -07002382 case CAM_VFE_HW_CMD_GET_HFR_UPDATE:
2383 rc = cam_vfe_bus_update_hfr(priv, cmd_args, arg_size);
2384 break;
Harsh Shaha1af8822017-05-11 22:06:36 -07002385 default:
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07002386 CAM_ERR_RATE_LIMIT(CAM_ISP, "Inval camif process command:%d\n",
Harsh Shaha1af8822017-05-11 22:06:36 -07002387 cmd_type);
2388 break;
2389 }
2390
2391 return rc;
2392}
2393
2394int cam_vfe_bus_ver2_init(
Harsh Shah19f55812017-06-26 18:58:49 -07002395 struct cam_hw_soc_info *soc_info,
Harsh Shaha1af8822017-05-11 22:06:36 -07002396 struct cam_hw_intf *hw_intf,
2397 void *bus_hw_info,
2398 void *vfe_irq_controller,
2399 struct cam_vfe_bus **vfe_bus)
2400{
2401 int i, rc = 0;
2402 struct cam_vfe_bus_ver2_priv *bus_priv = NULL;
2403 struct cam_vfe_bus *vfe_bus_local;
2404 struct cam_vfe_bus_ver2_hw_info *ver2_hw_info = bus_hw_info;
2405
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07002406 CAM_DBG(CAM_ISP, "Enter");
Harsh Shaha1af8822017-05-11 22:06:36 -07002407
Harsh Shah19f55812017-06-26 18:58:49 -07002408 if (!soc_info || !hw_intf || !bus_hw_info || !vfe_irq_controller) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07002409 CAM_ERR(CAM_ISP,
2410 "Inval_prms soc_info:%pK hw_intf:%pK hw_info%pK",
2411 soc_info, hw_intf, bus_hw_info);
2412 CAM_ERR(CAM_ISP, "controller: %pK", vfe_irq_controller);
Harsh Shah19f55812017-06-26 18:58:49 -07002413 rc = -EINVAL;
2414 goto end;
2415 }
2416
Harsh Shaha1af8822017-05-11 22:06:36 -07002417 vfe_bus_local = kzalloc(sizeof(struct cam_vfe_bus), GFP_KERNEL);
2418 if (!vfe_bus_local) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07002419 CAM_DBG(CAM_ISP, "Failed to alloc for vfe_bus");
Harsh Shaha1af8822017-05-11 22:06:36 -07002420 rc = -ENOMEM;
Harsh Shah545df9a2017-06-16 16:43:17 -07002421 goto end;
Harsh Shaha1af8822017-05-11 22:06:36 -07002422 }
2423
2424 bus_priv = kzalloc(sizeof(struct cam_vfe_bus_ver2_priv),
2425 GFP_KERNEL);
2426 if (!bus_priv) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07002427 CAM_DBG(CAM_ISP, "Failed to alloc for vfe_bus_priv");
Harsh Shaha1af8822017-05-11 22:06:36 -07002428 rc = -ENOMEM;
Harsh Shah545df9a2017-06-16 16:43:17 -07002429 goto free_bus_local;
Harsh Shaha1af8822017-05-11 22:06:36 -07002430 }
2431 vfe_bus_local->bus_priv = bus_priv;
2432
Harsh Shah19f55812017-06-26 18:58:49 -07002433 bus_priv->common_data.core_index = soc_info->index;
2434 bus_priv->common_data.mem_base =
2435 CAM_SOC_GET_REG_MAP_START(soc_info, VFE_CORE_BASE_IDX);
Harsh Shaha1af8822017-05-11 22:06:36 -07002436 bus_priv->common_data.hw_intf = hw_intf;
2437 bus_priv->common_data.vfe_irq_controller = vfe_irq_controller;
2438 bus_priv->common_data.common_reg = &ver2_hw_info->common_reg;
2439
Harsh Shah19f55812017-06-26 18:58:49 -07002440 rc = cam_irq_controller_init(drv_name, bus_priv->common_data.mem_base,
2441 &ver2_hw_info->common_reg.irq_reg_info,
2442 &bus_priv->common_data.bus_irq_controller);
2443 if (rc) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07002444 CAM_ERR(CAM_ISP, "Error! cam_irq_controller_init failed");
Harsh Shah19f55812017-06-26 18:58:49 -07002445 goto free_bus_priv;
2446 }
2447
Harsh Shaha1af8822017-05-11 22:06:36 -07002448 INIT_LIST_HEAD(&bus_priv->free_comp_grp);
2449 INIT_LIST_HEAD(&bus_priv->free_dual_comp_grp);
2450 INIT_LIST_HEAD(&bus_priv->used_comp_grp);
2451
2452 for (i = 0; i < CAM_VFE_BUS_VER2_MAX_CLIENTS; i++) {
2453 rc = cam_vfe_bus_init_wm_resource(i, bus_priv, bus_hw_info,
2454 &bus_priv->bus_client[i]);
2455 if (rc < 0) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07002456 CAM_ERR(CAM_ISP, "Error! Init WM failed rc=%d", rc);
Harsh Shah545df9a2017-06-16 16:43:17 -07002457 goto deinit_wm;
Harsh Shaha1af8822017-05-11 22:06:36 -07002458 }
2459 }
2460
2461 for (i = 0; i < CAM_VFE_BUS_VER2_COMP_GRP_MAX; i++) {
2462 rc = cam_vfe_bus_init_comp_grp(i, bus_priv, bus_hw_info,
2463 &bus_priv->comp_grp[i]);
2464 if (rc < 0) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07002465 CAM_ERR(CAM_ISP, "Init Comp Grp failed rc=%d", rc);
Harsh Shah545df9a2017-06-16 16:43:17 -07002466 goto deinit_comp_grp;
Harsh Shaha1af8822017-05-11 22:06:36 -07002467 }
2468 }
2469
2470 for (i = 0; i < CAM_VFE_BUS_VER2_VFE_OUT_MAX; i++) {
2471 rc = cam_vfe_bus_init_vfe_out_resource(i, bus_priv, bus_hw_info,
2472 &bus_priv->vfe_out[i]);
2473 if (rc < 0) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07002474 CAM_ERR(CAM_ISP, "Init VFE Out failed rc=%d", rc);
Harsh Shah545df9a2017-06-16 16:43:17 -07002475 goto deinit_vfe_out;
Harsh Shaha1af8822017-05-11 22:06:36 -07002476 }
2477 }
2478
Harsh Shah19f55812017-06-26 18:58:49 -07002479 INIT_LIST_HEAD(&bus_priv->common_data.free_payload_list);
2480 for (i = 0; i < CAM_VFE_BUS_VER2_PAYLOAD_MAX; i++) {
2481 INIT_LIST_HEAD(&bus_priv->common_data.evt_payload[i].list);
2482 list_add_tail(&bus_priv->common_data.evt_payload[i].list,
2483 &bus_priv->common_data.free_payload_list);
Harsh Shaha1af8822017-05-11 22:06:36 -07002484 }
2485
Harsh Shah19f55812017-06-26 18:58:49 -07002486 vfe_bus_local->hw_ops.reserve = cam_vfe_bus_acquire_vfe_out;
2487 vfe_bus_local->hw_ops.release = cam_vfe_bus_release_vfe_out;
2488 vfe_bus_local->hw_ops.start = cam_vfe_bus_start_hw;
2489 vfe_bus_local->hw_ops.stop = cam_vfe_bus_stop_hw;
2490 vfe_bus_local->hw_ops.init = cam_vfe_bus_init_hw;
2491 vfe_bus_local->hw_ops.deinit = cam_vfe_bus_deinit_hw;
2492 vfe_bus_local->top_half_handler = cam_vfe_bus_ver2_handle_irq;
Harsh Shaha1af8822017-05-11 22:06:36 -07002493 vfe_bus_local->bottom_half_handler = NULL;
Harsh Shah19f55812017-06-26 18:58:49 -07002494 vfe_bus_local->hw_ops.process_cmd = cam_vfe_bus_process_cmd;
Harsh Shaha1af8822017-05-11 22:06:36 -07002495
2496 *vfe_bus = vfe_bus_local;
2497
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07002498 CAM_DBG(CAM_ISP, "Exit");
Harsh Shaha1af8822017-05-11 22:06:36 -07002499 return rc;
2500
Harsh Shah545df9a2017-06-16 16:43:17 -07002501deinit_vfe_out:
2502 if (i < 0)
2503 i = CAM_VFE_BUS_VER2_VFE_OUT_MAX;
2504 for (--i; i >= 0; i--)
2505 cam_vfe_bus_deinit_vfe_out_resource(&bus_priv->vfe_out[i]);
2506
2507deinit_comp_grp:
2508 if (i < 0)
2509 i = CAM_VFE_BUS_VER2_COMP_GRP_MAX;
2510 for (--i; i >= 0; i--)
2511 cam_vfe_bus_deinit_comp_grp(&bus_priv->comp_grp[i]);
2512
2513deinit_wm:
2514 if (i < 0)
2515 i = CAM_VFE_BUS_VER2_MAX_CLIENTS;
2516 for (--i; i >= 0; i--)
2517 cam_vfe_bus_deinit_wm_resource(&bus_priv->bus_client[i]);
2518
Harsh Shah19f55812017-06-26 18:58:49 -07002519free_bus_priv:
Harsh Shaha1af8822017-05-11 22:06:36 -07002520 kfree(vfe_bus_local->bus_priv);
Harsh Shah545df9a2017-06-16 16:43:17 -07002521
2522free_bus_local:
Harsh Shaha1af8822017-05-11 22:06:36 -07002523 kfree(vfe_bus_local);
Harsh Shah545df9a2017-06-16 16:43:17 -07002524
2525end:
Harsh Shaha1af8822017-05-11 22:06:36 -07002526 return rc;
2527}
Harsh Shah545df9a2017-06-16 16:43:17 -07002528
2529int cam_vfe_bus_ver2_deinit(
2530 struct cam_vfe_bus **vfe_bus)
2531{
2532 int i, rc = 0;
2533 struct cam_vfe_bus_ver2_priv *bus_priv = NULL;
2534 struct cam_vfe_bus *vfe_bus_local;
2535
2536 if (!vfe_bus || !*vfe_bus) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07002537 CAM_ERR(CAM_ISP, "Error! Invalid input");
Harsh Shah545df9a2017-06-16 16:43:17 -07002538 return -EINVAL;
2539 }
2540 vfe_bus_local = *vfe_bus;
2541
2542 bus_priv = vfe_bus_local->bus_priv;
2543 if (!bus_priv) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07002544 CAM_ERR(CAM_ISP, "Error! bus_priv is NULL");
Harsh Shah545df9a2017-06-16 16:43:17 -07002545 rc = -ENODEV;
2546 goto free_bus_local;
2547 }
2548
Harsh Shah19f55812017-06-26 18:58:49 -07002549 INIT_LIST_HEAD(&bus_priv->common_data.free_payload_list);
2550 for (i = 0; i < CAM_VFE_BUS_VER2_PAYLOAD_MAX; i++)
2551 INIT_LIST_HEAD(&bus_priv->common_data.evt_payload[i].list);
Harsh Shah545df9a2017-06-16 16:43:17 -07002552
2553 for (i = 0; i < CAM_VFE_BUS_VER2_MAX_CLIENTS; i++) {
2554 rc = cam_vfe_bus_deinit_wm_resource(&bus_priv->bus_client[i]);
2555 if (rc < 0)
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07002556 CAM_ERR(CAM_ISP,
2557 "Error! Deinit WM failed rc=%d", rc);
Harsh Shah545df9a2017-06-16 16:43:17 -07002558 }
2559
2560 for (i = 0; i < CAM_VFE_BUS_VER2_COMP_GRP_MAX; i++) {
2561 rc = cam_vfe_bus_deinit_comp_grp(&bus_priv->comp_grp[i]);
2562 if (rc < 0)
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07002563 CAM_ERR(CAM_ISP,
2564 "Error! Deinit Comp Grp failed rc=%d", rc);
Harsh Shah545df9a2017-06-16 16:43:17 -07002565 }
2566
2567 for (i = 0; i < CAM_VFE_BUS_VER2_VFE_OUT_MAX; i++) {
2568 rc = cam_vfe_bus_deinit_vfe_out_resource(&bus_priv->vfe_out[i]);
2569 if (rc < 0)
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07002570 CAM_ERR(CAM_ISP,
2571 "Error! Deinit VFE Out failed rc=%d", rc);
Harsh Shah545df9a2017-06-16 16:43:17 -07002572 }
2573
2574 INIT_LIST_HEAD(&bus_priv->free_comp_grp);
2575 INIT_LIST_HEAD(&bus_priv->free_dual_comp_grp);
2576 INIT_LIST_HEAD(&bus_priv->used_comp_grp);
2577
Harsh Shah19f55812017-06-26 18:58:49 -07002578 rc = cam_irq_controller_deinit(
2579 &bus_priv->common_data.bus_irq_controller);
2580 if (rc)
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07002581 CAM_ERR(CAM_ISP,
2582 "Error! Deinit IRQ Controller failed rc=%d", rc);
Harsh Shah19f55812017-06-26 18:58:49 -07002583
Harsh Shah545df9a2017-06-16 16:43:17 -07002584 kfree(vfe_bus_local->bus_priv);
2585
2586free_bus_local:
2587 kfree(vfe_bus_local);
2588
2589 *vfe_bus = NULL;
2590
2591 return rc;
2592}
2593