blob: c041eefd5ae204db7e5958e0debd1dec1faa7047 [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"
16#include "cam_cdm_util.h"
17#include "cam_hw_intf.h"
Harsh Shah19f55812017-06-26 18:58:49 -070018#include "cam_ife_hw_mgr.h"
Harsh Shaha1af8822017-05-11 22:06:36 -070019#include "cam_vfe_hw_intf.h"
20#include "cam_irq_controller.h"
Harsh Shah19f55812017-06-26 18:58:49 -070021#include "cam_tasklet_util.h"
Harsh Shaha1af8822017-05-11 22:06:36 -070022#include "cam_vfe_bus.h"
23#include "cam_vfe_bus_ver2.h"
24#include "cam_vfe_core.h"
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -070025#include "cam_debug_util.h"
Harsh Shaha1af8822017-05-11 22:06:36 -070026
Harsh Shah19f55812017-06-26 18:58:49 -070027static const char drv_name[] = "vfe_bus";
28
29#define CAM_VFE_BUS_IRQ_REG0 0
30#define CAM_VFE_BUS_IRQ_REG1 1
31#define CAM_VFE_BUS_IRQ_REG2 2
32#define CAM_VFE_BUS_IRQ_MAX 3
33
34#define CAM_VFE_BUS_VER2_PAYLOAD_MAX 256
Harsh Shah23557ae2017-05-13 18:14:34 -070035
Ravikishore Pampanaad6bc902017-07-12 19:37:06 +053036#define CAM_VFE_RDI_BUS_DEFAULT_WIDTH 0xFF01
37#define CAM_VFE_RDI_BUS_DEFAULT_STRIDE 0xFF01
38
Krishnankutty Kolathappilly06406e52017-08-17 00:50:21 -070039#define ALIGNUP(value, alignment) \
40 ((value + alignment - 1) / alignment * alignment)
41
Junzhe Zou193d78c2017-05-16 15:10:54 -070042#define MAX_BUF_UPDATE_REG_NUM \
43 (sizeof(struct cam_vfe_bus_ver2_reg_offset_bus_client)/4)
Jing Zhoua4e9fbe2017-05-15 14:37:21 -070044#define MAX_REG_VAL_PAIR_SIZE \
Harsh Shah19f55812017-06-26 18:58:49 -070045 (MAX_BUF_UPDATE_REG_NUM * 2 * CAM_PACKET_MAX_PLANES)
Jing Zhoua4e9fbe2017-05-15 14:37:21 -070046
47#define CAM_VFE_ADD_REG_VAL_PAIR(buf_array, index, offset, val) \
Harsh Shah19f55812017-06-26 18:58:49 -070048 do { \
49 buf_array[index++] = offset; \
50 buf_array[index++] = val; \
51 } while (0)
Harsh Shaha1af8822017-05-11 22:06:36 -070052
53enum cam_vfe_bus_packer_format {
54 PACKER_FMT_PLAIN_128 = 0x0,
55 PACKER_FMT_PLAIN_8 = 0x1,
56 PACKER_FMT_PLAIN_16_10BPP = 0x2,
57 PACKER_FMT_PLAIN_16_12BPP = 0x3,
58 PACKER_FMT_PLAIN_16_14BPP = 0x4,
59 PACKER_FMT_PLAIN_16_16BPP = 0x5,
60 PACKER_FMT_ARGB_10 = 0x6,
61 PACKER_FMT_ARGB_12 = 0x7,
62 PACKER_FMT_ARGB_14 = 0x8,
63 PACKER_FMT_PLAIN_32_20BPP = 0x9,
64 PACKER_FMT_PLAIN_64 = 0xA,
65 PACKER_FMT_TP_10 = 0xB,
66 PACKER_FMT_PLAIN_32_32BPP = 0xC,
67 PACKER_FMT_PLAIN_8_ODD_EVEN = 0xD,
68 PACKER_FMT_PLAIN_8_LSB_MSB_10 = 0xE,
69 PACKER_FMT_PLAIN_8_LSB_MSB_10_ODD_EVEN = 0xF,
70 PACKER_FMT_MAX = 0xF,
71};
72
73struct cam_vfe_bus_ver2_common_data {
Harsh Shah19f55812017-06-26 18:58:49 -070074 uint32_t core_index;
Harsh Shaha1af8822017-05-11 22:06:36 -070075 void __iomem *mem_base;
76 struct cam_hw_intf *hw_intf;
77 void *bus_irq_controller;
78 void *vfe_irq_controller;
79 struct cam_vfe_bus_ver2_reg_offset_common *common_reg;
Jing Zhoua4e9fbe2017-05-15 14:37:21 -070080 uint32_t io_buf_update[
Harsh Shah19f55812017-06-26 18:58:49 -070081 MAX_REG_VAL_PAIR_SIZE];
82
83 struct cam_vfe_bus_irq_evt_payload evt_payload[
84 CAM_VFE_BUS_VER2_PAYLOAD_MAX];
85 struct list_head free_payload_list;
Harsh Shaha1af8822017-05-11 22:06:36 -070086};
87
88struct cam_vfe_bus_ver2_wm_resource_data {
89 uint32_t index;
90 struct cam_vfe_bus_ver2_common_data *common_data;
91 struct cam_vfe_bus_ver2_reg_offset_bus_client *hw_regs;
Harsh Shah19f55812017-06-26 18:58:49 -070092 void *ctx;
Harsh Shaha1af8822017-05-11 22:06:36 -070093
94 uint32_t irq_enabled;
Jing Zhoua4e9fbe2017-05-15 14:37:21 -070095 uint32_t init_cfg_done;
Harsh Shah19f55812017-06-26 18:58:49 -070096
Harsh Shaha1af8822017-05-11 22:06:36 -070097 uint32_t offset;
98 uint32_t width;
99 uint32_t height;
100 uint32_t stride;
101 uint32_t format;
102 enum cam_vfe_bus_packer_format pack_fmt;
103
104 uint32_t burst_len;
105 uint32_t frame_based;
106
Jing Zhoua4e9fbe2017-05-15 14:37:21 -0700107 uint32_t en_ubwc;
108 uint32_t packer_cfg;
109 uint32_t tile_cfg;
110 uint32_t h_init;
111 uint32_t v_init;
112 uint32_t ubwc_meta_stride;
113 uint32_t ubwc_mode_cfg;
114 uint32_t ubwc_meta_offset;
115
Harsh Shaha1af8822017-05-11 22:06:36 -0700116 uint32_t irq_subsample_period;
117 uint32_t irq_subsample_pattern;
118 uint32_t framedrop_period;
119 uint32_t framedrop_pattern;
Jing Zhoua4e9fbe2017-05-15 14:37:21 -0700120
121 uint32_t en_cfg;
Harsh Shaha1af8822017-05-11 22:06:36 -0700122};
123
124struct cam_vfe_bus_ver2_comp_grp_data {
125 enum cam_vfe_bus_ver2_comp_grp_type comp_grp_type;
126 struct cam_vfe_bus_ver2_common_data *common_data;
127 struct cam_vfe_bus_ver2_reg_offset_comp_grp *hw_regs;
128
129 uint32_t irq_enabled;
130 uint32_t comp_grp_local_idx;
131 uint32_t unique_id;
132
133 uint32_t is_master;
134 uint32_t dual_slave_core;
135 uint32_t intra_client_mask;
136 uint32_t composite_mask;
Harsh Shah19f55812017-06-26 18:58:49 -0700137
138 void *ctx;
Harsh Shaha1af8822017-05-11 22:06:36 -0700139};
140
141struct cam_vfe_bus_ver2_vfe_out_data {
142 uint32_t out_type;
143 struct cam_vfe_bus_ver2_common_data *common_data;
144
145 uint32_t num_wm;
146 struct cam_isp_resource_node *wm_res[PLANE_MAX];
147
148 struct cam_isp_resource_node *comp_grp;
149 enum cam_isp_hw_sync_mode dual_comp_sync_mode;
150 uint32_t dual_hw_alternate_vfe_id;
151 struct list_head vfe_out_list;
152
153 uint32_t format;
154 uint32_t max_width;
155 uint32_t max_height;
156 struct cam_cdm_utils_ops *cdm_util_ops;
157};
158
Harsh Shaha1af8822017-05-11 22:06:36 -0700159struct cam_vfe_bus_ver2_priv {
160 struct cam_vfe_bus_ver2_common_data common_data;
161
162 struct cam_isp_resource_node bus_client[CAM_VFE_BUS_VER2_MAX_CLIENTS];
163 struct cam_isp_resource_node comp_grp[CAM_VFE_BUS_VER2_COMP_GRP_MAX];
164 struct cam_isp_resource_node vfe_out[CAM_VFE_BUS_VER2_VFE_OUT_MAX];
165
166 struct list_head free_comp_grp;
167 struct list_head free_dual_comp_grp;
168 struct list_head used_comp_grp;
169
Harsh Shah19f55812017-06-26 18:58:49 -0700170 uint32_t irq_handle;
Harsh Shaha1af8822017-05-11 22:06:36 -0700171};
172
Harsh Shah19f55812017-06-26 18:58:49 -0700173static int cam_vfe_bus_get_evt_payload(
174 struct cam_vfe_bus_ver2_common_data *common_data,
175 struct cam_vfe_bus_irq_evt_payload **evt_payload)
176{
177 if (list_empty(&common_data->free_payload_list)) {
178 *evt_payload = NULL;
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -0700179 CAM_ERR(CAM_ISP, "No free payload");
Harsh Shah19f55812017-06-26 18:58:49 -0700180 return -ENODEV;
181 }
182
183 *evt_payload = list_first_entry(&common_data->free_payload_list,
184 struct cam_vfe_bus_irq_evt_payload, list);
185 list_del_init(&(*evt_payload)->list);
186 return 0;
187}
188
Harsh Shaha1af8822017-05-11 22:06:36 -0700189static int cam_vfe_bus_put_evt_payload(void *core_info,
Harsh Shah19f55812017-06-26 18:58:49 -0700190 struct cam_vfe_bus_irq_evt_payload **evt_payload)
191{
192 struct cam_vfe_bus_ver2_common_data *common_data = NULL;
193 uint32_t *ife_irq_regs = NULL;
194 uint32_t status_reg0, status_reg1, status_reg2;
195
196 if (!core_info) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -0700197 CAM_ERR(CAM_ISP, "Invalid param core_info NULL");
Harsh Shah19f55812017-06-26 18:58:49 -0700198 return -EINVAL;
199 }
200 if (*evt_payload == NULL) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -0700201 CAM_ERR(CAM_ISP, "No payload to put");
Harsh Shah19f55812017-06-26 18:58:49 -0700202 return -EINVAL;
203 }
204
205 ife_irq_regs = (*evt_payload)->irq_reg_val;
206 status_reg0 = ife_irq_regs[CAM_IFE_IRQ_BUS_REG_STATUS0];
207 status_reg1 = ife_irq_regs[CAM_IFE_IRQ_BUS_REG_STATUS1];
208 status_reg2 = ife_irq_regs[CAM_IFE_IRQ_BUS_REG_STATUS2];
209
210 if (status_reg0 || status_reg1 || status_reg2) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -0700211 CAM_DBG(CAM_ISP, "status0 0x%x status1 0x%x status2 0x%x",
Harsh Shah19f55812017-06-26 18:58:49 -0700212 status_reg0, status_reg1, status_reg2);
213 return 0;
214 }
215
216 common_data = core_info;
217 list_add_tail(&(*evt_payload)->list,
218 &common_data->free_payload_list);
219 *evt_payload = NULL;
220
221 return 0;
222}
Harsh Shaha1af8822017-05-11 22:06:36 -0700223
224static int cam_vfe_bus_ver2_get_intra_client_mask(
225 enum cam_vfe_bus_ver2_vfe_core_id dual_slave_core,
226 enum cam_vfe_bus_ver2_vfe_core_id current_core,
227 uint32_t *intra_client_mask)
228{
229 int rc = 0;
230
231 *intra_client_mask = 0;
232
233 if (dual_slave_core == current_core) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -0700234 CAM_ERR(CAM_ISP,
235 "Invalid params. Same core as Master and Slave");
Harsh Shaha1af8822017-05-11 22:06:36 -0700236 return -EINVAL;
237 }
238
239 switch (current_core) {
240 case CAM_VFE_BUS_VER2_VFE_CORE_0:
241 switch (dual_slave_core) {
242 case CAM_VFE_BUS_VER2_VFE_CORE_1:
243 *intra_client_mask = 0x1;
244 break;
245 case CAM_VFE_BUS_VER2_VFE_CORE_2:
246 *intra_client_mask = 0x2;
247 break;
248 default:
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -0700249 CAM_ERR(CAM_ISP, "Invalid value for slave core %u",
Harsh Shaha1af8822017-05-11 22:06:36 -0700250 dual_slave_core);
251 rc = -EINVAL;
252 break;
253 }
254 break;
255 case CAM_VFE_BUS_VER2_VFE_CORE_1:
256 switch (dual_slave_core) {
257 case CAM_VFE_BUS_VER2_VFE_CORE_0:
258 *intra_client_mask = 0x1;
259 break;
260 case CAM_VFE_BUS_VER2_VFE_CORE_2:
261 *intra_client_mask = 0x2;
262 break;
263 default:
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -0700264 CAM_ERR(CAM_ISP, "Invalid value for slave core %u",
Harsh Shaha1af8822017-05-11 22:06:36 -0700265 dual_slave_core);
266 rc = -EINVAL;
267 break;
268 }
269 break;
270 case CAM_VFE_BUS_VER2_VFE_CORE_2:
271 switch (dual_slave_core) {
272 case CAM_VFE_BUS_VER2_VFE_CORE_0:
273 *intra_client_mask = 0x1;
274 break;
275 case CAM_VFE_BUS_VER2_VFE_CORE_1:
276 *intra_client_mask = 0x2;
277 break;
278 default:
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -0700279 CAM_ERR(CAM_ISP, "Invalid value for slave core %u",
Harsh Shaha1af8822017-05-11 22:06:36 -0700280 dual_slave_core);
281 rc = -EINVAL;
282 break;
283 }
284 break;
285 default:
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -0700286 CAM_ERR(CAM_ISP,
287 "Invalid value for master core %u", current_core);
Harsh Shaha1af8822017-05-11 22:06:36 -0700288 rc = -EINVAL;
289 break;
290 }
291
292 return rc;
293}
294
295static enum cam_vfe_bus_ver2_vfe_out_type
296 cam_vfe_bus_get_out_res_id(uint32_t res_type)
297{
298 switch (res_type) {
299 case CAM_ISP_IFE_OUT_RES_FULL:
300 return CAM_VFE_BUS_VER2_VFE_OUT_FULL;
301 case CAM_ISP_IFE_OUT_RES_DS4:
302 return CAM_VFE_BUS_VER2_VFE_OUT_DS4;
303 case CAM_ISP_IFE_OUT_RES_DS16:
304 return CAM_VFE_BUS_VER2_VFE_OUT_DS16;
305 case CAM_ISP_IFE_OUT_RES_FD:
306 return CAM_VFE_BUS_VER2_VFE_OUT_FD;
307 case CAM_ISP_IFE_OUT_RES_RAW_DUMP:
308 return CAM_VFE_BUS_VER2_VFE_OUT_RAW_DUMP;
309 case CAM_ISP_IFE_OUT_RES_PDAF:
310 return CAM_VFE_BUS_VER2_VFE_OUT_PDAF;
311 case CAM_ISP_IFE_OUT_RES_RDI_0:
312 return CAM_VFE_BUS_VER2_VFE_OUT_RDI0;
313 case CAM_ISP_IFE_OUT_RES_RDI_1:
314 return CAM_VFE_BUS_VER2_VFE_OUT_RDI1;
315 case CAM_ISP_IFE_OUT_RES_RDI_2:
316 return CAM_VFE_BUS_VER2_VFE_OUT_RDI2;
317 case CAM_ISP_IFE_OUT_RES_STATS_HDR_BE:
318 return CAM_VFE_BUS_VER2_VFE_OUT_STATS_HDR_BE;
319 case CAM_ISP_IFE_OUT_RES_STATS_HDR_BHIST:
320 return CAM_VFE_BUS_VER2_VFE_OUT_STATS_HDR_BHIST;
321 case CAM_ISP_IFE_OUT_RES_STATS_TL_BG:
322 return CAM_VFE_BUS_VER2_VFE_OUT_STATS_TL_BG;
323 case CAM_ISP_IFE_OUT_RES_STATS_BF:
324 return CAM_VFE_BUS_VER2_VFE_OUT_STATS_BF;
325 case CAM_ISP_IFE_OUT_RES_STATS_AWB_BG:
326 return CAM_VFE_BUS_VER2_VFE_OUT_STATS_AWB_BG;
327 case CAM_ISP_IFE_OUT_RES_STATS_BHIST:
328 return CAM_VFE_BUS_VER2_VFE_OUT_STATS_BHIST;
329 case CAM_ISP_IFE_OUT_RES_STATS_RS:
330 return CAM_VFE_BUS_VER2_VFE_OUT_STATS_RS;
331 case CAM_ISP_IFE_OUT_RES_STATS_CS:
332 return CAM_VFE_BUS_VER2_VFE_OUT_STATS_CS;
333 case CAM_ISP_IFE_OUT_RES_STATS_IHIST:
334 return CAM_VFE_BUS_VER2_VFE_OUT_STATS_IHIST;
335 default:
336 return CAM_VFE_BUS_VER2_VFE_OUT_MAX;
337 }
338}
339
340static int cam_vfe_bus_get_num_wm(
341 enum cam_vfe_bus_ver2_vfe_out_type res_type,
342 uint32_t format)
343{
344 switch (res_type) {
345 case CAM_VFE_BUS_VER2_VFE_OUT_RDI0:
346 case CAM_VFE_BUS_VER2_VFE_OUT_RDI1:
347 case CAM_VFE_BUS_VER2_VFE_OUT_RDI2:
348 switch (format) {
349 case CAM_FORMAT_MIPI_RAW_8:
350 case CAM_FORMAT_MIPI_RAW_10:
351 case CAM_FORMAT_MIPI_RAW_12:
352 case CAM_FORMAT_MIPI_RAW_14:
353 case CAM_FORMAT_MIPI_RAW_16:
354 case CAM_FORMAT_MIPI_RAW_20:
Ravikishore Pampanaad6bc902017-07-12 19:37:06 +0530355 case CAM_FORMAT_DPCM_10_6_10:
356 case CAM_FORMAT_DPCM_10_8_10:
357 case CAM_FORMAT_DPCM_12_6_12:
358 case CAM_FORMAT_DPCM_12_8_12:
359 case CAM_FORMAT_DPCM_14_8_14:
360 case CAM_FORMAT_DPCM_14_10_14:
361 case CAM_FORMAT_PLAIN8:
362 case CAM_FORMAT_PLAIN16_8:
363 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;
Abhishek Kondaveeti170c8122017-07-06 04:45:12 +0530659 case CAM_FORMAT_PLAIN64:
660 return PACKER_FMT_PLAIN_64;
661 case CAM_FORMAT_MIPI_RAW_6:
662 case CAM_FORMAT_MIPI_RAW_8:
663 case CAM_FORMAT_MIPI_RAW_10:
664 case CAM_FORMAT_MIPI_RAW_12:
665 case CAM_FORMAT_MIPI_RAW_14:
666 case CAM_FORMAT_MIPI_RAW_16:
667 case CAM_FORMAT_MIPI_RAW_20:
Abhishek Kondaveeti170c8122017-07-06 04:45:12 +0530668 case CAM_FORMAT_PLAIN128:
Ravikishore Pampanaad6bc902017-07-12 19:37:06 +0530669 case CAM_FORMAT_PLAIN8:
670 case CAM_FORMAT_PLAIN16_8:
671 case CAM_FORMAT_PLAIN16_10:
672 case CAM_FORMAT_PLAIN16_12:
673 case CAM_FORMAT_PLAIN16_14:
674 case CAM_FORMAT_PLAIN16_16:
675 case CAM_FORMAT_PLAIN32_20:
Abhishek Kondaveeti170c8122017-07-06 04:45:12 +0530676 case CAM_FORMAT_PD8:
677 case CAM_FORMAT_PD10:
678 return PACKER_FMT_PLAIN_128;
Krishnankutty Kolathappillyf39e6412017-07-18 15:58:22 -0700679 case CAM_FORMAT_UBWC_TP10:
680 case CAM_FORMAT_TP10:
681 return PACKER_FMT_TP_10;
Harsh Shaha1af8822017-05-11 22:06:36 -0700682 default:
683 return PACKER_FMT_MAX;
684 }
685}
686
687static int cam_vfe_bus_acquire_wm(
688 struct cam_vfe_bus_ver2_priv *ver2_bus_priv,
689 struct cam_isp_out_port_info *out_port_info,
Harsh Shah19f55812017-06-26 18:58:49 -0700690 void *tasklet,
691 void *ctx,
Harsh Shaha1af8822017-05-11 22:06:36 -0700692 enum cam_vfe_bus_ver2_vfe_out_type vfe_out_res_id,
693 enum cam_vfe_bus_plane_type plane,
694 enum cam_isp_hw_split_id split_id,
695 uint32_t subscribe_irq,
696 struct cam_isp_resource_node **wm_res,
697 uint32_t *client_done_mask)
698{
699 uint32_t wm_idx = 0;
700 struct cam_isp_resource_node *wm_res_local = NULL;
701 struct cam_vfe_bus_ver2_wm_resource_data *rsrc_data = NULL;
702
703 *wm_res = NULL;
704 *client_done_mask = 0;
705
706 /* No need to allocate for BUS VER2. VFE OUT to WM is fixed. */
707 wm_idx = cam_vfe_bus_get_wm_idx(vfe_out_res_id, plane);
708 if (wm_idx < 0 || wm_idx >= CAM_VFE_BUS_VER2_MAX_CLIENTS) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -0700709 CAM_ERR(CAM_ISP, "Unsupported VFE out %d plane %d",
Harsh Shaha1af8822017-05-11 22:06:36 -0700710 vfe_out_res_id, plane);
711 return -EINVAL;
712 }
713
714 wm_res_local = &ver2_bus_priv->bus_client[wm_idx];
Harsh Shah19f55812017-06-26 18:58:49 -0700715 wm_res_local->tasklet_info = tasklet;
Harsh Shaha1af8822017-05-11 22:06:36 -0700716 wm_res_local->res_state = CAM_ISP_RESOURCE_STATE_RESERVED;
717
718 rsrc_data = wm_res_local->res_priv;
719 rsrc_data->irq_enabled = subscribe_irq;
Harsh Shah19f55812017-06-26 18:58:49 -0700720 rsrc_data->ctx = ctx;
Harsh Shaha1af8822017-05-11 22:06:36 -0700721 rsrc_data->format = out_port_info->format;
722 rsrc_data->pack_fmt = cam_vfe_bus_get_packer_fmt(rsrc_data->format);
723
724 rsrc_data->width = out_port_info->width;
725 rsrc_data->height = out_port_info->height;
Jing Zhoua4e9fbe2017-05-15 14:37:21 -0700726
727 if (rsrc_data->index < 3) {
Krishnankutty Kolathappillyf39e6412017-07-18 15:58:22 -0700728 /* Write master 0-2 refers to RDI 0/ RDI 1/RDI 2 */
Ravikishore Pampanaad6bc902017-07-12 19:37:06 +0530729 rsrc_data->width = CAM_VFE_RDI_BUS_DEFAULT_WIDTH;
730 rsrc_data->height = 0;
731 rsrc_data->stride = CAM_VFE_RDI_BUS_DEFAULT_STRIDE;
732 rsrc_data->pack_fmt = 0x0;
Jing Zhoua4e9fbe2017-05-15 14:37:21 -0700733 rsrc_data->en_cfg = 0x3;
Abhishek Kondaveetib31b46c2017-06-23 04:56:24 +0530734 } else if (rsrc_data->index < 5 ||
735 rsrc_data->index == 7 || rsrc_data->index == 8) {
Krishnankutty Kolathappillyf39e6412017-07-18 15:58:22 -0700736 /* Write master 3, 4 - for Full OUT , 7-8 FD OUT */
737 switch (rsrc_data->format) {
Krishnankutty Kolathappillyf39e6412017-07-18 15:58:22 -0700738 case CAM_FORMAT_UBWC_NV12_4R:
739 rsrc_data->en_ubwc = 1;
Krishnankutty Kolathappilly06406e52017-08-17 00:50:21 -0700740 rsrc_data->width = ALIGNUP(rsrc_data->width, 64);
741 switch (plane) {
742 case PLANE_C:
743 rsrc_data->height /= 2;
744 break;
745 case PLANE_Y:
746 break;
747 default:
748 CAM_ERR(CAM_ISP, "Invalid plane %d\n", plane);
749 return -EINVAL;
750 }
751 break;
752 case CAM_FORMAT_UBWC_NV12:
753 rsrc_data->en_ubwc = 1;
Krishnankutty Kolathappillyf39e6412017-07-18 15:58:22 -0700754 /* Fall through for NV12 */
755 case CAM_FORMAT_NV21:
756 case CAM_FORMAT_NV12:
757 switch (plane) {
758 case PLANE_C:
759 rsrc_data->height /= 2;
760 break;
761 case PLANE_Y:
Jing Zhoua4e9fbe2017-05-15 14:37:21 -0700762 break;
763 default:
Krishnankutty Kolathappillyf39e6412017-07-18 15:58:22 -0700764 CAM_ERR(CAM_ISP, "Invalid plane %d\n", plane);
765 return -EINVAL;
Jing Zhoua4e9fbe2017-05-15 14:37:21 -0700766 }
767 break;
Krishnankutty Kolathappillyf39e6412017-07-18 15:58:22 -0700768 case CAM_FORMAT_UBWC_TP10:
769 rsrc_data->en_ubwc = 1;
Krishnankutty Kolathappilly06406e52017-08-17 00:50:21 -0700770 rsrc_data->width =
771 ALIGNUP(rsrc_data->width, 48) * 4 / 3;
772 switch (plane) {
773 case PLANE_C:
774 rsrc_data->height /= 2;
775 break;
776 case PLANE_Y:
777 break;
778 default:
779 CAM_ERR(CAM_ISP, "Invalid plane %d\n", plane);
780 return -EINVAL;
781 }
782 break;
Krishnankutty Kolathappillyf39e6412017-07-18 15:58:22 -0700783 case CAM_FORMAT_TP10:
Krishnankutty Kolathappilly06406e52017-08-17 00:50:21 -0700784 rsrc_data->width =
785 ALIGNUP(rsrc_data->width, 3) * 4 / 3;
Krishnankutty Kolathappillyf39e6412017-07-18 15:58:22 -0700786 switch (plane) {
787 case PLANE_C:
Jing Zhoua4e9fbe2017-05-15 14:37:21 -0700788 rsrc_data->height /= 2;
789 break;
Krishnankutty Kolathappillyf39e6412017-07-18 15:58:22 -0700790 case PLANE_Y:
Jing Zhoua4e9fbe2017-05-15 14:37:21 -0700791 break;
792 default:
Krishnankutty Kolathappillyf39e6412017-07-18 15:58:22 -0700793 CAM_ERR(CAM_ISP, "Invalid plane %d\n", plane);
794 return -EINVAL;
Jing Zhoua4e9fbe2017-05-15 14:37:21 -0700795 }
Harsh Shaha1af8822017-05-11 22:06:36 -0700796 break;
797 default:
Krishnankutty Kolathappillyf39e6412017-07-18 15:58:22 -0700798 CAM_ERR(CAM_ISP, "Invalid format %d\n",
799 rsrc_data->format);
Jing Zhoua4e9fbe2017-05-15 14:37:21 -0700800 return -EINVAL;
Harsh Shaha1af8822017-05-11 22:06:36 -0700801 }
Jing Zhoua4e9fbe2017-05-15 14:37:21 -0700802 rsrc_data->en_cfg = 0x1;
Abhishek Kondaveetib31b46c2017-06-23 04:56:24 +0530803 } else if (rsrc_data->index >= 11) {
Krishnankutty Kolathappillyf39e6412017-07-18 15:58:22 -0700804 /* Write master 11-19 stats */
Abhishek Kondaveetib31b46c2017-06-23 04:56:24 +0530805 rsrc_data->width = 0;
806 rsrc_data->height = 0;
Abhishek Kondaveetib31b46c2017-06-23 04:56:24 +0530807 rsrc_data->stride = 1;
808 rsrc_data->en_cfg = 0x3;
Jing Zhoua4e9fbe2017-05-15 14:37:21 -0700809 } else {
Krishnankutty Kolathappillyf39e6412017-07-18 15:58:22 -0700810 /* Write master 5-6 DS ports , 9 - Raw dump , 10 PDAF */
Jing Zhoua4e9fbe2017-05-15 14:37:21 -0700811 rsrc_data->width = rsrc_data->width * 4;
812 rsrc_data->height = rsrc_data->height / 2;
Jing Zhoua4e9fbe2017-05-15 14:37:21 -0700813 rsrc_data->en_cfg = 0x1;
Harsh Shaha1af8822017-05-11 22:06:36 -0700814 }
Harsh Shaha1af8822017-05-11 22:06:36 -0700815 if (vfe_out_res_id >= CAM_ISP_IFE_OUT_RES_RDI_0 &&
816 vfe_out_res_id <= CAM_ISP_IFE_OUT_RES_RDI_3)
817 rsrc_data->frame_based = 1;
818
819 *client_done_mask = (1 << wm_idx);
820 *wm_res = wm_res_local;
821
822 return 0;
823}
824
825static int cam_vfe_bus_release_wm(void *bus_priv,
826 struct cam_isp_resource_node *wm_res)
827{
828 struct cam_vfe_bus_ver2_wm_resource_data *rsrc_data =
829 wm_res->res_priv;
830
831 rsrc_data->irq_enabled = 0;
832 rsrc_data->offset = 0;
833 rsrc_data->width = 0;
834 rsrc_data->height = 0;
835 rsrc_data->stride = 0;
836 rsrc_data->format = 0;
837 rsrc_data->pack_fmt = 0;
838 rsrc_data->burst_len = 0;
839 rsrc_data->frame_based = 0;
840 rsrc_data->irq_subsample_period = 0;
841 rsrc_data->irq_subsample_pattern = 0;
842 rsrc_data->framedrop_period = 0;
843 rsrc_data->framedrop_pattern = 0;
Jing Zhoua4e9fbe2017-05-15 14:37:21 -0700844 rsrc_data->packer_cfg = 0;
845 rsrc_data->en_ubwc = 0;
846 rsrc_data->tile_cfg = 0;
847 rsrc_data->h_init = 0;
848 rsrc_data->v_init = 0;
849 rsrc_data->ubwc_meta_stride = 0;
850 rsrc_data->ubwc_mode_cfg = 0;
851 rsrc_data->ubwc_meta_offset = 0;
852 rsrc_data->init_cfg_done = 0;
853 rsrc_data->en_cfg = 0;
Harsh Shah19f55812017-06-26 18:58:49 -0700854
855 wm_res->tasklet_info = NULL;
Harsh Shaha1af8822017-05-11 22:06:36 -0700856 wm_res->res_state = CAM_ISP_RESOURCE_STATE_AVAILABLE;
857
858 return 0;
859}
860
861static int cam_vfe_bus_start_wm(struct cam_isp_resource_node *wm_res)
862{
863 int rc = 0;
864 struct cam_vfe_bus_ver2_wm_resource_data *rsrc_data =
865 wm_res->res_priv;
866 struct cam_vfe_bus_ver2_common_data *common_data =
867 rsrc_data->common_data;
Harsh Shah19f55812017-06-26 18:58:49 -0700868 uint32_t bus_irq_reg_mask[CAM_VFE_BUS_IRQ_MAX] = {0};
Harsh Shaha1af8822017-05-11 22:06:36 -0700869
Harsh Shah23557ae2017-05-13 18:14:34 -0700870 cam_io_w_mb(0, common_data->mem_base + rsrc_data->hw_regs->header_addr);
871 cam_io_w_mb(0, common_data->mem_base + rsrc_data->hw_regs->header_cfg);
Harsh Shah23557ae2017-05-13 18:14:34 -0700872 cam_io_w(0xf, common_data->mem_base + rsrc_data->hw_regs->burst_limit);
873
Jing Zhoua4e9fbe2017-05-15 14:37:21 -0700874 cam_io_w_mb(rsrc_data->width,
Harsh Shaha1af8822017-05-11 22:06:36 -0700875 common_data->mem_base + rsrc_data->hw_regs->buffer_width_cfg);
Jing Zhoua4e9fbe2017-05-15 14:37:21 -0700876 cam_io_w(rsrc_data->height,
Harsh Shaha1af8822017-05-11 22:06:36 -0700877 common_data->mem_base + rsrc_data->hw_regs->buffer_height_cfg);
Jing Zhoua4e9fbe2017-05-15 14:37:21 -0700878 cam_io_w(rsrc_data->pack_fmt,
Harsh Shaha1af8822017-05-11 22:06:36 -0700879 common_data->mem_base + rsrc_data->hw_regs->packer_cfg);
Harsh Shaha1af8822017-05-11 22:06:36 -0700880
Ravikishore Pampanaad6bc902017-07-12 19:37:06 +0530881 /* Configure stride for RDIs */
882 if (rsrc_data->index < 3)
883 cam_io_w_mb(rsrc_data->stride, (common_data->mem_base +
884 rsrc_data->hw_regs->stride));
Harsh Shaha1af8822017-05-11 22:06:36 -0700885
Harsh Shah19f55812017-06-26 18:58:49 -0700886 /* Subscribe IRQ */
887 if (rsrc_data->irq_enabled) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -0700888 CAM_DBG(CAM_ISP, "Subscribe WM%d IRQ", rsrc_data->index);
Harsh Shah19f55812017-06-26 18:58:49 -0700889 bus_irq_reg_mask[CAM_VFE_BUS_IRQ_REG1] =
890 (1 << rsrc_data->index);
891 wm_res->irq_handle = cam_irq_controller_subscribe_irq(
892 common_data->bus_irq_controller, CAM_IRQ_PRIORITY_1,
893 bus_irq_reg_mask, wm_res,
894 wm_res->top_half_handler,
895 cam_ife_mgr_do_tasklet_buf_done,
896 wm_res->tasklet_info, cam_tasklet_enqueue_cmd);
897 if (wm_res->irq_handle < 0) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -0700898 CAM_ERR(CAM_ISP, "Subscribe IRQ failed for WM %d",
Harsh Shah19f55812017-06-26 18:58:49 -0700899 rsrc_data->index);
900 return -EFAULT;
901 }
902 }
903
Junzhe Zou3d292562017-07-12 17:59:58 -0700904 /* enable ubwc if needed*/
905 if (rsrc_data->en_ubwc) {
906 cam_io_w_mb(0x1, common_data->mem_base +
907 rsrc_data->hw_regs->ubwc_regs->mode_cfg);
908 }
909
Harsh Shah19f55812017-06-26 18:58:49 -0700910 /* Enable WM */
911 cam_io_w_mb(rsrc_data->en_cfg, common_data->mem_base +
912 rsrc_data->hw_regs->cfg);
913
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -0700914 CAM_DBG(CAM_ISP, "WM res %d width = %d, height = %d", rsrc_data->index,
Jing Zhoua4e9fbe2017-05-15 14:37:21 -0700915 rsrc_data->width, rsrc_data->height);
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -0700916 CAM_DBG(CAM_ISP, "WM res %d pk_fmt = %d", rsrc_data->index,
Jing Zhoua4e9fbe2017-05-15 14:37:21 -0700917 rsrc_data->pack_fmt & PACKER_FMT_MAX);
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -0700918 CAM_DBG(CAM_ISP, "WM res %d stride = %d, burst len = %d",
Jing Zhoua4e9fbe2017-05-15 14:37:21 -0700919 rsrc_data->index, rsrc_data->stride, 0xf);
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -0700920 CAM_DBG(CAM_ISP, "enable WM res %d offset 0x%x val 0x%x",
921 rsrc_data->index, (uint32_t) rsrc_data->hw_regs->cfg,
922 rsrc_data->en_cfg);
Harsh Shaha1af8822017-05-11 22:06:36 -0700923
924 wm_res->res_state = CAM_ISP_RESOURCE_STATE_STREAMING;
925
926 return rc;
927}
928
929static int cam_vfe_bus_stop_wm(struct cam_isp_resource_node *wm_res)
930{
931 int rc = 0;
932 struct cam_vfe_bus_ver2_wm_resource_data *rsrc_data =
933 wm_res->res_priv;
934 struct cam_vfe_bus_ver2_common_data *common_data =
935 rsrc_data->common_data;
936
937 /* Disble WM */
938 cam_io_w_mb(0x0,
939 common_data->mem_base + rsrc_data->hw_regs->cfg);
940
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -0700941 CAM_DBG(CAM_ISP, "irq_enabled %d", rsrc_data->irq_enabled);
Harsh Shaha1af8822017-05-11 22:06:36 -0700942 /* Unsubscribe IRQ */
Harsh Shah19f55812017-06-26 18:58:49 -0700943 if (rsrc_data->irq_enabled)
944 rc = cam_irq_controller_unsubscribe_irq(
945 common_data->bus_irq_controller,
946 wm_res->irq_handle);
Harsh Shaha1af8822017-05-11 22:06:36 -0700947
948 /* Halt & Reset WM */
949 cam_io_w_mb(BIT(rsrc_data->index),
950 common_data->mem_base + common_data->common_reg->sw_reset);
951
952 wm_res->res_state = CAM_ISP_RESOURCE_STATE_RESERVED;
953
954 return rc;
955}
956
957static int cam_vfe_bus_handle_wm_done_top_half(uint32_t evt_id,
958 struct cam_irq_th_payload *th_payload)
959{
Harsh Shah19f55812017-06-26 18:58:49 -0700960 int32_t rc;
961 int i;
962 struct cam_isp_resource_node *wm_res = NULL;
963 struct cam_vfe_bus_ver2_wm_resource_data *rsrc_data = NULL;
964 struct cam_vfe_bus_irq_evt_payload *evt_payload;
965
966 wm_res = th_payload->handler_priv;
967 if (!wm_res) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -0700968 CAM_ERR_RATE_LIMIT(CAM_ISP, "Error! No resource\n");
Harsh Shah19f55812017-06-26 18:58:49 -0700969 return -ENODEV;
970 }
971
972 rsrc_data = wm_res->res_priv;
973
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -0700974 CAM_DBG(CAM_ISP, "IRQ status_0 = %x", th_payload->evt_status_arr[0]);
975 CAM_DBG(CAM_ISP, "IRQ status_1 = %x", th_payload->evt_status_arr[1]);
Harsh Shah19f55812017-06-26 18:58:49 -0700976
977 rc = cam_vfe_bus_get_evt_payload(rsrc_data->common_data, &evt_payload);
978 if (rc) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -0700979 CAM_ERR_RATE_LIMIT(CAM_ISP,
980 "No tasklet_cmd is free in queue\n");
Harsh Shah19f55812017-06-26 18:58:49 -0700981 return rc;
982 }
983
984 cam_isp_hw_get_timestamp(&evt_payload->ts);
985
986 evt_payload->ctx = rsrc_data->ctx;
987 evt_payload->core_index = rsrc_data->common_data->core_index;
988 evt_payload->evt_id = evt_id;
989
990 for (i = 0; i < th_payload->num_registers; i++)
991 evt_payload->irq_reg_val[i] = th_payload->evt_status_arr[i];
992
993 th_payload->evt_payload_priv = evt_payload;
994
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -0700995 CAM_DBG(CAM_ISP, "Exit");
Harsh Shah19f55812017-06-26 18:58:49 -0700996 return rc;
Harsh Shaha1af8822017-05-11 22:06:36 -0700997}
998
999static int cam_vfe_bus_handle_wm_done_bottom_half(void *wm_node,
1000 void *evt_payload_priv)
1001{
1002 int rc = CAM_VFE_IRQ_STATUS_ERR;
1003 struct cam_isp_resource_node *wm_res = wm_node;
1004 struct cam_vfe_bus_irq_evt_payload *evt_payload = evt_payload_priv;
Harsh Shah23557ae2017-05-13 18:14:34 -07001005 struct cam_vfe_bus_ver2_wm_resource_data *rsrc_data =
1006 (wm_res == NULL) ? NULL : wm_res->res_priv;
1007 uint32_t *cam_ife_irq_regs;
Harsh Shaha1af8822017-05-11 22:06:36 -07001008 uint32_t status_reg;
1009
Harsh Shah23557ae2017-05-13 18:14:34 -07001010 if (!evt_payload || !rsrc_data)
1011 return rc;
Harsh Shaha1af8822017-05-11 22:06:36 -07001012
Harsh Shah23557ae2017-05-13 18:14:34 -07001013 cam_ife_irq_regs = evt_payload->irq_reg_val;
1014 status_reg = cam_ife_irq_regs[CAM_IFE_IRQ_BUS_REG_STATUS1];
1015
1016 if (status_reg & BIT(rsrc_data->index)) {
1017 cam_ife_irq_regs[CAM_IFE_IRQ_BUS_REG_STATUS1] &=
1018 ~BIT(rsrc_data->index);
Harsh Shaha1af8822017-05-11 22:06:36 -07001019 rc = CAM_VFE_IRQ_STATUS_SUCCESS;
Harsh Shah23557ae2017-05-13 18:14:34 -07001020 }
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07001021 CAM_DBG(CAM_ISP, "status_reg %x rc %d", status_reg, rc);
Harsh Shaha1af8822017-05-11 22:06:36 -07001022
1023 if (rc == CAM_VFE_IRQ_STATUS_SUCCESS)
Harsh Shah19f55812017-06-26 18:58:49 -07001024 cam_vfe_bus_put_evt_payload(rsrc_data->common_data,
Harsh Shaha1af8822017-05-11 22:06:36 -07001025 &evt_payload);
1026
1027 return rc;
1028}
1029
1030static int cam_vfe_bus_init_wm_resource(uint32_t index,
1031 struct cam_vfe_bus_ver2_priv *ver2_bus_priv,
1032 struct cam_vfe_bus_ver2_hw_info *ver2_hw_info,
1033 struct cam_isp_resource_node *wm_res)
1034{
Harsh Shaha1af8822017-05-11 22:06:36 -07001035 struct cam_vfe_bus_ver2_wm_resource_data *rsrc_data;
1036
1037 rsrc_data = kzalloc(sizeof(struct cam_vfe_bus_ver2_wm_resource_data),
1038 GFP_KERNEL);
1039 if (!rsrc_data) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07001040 CAM_DBG(CAM_ISP, "Failed to alloc for WM res priv");
Harsh Shah545df9a2017-06-16 16:43:17 -07001041 return -ENOMEM;
Harsh Shaha1af8822017-05-11 22:06:36 -07001042 }
1043 wm_res->res_priv = rsrc_data;
1044
1045 rsrc_data->index = index;
1046 rsrc_data->hw_regs = &ver2_hw_info->bus_client_reg[index];
1047 rsrc_data->common_data = &ver2_bus_priv->common_data;
1048
1049 wm_res->res_state = CAM_ISP_RESOURCE_STATE_AVAILABLE;
1050 INIT_LIST_HEAD(&wm_res->list);
1051
1052 wm_res->start = cam_vfe_bus_start_wm;
1053 wm_res->stop = cam_vfe_bus_stop_wm;
1054 wm_res->top_half_handler = cam_vfe_bus_handle_wm_done_top_half;
1055 wm_res->bottom_half_handler = cam_vfe_bus_handle_wm_done_bottom_half;
1056 wm_res->hw_intf = ver2_bus_priv->common_data.hw_intf;
1057
Harsh Shah545df9a2017-06-16 16:43:17 -07001058 return 0;
1059}
1060
1061static int cam_vfe_bus_deinit_wm_resource(
1062 struct cam_isp_resource_node *wm_res)
1063{
1064 struct cam_vfe_bus_ver2_wm_resource_data *rsrc_data;
1065
1066 wm_res->res_state = CAM_ISP_RESOURCE_STATE_UNAVAILABLE;
1067 INIT_LIST_HEAD(&wm_res->list);
1068
1069 wm_res->start = NULL;
1070 wm_res->stop = NULL;
1071 wm_res->top_half_handler = NULL;
1072 wm_res->bottom_half_handler = NULL;
1073 wm_res->hw_intf = NULL;
1074
1075 rsrc_data = wm_res->res_priv;
1076 wm_res->res_priv = NULL;
1077 if (!rsrc_data) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07001078 CAM_ERR(CAM_ISP, "Error! WM res priv is NULL");
Harsh Shah545df9a2017-06-16 16:43:17 -07001079 return -ENOMEM;
1080 }
1081 kfree(rsrc_data);
1082
1083 return 0;
Harsh Shaha1af8822017-05-11 22:06:36 -07001084}
1085
1086static void cam_vfe_bus_add_wm_to_comp_grp(
1087 struct cam_isp_resource_node *comp_grp,
1088 uint32_t composite_mask)
1089{
1090 struct cam_vfe_bus_ver2_comp_grp_data *rsrc_data = comp_grp->res_priv;
1091
1092 rsrc_data->composite_mask |= composite_mask;
1093}
1094
1095static void cam_vfe_bus_match_comp_grp(
1096 struct cam_vfe_bus_ver2_priv *ver2_bus_priv,
1097 struct cam_isp_resource_node **comp_grp,
1098 uint32_t comp_grp_local_idx,
1099 uint32_t unique_id)
1100{
1101 struct cam_vfe_bus_ver2_comp_grp_data *rsrc_data = NULL;
1102 struct cam_isp_resource_node *comp_grp_local = NULL;
1103
1104 list_for_each_entry(comp_grp_local,
1105 &ver2_bus_priv->used_comp_grp, list) {
1106 rsrc_data = comp_grp_local->res_priv;
1107 if (rsrc_data->comp_grp_local_idx == comp_grp_local_idx &&
1108 rsrc_data->unique_id == unique_id) {
1109 /* Match found */
1110 *comp_grp = comp_grp_local;
1111 return;
1112 }
1113 }
1114
1115 *comp_grp = NULL;
1116}
1117
1118static int cam_vfe_bus_acquire_comp_grp(
1119 struct cam_vfe_bus_ver2_priv *ver2_bus_priv,
1120 struct cam_isp_out_port_info *out_port_info,
Harsh Shah19f55812017-06-26 18:58:49 -07001121 void *tasklet,
1122 void *ctx,
Harsh Shaha1af8822017-05-11 22:06:36 -07001123 uint32_t unique_id,
1124 uint32_t is_dual,
1125 uint32_t is_master,
1126 enum cam_vfe_bus_ver2_vfe_core_id dual_slave_core,
1127 struct cam_isp_resource_node **comp_grp)
1128{
1129 int rc = 0;
1130 struct cam_isp_resource_node *comp_grp_local = NULL;
1131 struct cam_vfe_bus_ver2_comp_grp_data *rsrc_data = NULL;
1132
1133 /* Check if matching comp_grp already acquired */
1134 cam_vfe_bus_match_comp_grp(ver2_bus_priv, &comp_grp_local,
1135 out_port_info->comp_grp_id, unique_id);
1136
1137 if (!comp_grp_local) {
1138 /* First find a free group */
1139 if (is_dual) {
1140 if (list_empty(&ver2_bus_priv->free_dual_comp_grp)) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07001141 CAM_ERR(CAM_ISP, "No Free Composite Group");
Harsh Shaha1af8822017-05-11 22:06:36 -07001142 return -ENODEV;
1143 }
1144 comp_grp_local = list_first_entry(
1145 &ver2_bus_priv->free_dual_comp_grp,
1146 struct cam_isp_resource_node, list);
1147 rsrc_data = comp_grp_local->res_priv;
1148 rc = cam_vfe_bus_ver2_get_intra_client_mask(
1149 dual_slave_core,
1150 comp_grp_local->hw_intf->hw_idx,
1151 &rsrc_data->intra_client_mask);
1152 } else {
1153 if (list_empty(&ver2_bus_priv->free_comp_grp)) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07001154 CAM_ERR(CAM_ISP, "No Free Composite Group");
Harsh Shaha1af8822017-05-11 22:06:36 -07001155 return -ENODEV;
1156 }
1157 comp_grp_local = list_first_entry(
1158 &ver2_bus_priv->free_comp_grp,
1159 struct cam_isp_resource_node, list);
1160 rsrc_data = comp_grp_local->res_priv;
1161 }
1162
1163 list_del(&comp_grp_local->list);
Harsh Shah19f55812017-06-26 18:58:49 -07001164 comp_grp_local->tasklet_info = tasklet;
Harsh Shaha1af8822017-05-11 22:06:36 -07001165 comp_grp_local->res_state = CAM_ISP_RESOURCE_STATE_RESERVED;
1166
1167 rsrc_data->is_master = is_master;
1168 rsrc_data->composite_mask = 0;
1169 rsrc_data->unique_id = unique_id;
1170 rsrc_data->comp_grp_local_idx = out_port_info->comp_grp_id;
1171
1172 list_add_tail(&comp_grp_local->list,
1173 &ver2_bus_priv->used_comp_grp);
1174
1175 } else {
1176 rsrc_data = comp_grp_local->res_priv;
1177 /* Do not support runtime change in composite mask */
1178 if (comp_grp_local->res_state ==
1179 CAM_ISP_RESOURCE_STATE_STREAMING) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07001180 CAM_ERR(CAM_ISP, "Invalid State %d Comp Grp %u",
Harsh Shaha1af8822017-05-11 22:06:36 -07001181 comp_grp_local->res_state,
1182 rsrc_data->comp_grp_type);
1183 return -EBUSY;
1184 }
1185 }
1186
Harsh Shah19f55812017-06-26 18:58:49 -07001187 rsrc_data->ctx = ctx;
Harsh Shaha1af8822017-05-11 22:06:36 -07001188 *comp_grp = comp_grp_local;
1189
1190 return rc;
1191}
1192
1193static int cam_vfe_bus_release_comp_grp(
1194 struct cam_vfe_bus_ver2_priv *ver2_bus_priv,
1195 struct cam_isp_resource_node *in_comp_grp)
1196{
1197 struct cam_isp_resource_node *comp_grp = NULL;
1198 struct cam_vfe_bus_ver2_comp_grp_data *in_rsrc_data = NULL;
1199 int match_found = 0;
1200
1201 if (!in_comp_grp) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07001202 CAM_ERR(CAM_ISP, "Invalid Params Comp Grp %pK", in_rsrc_data);
Harsh Shaha1af8822017-05-11 22:06:36 -07001203 return -EINVAL;
1204 }
1205
1206 if (in_comp_grp->res_state == CAM_ISP_RESOURCE_STATE_AVAILABLE) {
1207 /* Already Released. Do Nothing */
1208 return 0;
1209 }
1210
1211 in_rsrc_data = in_comp_grp->res_priv;
1212
1213 list_for_each_entry(comp_grp, &ver2_bus_priv->used_comp_grp, list) {
1214 if (comp_grp == in_comp_grp) {
1215 match_found = 1;
1216 break;
1217 }
1218 }
1219
1220 if (!match_found) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07001221 CAM_ERR(CAM_ISP, "Could not find matching Comp Grp type %u",
Harsh Shaha1af8822017-05-11 22:06:36 -07001222 in_rsrc_data->comp_grp_type);
1223 return -ENODEV;
1224 }
1225
1226
1227 list_del(&comp_grp->list);
1228 if (in_rsrc_data->comp_grp_type >= CAM_VFE_BUS_VER2_COMP_GRP_DUAL_0 &&
1229 in_rsrc_data->comp_grp_type <= CAM_VFE_BUS_VER2_COMP_GRP_DUAL_5)
1230 list_add_tail(&comp_grp->list,
1231 &ver2_bus_priv->free_dual_comp_grp);
Jing Zhoue71fd4a2017-05-15 19:44:34 -07001232 else if (in_rsrc_data->comp_grp_type >= CAM_VFE_BUS_VER2_COMP_GRP_0
1233 && in_rsrc_data->comp_grp_type <= CAM_VFE_BUS_VER2_COMP_GRP_5)
Harsh Shaha1af8822017-05-11 22:06:36 -07001234 list_add_tail(&comp_grp->list, &ver2_bus_priv->free_comp_grp);
1235
Harsh Shaha1af8822017-05-11 22:06:36 -07001236 in_rsrc_data->unique_id = 0;
1237 in_rsrc_data->comp_grp_local_idx = 0;
1238 in_rsrc_data->composite_mask = 0;
1239 in_rsrc_data->dual_slave_core = CAM_VFE_BUS_VER2_VFE_CORE_MAX;
1240
Harsh Shah19f55812017-06-26 18:58:49 -07001241 comp_grp->tasklet_info = NULL;
Harsh Shaha1af8822017-05-11 22:06:36 -07001242 comp_grp->res_state = CAM_ISP_RESOURCE_STATE_AVAILABLE;
1243
Jing Zhoue71fd4a2017-05-15 19:44:34 -07001244 return 0;
Harsh Shaha1af8822017-05-11 22:06:36 -07001245}
1246
1247static int cam_vfe_bus_start_comp_grp(struct cam_isp_resource_node *comp_grp)
1248{
1249 int rc = 0;
1250 struct cam_vfe_bus_ver2_comp_grp_data *rsrc_data =
1251 comp_grp->res_priv;
1252 struct cam_vfe_bus_ver2_common_data *common_data =
1253 rsrc_data->common_data;
Harsh Shah19f55812017-06-26 18:58:49 -07001254 uint32_t bus_irq_reg_mask[CAM_VFE_BUS_IRQ_MAX] = {0};
Harsh Shaha1af8822017-05-11 22:06:36 -07001255
1256 cam_io_w_mb(rsrc_data->composite_mask, common_data->mem_base +
1257 rsrc_data->hw_regs->comp_mask);
1258
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07001259 CAM_DBG(CAM_ISP, "composite_mask is 0x%x", rsrc_data->composite_mask);
1260 CAM_DBG(CAM_ISP, "composite_mask addr 0x%x",
1261 rsrc_data->hw_regs->comp_mask);
Harsh Shaha1af8822017-05-11 22:06:36 -07001262
1263 if (rsrc_data->comp_grp_type >= CAM_VFE_BUS_VER2_COMP_GRP_DUAL_0 &&
1264 rsrc_data->comp_grp_type <= CAM_VFE_BUS_VER2_COMP_GRP_DUAL_5 &&
1265 rsrc_data->is_master) {
1266 int dual_comp_grp = (rsrc_data->comp_grp_type -
1267 CAM_VFE_BUS_VER2_COMP_GRP_DUAL_0);
1268 int intra_client_en = cam_io_r_mb(common_data->mem_base +
1269 common_data->common_reg->dual_master_comp_cfg);
1270
1271 /* 2 Bits per comp_grp. Hence left shift by comp_grp * 2 */
1272 intra_client_en |=
1273 (rsrc_data->intra_client_mask << dual_comp_grp * 2);
1274
1275 cam_io_w_mb(intra_client_en, common_data->mem_base +
1276 common_data->common_reg->dual_master_comp_cfg);
Harsh Shah19f55812017-06-26 18:58:49 -07001277
1278 bus_irq_reg_mask[CAM_VFE_BUS_IRQ_REG2] = (1 << dual_comp_grp);
1279 } else {
1280 /* IRQ bits for COMP GRP start at 5. So add 5 to the shift */
1281 bus_irq_reg_mask[CAM_VFE_BUS_IRQ_REG0] =
1282 (1 << (rsrc_data->comp_grp_type + 5));
1283 }
1284
1285 /* Subscribe IRQ */
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07001286 CAM_DBG(CAM_ISP, "Subscribe COMP_GRP%d IRQ", rsrc_data->comp_grp_type);
Harsh Shah19f55812017-06-26 18:58:49 -07001287 comp_grp->irq_handle = cam_irq_controller_subscribe_irq(
1288 common_data->bus_irq_controller, CAM_IRQ_PRIORITY_1,
1289 bus_irq_reg_mask, comp_grp,
1290 comp_grp->top_half_handler,
1291 cam_ife_mgr_do_tasklet_buf_done,
1292 comp_grp->tasklet_info, cam_tasklet_enqueue_cmd);
1293 if (comp_grp->irq_handle < 0) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07001294 CAM_ERR(CAM_ISP, "Subscribe IRQ failed for comp_grp %d",
Harsh Shah19f55812017-06-26 18:58:49 -07001295 rsrc_data->comp_grp_type);
1296 return -EFAULT;
Harsh Shaha1af8822017-05-11 22:06:36 -07001297 }
1298
1299 comp_grp->res_state = CAM_ISP_RESOURCE_STATE_STREAMING;
Harsh Shah19f55812017-06-26 18:58:49 -07001300
Harsh Shaha1af8822017-05-11 22:06:36 -07001301 return rc;
1302}
1303
1304static int cam_vfe_bus_stop_comp_grp(struct cam_isp_resource_node *comp_grp)
1305{
1306 int rc = 0;
1307 struct cam_vfe_bus_ver2_comp_grp_data *rsrc_data =
1308 comp_grp->res_priv;
1309 struct cam_vfe_bus_ver2_common_data *common_data =
1310 rsrc_data->common_data;
1311
1312 /* Unsubscribe IRQ */
Harsh Shah19f55812017-06-26 18:58:49 -07001313 rc = cam_irq_controller_unsubscribe_irq(
1314 common_data->bus_irq_controller,
1315 comp_grp->irq_handle);
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 if (rsrc_data->comp_grp_type >= CAM_VFE_BUS_VER2_COMP_GRP_DUAL_0 &&
1320 rsrc_data->comp_grp_type <= CAM_VFE_BUS_VER2_COMP_GRP_DUAL_5 &&
1321 rsrc_data->is_master) {
1322 int dual_comp_grp = (rsrc_data->comp_grp_type -
1323 CAM_VFE_BUS_VER2_COMP_GRP_DUAL_0);
1324 int intra_client_en = cam_io_r_mb(common_data->mem_base +
1325 common_data->common_reg->dual_master_comp_cfg);
1326
1327 /* 2 Bits per comp_grp. Hence left shift by comp_grp * 2 */
1328 intra_client_en &=
1329 ~(rsrc_data->intra_client_mask << dual_comp_grp * 2);
1330
1331 cam_io_w_mb(intra_client_en, common_data->mem_base +
1332 common_data->common_reg->dual_master_comp_cfg);
1333 }
1334
1335 comp_grp->res_state = CAM_ISP_RESOURCE_STATE_RESERVED;
1336
1337 return rc;
1338}
1339
1340static int cam_vfe_bus_handle_comp_done_top_half(uint32_t evt_id,
1341 struct cam_irq_th_payload *th_payload)
1342{
Harsh Shah19f55812017-06-26 18:58:49 -07001343 int32_t rc;
1344 int i;
1345 struct cam_isp_resource_node *comp_grp = NULL;
1346 struct cam_vfe_bus_ver2_comp_grp_data *rsrc_data = NULL;
1347 struct cam_vfe_bus_irq_evt_payload *evt_payload;
1348
1349 comp_grp = th_payload->handler_priv;
1350 if (!comp_grp) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07001351 CAM_ERR_RATE_LIMIT(CAM_ISP, "Error! No resource\n");
Harsh Shah19f55812017-06-26 18:58:49 -07001352 return -ENODEV;
1353 }
1354
1355 rsrc_data = comp_grp->res_priv;
1356
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07001357 CAM_DBG(CAM_ISP, "IRQ status_0 = %x", th_payload->evt_status_arr[0]);
1358 CAM_DBG(CAM_ISP, "IRQ status_1 = %x", th_payload->evt_status_arr[1]);
Harsh Shah19f55812017-06-26 18:58:49 -07001359
1360 rc = cam_vfe_bus_get_evt_payload(rsrc_data->common_data, &evt_payload);
1361 if (rc) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07001362 CAM_ERR_RATE_LIMIT(CAM_ISP,
1363 "No tasklet_cmd is free in queue\n");
Harsh Shah19f55812017-06-26 18:58:49 -07001364 return rc;
1365 }
1366
1367 cam_isp_hw_get_timestamp(&evt_payload->ts);
1368
1369 evt_payload->ctx = rsrc_data->ctx;
1370 evt_payload->core_index = rsrc_data->common_data->core_index;
1371 evt_payload->evt_id = evt_id;
1372
1373 for (i = 0; i < th_payload->num_registers; i++)
1374 evt_payload->irq_reg_val[i] = th_payload->evt_status_arr[i];
1375
1376 th_payload->evt_payload_priv = evt_payload;
1377
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07001378 CAM_DBG(CAM_ISP, "Exit");
Harsh Shah19f55812017-06-26 18:58:49 -07001379 return rc;
Harsh Shaha1af8822017-05-11 22:06:36 -07001380}
1381
1382static int cam_vfe_bus_handle_comp_done_bottom_half(
1383 void *handler_priv,
1384 void *evt_payload_priv)
1385{
1386 int rc = CAM_VFE_IRQ_STATUS_ERR;
1387 struct cam_isp_resource_node *comp_grp = handler_priv;
1388 struct cam_vfe_bus_irq_evt_payload *evt_payload = evt_payload_priv;
1389 struct cam_vfe_bus_ver2_comp_grp_data *rsrc_data = comp_grp->res_priv;
Harsh Shah23557ae2017-05-13 18:14:34 -07001390 uint32_t *cam_ife_irq_regs;
1391 uint32_t status_reg;
1392 uint32_t comp_err_reg;
1393 uint32_t comp_grp_id;
1394
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07001395 CAM_DBG(CAM_ISP, "comp grp type %d", rsrc_data->comp_grp_type);
Harsh Shah19f55812017-06-26 18:58:49 -07001396
Harsh Shah23557ae2017-05-13 18:14:34 -07001397 if (!evt_payload)
1398 return rc;
1399
1400 cam_ife_irq_regs = evt_payload->irq_reg_val;
Harsh Shaha1af8822017-05-11 22:06:36 -07001401
Harsh Shaha1af8822017-05-11 22:06:36 -07001402 switch (rsrc_data->comp_grp_type) {
1403 case CAM_VFE_BUS_VER2_COMP_GRP_0:
1404 case CAM_VFE_BUS_VER2_COMP_GRP_1:
1405 case CAM_VFE_BUS_VER2_COMP_GRP_2:
1406 case CAM_VFE_BUS_VER2_COMP_GRP_3:
1407 case CAM_VFE_BUS_VER2_COMP_GRP_4:
1408 case CAM_VFE_BUS_VER2_COMP_GRP_5:
Harsh Shah23557ae2017-05-13 18:14:34 -07001409 comp_grp_id = (rsrc_data->comp_grp_type -
Harsh Shaha1af8822017-05-11 22:06:36 -07001410 CAM_VFE_BUS_VER2_COMP_GRP_0);
1411
1412 /* Check for Regular composite error */
1413 status_reg = cam_ife_irq_regs[CAM_IFE_IRQ_BUS_REG_STATUS0];
1414
1415 comp_err_reg = cam_ife_irq_regs[CAM_IFE_IRQ_BUS_REG_COMP_ERR];
1416 if ((status_reg & BIT(11)) &&
1417 (comp_err_reg & rsrc_data->composite_mask)) {
1418 /* Check for Regular composite error */
1419 rc = CAM_VFE_IRQ_STATUS_ERR_COMP;
1420 break;
1421 }
1422
1423 comp_err_reg = cam_ife_irq_regs[CAM_IFE_IRQ_BUS_REG_COMP_OWRT];
1424 /* Check for Regular composite Overwrite */
1425 if ((status_reg & BIT(12)) &&
1426 (comp_err_reg & rsrc_data->composite_mask)) {
1427 rc = CAM_VFE_IRQ_STATUS_COMP_OWRT;
1428 break;
1429 }
1430
Harsh Shah23557ae2017-05-13 18:14:34 -07001431 /* Regular Composite SUCCESS */
1432 if (status_reg & BIT(comp_grp_id + 5)) {
1433 cam_ife_irq_regs[CAM_IFE_IRQ_BUS_REG_STATUS0] &=
1434 ~BIT(comp_grp_id + 5);
Harsh Shaha1af8822017-05-11 22:06:36 -07001435 rc = CAM_VFE_IRQ_STATUS_SUCCESS;
Harsh Shah23557ae2017-05-13 18:14:34 -07001436 }
Harsh Shaha1af8822017-05-11 22:06:36 -07001437
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07001438 CAM_DBG(CAM_ISP, "status reg = 0x%x, bit index = %d rc %d",
Harsh Shah19f55812017-06-26 18:58:49 -07001439 status_reg, (comp_grp_id + 5), rc);
Harsh Shaha1af8822017-05-11 22:06:36 -07001440 break;
1441
1442 case CAM_VFE_BUS_VER2_COMP_GRP_DUAL_0:
1443 case CAM_VFE_BUS_VER2_COMP_GRP_DUAL_1:
1444 case CAM_VFE_BUS_VER2_COMP_GRP_DUAL_2:
1445 case CAM_VFE_BUS_VER2_COMP_GRP_DUAL_3:
1446 case CAM_VFE_BUS_VER2_COMP_GRP_DUAL_4:
1447 case CAM_VFE_BUS_VER2_COMP_GRP_DUAL_5:
Harsh Shah23557ae2017-05-13 18:14:34 -07001448 comp_grp_id = (rsrc_data->comp_grp_type -
Harsh Shaha1af8822017-05-11 22:06:36 -07001449 CAM_VFE_BUS_VER2_COMP_GRP_DUAL_0);
1450
1451 /* Check for DUAL composite error */
1452 status_reg = cam_ife_irq_regs[CAM_IFE_IRQ_BUS_REG_STATUS2];
1453
1454 comp_err_reg = cam_ife_irq_regs[CAM_IFE_IRQ_BUS_DUAL_COMP_ERR];
1455 if ((status_reg & BIT(6)) &&
1456 (comp_err_reg & rsrc_data->composite_mask)) {
1457 /* Check for DUAL composite error */
1458 rc = CAM_VFE_IRQ_STATUS_ERR_COMP;
1459 break;
1460 }
1461
1462 /* Check for Dual composite Overwrite */
1463 comp_err_reg = cam_ife_irq_regs[CAM_IFE_IRQ_BUS_DUAL_COMP_OWRT];
1464 if ((status_reg & BIT(7)) &&
1465 (comp_err_reg & rsrc_data->composite_mask)) {
1466 rc = CAM_VFE_IRQ_STATUS_COMP_OWRT;
1467 break;
1468 }
1469
Harsh Shah23557ae2017-05-13 18:14:34 -07001470 /* DUAL Composite SUCCESS */
1471 if (status_reg & BIT(comp_grp_id)) {
1472 cam_ife_irq_regs[CAM_IFE_IRQ_BUS_REG_STATUS2] &=
1473 ~BIT(comp_grp_id + 5);
Harsh Shaha1af8822017-05-11 22:06:36 -07001474 rc = CAM_VFE_IRQ_STATUS_SUCCESS;
Harsh Shah23557ae2017-05-13 18:14:34 -07001475 }
Harsh Shaha1af8822017-05-11 22:06:36 -07001476
1477 break;
Harsh Shaha1af8822017-05-11 22:06:36 -07001478 default:
1479 rc = CAM_VFE_IRQ_STATUS_ERR;
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07001480 CAM_ERR(CAM_ISP, "Error! Invalid comp_grp_type %u",
Harsh Shah19f55812017-06-26 18:58:49 -07001481 rsrc_data->comp_grp_type);
Harsh Shaha1af8822017-05-11 22:06:36 -07001482 break;
1483 }
1484
1485 if (rc == CAM_VFE_IRQ_STATUS_SUCCESS)
Harsh Shah19f55812017-06-26 18:58:49 -07001486 cam_vfe_bus_put_evt_payload(rsrc_data->common_data,
Harsh Shaha1af8822017-05-11 22:06:36 -07001487 &evt_payload);
1488
1489 return rc;
1490}
1491
1492static int cam_vfe_bus_init_comp_grp(uint32_t index,
1493 struct cam_vfe_bus_ver2_priv *ver2_bus_priv,
1494 struct cam_vfe_bus_ver2_hw_info *ver2_hw_info,
1495 struct cam_isp_resource_node *comp_grp)
1496{
Harsh Shah545df9a2017-06-16 16:43:17 -07001497 struct cam_vfe_bus_ver2_comp_grp_data *rsrc_data = NULL;
Harsh Shaha1af8822017-05-11 22:06:36 -07001498
1499 rsrc_data = kzalloc(sizeof(struct cam_vfe_bus_ver2_comp_grp_data),
1500 GFP_KERNEL);
1501 if (!rsrc_data) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07001502 CAM_DBG(CAM_ISP, "Failed to alloc for comp_grp_priv");
Harsh Shaha1af8822017-05-11 22:06:36 -07001503 return -ENOMEM;
1504 }
1505 comp_grp->res_priv = rsrc_data;
1506
1507 comp_grp->res_state = CAM_ISP_RESOURCE_STATE_AVAILABLE;
1508 INIT_LIST_HEAD(&comp_grp->list);
1509
1510 rsrc_data->comp_grp_type = index;
1511 rsrc_data->common_data = &ver2_bus_priv->common_data;
1512 rsrc_data->hw_regs = &ver2_hw_info->comp_grp_reg[index];
1513 rsrc_data->dual_slave_core = CAM_VFE_BUS_VER2_VFE_CORE_MAX;
1514
Harsh Shaha1af8822017-05-11 22:06:36 -07001515 if (rsrc_data->comp_grp_type >= CAM_VFE_BUS_VER2_COMP_GRP_DUAL_0 &&
1516 rsrc_data->comp_grp_type <= CAM_VFE_BUS_VER2_COMP_GRP_DUAL_5)
1517 list_add_tail(&comp_grp->list,
1518 &ver2_bus_priv->free_dual_comp_grp);
1519 else if (rsrc_data->comp_grp_type >= CAM_VFE_BUS_VER2_COMP_GRP_0
1520 && rsrc_data->comp_grp_type <= CAM_VFE_BUS_VER2_COMP_GRP_5)
1521 list_add_tail(&comp_grp->list, &ver2_bus_priv->free_comp_grp);
1522
1523 comp_grp->start = cam_vfe_bus_start_comp_grp;
1524 comp_grp->stop = cam_vfe_bus_stop_comp_grp;
1525 comp_grp->top_half_handler = cam_vfe_bus_handle_comp_done_top_half;
1526 comp_grp->bottom_half_handler =
1527 cam_vfe_bus_handle_comp_done_bottom_half;
1528 comp_grp->hw_intf = ver2_bus_priv->common_data.hw_intf;
1529
1530 return 0;
1531}
1532
Harsh Shah545df9a2017-06-16 16:43:17 -07001533static int cam_vfe_bus_deinit_comp_grp(
1534 struct cam_isp_resource_node *comp_grp)
1535{
1536 struct cam_vfe_bus_ver2_comp_grp_data *rsrc_data =
1537 comp_grp->res_priv;
1538
1539 comp_grp->start = NULL;
1540 comp_grp->stop = NULL;
1541 comp_grp->top_half_handler = NULL;
1542 comp_grp->bottom_half_handler = NULL;
1543 comp_grp->hw_intf = NULL;
1544
1545 list_del_init(&comp_grp->list);
1546 comp_grp->res_state = CAM_ISP_RESOURCE_STATE_UNAVAILABLE;
1547
1548 comp_grp->res_priv = NULL;
1549
1550 if (!rsrc_data) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07001551 CAM_ERR(CAM_ISP, "Error! comp_grp_priv is NULL");
Harsh Shah545df9a2017-06-16 16:43:17 -07001552 return -ENODEV;
1553 }
1554 kfree(rsrc_data);
1555
1556 return 0;
1557}
1558
Harsh Shah19f55812017-06-26 18:58:49 -07001559static int cam_vfe_bus_acquire_vfe_out(void *bus_priv, void *acquire_args,
1560 uint32_t args_size)
Harsh Shaha1af8822017-05-11 22:06:36 -07001561{
1562 int rc = -ENODEV;
1563 int i;
1564 enum cam_vfe_bus_ver2_vfe_out_type vfe_out_res_id;
1565 uint32_t format;
1566 uint32_t num_wm;
1567 uint32_t subscribe_irq;
1568 uint32_t client_done_mask;
1569 struct cam_vfe_bus_ver2_priv *ver2_bus_priv = bus_priv;
1570 struct cam_vfe_acquire_args *acq_args = acquire_args;
1571 struct cam_vfe_hw_vfe_out_acquire_args *out_acquire_args;
1572 struct cam_isp_resource_node *rsrc_node = NULL;
1573 struct cam_vfe_bus_ver2_vfe_out_data *rsrc_data = NULL;
1574
1575 if (!bus_priv || !acquire_args) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07001576 CAM_ERR(CAM_ISP, "Invalid Param");
Harsh Shaha1af8822017-05-11 22:06:36 -07001577 return -EINVAL;
1578 }
1579
1580 out_acquire_args = &acq_args->vfe_out;
1581 format = out_acquire_args->out_port_info->format;
1582
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07001583 CAM_DBG(CAM_ISP, "Acquiring resource type 0x%x",
Harsh Shaha1af8822017-05-11 22:06:36 -07001584 out_acquire_args->out_port_info->res_type);
1585
1586 vfe_out_res_id = cam_vfe_bus_get_out_res_id(
1587 out_acquire_args->out_port_info->res_type);
1588 if (vfe_out_res_id == CAM_VFE_BUS_VER2_VFE_OUT_MAX)
1589 return -ENODEV;
1590
1591 num_wm = cam_vfe_bus_get_num_wm(vfe_out_res_id, format);
1592 if (num_wm < 1)
1593 return -EINVAL;
1594
1595 rsrc_node = &ver2_bus_priv->vfe_out[vfe_out_res_id];
1596 if (rsrc_node->res_state != CAM_ISP_RESOURCE_STATE_AVAILABLE) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07001597 CAM_ERR(CAM_ISP, "Resource not available: Res_id %d state:%d",
Harsh Shaha1af8822017-05-11 22:06:36 -07001598 vfe_out_res_id, rsrc_node->res_state);
1599 return -EBUSY;
1600 }
1601
1602 rsrc_data = rsrc_node->res_priv;
1603 rsrc_data->num_wm = num_wm;
1604 rsrc_node->res_id = out_acquire_args->out_port_info->res_type;
1605 rsrc_node->tasklet_info = acq_args->tasklet;
1606 rsrc_node->cdm_ops = out_acquire_args->cdm_ops;
1607 rsrc_data->cdm_util_ops = out_acquire_args->cdm_ops;
1608
1609 /* Reserve Composite Group */
1610 if (num_wm > 1 || (out_acquire_args->out_port_info->comp_grp_id >
1611 CAM_ISP_RES_COMP_GROUP_NONE &&
1612 out_acquire_args->out_port_info->comp_grp_id <
1613 CAM_ISP_RES_COMP_GROUP_ID_MAX)) {
1614 rc = cam_vfe_bus_acquire_comp_grp(ver2_bus_priv,
1615 out_acquire_args->out_port_info,
Harsh Shah19f55812017-06-26 18:58:49 -07001616 acq_args->tasklet,
1617 out_acquire_args->ctx,
Harsh Shaha1af8822017-05-11 22:06:36 -07001618 out_acquire_args->unique_id,
1619 out_acquire_args->is_dual,
1620 out_acquire_args->is_master,
1621 out_acquire_args->dual_slave_core,
1622 &rsrc_data->comp_grp);
Harsh Shah19f55812017-06-26 18:58:49 -07001623 if (rc) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07001624 CAM_ERR(CAM_ISP,
1625 "VFE%d Comp_Grp acquire fail for Out %d rc=%d",
Harsh Shah19f55812017-06-26 18:58:49 -07001626 rsrc_data->common_data->core_index,
1627 vfe_out_res_id, rc);
Harsh Shaha1af8822017-05-11 22:06:36 -07001628 return rc;
Harsh Shah19f55812017-06-26 18:58:49 -07001629 }
Harsh Shaha1af8822017-05-11 22:06:36 -07001630
1631 subscribe_irq = 0;
Harsh Shah19f55812017-06-26 18:58:49 -07001632 } else {
Harsh Shaha1af8822017-05-11 22:06:36 -07001633 subscribe_irq = 1;
Harsh Shah19f55812017-06-26 18:58:49 -07001634 }
Harsh Shaha1af8822017-05-11 22:06:36 -07001635
1636 /* Reserve WM */
1637 for (i = 0; i < num_wm; i++) {
1638 rc = cam_vfe_bus_acquire_wm(ver2_bus_priv,
1639 out_acquire_args->out_port_info,
Harsh Shah19f55812017-06-26 18:58:49 -07001640 acq_args->tasklet,
1641 out_acquire_args->ctx,
Harsh Shaha1af8822017-05-11 22:06:36 -07001642 vfe_out_res_id,
1643 i,
1644 out_acquire_args->split_id,
1645 subscribe_irq,
1646 &rsrc_data->wm_res[i],
1647 &client_done_mask);
Harsh Shah19f55812017-06-26 18:58:49 -07001648 if (rc) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07001649 CAM_ERR(CAM_ISP,
1650 "VFE%d WM acquire failed for Out %d rc=%d",
Harsh Shah19f55812017-06-26 18:58:49 -07001651 rsrc_data->common_data->core_index,
1652 vfe_out_res_id, rc);
Harsh Shaha1af8822017-05-11 22:06:36 -07001653 goto release_wm;
Harsh Shah19f55812017-06-26 18:58:49 -07001654 }
Harsh Shaha1af8822017-05-11 22:06:36 -07001655
1656 if (rsrc_data->comp_grp)
1657 cam_vfe_bus_add_wm_to_comp_grp(rsrc_data->comp_grp,
1658 client_done_mask);
1659 }
1660
1661 rsrc_node->res_state = CAM_ISP_RESOURCE_STATE_RESERVED;
1662 out_acquire_args->rsrc_node = rsrc_node;
1663
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07001664 CAM_DBG(CAM_ISP, "Acquire successful");
Harsh Shaha1af8822017-05-11 22:06:36 -07001665 return rc;
1666
1667release_wm:
1668 for (i--; i >= 0; i--)
1669 cam_vfe_bus_release_wm(ver2_bus_priv, rsrc_data->wm_res[i]);
1670
1671 cam_vfe_bus_release_comp_grp(ver2_bus_priv,
1672 rsrc_data->comp_grp);
1673
1674 return rc;
1675}
1676
Harsh Shah19f55812017-06-26 18:58:49 -07001677static int cam_vfe_bus_release_vfe_out(void *bus_priv, void *release_args,
1678 uint32_t args_size)
Harsh Shaha1af8822017-05-11 22:06:36 -07001679{
Jing Zhoue71fd4a2017-05-15 19:44:34 -07001680 uint32_t i;
Harsh Shah19f55812017-06-26 18:58:49 -07001681 struct cam_isp_resource_node *vfe_out = NULL;
1682 struct cam_vfe_bus_ver2_vfe_out_data *rsrc_data = NULL;
1683
1684 if (!bus_priv || !release_args) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07001685 CAM_ERR(CAM_ISP, "Invalid input bus_priv %pK release_args %pK",
Harsh Shah19f55812017-06-26 18:58:49 -07001686 bus_priv, release_args);
1687 return -EINVAL;
1688 }
1689
1690 vfe_out = release_args;
1691 rsrc_data = vfe_out->res_priv;
Jing Zhoue71fd4a2017-05-15 19:44:34 -07001692
Harsh Shaha1af8822017-05-11 22:06:36 -07001693 if (vfe_out->res_state != CAM_ISP_RESOURCE_STATE_RESERVED) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07001694 CAM_ERR(CAM_ISP, "Error! Invalid resource state:%d",
Harsh Shaha1af8822017-05-11 22:06:36 -07001695 vfe_out->res_state);
1696 }
1697
Jing Zhoue71fd4a2017-05-15 19:44:34 -07001698 for (i = 0; i < rsrc_data->num_wm; i++)
1699 cam_vfe_bus_release_wm(bus_priv, rsrc_data->wm_res[i]);
1700 rsrc_data->num_wm = 0;
1701
1702 if (rsrc_data->comp_grp)
1703 cam_vfe_bus_release_comp_grp(bus_priv, rsrc_data->comp_grp);
1704 rsrc_data->comp_grp = NULL;
1705
1706 vfe_out->tasklet_info = NULL;
1707 vfe_out->cdm_ops = NULL;
1708 rsrc_data->cdm_util_ops = NULL;
1709
Harsh Shaha1af8822017-05-11 22:06:36 -07001710 if (vfe_out->res_state == CAM_ISP_RESOURCE_STATE_RESERVED)
1711 vfe_out->res_state = CAM_ISP_RESOURCE_STATE_AVAILABLE;
1712
1713 return 0;
1714}
1715
Harsh Shah19f55812017-06-26 18:58:49 -07001716static int cam_vfe_bus_start_vfe_out(
1717 struct cam_isp_resource_node *vfe_out)
Harsh Shaha1af8822017-05-11 22:06:36 -07001718{
1719 int rc = 0, i;
Harsh Shah19f55812017-06-26 18:58:49 -07001720 struct cam_vfe_bus_ver2_vfe_out_data *rsrc_data = NULL;
1721 struct cam_vfe_bus_ver2_common_data *common_data = NULL;
1722
1723 if (!vfe_out) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07001724 CAM_ERR(CAM_ISP, "Invalid input");
Harsh Shah19f55812017-06-26 18:58:49 -07001725 return -EINVAL;
1726 }
1727
1728 rsrc_data = vfe_out->res_priv;
1729 common_data = rsrc_data->common_data;
Harsh Shaha1af8822017-05-11 22:06:36 -07001730
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07001731 CAM_DBG(CAM_ISP, "Start resource index %d", rsrc_data->out_type);
Harsh Shaha1af8822017-05-11 22:06:36 -07001732
1733 if (vfe_out->res_state != CAM_ISP_RESOURCE_STATE_RESERVED) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07001734 CAM_ERR(CAM_ISP, "Error! Invalid resource state:%d",
Harsh Shaha1af8822017-05-11 22:06:36 -07001735 vfe_out->res_state);
1736 return -EACCES;
1737 }
1738
1739 for (i = 0; i < rsrc_data->num_wm; i++)
1740 rc = cam_vfe_bus_start_wm(rsrc_data->wm_res[i]);
1741
1742 if (rsrc_data->comp_grp)
1743 rc = cam_vfe_bus_start_comp_grp(rsrc_data->comp_grp);
1744
Harsh Shaha1af8822017-05-11 22:06:36 -07001745 /* BUS_WR_INPUT_IF_ADDR_SYNC_CFG */
1746 cam_io_w_mb(0x0, rsrc_data->common_data->mem_base + 0x0000207C);
1747 /* BUS_WR_INPUT_IF_ADDR_SYNC_FRAME_HEADER */
1748 cam_io_w_mb(0x0, rsrc_data->common_data->mem_base + 0x00002080);
1749 /* BUS_WR_INPUT_IF_ADDR_SYNC_NO_SYNC */
1750 cam_io_w_mb(0xFFFFF, rsrc_data->common_data->mem_base + 0x00002084);
Harsh Shaha1af8822017-05-11 22:06:36 -07001751 /* BUS_WR_INPUT_IF_ADDR_SYNC_0 */
1752 cam_io_w_mb(0x0, rsrc_data->common_data->mem_base + 0x00002088);
1753 cam_io_w_mb(0x0, rsrc_data->common_data->mem_base + 0x0000208c);
1754 cam_io_w_mb(0x0, rsrc_data->common_data->mem_base + 0x00002090);
1755 cam_io_w_mb(0x0, rsrc_data->common_data->mem_base + 0x00002094);
1756 cam_io_w_mb(0x0, rsrc_data->common_data->mem_base + 0x00002098);
1757 cam_io_w_mb(0x0, rsrc_data->common_data->mem_base + 0x0000209c);
1758 cam_io_w_mb(0x0, rsrc_data->common_data->mem_base + 0x000020a0);
1759 cam_io_w_mb(0x0, rsrc_data->common_data->mem_base + 0x000020a4);
1760
Harsh Shah23557ae2017-05-13 18:14:34 -07001761 /* no clock gating at bus input */
1762 cam_io_w_mb(0xFFFFF, rsrc_data->common_data->mem_base + 0x0000200C);
1763
1764 /* BUS_WR_TEST_BUS_CTRL */
1765 cam_io_w_mb(0x0, rsrc_data->common_data->mem_base + 0x0000211C);
1766
Abhishek Kondaveeti157ae882017-07-08 06:56:48 +05301767 vfe_out->res_state = CAM_ISP_RESOURCE_STATE_STREAMING;
Harsh Shaha1af8822017-05-11 22:06:36 -07001768 return rc;
1769}
1770
Harsh Shah19f55812017-06-26 18:58:49 -07001771static int cam_vfe_bus_stop_vfe_out(
1772 struct cam_isp_resource_node *vfe_out)
Harsh Shaha1af8822017-05-11 22:06:36 -07001773{
1774 int rc = 0, i;
Harsh Shah19f55812017-06-26 18:58:49 -07001775 struct cam_vfe_bus_ver2_vfe_out_data *rsrc_data = NULL;
1776
1777 if (!vfe_out) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07001778 CAM_ERR(CAM_ISP, "Invalid input");
Harsh Shah19f55812017-06-26 18:58:49 -07001779 return -EINVAL;
1780 }
1781
1782 rsrc_data = vfe_out->res_priv;
Harsh Shaha1af8822017-05-11 22:06:36 -07001783
1784 if (vfe_out->res_state == CAM_ISP_RESOURCE_STATE_AVAILABLE ||
1785 vfe_out->res_state == CAM_ISP_RESOURCE_STATE_RESERVED) {
1786 return rc;
1787 }
1788
1789 if (rsrc_data->comp_grp)
1790 rc = cam_vfe_bus_stop_comp_grp(rsrc_data->comp_grp);
1791
1792 for (i = 0; i < rsrc_data->num_wm; i++)
1793 rc = cam_vfe_bus_stop_wm(rsrc_data->wm_res[i]);
1794
Harsh Shaha1af8822017-05-11 22:06:36 -07001795
1796 vfe_out->res_state = CAM_ISP_RESOURCE_STATE_RESERVED;
1797 return rc;
1798}
1799
1800static int cam_vfe_bus_handle_vfe_out_done_top_half(uint32_t evt_id,
1801 struct cam_irq_th_payload *th_payload)
1802{
1803 return -EPERM;
1804}
1805
1806static int cam_vfe_bus_handle_vfe_out_done_bottom_half(
1807 void *handler_priv,
1808 void *evt_payload_priv)
1809{
1810 int rc = -EINVAL;
1811 struct cam_isp_resource_node *vfe_out = handler_priv;
1812 struct cam_vfe_bus_ver2_vfe_out_data *rsrc_data = vfe_out->res_priv;
1813
1814 /*
1815 * If this resource has Composite Group then we only handle
1816 * Composite done. We acquire Composite if number of WM > 1.
1817 * So Else case is only one individual buf_done = WM[0].
1818 */
1819 if (rsrc_data->comp_grp) {
1820 rc = rsrc_data->comp_grp->bottom_half_handler(
1821 rsrc_data->comp_grp, evt_payload_priv);
1822 } else {
1823 rc = rsrc_data->wm_res[0]->bottom_half_handler(
Harsh Shah23557ae2017-05-13 18:14:34 -07001824 rsrc_data->wm_res[0], evt_payload_priv);
Harsh Shaha1af8822017-05-11 22:06:36 -07001825 }
1826
1827 return rc;
1828}
1829
1830static int cam_vfe_bus_init_vfe_out_resource(uint32_t index,
1831 struct cam_vfe_bus_ver2_priv *ver2_bus_priv,
1832 struct cam_vfe_bus_ver2_hw_info *ver2_hw_info,
1833 struct cam_isp_resource_node *vfe_out)
1834{
1835 struct cam_vfe_bus_ver2_vfe_out_data *rsrc_data = NULL;
1836 int rc = 0;
1837
1838 rsrc_data = kzalloc(sizeof(struct cam_vfe_bus_ver2_vfe_out_data),
1839 GFP_KERNEL);
1840 if (!rsrc_data) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07001841 CAM_DBG(CAM_ISP, "Error! Failed to alloc for vfe out priv");
Harsh Shaha1af8822017-05-11 22:06:36 -07001842 rc = -ENOMEM;
1843 return rc;
1844 }
1845 vfe_out->res_priv = rsrc_data;
1846
1847 vfe_out->res_type = CAM_ISP_RESOURCE_VFE_OUT;
1848 vfe_out->res_state = CAM_ISP_RESOURCE_STATE_AVAILABLE;
1849 INIT_LIST_HEAD(&vfe_out->list);
1850
1851 rsrc_data->out_type = index;
1852 rsrc_data->common_data = &ver2_bus_priv->common_data;
1853 rsrc_data->max_width =
1854 ver2_hw_info->vfe_out_hw_info[index].max_width;
1855 rsrc_data->max_height =
1856 ver2_hw_info->vfe_out_hw_info[index].max_height;
1857
1858 vfe_out->start = cam_vfe_bus_start_vfe_out;
1859 vfe_out->stop = cam_vfe_bus_stop_vfe_out;
1860 vfe_out->top_half_handler = cam_vfe_bus_handle_vfe_out_done_top_half;
1861 vfe_out->bottom_half_handler =
1862 cam_vfe_bus_handle_vfe_out_done_bottom_half;
1863 vfe_out->hw_intf = ver2_bus_priv->common_data.hw_intf;
1864
1865 return 0;
1866}
1867
Harsh Shah545df9a2017-06-16 16:43:17 -07001868static int cam_vfe_bus_deinit_vfe_out_resource(
1869 struct cam_isp_resource_node *vfe_out)
1870{
1871 struct cam_vfe_bus_ver2_vfe_out_data *rsrc_data = vfe_out->res_priv;
1872
1873 vfe_out->start = NULL;
1874 vfe_out->stop = NULL;
1875 vfe_out->top_half_handler = NULL;
1876 vfe_out->bottom_half_handler = NULL;
1877 vfe_out->hw_intf = NULL;
1878
1879 vfe_out->res_state = CAM_ISP_RESOURCE_STATE_UNAVAILABLE;
1880 INIT_LIST_HEAD(&vfe_out->list);
1881 vfe_out->res_priv = NULL;
1882
1883 if (!rsrc_data) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07001884 CAM_ERR(CAM_ISP, "Error! vfe out priv is NULL");
Harsh Shah545df9a2017-06-16 16:43:17 -07001885 return -ENOMEM;
1886 }
1887 kfree(rsrc_data);
1888
1889 return 0;
1890}
1891
Harsh Shaha1af8822017-05-11 22:06:36 -07001892static int cam_vfe_bus_ver2_handle_irq(uint32_t evt_id,
1893 struct cam_irq_th_payload *th_payload)
1894{
Harsh Shaha1af8822017-05-11 22:06:36 -07001895 struct cam_vfe_bus_ver2_priv *bus_priv;
Harsh Shaha1af8822017-05-11 22:06:36 -07001896
Harsh Shah19f55812017-06-26 18:58:49 -07001897 bus_priv = th_payload->handler_priv;
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07001898 CAM_DBG(CAM_ISP, "Enter");
Harsh Shah19f55812017-06-26 18:58:49 -07001899 return cam_irq_controller_handle_irq(evt_id,
1900 bus_priv->common_data.bus_irq_controller);
Harsh Shaha1af8822017-05-11 22:06:36 -07001901}
1902
1903static int cam_vfe_bus_update_buf(void *priv, void *cmd_args,
1904 uint32_t arg_size)
1905{
1906 struct cam_vfe_bus_ver2_priv *bus_priv;
1907 struct cam_isp_hw_get_buf_update *update_buf;
Jing Zhoua4e9fbe2017-05-15 14:37:21 -07001908 struct cam_buf_io_cfg *io_cfg;
Harsh Shaha1af8822017-05-11 22:06:36 -07001909 struct cam_vfe_bus_ver2_vfe_out_data *vfe_out_data = NULL;
1910 struct cam_vfe_bus_ver2_wm_resource_data *wm_data = NULL;
Jing Zhoua4e9fbe2017-05-15 14:37:21 -07001911 uint32_t *reg_val_pair;
1912 uint32_t i, j, size = 0;
Junzhe Zou193d78c2017-05-16 15:10:54 -07001913 uint32_t frame_inc = 0;
Harsh Shaha1af8822017-05-11 22:06:36 -07001914
1915 /*
1916 * Need the entire buf io config so we can get the stride info
1917 * for the wm.
1918 */
1919
1920 bus_priv = (struct cam_vfe_bus_ver2_priv *) priv;
1921 update_buf = (struct cam_isp_hw_get_buf_update *) cmd_args;
1922
1923 vfe_out_data = (struct cam_vfe_bus_ver2_vfe_out_data *)
1924 update_buf->cdm.res->res_priv;
1925
1926 if (!vfe_out_data || !vfe_out_data->cdm_util_ops) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07001927 CAM_ERR(CAM_ISP, "Failed! Invalid data");
Harsh Shaha1af8822017-05-11 22:06:36 -07001928 return -EINVAL;
1929 }
1930
Jing Zhoua4e9fbe2017-05-15 14:37:21 -07001931 if (update_buf->num_buf != vfe_out_data->num_wm) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07001932 CAM_ERR(CAM_ISP,
1933 "Failed! Invalid number buffers:%d required:%d",
Harsh Shaha1af8822017-05-11 22:06:36 -07001934 update_buf->num_buf, vfe_out_data->num_wm);
Junzhe Zou193d78c2017-05-16 15:10:54 -07001935 return -EINVAL;
Harsh Shaha1af8822017-05-11 22:06:36 -07001936 }
1937
Jing Zhoua4e9fbe2017-05-15 14:37:21 -07001938 reg_val_pair = &vfe_out_data->common_data->io_buf_update[0];
1939 io_cfg = update_buf->io_cfg;
1940
1941 for (i = 0, j = 0; i < vfe_out_data->num_wm; i++) {
Junzhe Zou193d78c2017-05-16 15:10:54 -07001942 if (j >= (MAX_REG_VAL_PAIR_SIZE - MAX_BUF_UPDATE_REG_NUM * 2)) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07001943 CAM_ERR(CAM_ISP,
1944 "reg_val_pair %d exceeds the array limit %lu",
Junzhe Zou193d78c2017-05-16 15:10:54 -07001945 j, MAX_REG_VAL_PAIR_SIZE);
1946 return -ENOMEM;
1947 }
1948
Jing Zhoua4e9fbe2017-05-15 14:37:21 -07001949 wm_data = vfe_out_data->wm_res[i]->res_priv;
1950
1951 /* For initial configuration program all bus registers */
Ravikishore Pampanaad6bc902017-07-12 19:37:06 +05301952 if ((wm_data->stride != io_cfg->planes[i].plane_stride ||
1953 !wm_data->init_cfg_done) && (wm_data->index >= 3)) {
Jing Zhoua4e9fbe2017-05-15 14:37:21 -07001954 CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j,
1955 wm_data->hw_regs->stride,
1956 io_cfg->planes[i].plane_stride);
1957 wm_data->stride = io_cfg->planes[i].plane_stride;
1958 }
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07001959 CAM_DBG(CAM_ISP, "image stride 0x%x", wm_data->stride);
Jing Zhoua4e9fbe2017-05-15 14:37:21 -07001960
1961 if (wm_data->framedrop_pattern != io_cfg->framedrop_pattern ||
1962 !wm_data->init_cfg_done) {
1963 CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j,
1964 wm_data->hw_regs->framedrop_pattern,
1965 io_cfg->framedrop_pattern);
1966 wm_data->framedrop_pattern = io_cfg->framedrop_pattern;
1967 }
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07001968 CAM_DBG(CAM_ISP, "framedrop pattern 0x%x",
1969 wm_data->framedrop_pattern);
Jing Zhoua4e9fbe2017-05-15 14:37:21 -07001970
1971 if (wm_data->framedrop_period != io_cfg->framedrop_period ||
1972 !wm_data->init_cfg_done) {
1973 CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j,
1974 wm_data->hw_regs->framedrop_period,
1975 io_cfg->framedrop_period);
1976 wm_data->framedrop_period = io_cfg->framedrop_period;
1977 }
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07001978 CAM_DBG(CAM_ISP, "framedrop period 0x%x",
1979 wm_data->framedrop_period);
Jing Zhoua4e9fbe2017-05-15 14:37:21 -07001980
1981 if (wm_data->irq_subsample_period != io_cfg->subsample_period
1982 || !wm_data->init_cfg_done) {
1983 CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j,
1984 wm_data->hw_regs->irq_subsample_period,
1985 io_cfg->subsample_period);
1986 wm_data->irq_subsample_period =
1987 io_cfg->subsample_period;
1988 }
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07001989 CAM_DBG(CAM_ISP, "irq subsample period 0x%x",
Jing Zhoua4e9fbe2017-05-15 14:37:21 -07001990 wm_data->irq_subsample_period);
1991
1992 if (wm_data->irq_subsample_pattern != io_cfg->subsample_pattern
1993 || !wm_data->init_cfg_done) {
1994 CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j,
1995 wm_data->hw_regs->irq_subsample_pattern,
1996 io_cfg->subsample_pattern);
1997 wm_data->irq_subsample_pattern =
1998 io_cfg->subsample_pattern;
1999 }
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07002000 CAM_DBG(CAM_ISP, "irq subsample pattern 0x%x",
Jing Zhoua4e9fbe2017-05-15 14:37:21 -07002001 wm_data->irq_subsample_pattern);
2002
2003 if (wm_data->en_ubwc) {
2004 if (!wm_data->hw_regs->ubwc_regs) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07002005 CAM_ERR(CAM_ISP,
2006 "No UBWC register to configure.");
Jing Zhoua4e9fbe2017-05-15 14:37:21 -07002007 return -EINVAL;
2008 }
2009 if (wm_data->packer_cfg !=
2010 io_cfg->planes[i].packer_config ||
2011 !wm_data->init_cfg_done) {
2012 CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j,
2013 wm_data->hw_regs->packer_cfg,
2014 io_cfg->planes[i].packer_config);
2015 wm_data->packer_cfg =
2016 io_cfg->planes[i].packer_config;
2017 }
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07002018 CAM_DBG(CAM_ISP, "packer cfg 0x%x",
2019 wm_data->packer_cfg);
Jing Zhoua4e9fbe2017-05-15 14:37:21 -07002020
2021 if (wm_data->tile_cfg != io_cfg->planes[i].tile_config
2022 || !wm_data->init_cfg_done) {
2023 CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j,
2024 wm_data->hw_regs->ubwc_regs->tile_cfg,
2025 io_cfg->planes[i].tile_config);
2026 wm_data->tile_cfg =
2027 io_cfg->planes[i].tile_config;
2028 }
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07002029 CAM_DBG(CAM_ISP, "tile cfg 0x%x", wm_data->tile_cfg);
Jing Zhoua4e9fbe2017-05-15 14:37:21 -07002030
2031 if (wm_data->h_init != io_cfg->planes[i].h_init ||
2032 !wm_data->init_cfg_done) {
2033 CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j,
2034 wm_data->hw_regs->ubwc_regs->h_init,
2035 io_cfg->planes[i].h_init);
2036 wm_data->h_init = io_cfg->planes[i].h_init;
2037 }
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07002038 CAM_DBG(CAM_ISP, "h_init 0x%x", wm_data->h_init);
Jing Zhoua4e9fbe2017-05-15 14:37:21 -07002039
2040 if (wm_data->v_init != io_cfg->planes[i].v_init ||
2041 !wm_data->init_cfg_done) {
2042 CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j,
2043 wm_data->hw_regs->ubwc_regs->v_init,
2044 io_cfg->planes[i].v_init);
2045 wm_data->v_init = io_cfg->planes[i].v_init;
2046 }
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07002047 CAM_DBG(CAM_ISP, "v_init 0x%x", wm_data->v_init);
Jing Zhoua4e9fbe2017-05-15 14:37:21 -07002048
2049 if (wm_data->ubwc_meta_stride !=
2050 io_cfg->planes[i].meta_stride ||
2051 !wm_data->init_cfg_done) {
2052 CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j,
2053 wm_data->hw_regs->ubwc_regs->
2054 meta_stride,
2055 io_cfg->planes[i].meta_stride);
2056 wm_data->ubwc_meta_stride =
2057 io_cfg->planes[i].meta_stride;
2058 }
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07002059 CAM_DBG(CAM_ISP, "meta stride 0x%x",
2060 wm_data->ubwc_meta_stride);
Jing Zhoua4e9fbe2017-05-15 14:37:21 -07002061
2062 if (wm_data->ubwc_mode_cfg !=
2063 io_cfg->planes[i].mode_config ||
2064 !wm_data->init_cfg_done) {
2065 CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j,
2066 wm_data->hw_regs->ubwc_regs->mode_cfg,
2067 io_cfg->planes[i].mode_config);
2068 wm_data->ubwc_mode_cfg =
2069 io_cfg->planes[i].mode_config;
2070 }
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07002071 CAM_DBG(CAM_ISP, "ubwc mode cfg 0x%x",
2072 wm_data->ubwc_mode_cfg);
Jing Zhoua4e9fbe2017-05-15 14:37:21 -07002073
2074 if (wm_data->ubwc_meta_offset !=
2075 io_cfg->planes[i].meta_offset ||
2076 !wm_data->init_cfg_done) {
2077 CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j,
2078 wm_data->hw_regs->ubwc_regs->
2079 meta_offset,
2080 io_cfg->planes[i].meta_offset);
2081 wm_data->ubwc_meta_offset =
2082 io_cfg->planes[i].meta_offset;
2083 }
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07002084 CAM_DBG(CAM_ISP, "ubwc meta offset 0x%x",
Jing Zhoua4e9fbe2017-05-15 14:37:21 -07002085 wm_data->ubwc_meta_offset);
2086
2087 /* UBWC meta address */
2088 CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j,
2089 wm_data->hw_regs->ubwc_regs->meta_addr,
2090 update_buf->image_buf[i]);
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07002091 CAM_DBG(CAM_ISP, "ubwc meta addr 0x%llx",
Jing Zhoua4e9fbe2017-05-15 14:37:21 -07002092 update_buf->image_buf[i]);
2093 }
2094
2095 /* WM Image address */
2096 if (wm_data->en_ubwc)
2097 CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j,
2098 wm_data->hw_regs->image_addr,
2099 (update_buf->image_buf[i] +
2100 io_cfg->planes[i].meta_size));
2101 else
2102 CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j,
2103 wm_data->hw_regs->image_addr,
2104 update_buf->image_buf[i]);
2105
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07002106 CAM_DBG(CAM_ISP, "image address 0x%x", reg_val_pair[j-1]);
Jing Zhoua4e9fbe2017-05-15 14:37:21 -07002107
Junzhe Zou193d78c2017-05-16 15:10:54 -07002108 frame_inc = io_cfg->planes[i].plane_stride *
2109 io_cfg->planes[i].slice_height;
2110 CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j,
2111 wm_data->hw_regs->frame_inc, frame_inc);
2112
Jing Zhoua4e9fbe2017-05-15 14:37:21 -07002113 /* enable the WM */
2114 CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j,
2115 wm_data->hw_regs->cfg,
2116 wm_data->en_cfg);
2117
2118 /* set initial configuration done */
2119 if (!wm_data->init_cfg_done)
2120 wm_data->init_cfg_done = 1;
2121 }
2122
2123 size = vfe_out_data->cdm_util_ops->cdm_required_size_reg_random(j/2);
Harsh Shaha1af8822017-05-11 22:06:36 -07002124
2125 /* cdm util returns dwords, need to convert to bytes */
2126 if ((size * 4) > update_buf->cdm.size) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07002127 CAM_ERR(CAM_ISP,
2128 "Failed! Buf size:%d insufficient, expected size:%d",
Harsh Shaha1af8822017-05-11 22:06:36 -07002129 update_buf->cdm.size, size);
2130 return -ENOMEM;
2131 }
2132
Harsh Shaha1af8822017-05-11 22:06:36 -07002133 vfe_out_data->cdm_util_ops->cdm_write_regrandom(
Jing Zhoua4e9fbe2017-05-15 14:37:21 -07002134 update_buf->cdm.cmd_buf_addr, j/2, reg_val_pair);
2135
Harsh Shaha1af8822017-05-11 22:06:36 -07002136 /* cdm util returns dwords, need to convert to bytes */
2137 update_buf->cdm.used_bytes = size * 4;
2138
2139 return 0;
2140}
2141
Harsh Shah19f55812017-06-26 18:58:49 -07002142static int cam_vfe_bus_start_hw(void *hw_priv,
2143 void *start_hw_args, uint32_t arg_size)
2144{
2145 return cam_vfe_bus_start_vfe_out(hw_priv);
2146}
2147
2148static int cam_vfe_bus_stop_hw(void *hw_priv,
2149 void *stop_hw_args, uint32_t arg_size)
2150{
2151 return cam_vfe_bus_stop_vfe_out(hw_priv);
2152}
2153
2154static int cam_vfe_bus_init_hw(void *hw_priv,
2155 void *init_hw_args, uint32_t arg_size)
2156{
2157 struct cam_vfe_bus_ver2_priv *bus_priv = hw_priv;
2158 uint32_t top_irq_reg_mask[2] = {0};
2159
2160 if (!bus_priv) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07002161 CAM_ERR(CAM_ISP, "Error! Invalid args");
Harsh Shah19f55812017-06-26 18:58:49 -07002162 return -EINVAL;
2163 }
2164
2165 top_irq_reg_mask[0] = (1 << 9);
2166
2167 bus_priv->irq_handle = cam_irq_controller_subscribe_irq(
2168 bus_priv->common_data.vfe_irq_controller,
2169 CAM_IRQ_PRIORITY_2,
2170 top_irq_reg_mask,
2171 bus_priv,
2172 cam_vfe_bus_ver2_handle_irq,
2173 NULL,
2174 NULL,
2175 NULL);
2176
2177 if (bus_priv->irq_handle <= 0) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07002178 CAM_ERR(CAM_ISP, "Failed to subscribe BUS IRQ");
Harsh Shah19f55812017-06-26 18:58:49 -07002179 return -EFAULT;
2180 }
2181
2182 return 0;
2183}
2184
2185static int cam_vfe_bus_deinit_hw(void *hw_priv,
2186 void *deinit_hw_args, uint32_t arg_size)
2187{
2188 struct cam_vfe_bus_ver2_priv *bus_priv = hw_priv;
2189 int rc;
2190
2191 if (!bus_priv || (bus_priv->irq_handle <= 0)) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07002192 CAM_ERR(CAM_ISP, "Error! Invalid args");
Harsh Shah19f55812017-06-26 18:58:49 -07002193 return -EINVAL;
2194 }
2195
2196 rc = cam_irq_controller_unsubscribe_irq(
2197 bus_priv->common_data.vfe_irq_controller,
2198 bus_priv->irq_handle);
2199 if (rc)
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07002200 CAM_ERR(CAM_ISP, "Failed to unsubscribe irq rc=%d", rc);
Harsh Shah19f55812017-06-26 18:58:49 -07002201
2202 return rc;
2203}
2204
Harsh Shaha1af8822017-05-11 22:06:36 -07002205static int cam_vfe_bus_process_cmd(void *priv,
2206 uint32_t cmd_type, void *cmd_args, uint32_t arg_size)
2207{
2208 int rc = -EINVAL;
2209
2210 if (!priv || !cmd_args) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07002211 CAM_ERR_RATE_LIMIT(CAM_ISP, "Error! Invalid input arguments\n");
Harsh Shaha1af8822017-05-11 22:06:36 -07002212 return -EINVAL;
2213 }
2214
2215 switch (cmd_type) {
2216 case CAM_VFE_HW_CMD_GET_BUF_UPDATE:
2217 rc = cam_vfe_bus_update_buf(priv, cmd_args, arg_size);
2218 break;
2219 default:
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07002220 CAM_ERR_RATE_LIMIT(CAM_ISP, "Inval camif process command:%d\n",
Harsh Shaha1af8822017-05-11 22:06:36 -07002221 cmd_type);
2222 break;
2223 }
2224
2225 return rc;
2226}
2227
2228int cam_vfe_bus_ver2_init(
Harsh Shah19f55812017-06-26 18:58:49 -07002229 struct cam_hw_soc_info *soc_info,
Harsh Shaha1af8822017-05-11 22:06:36 -07002230 struct cam_hw_intf *hw_intf,
2231 void *bus_hw_info,
2232 void *vfe_irq_controller,
2233 struct cam_vfe_bus **vfe_bus)
2234{
2235 int i, rc = 0;
2236 struct cam_vfe_bus_ver2_priv *bus_priv = NULL;
2237 struct cam_vfe_bus *vfe_bus_local;
2238 struct cam_vfe_bus_ver2_hw_info *ver2_hw_info = bus_hw_info;
2239
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07002240 CAM_DBG(CAM_ISP, "Enter");
Harsh Shaha1af8822017-05-11 22:06:36 -07002241
Harsh Shah19f55812017-06-26 18:58:49 -07002242 if (!soc_info || !hw_intf || !bus_hw_info || !vfe_irq_controller) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07002243 CAM_ERR(CAM_ISP,
2244 "Inval_prms soc_info:%pK hw_intf:%pK hw_info%pK",
2245 soc_info, hw_intf, bus_hw_info);
2246 CAM_ERR(CAM_ISP, "controller: %pK", vfe_irq_controller);
Harsh Shah19f55812017-06-26 18:58:49 -07002247 rc = -EINVAL;
2248 goto end;
2249 }
2250
Harsh Shaha1af8822017-05-11 22:06:36 -07002251 vfe_bus_local = kzalloc(sizeof(struct cam_vfe_bus), GFP_KERNEL);
2252 if (!vfe_bus_local) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07002253 CAM_DBG(CAM_ISP, "Failed to alloc for vfe_bus");
Harsh Shaha1af8822017-05-11 22:06:36 -07002254 rc = -ENOMEM;
Harsh Shah545df9a2017-06-16 16:43:17 -07002255 goto end;
Harsh Shaha1af8822017-05-11 22:06:36 -07002256 }
2257
2258 bus_priv = kzalloc(sizeof(struct cam_vfe_bus_ver2_priv),
2259 GFP_KERNEL);
2260 if (!bus_priv) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07002261 CAM_DBG(CAM_ISP, "Failed to alloc for vfe_bus_priv");
Harsh Shaha1af8822017-05-11 22:06:36 -07002262 rc = -ENOMEM;
Harsh Shah545df9a2017-06-16 16:43:17 -07002263 goto free_bus_local;
Harsh Shaha1af8822017-05-11 22:06:36 -07002264 }
2265 vfe_bus_local->bus_priv = bus_priv;
2266
Harsh Shah19f55812017-06-26 18:58:49 -07002267 bus_priv->common_data.core_index = soc_info->index;
2268 bus_priv->common_data.mem_base =
2269 CAM_SOC_GET_REG_MAP_START(soc_info, VFE_CORE_BASE_IDX);
Harsh Shaha1af8822017-05-11 22:06:36 -07002270 bus_priv->common_data.hw_intf = hw_intf;
2271 bus_priv->common_data.vfe_irq_controller = vfe_irq_controller;
2272 bus_priv->common_data.common_reg = &ver2_hw_info->common_reg;
2273
Harsh Shah19f55812017-06-26 18:58:49 -07002274 rc = cam_irq_controller_init(drv_name, bus_priv->common_data.mem_base,
2275 &ver2_hw_info->common_reg.irq_reg_info,
2276 &bus_priv->common_data.bus_irq_controller);
2277 if (rc) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07002278 CAM_ERR(CAM_ISP, "Error! cam_irq_controller_init failed");
Harsh Shah19f55812017-06-26 18:58:49 -07002279 goto free_bus_priv;
2280 }
2281
Harsh Shaha1af8822017-05-11 22:06:36 -07002282 INIT_LIST_HEAD(&bus_priv->free_comp_grp);
2283 INIT_LIST_HEAD(&bus_priv->free_dual_comp_grp);
2284 INIT_LIST_HEAD(&bus_priv->used_comp_grp);
2285
2286 for (i = 0; i < CAM_VFE_BUS_VER2_MAX_CLIENTS; i++) {
2287 rc = cam_vfe_bus_init_wm_resource(i, bus_priv, bus_hw_info,
2288 &bus_priv->bus_client[i]);
2289 if (rc < 0) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07002290 CAM_ERR(CAM_ISP, "Error! Init WM failed rc=%d", rc);
Harsh Shah545df9a2017-06-16 16:43:17 -07002291 goto deinit_wm;
Harsh Shaha1af8822017-05-11 22:06:36 -07002292 }
2293 }
2294
2295 for (i = 0; i < CAM_VFE_BUS_VER2_COMP_GRP_MAX; i++) {
2296 rc = cam_vfe_bus_init_comp_grp(i, bus_priv, bus_hw_info,
2297 &bus_priv->comp_grp[i]);
2298 if (rc < 0) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07002299 CAM_ERR(CAM_ISP, "Init Comp Grp failed rc=%d", rc);
Harsh Shah545df9a2017-06-16 16:43:17 -07002300 goto deinit_comp_grp;
Harsh Shaha1af8822017-05-11 22:06:36 -07002301 }
2302 }
2303
2304 for (i = 0; i < CAM_VFE_BUS_VER2_VFE_OUT_MAX; i++) {
2305 rc = cam_vfe_bus_init_vfe_out_resource(i, bus_priv, bus_hw_info,
2306 &bus_priv->vfe_out[i]);
2307 if (rc < 0) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07002308 CAM_ERR(CAM_ISP, "Init VFE Out failed rc=%d", rc);
Harsh Shah545df9a2017-06-16 16:43:17 -07002309 goto deinit_vfe_out;
Harsh Shaha1af8822017-05-11 22:06:36 -07002310 }
2311 }
2312
Harsh Shah19f55812017-06-26 18:58:49 -07002313 INIT_LIST_HEAD(&bus_priv->common_data.free_payload_list);
2314 for (i = 0; i < CAM_VFE_BUS_VER2_PAYLOAD_MAX; i++) {
2315 INIT_LIST_HEAD(&bus_priv->common_data.evt_payload[i].list);
2316 list_add_tail(&bus_priv->common_data.evt_payload[i].list,
2317 &bus_priv->common_data.free_payload_list);
Harsh Shaha1af8822017-05-11 22:06:36 -07002318 }
2319
Harsh Shah19f55812017-06-26 18:58:49 -07002320 vfe_bus_local->hw_ops.reserve = cam_vfe_bus_acquire_vfe_out;
2321 vfe_bus_local->hw_ops.release = cam_vfe_bus_release_vfe_out;
2322 vfe_bus_local->hw_ops.start = cam_vfe_bus_start_hw;
2323 vfe_bus_local->hw_ops.stop = cam_vfe_bus_stop_hw;
2324 vfe_bus_local->hw_ops.init = cam_vfe_bus_init_hw;
2325 vfe_bus_local->hw_ops.deinit = cam_vfe_bus_deinit_hw;
2326 vfe_bus_local->top_half_handler = cam_vfe_bus_ver2_handle_irq;
Harsh Shaha1af8822017-05-11 22:06:36 -07002327 vfe_bus_local->bottom_half_handler = NULL;
Harsh Shah19f55812017-06-26 18:58:49 -07002328 vfe_bus_local->hw_ops.process_cmd = cam_vfe_bus_process_cmd;
Harsh Shaha1af8822017-05-11 22:06:36 -07002329
2330 *vfe_bus = vfe_bus_local;
2331
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07002332 CAM_DBG(CAM_ISP, "Exit");
Harsh Shaha1af8822017-05-11 22:06:36 -07002333 return rc;
2334
Harsh Shah545df9a2017-06-16 16:43:17 -07002335deinit_vfe_out:
2336 if (i < 0)
2337 i = CAM_VFE_BUS_VER2_VFE_OUT_MAX;
2338 for (--i; i >= 0; i--)
2339 cam_vfe_bus_deinit_vfe_out_resource(&bus_priv->vfe_out[i]);
2340
2341deinit_comp_grp:
2342 if (i < 0)
2343 i = CAM_VFE_BUS_VER2_COMP_GRP_MAX;
2344 for (--i; i >= 0; i--)
2345 cam_vfe_bus_deinit_comp_grp(&bus_priv->comp_grp[i]);
2346
2347deinit_wm:
2348 if (i < 0)
2349 i = CAM_VFE_BUS_VER2_MAX_CLIENTS;
2350 for (--i; i >= 0; i--)
2351 cam_vfe_bus_deinit_wm_resource(&bus_priv->bus_client[i]);
2352
Harsh Shah19f55812017-06-26 18:58:49 -07002353free_bus_priv:
Harsh Shaha1af8822017-05-11 22:06:36 -07002354 kfree(vfe_bus_local->bus_priv);
Harsh Shah545df9a2017-06-16 16:43:17 -07002355
2356free_bus_local:
Harsh Shaha1af8822017-05-11 22:06:36 -07002357 kfree(vfe_bus_local);
Harsh Shah545df9a2017-06-16 16:43:17 -07002358
2359end:
Harsh Shaha1af8822017-05-11 22:06:36 -07002360 return rc;
2361}
Harsh Shah545df9a2017-06-16 16:43:17 -07002362
2363int cam_vfe_bus_ver2_deinit(
2364 struct cam_vfe_bus **vfe_bus)
2365{
2366 int i, rc = 0;
2367 struct cam_vfe_bus_ver2_priv *bus_priv = NULL;
2368 struct cam_vfe_bus *vfe_bus_local;
2369
2370 if (!vfe_bus || !*vfe_bus) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07002371 CAM_ERR(CAM_ISP, "Error! Invalid input");
Harsh Shah545df9a2017-06-16 16:43:17 -07002372 return -EINVAL;
2373 }
2374 vfe_bus_local = *vfe_bus;
2375
2376 bus_priv = vfe_bus_local->bus_priv;
2377 if (!bus_priv) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07002378 CAM_ERR(CAM_ISP, "Error! bus_priv is NULL");
Harsh Shah545df9a2017-06-16 16:43:17 -07002379 rc = -ENODEV;
2380 goto free_bus_local;
2381 }
2382
Harsh Shah19f55812017-06-26 18:58:49 -07002383 INIT_LIST_HEAD(&bus_priv->common_data.free_payload_list);
2384 for (i = 0; i < CAM_VFE_BUS_VER2_PAYLOAD_MAX; i++)
2385 INIT_LIST_HEAD(&bus_priv->common_data.evt_payload[i].list);
Harsh Shah545df9a2017-06-16 16:43:17 -07002386
2387 for (i = 0; i < CAM_VFE_BUS_VER2_MAX_CLIENTS; i++) {
2388 rc = cam_vfe_bus_deinit_wm_resource(&bus_priv->bus_client[i]);
2389 if (rc < 0)
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07002390 CAM_ERR(CAM_ISP,
2391 "Error! Deinit WM failed rc=%d", rc);
Harsh Shah545df9a2017-06-16 16:43:17 -07002392 }
2393
2394 for (i = 0; i < CAM_VFE_BUS_VER2_COMP_GRP_MAX; i++) {
2395 rc = cam_vfe_bus_deinit_comp_grp(&bus_priv->comp_grp[i]);
2396 if (rc < 0)
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07002397 CAM_ERR(CAM_ISP,
2398 "Error! Deinit Comp Grp failed rc=%d", rc);
Harsh Shah545df9a2017-06-16 16:43:17 -07002399 }
2400
2401 for (i = 0; i < CAM_VFE_BUS_VER2_VFE_OUT_MAX; i++) {
2402 rc = cam_vfe_bus_deinit_vfe_out_resource(&bus_priv->vfe_out[i]);
2403 if (rc < 0)
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07002404 CAM_ERR(CAM_ISP,
2405 "Error! Deinit VFE Out failed rc=%d", rc);
Harsh Shah545df9a2017-06-16 16:43:17 -07002406 }
2407
2408 INIT_LIST_HEAD(&bus_priv->free_comp_grp);
2409 INIT_LIST_HEAD(&bus_priv->free_dual_comp_grp);
2410 INIT_LIST_HEAD(&bus_priv->used_comp_grp);
2411
Harsh Shah19f55812017-06-26 18:58:49 -07002412 rc = cam_irq_controller_deinit(
2413 &bus_priv->common_data.bus_irq_controller);
2414 if (rc)
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07002415 CAM_ERR(CAM_ISP,
2416 "Error! Deinit IRQ Controller failed rc=%d", rc);
Harsh Shah19f55812017-06-26 18:58:49 -07002417
Harsh Shah545df9a2017-06-16 16:43:17 -07002418 kfree(vfe_bus_local->bus_priv);
2419
2420free_bus_local:
2421 kfree(vfe_bus_local);
2422
2423 *vfe_bus = NULL;
2424
2425 return rc;
2426}
2427