blob: 1fbc105f27742a7f82f1a463cfdd37782b271675 [file] [log] [blame]
Harsh Shaha1af8822017-05-11 22:06:36 -07001/* Copyright (c) 2017, The Linux Foundation. All rights reserved.
2 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 and
5 * only version 2 as published by the Free Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 */
12
Harsh Shaha1af8822017-05-11 22:06:36 -070013#include <linux/ratelimit.h>
14#include <linux/slab.h>
15#include "cam_io_util.h"
Harsh Shahf7136392017-08-29 12:42:52 -070016#include "cam_debug_util.h"
Harsh Shaha1af8822017-05-11 22:06:36 -070017#include "cam_cdm_util.h"
18#include "cam_hw_intf.h"
Harsh Shah19f55812017-06-26 18:58:49 -070019#include "cam_ife_hw_mgr.h"
Harsh Shaha1af8822017-05-11 22:06:36 -070020#include "cam_vfe_hw_intf.h"
21#include "cam_irq_controller.h"
Harsh Shah19f55812017-06-26 18:58:49 -070022#include "cam_tasklet_util.h"
Harsh Shaha1af8822017-05-11 22:06:36 -070023#include "cam_vfe_bus.h"
24#include "cam_vfe_bus_ver2.h"
25#include "cam_vfe_core.h"
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -070026#include "cam_debug_util.h"
Harsh Shaha1af8822017-05-11 22:06:36 -070027
Harsh Shah19f55812017-06-26 18:58:49 -070028static const char drv_name[] = "vfe_bus";
29
30#define CAM_VFE_BUS_IRQ_REG0 0
31#define CAM_VFE_BUS_IRQ_REG1 1
32#define CAM_VFE_BUS_IRQ_REG2 2
33#define CAM_VFE_BUS_IRQ_MAX 3
34
35#define CAM_VFE_BUS_VER2_PAYLOAD_MAX 256
Harsh Shah23557ae2017-05-13 18:14:34 -070036
Ravikishore Pampanaad6bc902017-07-12 19:37:06 +053037#define CAM_VFE_RDI_BUS_DEFAULT_WIDTH 0xFF01
38#define CAM_VFE_RDI_BUS_DEFAULT_STRIDE 0xFF01
39
Krishnankutty Kolathappilly06406e52017-08-17 00:50:21 -070040#define ALIGNUP(value, alignment) \
41 ((value + alignment - 1) / alignment * alignment)
42
Junzhe Zou193d78c2017-05-16 15:10:54 -070043#define MAX_BUF_UPDATE_REG_NUM \
44 (sizeof(struct cam_vfe_bus_ver2_reg_offset_bus_client)/4)
Jing Zhoua4e9fbe2017-05-15 14:37:21 -070045#define MAX_REG_VAL_PAIR_SIZE \
Harsh Shah19f55812017-06-26 18:58:49 -070046 (MAX_BUF_UPDATE_REG_NUM * 2 * CAM_PACKET_MAX_PLANES)
Jing Zhoua4e9fbe2017-05-15 14:37:21 -070047
48#define CAM_VFE_ADD_REG_VAL_PAIR(buf_array, index, offset, val) \
Harsh Shah19f55812017-06-26 18:58:49 -070049 do { \
50 buf_array[index++] = offset; \
51 buf_array[index++] = val; \
52 } while (0)
Harsh Shaha1af8822017-05-11 22:06:36 -070053
54enum cam_vfe_bus_packer_format {
55 PACKER_FMT_PLAIN_128 = 0x0,
56 PACKER_FMT_PLAIN_8 = 0x1,
57 PACKER_FMT_PLAIN_16_10BPP = 0x2,
58 PACKER_FMT_PLAIN_16_12BPP = 0x3,
59 PACKER_FMT_PLAIN_16_14BPP = 0x4,
60 PACKER_FMT_PLAIN_16_16BPP = 0x5,
61 PACKER_FMT_ARGB_10 = 0x6,
62 PACKER_FMT_ARGB_12 = 0x7,
63 PACKER_FMT_ARGB_14 = 0x8,
64 PACKER_FMT_PLAIN_32_20BPP = 0x9,
65 PACKER_FMT_PLAIN_64 = 0xA,
66 PACKER_FMT_TP_10 = 0xB,
67 PACKER_FMT_PLAIN_32_32BPP = 0xC,
68 PACKER_FMT_PLAIN_8_ODD_EVEN = 0xD,
69 PACKER_FMT_PLAIN_8_LSB_MSB_10 = 0xE,
70 PACKER_FMT_PLAIN_8_LSB_MSB_10_ODD_EVEN = 0xF,
71 PACKER_FMT_MAX = 0xF,
72};
73
74struct cam_vfe_bus_ver2_common_data {
Harsh Shah19f55812017-06-26 18:58:49 -070075 uint32_t core_index;
Harsh Shaha1af8822017-05-11 22:06:36 -070076 void __iomem *mem_base;
77 struct cam_hw_intf *hw_intf;
78 void *bus_irq_controller;
79 void *vfe_irq_controller;
80 struct cam_vfe_bus_ver2_reg_offset_common *common_reg;
Jing Zhoua4e9fbe2017-05-15 14:37:21 -070081 uint32_t io_buf_update[
Harsh Shah19f55812017-06-26 18:58:49 -070082 MAX_REG_VAL_PAIR_SIZE];
83
84 struct cam_vfe_bus_irq_evt_payload evt_payload[
85 CAM_VFE_BUS_VER2_PAYLOAD_MAX];
86 struct list_head free_payload_list;
Harsh Shaha1af8822017-05-11 22:06:36 -070087};
88
89struct cam_vfe_bus_ver2_wm_resource_data {
90 uint32_t index;
91 struct cam_vfe_bus_ver2_common_data *common_data;
92 struct cam_vfe_bus_ver2_reg_offset_bus_client *hw_regs;
Harsh Shah19f55812017-06-26 18:58:49 -070093 void *ctx;
Harsh Shaha1af8822017-05-11 22:06:36 -070094
95 uint32_t irq_enabled;
Pavan Kumar Chilamkurthi649cdf92017-08-15 01:40:57 -070096 bool init_cfg_done;
97 bool hfr_cfg_done;
Harsh Shah19f55812017-06-26 18:58:49 -070098
Harsh Shaha1af8822017-05-11 22:06:36 -070099 uint32_t offset;
100 uint32_t width;
101 uint32_t height;
102 uint32_t stride;
103 uint32_t format;
104 enum cam_vfe_bus_packer_format pack_fmt;
105
106 uint32_t burst_len;
Harsh Shaha1af8822017-05-11 22:06:36 -0700107
Jing Zhoua4e9fbe2017-05-15 14:37:21 -0700108 uint32_t en_ubwc;
109 uint32_t packer_cfg;
110 uint32_t tile_cfg;
111 uint32_t h_init;
112 uint32_t v_init;
113 uint32_t ubwc_meta_stride;
114 uint32_t ubwc_mode_cfg;
115 uint32_t ubwc_meta_offset;
116
Harsh Shaha1af8822017-05-11 22:06:36 -0700117 uint32_t irq_subsample_period;
118 uint32_t irq_subsample_pattern;
119 uint32_t framedrop_period;
120 uint32_t framedrop_pattern;
Jing Zhoua4e9fbe2017-05-15 14:37:21 -0700121
122 uint32_t en_cfg;
Harsh Shaha1af8822017-05-11 22:06:36 -0700123};
124
125struct cam_vfe_bus_ver2_comp_grp_data {
126 enum cam_vfe_bus_ver2_comp_grp_type comp_grp_type;
127 struct cam_vfe_bus_ver2_common_data *common_data;
128 struct cam_vfe_bus_ver2_reg_offset_comp_grp *hw_regs;
129
130 uint32_t irq_enabled;
131 uint32_t comp_grp_local_idx;
132 uint32_t unique_id;
133
134 uint32_t is_master;
135 uint32_t dual_slave_core;
136 uint32_t intra_client_mask;
137 uint32_t composite_mask;
Harsh Shah19f55812017-06-26 18:58:49 -0700138
139 void *ctx;
Harsh Shaha1af8822017-05-11 22:06:36 -0700140};
141
142struct cam_vfe_bus_ver2_vfe_out_data {
143 uint32_t out_type;
144 struct cam_vfe_bus_ver2_common_data *common_data;
145
146 uint32_t num_wm;
147 struct cam_isp_resource_node *wm_res[PLANE_MAX];
148
149 struct cam_isp_resource_node *comp_grp;
150 enum cam_isp_hw_sync_mode dual_comp_sync_mode;
151 uint32_t dual_hw_alternate_vfe_id;
152 struct list_head vfe_out_list;
153
154 uint32_t format;
155 uint32_t max_width;
156 uint32_t max_height;
157 struct cam_cdm_utils_ops *cdm_util_ops;
158};
159
Harsh Shaha1af8822017-05-11 22:06:36 -0700160struct cam_vfe_bus_ver2_priv {
161 struct cam_vfe_bus_ver2_common_data common_data;
162
163 struct cam_isp_resource_node bus_client[CAM_VFE_BUS_VER2_MAX_CLIENTS];
164 struct cam_isp_resource_node comp_grp[CAM_VFE_BUS_VER2_COMP_GRP_MAX];
165 struct cam_isp_resource_node vfe_out[CAM_VFE_BUS_VER2_VFE_OUT_MAX];
166
167 struct list_head free_comp_grp;
168 struct list_head free_dual_comp_grp;
169 struct list_head used_comp_grp;
170
Harsh Shah19f55812017-06-26 18:58:49 -0700171 uint32_t irq_handle;
Harsh Shaha1af8822017-05-11 22:06:36 -0700172};
173
Harsh Shah19f55812017-06-26 18:58:49 -0700174static int cam_vfe_bus_get_evt_payload(
175 struct cam_vfe_bus_ver2_common_data *common_data,
176 struct cam_vfe_bus_irq_evt_payload **evt_payload)
177{
178 if (list_empty(&common_data->free_payload_list)) {
179 *evt_payload = NULL;
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -0700180 CAM_ERR(CAM_ISP, "No free payload");
Harsh Shah19f55812017-06-26 18:58:49 -0700181 return -ENODEV;
182 }
183
184 *evt_payload = list_first_entry(&common_data->free_payload_list,
185 struct cam_vfe_bus_irq_evt_payload, list);
186 list_del_init(&(*evt_payload)->list);
187 return 0;
188}
189
Harsh Shaha1af8822017-05-11 22:06:36 -0700190static int cam_vfe_bus_put_evt_payload(void *core_info,
Harsh Shah19f55812017-06-26 18:58:49 -0700191 struct cam_vfe_bus_irq_evt_payload **evt_payload)
192{
193 struct cam_vfe_bus_ver2_common_data *common_data = NULL;
194 uint32_t *ife_irq_regs = NULL;
195 uint32_t status_reg0, status_reg1, status_reg2;
196
197 if (!core_info) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -0700198 CAM_ERR(CAM_ISP, "Invalid param core_info NULL");
Harsh Shah19f55812017-06-26 18:58:49 -0700199 return -EINVAL;
200 }
201 if (*evt_payload == NULL) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -0700202 CAM_ERR(CAM_ISP, "No payload to put");
Harsh Shah19f55812017-06-26 18:58:49 -0700203 return -EINVAL;
204 }
205
206 ife_irq_regs = (*evt_payload)->irq_reg_val;
207 status_reg0 = ife_irq_regs[CAM_IFE_IRQ_BUS_REG_STATUS0];
208 status_reg1 = ife_irq_regs[CAM_IFE_IRQ_BUS_REG_STATUS1];
209 status_reg2 = ife_irq_regs[CAM_IFE_IRQ_BUS_REG_STATUS2];
210
211 if (status_reg0 || status_reg1 || status_reg2) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -0700212 CAM_DBG(CAM_ISP, "status0 0x%x status1 0x%x status2 0x%x",
Harsh Shah19f55812017-06-26 18:58:49 -0700213 status_reg0, status_reg1, status_reg2);
214 return 0;
215 }
216
217 common_data = core_info;
218 list_add_tail(&(*evt_payload)->list,
219 &common_data->free_payload_list);
220 *evt_payload = NULL;
221
222 return 0;
223}
Harsh Shaha1af8822017-05-11 22:06:36 -0700224
225static int cam_vfe_bus_ver2_get_intra_client_mask(
226 enum cam_vfe_bus_ver2_vfe_core_id dual_slave_core,
227 enum cam_vfe_bus_ver2_vfe_core_id current_core,
228 uint32_t *intra_client_mask)
229{
230 int rc = 0;
231
232 *intra_client_mask = 0;
233
234 if (dual_slave_core == current_core) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -0700235 CAM_ERR(CAM_ISP,
236 "Invalid params. Same core as Master and Slave");
Harsh Shaha1af8822017-05-11 22:06:36 -0700237 return -EINVAL;
238 }
239
240 switch (current_core) {
241 case CAM_VFE_BUS_VER2_VFE_CORE_0:
242 switch (dual_slave_core) {
243 case CAM_VFE_BUS_VER2_VFE_CORE_1:
244 *intra_client_mask = 0x1;
245 break;
246 case CAM_VFE_BUS_VER2_VFE_CORE_2:
247 *intra_client_mask = 0x2;
248 break;
249 default:
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -0700250 CAM_ERR(CAM_ISP, "Invalid value for slave core %u",
Harsh Shaha1af8822017-05-11 22:06:36 -0700251 dual_slave_core);
252 rc = -EINVAL;
253 break;
254 }
255 break;
256 case CAM_VFE_BUS_VER2_VFE_CORE_1:
257 switch (dual_slave_core) {
258 case CAM_VFE_BUS_VER2_VFE_CORE_0:
259 *intra_client_mask = 0x1;
260 break;
261 case CAM_VFE_BUS_VER2_VFE_CORE_2:
262 *intra_client_mask = 0x2;
263 break;
264 default:
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -0700265 CAM_ERR(CAM_ISP, "Invalid value for slave core %u",
Harsh Shaha1af8822017-05-11 22:06:36 -0700266 dual_slave_core);
267 rc = -EINVAL;
268 break;
269 }
270 break;
271 case CAM_VFE_BUS_VER2_VFE_CORE_2:
272 switch (dual_slave_core) {
273 case CAM_VFE_BUS_VER2_VFE_CORE_0:
274 *intra_client_mask = 0x1;
275 break;
276 case CAM_VFE_BUS_VER2_VFE_CORE_1:
277 *intra_client_mask = 0x2;
278 break;
279 default:
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -0700280 CAM_ERR(CAM_ISP, "Invalid value for slave core %u",
Harsh Shaha1af8822017-05-11 22:06:36 -0700281 dual_slave_core);
282 rc = -EINVAL;
283 break;
284 }
285 break;
286 default:
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -0700287 CAM_ERR(CAM_ISP,
288 "Invalid value for master core %u", current_core);
Harsh Shaha1af8822017-05-11 22:06:36 -0700289 rc = -EINVAL;
290 break;
291 }
292
293 return rc;
294}
295
296static enum cam_vfe_bus_ver2_vfe_out_type
297 cam_vfe_bus_get_out_res_id(uint32_t res_type)
298{
299 switch (res_type) {
300 case CAM_ISP_IFE_OUT_RES_FULL:
301 return CAM_VFE_BUS_VER2_VFE_OUT_FULL;
302 case CAM_ISP_IFE_OUT_RES_DS4:
303 return CAM_VFE_BUS_VER2_VFE_OUT_DS4;
304 case CAM_ISP_IFE_OUT_RES_DS16:
305 return CAM_VFE_BUS_VER2_VFE_OUT_DS16;
306 case CAM_ISP_IFE_OUT_RES_FD:
307 return CAM_VFE_BUS_VER2_VFE_OUT_FD;
308 case CAM_ISP_IFE_OUT_RES_RAW_DUMP:
309 return CAM_VFE_BUS_VER2_VFE_OUT_RAW_DUMP;
310 case CAM_ISP_IFE_OUT_RES_PDAF:
311 return CAM_VFE_BUS_VER2_VFE_OUT_PDAF;
312 case CAM_ISP_IFE_OUT_RES_RDI_0:
313 return CAM_VFE_BUS_VER2_VFE_OUT_RDI0;
314 case CAM_ISP_IFE_OUT_RES_RDI_1:
315 return CAM_VFE_BUS_VER2_VFE_OUT_RDI1;
316 case CAM_ISP_IFE_OUT_RES_RDI_2:
317 return CAM_VFE_BUS_VER2_VFE_OUT_RDI2;
318 case CAM_ISP_IFE_OUT_RES_STATS_HDR_BE:
319 return CAM_VFE_BUS_VER2_VFE_OUT_STATS_HDR_BE;
320 case CAM_ISP_IFE_OUT_RES_STATS_HDR_BHIST:
321 return CAM_VFE_BUS_VER2_VFE_OUT_STATS_HDR_BHIST;
322 case CAM_ISP_IFE_OUT_RES_STATS_TL_BG:
323 return CAM_VFE_BUS_VER2_VFE_OUT_STATS_TL_BG;
324 case CAM_ISP_IFE_OUT_RES_STATS_BF:
325 return CAM_VFE_BUS_VER2_VFE_OUT_STATS_BF;
326 case CAM_ISP_IFE_OUT_RES_STATS_AWB_BG:
327 return CAM_VFE_BUS_VER2_VFE_OUT_STATS_AWB_BG;
328 case CAM_ISP_IFE_OUT_RES_STATS_BHIST:
329 return CAM_VFE_BUS_VER2_VFE_OUT_STATS_BHIST;
330 case CAM_ISP_IFE_OUT_RES_STATS_RS:
331 return CAM_VFE_BUS_VER2_VFE_OUT_STATS_RS;
332 case CAM_ISP_IFE_OUT_RES_STATS_CS:
333 return CAM_VFE_BUS_VER2_VFE_OUT_STATS_CS;
334 case CAM_ISP_IFE_OUT_RES_STATS_IHIST:
335 return CAM_VFE_BUS_VER2_VFE_OUT_STATS_IHIST;
336 default:
337 return CAM_VFE_BUS_VER2_VFE_OUT_MAX;
338 }
339}
340
341static int cam_vfe_bus_get_num_wm(
342 enum cam_vfe_bus_ver2_vfe_out_type res_type,
343 uint32_t format)
344{
345 switch (res_type) {
346 case CAM_VFE_BUS_VER2_VFE_OUT_RDI0:
347 case CAM_VFE_BUS_VER2_VFE_OUT_RDI1:
348 case CAM_VFE_BUS_VER2_VFE_OUT_RDI2:
349 switch (format) {
350 case CAM_FORMAT_MIPI_RAW_8:
351 case CAM_FORMAT_MIPI_RAW_10:
352 case CAM_FORMAT_MIPI_RAW_12:
353 case CAM_FORMAT_MIPI_RAW_14:
354 case CAM_FORMAT_MIPI_RAW_16:
355 case CAM_FORMAT_MIPI_RAW_20:
Ravikishore Pampanaad6bc902017-07-12 19:37:06 +0530356 case CAM_FORMAT_DPCM_10_6_10:
357 case CAM_FORMAT_DPCM_10_8_10:
358 case CAM_FORMAT_DPCM_12_6_12:
359 case CAM_FORMAT_DPCM_12_8_12:
360 case CAM_FORMAT_DPCM_14_8_14:
361 case CAM_FORMAT_DPCM_14_10_14:
362 case CAM_FORMAT_PLAIN8:
Ravikishore Pampanaad6bc902017-07-12 19:37:06 +0530363 case CAM_FORMAT_PLAIN16_10:
364 case CAM_FORMAT_PLAIN16_12:
365 case CAM_FORMAT_PLAIN16_14:
366 case CAM_FORMAT_PLAIN16_16:
367 case CAM_FORMAT_PLAIN32_20:
Harsh Shaha1af8822017-05-11 22:06:36 -0700368 case CAM_FORMAT_PLAIN128:
369 return 1;
370 default:
371 break;
372 }
373 break;
374 case CAM_VFE_BUS_VER2_VFE_OUT_FULL:
375 switch (format) {
376 case CAM_FORMAT_NV21:
377 case CAM_FORMAT_NV12:
378 case CAM_FORMAT_MIPI_RAW_8:
379 case CAM_FORMAT_PLAIN8:
380 case CAM_FORMAT_TP10:
381 case CAM_FORMAT_UBWC_NV12:
382 case CAM_FORMAT_UBWC_NV12_4R:
383 case CAM_FORMAT_UBWC_TP10:
384 case CAM_FORMAT_UBWC_P010:
385 return 2;
386 default:
387 break;
388 }
389 break;
390 case CAM_VFE_BUS_VER2_VFE_OUT_FD:
391 switch (format) {
392 case CAM_FORMAT_NV21:
393 case CAM_FORMAT_NV12:
394 case CAM_FORMAT_PLAIN8:
395 case CAM_FORMAT_TP10:
396 case CAM_FORMAT_PLAIN16_10:
397 return 2;
398 default:
399 break;
400 }
401 break;
402 case CAM_VFE_BUS_VER2_VFE_OUT_DS4:
403 case CAM_VFE_BUS_VER2_VFE_OUT_DS16:
404 switch (format) {
405 case CAM_FORMAT_PD8:
406 case CAM_FORMAT_PD10:
407 return 1;
408 default:
409 break;
410 }
411 break;
412 case CAM_VFE_BUS_VER2_VFE_OUT_RAW_DUMP:
413 switch (format) {
414 case CAM_FORMAT_ARGB_14:
415 case CAM_FORMAT_PLAIN8:
416 case CAM_FORMAT_PLAIN16_10:
417 case CAM_FORMAT_PLAIN16_12:
418 case CAM_FORMAT_PLAIN16_14:
419 return 1;
420 default:
421 break;
422 }
423 break;
424 case CAM_VFE_BUS_VER2_VFE_OUT_PDAF:
425 switch (format) {
426 case CAM_FORMAT_PLAIN8:
427 case CAM_FORMAT_PLAIN16_10:
428 case CAM_FORMAT_PLAIN16_12:
429 case CAM_FORMAT_PLAIN16_14:
430 return 1;
431 default:
432 break;
433 }
434 break;
435 case CAM_VFE_BUS_VER2_VFE_OUT_STATS_HDR_BE:
436 case CAM_VFE_BUS_VER2_VFE_OUT_STATS_HDR_BHIST:
437 case CAM_VFE_BUS_VER2_VFE_OUT_STATS_TL_BG:
438 case CAM_VFE_BUS_VER2_VFE_OUT_STATS_BF:
439 case CAM_VFE_BUS_VER2_VFE_OUT_STATS_AWB_BG:
440 case CAM_VFE_BUS_VER2_VFE_OUT_STATS_BHIST:
441 case CAM_VFE_BUS_VER2_VFE_OUT_STATS_CS:
442 switch (format) {
443 case CAM_FORMAT_PLAIN64:
444 return 1;
445 default:
446 break;
447 }
448 break;
449 case CAM_VFE_BUS_VER2_VFE_OUT_STATS_RS:
450 case CAM_VFE_BUS_VER2_VFE_OUT_STATS_IHIST:
451 switch (format) {
452 case CAM_FORMAT_PLAIN16_16:
453 return 1;
454 default:
455 break;
456 }
457 break;
458 default:
459 break;
460 }
461
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -0700462 CAM_ERR(CAM_ISP, "Unsupported format %u for resource_type %u",
463 format, res_type);
Harsh Shaha1af8822017-05-11 22:06:36 -0700464
465 return -EINVAL;
466}
467
468static int cam_vfe_bus_get_wm_idx(
469 enum cam_vfe_bus_ver2_vfe_out_type vfe_out_res_id,
470 enum cam_vfe_bus_plane_type plane)
471{
472 int wm_idx = -1;
473
474 switch (vfe_out_res_id) {
475 case CAM_VFE_BUS_VER2_VFE_OUT_FULL:
476 switch (plane) {
477 case PLANE_Y:
478 wm_idx = 3;
479 break;
480 case PLANE_C:
481 wm_idx = 4;
482 break;
483 default:
484 break;
485 }
486 break;
487 case CAM_VFE_BUS_VER2_VFE_OUT_DS4:
488 switch (plane) {
489 case PLANE_Y:
490 wm_idx = 5;
491 break;
492 default:
493 break;
494 }
495 break;
496 case CAM_VFE_BUS_VER2_VFE_OUT_DS16:
497 switch (plane) {
498 case PLANE_Y:
499 wm_idx = 6;
500 break;
501 default:
502 break;
503 }
504 break;
505 case CAM_VFE_BUS_VER2_VFE_OUT_FD:
506 switch (plane) {
507 case PLANE_Y:
508 wm_idx = 7;
509 break;
510 case PLANE_C:
511 wm_idx = 8;
512 break;
513 default:
514 break;
515 }
516 break;
517 case CAM_VFE_BUS_VER2_VFE_OUT_RAW_DUMP:
518 switch (plane) {
519 case PLANE_Y:
520 wm_idx = 9;
521 break;
522 default:
523 break;
524 }
525 break;
526 case CAM_VFE_BUS_VER2_VFE_OUT_PDAF:
527 switch (plane) {
528 case PLANE_Y:
529 wm_idx = 10;
530 break;
531 default:
532 break;
533 }
534 break;
535 case CAM_VFE_BUS_VER2_VFE_OUT_RDI0:
536 switch (plane) {
537 case PLANE_Y:
538 wm_idx = 0;
539 break;
540 default:
541 break;
542 }
543 break;
544 case CAM_VFE_BUS_VER2_VFE_OUT_RDI1:
545 switch (plane) {
546 case PLANE_Y:
547 wm_idx = 1;
548 break;
549 default:
550 break;
551 }
552 break;
553 case CAM_VFE_BUS_VER2_VFE_OUT_RDI2:
554 switch (plane) {
555 case PLANE_Y:
556 wm_idx = 2;
557 break;
558 default:
559 break;
560 }
561 break;
562 case CAM_VFE_BUS_VER2_VFE_OUT_STATS_HDR_BE:
563 switch (plane) {
564 case PLANE_Y:
565 wm_idx = 11;
566 break;
567 default:
568 break;
569 }
570 break;
571 case CAM_VFE_BUS_VER2_VFE_OUT_STATS_HDR_BHIST:
572 switch (plane) {
573 case PLANE_Y:
574 wm_idx = 12;
575 break;
576 default:
577 break;
578 }
579 break;
580 case CAM_VFE_BUS_VER2_VFE_OUT_STATS_TL_BG:
581 switch (plane) {
582 case PLANE_Y:
583 wm_idx = 13;
584 break;
585 default:
586 break;
587 }
588 break;
589 case CAM_VFE_BUS_VER2_VFE_OUT_STATS_BF:
590 switch (plane) {
591 case PLANE_Y:
592 wm_idx = 14;
593 break;
594 default:
595 break;
596 }
597 break;
598 case CAM_VFE_BUS_VER2_VFE_OUT_STATS_AWB_BG:
599 switch (plane) {
600 case PLANE_Y:
601 wm_idx = 15;
602 break;
603 default:
604 break;
605 }
606 break;
607 case CAM_VFE_BUS_VER2_VFE_OUT_STATS_BHIST:
608 switch (plane) {
609 case PLANE_Y:
610 wm_idx = 16;
611 break;
612 default:
613 break;
614 }
615 break;
616 case CAM_VFE_BUS_VER2_VFE_OUT_STATS_RS:
617 switch (plane) {
618 case PLANE_Y:
619 wm_idx = 17;
620 break;
621 default:
622 break;
623 }
624 break;
625 case CAM_VFE_BUS_VER2_VFE_OUT_STATS_CS:
626 switch (plane) {
627 case PLANE_Y:
628 wm_idx = 18;
629 break;
630 default:
631 break;
632 }
633 break;
634 case CAM_VFE_BUS_VER2_VFE_OUT_STATS_IHIST:
635 switch (plane) {
636 case PLANE_Y:
637 wm_idx = 19;
638 break;
639 default:
640 break;
641 }
642 break;
643 default:
644 break;
645 }
646
647 return wm_idx;
648}
649
650static enum cam_vfe_bus_packer_format
651 cam_vfe_bus_get_packer_fmt(uint32_t out_fmt)
652{
653 switch (out_fmt) {
654 case CAM_FORMAT_NV21:
655 case CAM_FORMAT_NV12:
Krishnankutty Kolathappillyf39e6412017-07-18 15:58:22 -0700656 case CAM_FORMAT_UBWC_NV12:
657 case CAM_FORMAT_UBWC_NV12_4R:
Abhishek Kondaveeti170c8122017-07-06 04:45:12 +0530658 return PACKER_FMT_PLAIN_8_LSB_MSB_10;
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;
Harsh Shahf7136392017-08-29 12:42:52 -0700726 CAM_DBG(CAM_ISP, "WM %d width %d height %d", rsrc_data->index,
727 rsrc_data->width, rsrc_data->height);
Jing Zhoua4e9fbe2017-05-15 14:37:21 -0700728
729 if (rsrc_data->index < 3) {
Krishnankutty Kolathappillyf39e6412017-07-18 15:58:22 -0700730 /* Write master 0-2 refers to RDI 0/ RDI 1/RDI 2 */
Harsh Shahf7136392017-08-29 12:42:52 -0700731 switch (rsrc_data->format) {
732 case CAM_FORMAT_MIPI_RAW_6:
733 case CAM_FORMAT_MIPI_RAW_8:
734 case CAM_FORMAT_MIPI_RAW_10:
735 case CAM_FORMAT_MIPI_RAW_12:
736 case CAM_FORMAT_MIPI_RAW_14:
737 case CAM_FORMAT_MIPI_RAW_16:
738 case CAM_FORMAT_MIPI_RAW_20:
739 rsrc_data->width = CAM_VFE_RDI_BUS_DEFAULT_WIDTH;
740 rsrc_data->height = 0;
741 rsrc_data->stride = CAM_VFE_RDI_BUS_DEFAULT_STRIDE;
742 rsrc_data->pack_fmt = 0x0;
743 rsrc_data->en_cfg = 0x3;
744 break;
745 case CAM_FORMAT_PLAIN8:
746 rsrc_data->en_cfg = 0x1;
747 rsrc_data->pack_fmt = 0x1;
748 rsrc_data->width = rsrc_data->width * 2;
749 rsrc_data->stride = rsrc_data->width;
750 break;
751 case CAM_FORMAT_PLAIN16_10:
752 rsrc_data->en_cfg = 0x1;
753 rsrc_data->pack_fmt = 0x2;
754 rsrc_data->width = rsrc_data->width * 2;
755 rsrc_data->stride = rsrc_data->width;
756 break;
757 case CAM_FORMAT_PLAIN16_12:
758 rsrc_data->en_cfg = 0x1;
759 rsrc_data->pack_fmt = 0x3;
760 rsrc_data->width = rsrc_data->width * 2;
761 rsrc_data->stride = rsrc_data->width;
762 break;
763 case CAM_FORMAT_PLAIN16_14:
764 rsrc_data->en_cfg = 0x1;
765 rsrc_data->pack_fmt = 0x4;
766 rsrc_data->width = rsrc_data->width * 2;
767 rsrc_data->stride = rsrc_data->width;
768 break;
769 case CAM_FORMAT_PLAIN16_16:
770 rsrc_data->en_cfg = 0x1;
771 rsrc_data->pack_fmt = 0x5;
772 rsrc_data->width = rsrc_data->width * 2;
773 rsrc_data->stride = rsrc_data->width;
774 break;
775 case CAM_FORMAT_PLAIN32_20:
776 rsrc_data->en_cfg = 0x1;
777 rsrc_data->pack_fmt = 0x9;
778 break;
779 case CAM_FORMAT_PLAIN64:
780 rsrc_data->en_cfg = 0x1;
781 rsrc_data->pack_fmt = 0xA;
782 break;
783 case CAM_FORMAT_PLAIN128:
784 rsrc_data->en_cfg = 0x1;
785 rsrc_data->pack_fmt = 0x0;
786 break;
787 default:
788 CAM_ERR(CAM_ISP, "Unsupported RDI format %d",
789 rsrc_data->format);
790 return -EINVAL;
791 }
Abhishek Kondaveetib31b46c2017-06-23 04:56:24 +0530792 } else if (rsrc_data->index < 5 ||
793 rsrc_data->index == 7 || rsrc_data->index == 8) {
Krishnankutty Kolathappillyf39e6412017-07-18 15:58:22 -0700794 /* Write master 3, 4 - for Full OUT , 7-8 FD OUT */
795 switch (rsrc_data->format) {
Krishnankutty Kolathappillyf39e6412017-07-18 15:58:22 -0700796 case CAM_FORMAT_UBWC_NV12_4R:
797 rsrc_data->en_ubwc = 1;
Krishnankutty Kolathappilly06406e52017-08-17 00:50:21 -0700798 rsrc_data->width = ALIGNUP(rsrc_data->width, 64);
799 switch (plane) {
800 case PLANE_C:
801 rsrc_data->height /= 2;
802 break;
803 case PLANE_Y:
804 break;
805 default:
806 CAM_ERR(CAM_ISP, "Invalid plane %d\n", plane);
807 return -EINVAL;
808 }
809 break;
810 case CAM_FORMAT_UBWC_NV12:
811 rsrc_data->en_ubwc = 1;
Krishnankutty Kolathappillyf39e6412017-07-18 15:58:22 -0700812 /* Fall through for NV12 */
813 case CAM_FORMAT_NV21:
814 case CAM_FORMAT_NV12:
815 switch (plane) {
816 case PLANE_C:
817 rsrc_data->height /= 2;
818 break;
819 case PLANE_Y:
Jing Zhoua4e9fbe2017-05-15 14:37:21 -0700820 break;
821 default:
Krishnankutty Kolathappillyf39e6412017-07-18 15:58:22 -0700822 CAM_ERR(CAM_ISP, "Invalid plane %d\n", plane);
823 return -EINVAL;
Jing Zhoua4e9fbe2017-05-15 14:37:21 -0700824 }
825 break;
Krishnankutty Kolathappillyf39e6412017-07-18 15:58:22 -0700826 case CAM_FORMAT_UBWC_TP10:
827 rsrc_data->en_ubwc = 1;
Krishnankutty Kolathappilly06406e52017-08-17 00:50:21 -0700828 rsrc_data->width =
829 ALIGNUP(rsrc_data->width, 48) * 4 / 3;
830 switch (plane) {
831 case PLANE_C:
832 rsrc_data->height /= 2;
833 break;
834 case PLANE_Y:
835 break;
836 default:
837 CAM_ERR(CAM_ISP, "Invalid plane %d\n", plane);
838 return -EINVAL;
839 }
840 break;
Krishnankutty Kolathappillyf39e6412017-07-18 15:58:22 -0700841 case CAM_FORMAT_TP10:
Krishnankutty Kolathappilly06406e52017-08-17 00:50:21 -0700842 rsrc_data->width =
843 ALIGNUP(rsrc_data->width, 3) * 4 / 3;
Krishnankutty Kolathappillyf39e6412017-07-18 15:58:22 -0700844 switch (plane) {
845 case PLANE_C:
Jing Zhoua4e9fbe2017-05-15 14:37:21 -0700846 rsrc_data->height /= 2;
847 break;
Krishnankutty Kolathappillyf39e6412017-07-18 15:58:22 -0700848 case PLANE_Y:
Jing Zhoua4e9fbe2017-05-15 14:37:21 -0700849 break;
850 default:
Krishnankutty Kolathappillyf39e6412017-07-18 15:58:22 -0700851 CAM_ERR(CAM_ISP, "Invalid plane %d\n", plane);
852 return -EINVAL;
Jing Zhoua4e9fbe2017-05-15 14:37:21 -0700853 }
Harsh Shaha1af8822017-05-11 22:06:36 -0700854 break;
855 default:
Krishnankutty Kolathappillyf39e6412017-07-18 15:58:22 -0700856 CAM_ERR(CAM_ISP, "Invalid format %d\n",
857 rsrc_data->format);
Jing Zhoua4e9fbe2017-05-15 14:37:21 -0700858 return -EINVAL;
Harsh Shaha1af8822017-05-11 22:06:36 -0700859 }
Jing Zhoua4e9fbe2017-05-15 14:37:21 -0700860 rsrc_data->en_cfg = 0x1;
Abhishek Kondaveetib31b46c2017-06-23 04:56:24 +0530861 } else if (rsrc_data->index >= 11) {
Krishnankutty Kolathappillyf39e6412017-07-18 15:58:22 -0700862 /* Write master 11-19 stats */
Abhishek Kondaveetib31b46c2017-06-23 04:56:24 +0530863 rsrc_data->width = 0;
864 rsrc_data->height = 0;
Abhishek Kondaveetib31b46c2017-06-23 04:56:24 +0530865 rsrc_data->stride = 1;
866 rsrc_data->en_cfg = 0x3;
Jing Zhoua4e9fbe2017-05-15 14:37:21 -0700867 } else {
Krishnankutty Kolathappillyf39e6412017-07-18 15:58:22 -0700868 /* Write master 5-6 DS ports , 9 - Raw dump , 10 PDAF */
Jing Zhoua4e9fbe2017-05-15 14:37:21 -0700869 rsrc_data->width = rsrc_data->width * 4;
870 rsrc_data->height = rsrc_data->height / 2;
Jing Zhoua4e9fbe2017-05-15 14:37:21 -0700871 rsrc_data->en_cfg = 0x1;
Harsh Shaha1af8822017-05-11 22:06:36 -0700872 }
Harsh Shaha1af8822017-05-11 22:06:36 -0700873
874 *client_done_mask = (1 << wm_idx);
875 *wm_res = wm_res_local;
876
877 return 0;
878}
879
880static int cam_vfe_bus_release_wm(void *bus_priv,
881 struct cam_isp_resource_node *wm_res)
882{
883 struct cam_vfe_bus_ver2_wm_resource_data *rsrc_data =
884 wm_res->res_priv;
885
886 rsrc_data->irq_enabled = 0;
887 rsrc_data->offset = 0;
888 rsrc_data->width = 0;
889 rsrc_data->height = 0;
890 rsrc_data->stride = 0;
891 rsrc_data->format = 0;
892 rsrc_data->pack_fmt = 0;
893 rsrc_data->burst_len = 0;
Harsh Shaha1af8822017-05-11 22:06:36 -0700894 rsrc_data->irq_subsample_period = 0;
895 rsrc_data->irq_subsample_pattern = 0;
896 rsrc_data->framedrop_period = 0;
897 rsrc_data->framedrop_pattern = 0;
Jing Zhoua4e9fbe2017-05-15 14:37:21 -0700898 rsrc_data->packer_cfg = 0;
899 rsrc_data->en_ubwc = 0;
900 rsrc_data->tile_cfg = 0;
901 rsrc_data->h_init = 0;
902 rsrc_data->v_init = 0;
903 rsrc_data->ubwc_meta_stride = 0;
904 rsrc_data->ubwc_mode_cfg = 0;
905 rsrc_data->ubwc_meta_offset = 0;
Pavan Kumar Chilamkurthi649cdf92017-08-15 01:40:57 -0700906 rsrc_data->init_cfg_done = false;
907 rsrc_data->hfr_cfg_done = false;
Jing Zhoua4e9fbe2017-05-15 14:37:21 -0700908 rsrc_data->en_cfg = 0;
Harsh Shah19f55812017-06-26 18:58:49 -0700909
910 wm_res->tasklet_info = NULL;
Harsh Shaha1af8822017-05-11 22:06:36 -0700911 wm_res->res_state = CAM_ISP_RESOURCE_STATE_AVAILABLE;
912
913 return 0;
914}
915
916static int cam_vfe_bus_start_wm(struct cam_isp_resource_node *wm_res)
917{
918 int rc = 0;
919 struct cam_vfe_bus_ver2_wm_resource_data *rsrc_data =
920 wm_res->res_priv;
921 struct cam_vfe_bus_ver2_common_data *common_data =
922 rsrc_data->common_data;
Harsh Shah19f55812017-06-26 18:58:49 -0700923 uint32_t bus_irq_reg_mask[CAM_VFE_BUS_IRQ_MAX] = {0};
Harsh Shaha1af8822017-05-11 22:06:36 -0700924
Harsh Shah23557ae2017-05-13 18:14:34 -0700925 cam_io_w_mb(0, common_data->mem_base + rsrc_data->hw_regs->header_addr);
926 cam_io_w_mb(0, common_data->mem_base + rsrc_data->hw_regs->header_cfg);
Harsh Shah23557ae2017-05-13 18:14:34 -0700927 cam_io_w(0xf, common_data->mem_base + rsrc_data->hw_regs->burst_limit);
928
Jing Zhoua4e9fbe2017-05-15 14:37:21 -0700929 cam_io_w_mb(rsrc_data->width,
Harsh Shaha1af8822017-05-11 22:06:36 -0700930 common_data->mem_base + rsrc_data->hw_regs->buffer_width_cfg);
Jing Zhoua4e9fbe2017-05-15 14:37:21 -0700931 cam_io_w(rsrc_data->height,
Harsh Shaha1af8822017-05-11 22:06:36 -0700932 common_data->mem_base + rsrc_data->hw_regs->buffer_height_cfg);
Jing Zhoua4e9fbe2017-05-15 14:37:21 -0700933 cam_io_w(rsrc_data->pack_fmt,
Harsh Shaha1af8822017-05-11 22:06:36 -0700934 common_data->mem_base + rsrc_data->hw_regs->packer_cfg);
Harsh Shaha1af8822017-05-11 22:06:36 -0700935
Ravikishore Pampanaad6bc902017-07-12 19:37:06 +0530936 /* Configure stride for RDIs */
937 if (rsrc_data->index < 3)
938 cam_io_w_mb(rsrc_data->stride, (common_data->mem_base +
939 rsrc_data->hw_regs->stride));
Harsh Shaha1af8822017-05-11 22:06:36 -0700940
Harsh Shah19f55812017-06-26 18:58:49 -0700941 /* Subscribe IRQ */
942 if (rsrc_data->irq_enabled) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -0700943 CAM_DBG(CAM_ISP, "Subscribe WM%d IRQ", rsrc_data->index);
Harsh Shah19f55812017-06-26 18:58:49 -0700944 bus_irq_reg_mask[CAM_VFE_BUS_IRQ_REG1] =
945 (1 << rsrc_data->index);
946 wm_res->irq_handle = cam_irq_controller_subscribe_irq(
947 common_data->bus_irq_controller, CAM_IRQ_PRIORITY_1,
948 bus_irq_reg_mask, wm_res,
949 wm_res->top_half_handler,
950 cam_ife_mgr_do_tasklet_buf_done,
951 wm_res->tasklet_info, cam_tasklet_enqueue_cmd);
952 if (wm_res->irq_handle < 0) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -0700953 CAM_ERR(CAM_ISP, "Subscribe IRQ failed for WM %d",
Harsh Shah19f55812017-06-26 18:58:49 -0700954 rsrc_data->index);
955 return -EFAULT;
956 }
957 }
958
Junzhe Zou3d292562017-07-12 17:59:58 -0700959 /* enable ubwc if needed*/
960 if (rsrc_data->en_ubwc) {
961 cam_io_w_mb(0x1, common_data->mem_base +
962 rsrc_data->hw_regs->ubwc_regs->mode_cfg);
963 }
964
Harsh Shah19f55812017-06-26 18:58:49 -0700965 /* Enable WM */
966 cam_io_w_mb(rsrc_data->en_cfg, common_data->mem_base +
967 rsrc_data->hw_regs->cfg);
968
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -0700969 CAM_DBG(CAM_ISP, "WM res %d width = %d, height = %d", rsrc_data->index,
Jing Zhoua4e9fbe2017-05-15 14:37:21 -0700970 rsrc_data->width, rsrc_data->height);
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -0700971 CAM_DBG(CAM_ISP, "WM res %d pk_fmt = %d", rsrc_data->index,
Jing Zhoua4e9fbe2017-05-15 14:37:21 -0700972 rsrc_data->pack_fmt & PACKER_FMT_MAX);
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -0700973 CAM_DBG(CAM_ISP, "WM res %d stride = %d, burst len = %d",
Jing Zhoua4e9fbe2017-05-15 14:37:21 -0700974 rsrc_data->index, rsrc_data->stride, 0xf);
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -0700975 CAM_DBG(CAM_ISP, "enable WM res %d offset 0x%x val 0x%x",
976 rsrc_data->index, (uint32_t) rsrc_data->hw_regs->cfg,
977 rsrc_data->en_cfg);
Harsh Shaha1af8822017-05-11 22:06:36 -0700978
979 wm_res->res_state = CAM_ISP_RESOURCE_STATE_STREAMING;
980
981 return rc;
982}
983
984static int cam_vfe_bus_stop_wm(struct cam_isp_resource_node *wm_res)
985{
986 int rc = 0;
987 struct cam_vfe_bus_ver2_wm_resource_data *rsrc_data =
988 wm_res->res_priv;
989 struct cam_vfe_bus_ver2_common_data *common_data =
990 rsrc_data->common_data;
991
992 /* Disble WM */
993 cam_io_w_mb(0x0,
994 common_data->mem_base + rsrc_data->hw_regs->cfg);
995
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -0700996 CAM_DBG(CAM_ISP, "irq_enabled %d", rsrc_data->irq_enabled);
Harsh Shaha1af8822017-05-11 22:06:36 -0700997 /* Unsubscribe IRQ */
Harsh Shah19f55812017-06-26 18:58:49 -0700998 if (rsrc_data->irq_enabled)
999 rc = cam_irq_controller_unsubscribe_irq(
1000 common_data->bus_irq_controller,
1001 wm_res->irq_handle);
Harsh Shaha1af8822017-05-11 22:06:36 -07001002
1003 /* Halt & Reset WM */
1004 cam_io_w_mb(BIT(rsrc_data->index),
1005 common_data->mem_base + common_data->common_reg->sw_reset);
1006
1007 wm_res->res_state = CAM_ISP_RESOURCE_STATE_RESERVED;
1008
1009 return rc;
1010}
1011
1012static int cam_vfe_bus_handle_wm_done_top_half(uint32_t evt_id,
1013 struct cam_irq_th_payload *th_payload)
1014{
Harsh Shah19f55812017-06-26 18:58:49 -07001015 int32_t rc;
1016 int i;
1017 struct cam_isp_resource_node *wm_res = NULL;
1018 struct cam_vfe_bus_ver2_wm_resource_data *rsrc_data = NULL;
1019 struct cam_vfe_bus_irq_evt_payload *evt_payload;
1020
1021 wm_res = th_payload->handler_priv;
1022 if (!wm_res) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07001023 CAM_ERR_RATE_LIMIT(CAM_ISP, "Error! No resource\n");
Harsh Shah19f55812017-06-26 18:58:49 -07001024 return -ENODEV;
1025 }
1026
1027 rsrc_data = wm_res->res_priv;
1028
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07001029 CAM_DBG(CAM_ISP, "IRQ status_0 = %x", th_payload->evt_status_arr[0]);
1030 CAM_DBG(CAM_ISP, "IRQ status_1 = %x", th_payload->evt_status_arr[1]);
Harsh Shah19f55812017-06-26 18:58:49 -07001031
1032 rc = cam_vfe_bus_get_evt_payload(rsrc_data->common_data, &evt_payload);
1033 if (rc) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07001034 CAM_ERR_RATE_LIMIT(CAM_ISP,
1035 "No tasklet_cmd is free in queue\n");
Harsh Shah19f55812017-06-26 18:58:49 -07001036 return rc;
1037 }
1038
1039 cam_isp_hw_get_timestamp(&evt_payload->ts);
1040
1041 evt_payload->ctx = rsrc_data->ctx;
1042 evt_payload->core_index = rsrc_data->common_data->core_index;
1043 evt_payload->evt_id = evt_id;
1044
1045 for (i = 0; i < th_payload->num_registers; i++)
1046 evt_payload->irq_reg_val[i] = th_payload->evt_status_arr[i];
1047
1048 th_payload->evt_payload_priv = evt_payload;
1049
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07001050 CAM_DBG(CAM_ISP, "Exit");
Harsh Shah19f55812017-06-26 18:58:49 -07001051 return rc;
Harsh Shaha1af8822017-05-11 22:06:36 -07001052}
1053
1054static int cam_vfe_bus_handle_wm_done_bottom_half(void *wm_node,
1055 void *evt_payload_priv)
1056{
1057 int rc = CAM_VFE_IRQ_STATUS_ERR;
1058 struct cam_isp_resource_node *wm_res = wm_node;
1059 struct cam_vfe_bus_irq_evt_payload *evt_payload = evt_payload_priv;
Harsh Shah23557ae2017-05-13 18:14:34 -07001060 struct cam_vfe_bus_ver2_wm_resource_data *rsrc_data =
1061 (wm_res == NULL) ? NULL : wm_res->res_priv;
1062 uint32_t *cam_ife_irq_regs;
Harsh Shaha1af8822017-05-11 22:06:36 -07001063 uint32_t status_reg;
1064
Harsh Shah23557ae2017-05-13 18:14:34 -07001065 if (!evt_payload || !rsrc_data)
1066 return rc;
Harsh Shaha1af8822017-05-11 22:06:36 -07001067
Harsh Shah23557ae2017-05-13 18:14:34 -07001068 cam_ife_irq_regs = evt_payload->irq_reg_val;
1069 status_reg = cam_ife_irq_regs[CAM_IFE_IRQ_BUS_REG_STATUS1];
1070
1071 if (status_reg & BIT(rsrc_data->index)) {
1072 cam_ife_irq_regs[CAM_IFE_IRQ_BUS_REG_STATUS1] &=
1073 ~BIT(rsrc_data->index);
Harsh Shaha1af8822017-05-11 22:06:36 -07001074 rc = CAM_VFE_IRQ_STATUS_SUCCESS;
Harsh Shah23557ae2017-05-13 18:14:34 -07001075 }
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07001076 CAM_DBG(CAM_ISP, "status_reg %x rc %d", status_reg, rc);
Harsh Shaha1af8822017-05-11 22:06:36 -07001077
1078 if (rc == CAM_VFE_IRQ_STATUS_SUCCESS)
Harsh Shah19f55812017-06-26 18:58:49 -07001079 cam_vfe_bus_put_evt_payload(rsrc_data->common_data,
Harsh Shaha1af8822017-05-11 22:06:36 -07001080 &evt_payload);
1081
1082 return rc;
1083}
1084
1085static int cam_vfe_bus_init_wm_resource(uint32_t index,
1086 struct cam_vfe_bus_ver2_priv *ver2_bus_priv,
1087 struct cam_vfe_bus_ver2_hw_info *ver2_hw_info,
1088 struct cam_isp_resource_node *wm_res)
1089{
Harsh Shaha1af8822017-05-11 22:06:36 -07001090 struct cam_vfe_bus_ver2_wm_resource_data *rsrc_data;
1091
1092 rsrc_data = kzalloc(sizeof(struct cam_vfe_bus_ver2_wm_resource_data),
1093 GFP_KERNEL);
1094 if (!rsrc_data) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07001095 CAM_DBG(CAM_ISP, "Failed to alloc for WM res priv");
Harsh Shah545df9a2017-06-16 16:43:17 -07001096 return -ENOMEM;
Harsh Shaha1af8822017-05-11 22:06:36 -07001097 }
1098 wm_res->res_priv = rsrc_data;
1099
1100 rsrc_data->index = index;
1101 rsrc_data->hw_regs = &ver2_hw_info->bus_client_reg[index];
1102 rsrc_data->common_data = &ver2_bus_priv->common_data;
1103
1104 wm_res->res_state = CAM_ISP_RESOURCE_STATE_AVAILABLE;
1105 INIT_LIST_HEAD(&wm_res->list);
1106
1107 wm_res->start = cam_vfe_bus_start_wm;
1108 wm_res->stop = cam_vfe_bus_stop_wm;
1109 wm_res->top_half_handler = cam_vfe_bus_handle_wm_done_top_half;
1110 wm_res->bottom_half_handler = cam_vfe_bus_handle_wm_done_bottom_half;
1111 wm_res->hw_intf = ver2_bus_priv->common_data.hw_intf;
1112
Harsh Shah545df9a2017-06-16 16:43:17 -07001113 return 0;
1114}
1115
1116static int cam_vfe_bus_deinit_wm_resource(
1117 struct cam_isp_resource_node *wm_res)
1118{
1119 struct cam_vfe_bus_ver2_wm_resource_data *rsrc_data;
1120
1121 wm_res->res_state = CAM_ISP_RESOURCE_STATE_UNAVAILABLE;
1122 INIT_LIST_HEAD(&wm_res->list);
1123
1124 wm_res->start = NULL;
1125 wm_res->stop = NULL;
1126 wm_res->top_half_handler = NULL;
1127 wm_res->bottom_half_handler = NULL;
1128 wm_res->hw_intf = NULL;
1129
1130 rsrc_data = wm_res->res_priv;
1131 wm_res->res_priv = NULL;
1132 if (!rsrc_data) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07001133 CAM_ERR(CAM_ISP, "Error! WM res priv is NULL");
Harsh Shah545df9a2017-06-16 16:43:17 -07001134 return -ENOMEM;
1135 }
1136 kfree(rsrc_data);
1137
1138 return 0;
Harsh Shaha1af8822017-05-11 22:06:36 -07001139}
1140
1141static void cam_vfe_bus_add_wm_to_comp_grp(
1142 struct cam_isp_resource_node *comp_grp,
1143 uint32_t composite_mask)
1144{
1145 struct cam_vfe_bus_ver2_comp_grp_data *rsrc_data = comp_grp->res_priv;
1146
1147 rsrc_data->composite_mask |= composite_mask;
1148}
1149
1150static void cam_vfe_bus_match_comp_grp(
1151 struct cam_vfe_bus_ver2_priv *ver2_bus_priv,
1152 struct cam_isp_resource_node **comp_grp,
1153 uint32_t comp_grp_local_idx,
1154 uint32_t unique_id)
1155{
1156 struct cam_vfe_bus_ver2_comp_grp_data *rsrc_data = NULL;
1157 struct cam_isp_resource_node *comp_grp_local = NULL;
1158
1159 list_for_each_entry(comp_grp_local,
1160 &ver2_bus_priv->used_comp_grp, list) {
1161 rsrc_data = comp_grp_local->res_priv;
1162 if (rsrc_data->comp_grp_local_idx == comp_grp_local_idx &&
1163 rsrc_data->unique_id == unique_id) {
1164 /* Match found */
1165 *comp_grp = comp_grp_local;
1166 return;
1167 }
1168 }
1169
1170 *comp_grp = NULL;
1171}
1172
1173static int cam_vfe_bus_acquire_comp_grp(
1174 struct cam_vfe_bus_ver2_priv *ver2_bus_priv,
1175 struct cam_isp_out_port_info *out_port_info,
Harsh Shah19f55812017-06-26 18:58:49 -07001176 void *tasklet,
1177 void *ctx,
Harsh Shaha1af8822017-05-11 22:06:36 -07001178 uint32_t unique_id,
1179 uint32_t is_dual,
1180 uint32_t is_master,
1181 enum cam_vfe_bus_ver2_vfe_core_id dual_slave_core,
1182 struct cam_isp_resource_node **comp_grp)
1183{
1184 int rc = 0;
1185 struct cam_isp_resource_node *comp_grp_local = NULL;
1186 struct cam_vfe_bus_ver2_comp_grp_data *rsrc_data = NULL;
1187
1188 /* Check if matching comp_grp already acquired */
1189 cam_vfe_bus_match_comp_grp(ver2_bus_priv, &comp_grp_local,
1190 out_port_info->comp_grp_id, unique_id);
1191
1192 if (!comp_grp_local) {
1193 /* First find a free group */
1194 if (is_dual) {
1195 if (list_empty(&ver2_bus_priv->free_dual_comp_grp)) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07001196 CAM_ERR(CAM_ISP, "No Free Composite Group");
Harsh Shaha1af8822017-05-11 22:06:36 -07001197 return -ENODEV;
1198 }
1199 comp_grp_local = list_first_entry(
1200 &ver2_bus_priv->free_dual_comp_grp,
1201 struct cam_isp_resource_node, list);
1202 rsrc_data = comp_grp_local->res_priv;
1203 rc = cam_vfe_bus_ver2_get_intra_client_mask(
1204 dual_slave_core,
1205 comp_grp_local->hw_intf->hw_idx,
1206 &rsrc_data->intra_client_mask);
1207 } else {
1208 if (list_empty(&ver2_bus_priv->free_comp_grp)) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07001209 CAM_ERR(CAM_ISP, "No Free Composite Group");
Harsh Shaha1af8822017-05-11 22:06:36 -07001210 return -ENODEV;
1211 }
1212 comp_grp_local = list_first_entry(
1213 &ver2_bus_priv->free_comp_grp,
1214 struct cam_isp_resource_node, list);
1215 rsrc_data = comp_grp_local->res_priv;
1216 }
1217
1218 list_del(&comp_grp_local->list);
Harsh Shah19f55812017-06-26 18:58:49 -07001219 comp_grp_local->tasklet_info = tasklet;
Harsh Shaha1af8822017-05-11 22:06:36 -07001220 comp_grp_local->res_state = CAM_ISP_RESOURCE_STATE_RESERVED;
1221
1222 rsrc_data->is_master = is_master;
1223 rsrc_data->composite_mask = 0;
1224 rsrc_data->unique_id = unique_id;
1225 rsrc_data->comp_grp_local_idx = out_port_info->comp_grp_id;
1226
1227 list_add_tail(&comp_grp_local->list,
1228 &ver2_bus_priv->used_comp_grp);
1229
1230 } else {
1231 rsrc_data = comp_grp_local->res_priv;
1232 /* Do not support runtime change in composite mask */
1233 if (comp_grp_local->res_state ==
1234 CAM_ISP_RESOURCE_STATE_STREAMING) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07001235 CAM_ERR(CAM_ISP, "Invalid State %d Comp Grp %u",
Harsh Shaha1af8822017-05-11 22:06:36 -07001236 comp_grp_local->res_state,
1237 rsrc_data->comp_grp_type);
1238 return -EBUSY;
1239 }
1240 }
1241
Harsh Shah19f55812017-06-26 18:58:49 -07001242 rsrc_data->ctx = ctx;
Harsh Shaha1af8822017-05-11 22:06:36 -07001243 *comp_grp = comp_grp_local;
1244
1245 return rc;
1246}
1247
1248static int cam_vfe_bus_release_comp_grp(
1249 struct cam_vfe_bus_ver2_priv *ver2_bus_priv,
1250 struct cam_isp_resource_node *in_comp_grp)
1251{
1252 struct cam_isp_resource_node *comp_grp = NULL;
1253 struct cam_vfe_bus_ver2_comp_grp_data *in_rsrc_data = NULL;
1254 int match_found = 0;
1255
1256 if (!in_comp_grp) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07001257 CAM_ERR(CAM_ISP, "Invalid Params Comp Grp %pK", in_rsrc_data);
Harsh Shaha1af8822017-05-11 22:06:36 -07001258 return -EINVAL;
1259 }
1260
1261 if (in_comp_grp->res_state == CAM_ISP_RESOURCE_STATE_AVAILABLE) {
1262 /* Already Released. Do Nothing */
1263 return 0;
1264 }
1265
1266 in_rsrc_data = in_comp_grp->res_priv;
1267
1268 list_for_each_entry(comp_grp, &ver2_bus_priv->used_comp_grp, list) {
1269 if (comp_grp == in_comp_grp) {
1270 match_found = 1;
1271 break;
1272 }
1273 }
1274
1275 if (!match_found) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07001276 CAM_ERR(CAM_ISP, "Could not find matching Comp Grp type %u",
Harsh Shaha1af8822017-05-11 22:06:36 -07001277 in_rsrc_data->comp_grp_type);
1278 return -ENODEV;
1279 }
1280
1281
1282 list_del(&comp_grp->list);
1283 if (in_rsrc_data->comp_grp_type >= CAM_VFE_BUS_VER2_COMP_GRP_DUAL_0 &&
1284 in_rsrc_data->comp_grp_type <= CAM_VFE_BUS_VER2_COMP_GRP_DUAL_5)
1285 list_add_tail(&comp_grp->list,
1286 &ver2_bus_priv->free_dual_comp_grp);
Jing Zhoue71fd4a2017-05-15 19:44:34 -07001287 else if (in_rsrc_data->comp_grp_type >= CAM_VFE_BUS_VER2_COMP_GRP_0
1288 && in_rsrc_data->comp_grp_type <= CAM_VFE_BUS_VER2_COMP_GRP_5)
Harsh Shaha1af8822017-05-11 22:06:36 -07001289 list_add_tail(&comp_grp->list, &ver2_bus_priv->free_comp_grp);
1290
Harsh Shaha1af8822017-05-11 22:06:36 -07001291 in_rsrc_data->unique_id = 0;
1292 in_rsrc_data->comp_grp_local_idx = 0;
1293 in_rsrc_data->composite_mask = 0;
1294 in_rsrc_data->dual_slave_core = CAM_VFE_BUS_VER2_VFE_CORE_MAX;
1295
Harsh Shah19f55812017-06-26 18:58:49 -07001296 comp_grp->tasklet_info = NULL;
Harsh Shaha1af8822017-05-11 22:06:36 -07001297 comp_grp->res_state = CAM_ISP_RESOURCE_STATE_AVAILABLE;
1298
Jing Zhoue71fd4a2017-05-15 19:44:34 -07001299 return 0;
Harsh Shaha1af8822017-05-11 22:06:36 -07001300}
1301
1302static int cam_vfe_bus_start_comp_grp(struct cam_isp_resource_node *comp_grp)
1303{
1304 int rc = 0;
1305 struct cam_vfe_bus_ver2_comp_grp_data *rsrc_data =
1306 comp_grp->res_priv;
1307 struct cam_vfe_bus_ver2_common_data *common_data =
1308 rsrc_data->common_data;
Harsh Shah19f55812017-06-26 18:58:49 -07001309 uint32_t bus_irq_reg_mask[CAM_VFE_BUS_IRQ_MAX] = {0};
Harsh Shaha1af8822017-05-11 22:06:36 -07001310
1311 cam_io_w_mb(rsrc_data->composite_mask, common_data->mem_base +
1312 rsrc_data->hw_regs->comp_mask);
1313
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07001314 CAM_DBG(CAM_ISP, "composite_mask is 0x%x", rsrc_data->composite_mask);
1315 CAM_DBG(CAM_ISP, "composite_mask addr 0x%x",
1316 rsrc_data->hw_regs->comp_mask);
Harsh Shaha1af8822017-05-11 22:06:36 -07001317
1318 if (rsrc_data->comp_grp_type >= CAM_VFE_BUS_VER2_COMP_GRP_DUAL_0 &&
1319 rsrc_data->comp_grp_type <= CAM_VFE_BUS_VER2_COMP_GRP_DUAL_5 &&
1320 rsrc_data->is_master) {
1321 int dual_comp_grp = (rsrc_data->comp_grp_type -
1322 CAM_VFE_BUS_VER2_COMP_GRP_DUAL_0);
1323 int intra_client_en = cam_io_r_mb(common_data->mem_base +
1324 common_data->common_reg->dual_master_comp_cfg);
1325
1326 /* 2 Bits per comp_grp. Hence left shift by comp_grp * 2 */
1327 intra_client_en |=
1328 (rsrc_data->intra_client_mask << dual_comp_grp * 2);
1329
1330 cam_io_w_mb(intra_client_en, common_data->mem_base +
1331 common_data->common_reg->dual_master_comp_cfg);
Harsh Shah19f55812017-06-26 18:58:49 -07001332
1333 bus_irq_reg_mask[CAM_VFE_BUS_IRQ_REG2] = (1 << dual_comp_grp);
1334 } else {
1335 /* IRQ bits for COMP GRP start at 5. So add 5 to the shift */
1336 bus_irq_reg_mask[CAM_VFE_BUS_IRQ_REG0] =
1337 (1 << (rsrc_data->comp_grp_type + 5));
1338 }
1339
1340 /* Subscribe IRQ */
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07001341 CAM_DBG(CAM_ISP, "Subscribe COMP_GRP%d IRQ", rsrc_data->comp_grp_type);
Harsh Shah19f55812017-06-26 18:58:49 -07001342 comp_grp->irq_handle = cam_irq_controller_subscribe_irq(
1343 common_data->bus_irq_controller, CAM_IRQ_PRIORITY_1,
1344 bus_irq_reg_mask, comp_grp,
1345 comp_grp->top_half_handler,
1346 cam_ife_mgr_do_tasklet_buf_done,
1347 comp_grp->tasklet_info, cam_tasklet_enqueue_cmd);
1348 if (comp_grp->irq_handle < 0) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07001349 CAM_ERR(CAM_ISP, "Subscribe IRQ failed for comp_grp %d",
Harsh Shah19f55812017-06-26 18:58:49 -07001350 rsrc_data->comp_grp_type);
1351 return -EFAULT;
Harsh Shaha1af8822017-05-11 22:06:36 -07001352 }
1353
1354 comp_grp->res_state = CAM_ISP_RESOURCE_STATE_STREAMING;
Harsh Shah19f55812017-06-26 18:58:49 -07001355
Harsh Shaha1af8822017-05-11 22:06:36 -07001356 return rc;
1357}
1358
1359static int cam_vfe_bus_stop_comp_grp(struct cam_isp_resource_node *comp_grp)
1360{
1361 int rc = 0;
1362 struct cam_vfe_bus_ver2_comp_grp_data *rsrc_data =
1363 comp_grp->res_priv;
1364 struct cam_vfe_bus_ver2_common_data *common_data =
1365 rsrc_data->common_data;
1366
1367 /* Unsubscribe IRQ */
Harsh Shah19f55812017-06-26 18:58:49 -07001368 rc = cam_irq_controller_unsubscribe_irq(
1369 common_data->bus_irq_controller,
1370 comp_grp->irq_handle);
Harsh Shaha1af8822017-05-11 22:06:36 -07001371
1372 cam_io_w_mb(rsrc_data->composite_mask, common_data->mem_base +
1373 rsrc_data->hw_regs->comp_mask);
1374 if (rsrc_data->comp_grp_type >= CAM_VFE_BUS_VER2_COMP_GRP_DUAL_0 &&
1375 rsrc_data->comp_grp_type <= CAM_VFE_BUS_VER2_COMP_GRP_DUAL_5 &&
1376 rsrc_data->is_master) {
1377 int dual_comp_grp = (rsrc_data->comp_grp_type -
1378 CAM_VFE_BUS_VER2_COMP_GRP_DUAL_0);
1379 int intra_client_en = cam_io_r_mb(common_data->mem_base +
1380 common_data->common_reg->dual_master_comp_cfg);
1381
1382 /* 2 Bits per comp_grp. Hence left shift by comp_grp * 2 */
1383 intra_client_en &=
1384 ~(rsrc_data->intra_client_mask << dual_comp_grp * 2);
1385
1386 cam_io_w_mb(intra_client_en, common_data->mem_base +
1387 common_data->common_reg->dual_master_comp_cfg);
1388 }
1389
1390 comp_grp->res_state = CAM_ISP_RESOURCE_STATE_RESERVED;
1391
1392 return rc;
1393}
1394
1395static int cam_vfe_bus_handle_comp_done_top_half(uint32_t evt_id,
1396 struct cam_irq_th_payload *th_payload)
1397{
Harsh Shah19f55812017-06-26 18:58:49 -07001398 int32_t rc;
1399 int i;
1400 struct cam_isp_resource_node *comp_grp = NULL;
1401 struct cam_vfe_bus_ver2_comp_grp_data *rsrc_data = NULL;
1402 struct cam_vfe_bus_irq_evt_payload *evt_payload;
1403
1404 comp_grp = th_payload->handler_priv;
1405 if (!comp_grp) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07001406 CAM_ERR_RATE_LIMIT(CAM_ISP, "Error! No resource\n");
Harsh Shah19f55812017-06-26 18:58:49 -07001407 return -ENODEV;
1408 }
1409
1410 rsrc_data = comp_grp->res_priv;
1411
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07001412 CAM_DBG(CAM_ISP, "IRQ status_0 = %x", th_payload->evt_status_arr[0]);
1413 CAM_DBG(CAM_ISP, "IRQ status_1 = %x", th_payload->evt_status_arr[1]);
Harsh Shah19f55812017-06-26 18:58:49 -07001414
1415 rc = cam_vfe_bus_get_evt_payload(rsrc_data->common_data, &evt_payload);
1416 if (rc) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07001417 CAM_ERR_RATE_LIMIT(CAM_ISP,
1418 "No tasklet_cmd is free in queue\n");
Harsh Shah19f55812017-06-26 18:58:49 -07001419 return rc;
1420 }
1421
1422 cam_isp_hw_get_timestamp(&evt_payload->ts);
1423
1424 evt_payload->ctx = rsrc_data->ctx;
1425 evt_payload->core_index = rsrc_data->common_data->core_index;
1426 evt_payload->evt_id = evt_id;
1427
1428 for (i = 0; i < th_payload->num_registers; i++)
1429 evt_payload->irq_reg_val[i] = th_payload->evt_status_arr[i];
1430
1431 th_payload->evt_payload_priv = evt_payload;
1432
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07001433 CAM_DBG(CAM_ISP, "Exit");
Harsh Shah19f55812017-06-26 18:58:49 -07001434 return rc;
Harsh Shaha1af8822017-05-11 22:06:36 -07001435}
1436
1437static int cam_vfe_bus_handle_comp_done_bottom_half(
1438 void *handler_priv,
1439 void *evt_payload_priv)
1440{
1441 int rc = CAM_VFE_IRQ_STATUS_ERR;
1442 struct cam_isp_resource_node *comp_grp = handler_priv;
1443 struct cam_vfe_bus_irq_evt_payload *evt_payload = evt_payload_priv;
1444 struct cam_vfe_bus_ver2_comp_grp_data *rsrc_data = comp_grp->res_priv;
Harsh Shah23557ae2017-05-13 18:14:34 -07001445 uint32_t *cam_ife_irq_regs;
1446 uint32_t status_reg;
1447 uint32_t comp_err_reg;
1448 uint32_t comp_grp_id;
1449
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07001450 CAM_DBG(CAM_ISP, "comp grp type %d", rsrc_data->comp_grp_type);
Harsh Shah19f55812017-06-26 18:58:49 -07001451
Harsh Shah23557ae2017-05-13 18:14:34 -07001452 if (!evt_payload)
1453 return rc;
1454
1455 cam_ife_irq_regs = evt_payload->irq_reg_val;
Harsh Shaha1af8822017-05-11 22:06:36 -07001456
Harsh Shaha1af8822017-05-11 22:06:36 -07001457 switch (rsrc_data->comp_grp_type) {
1458 case CAM_VFE_BUS_VER2_COMP_GRP_0:
1459 case CAM_VFE_BUS_VER2_COMP_GRP_1:
1460 case CAM_VFE_BUS_VER2_COMP_GRP_2:
1461 case CAM_VFE_BUS_VER2_COMP_GRP_3:
1462 case CAM_VFE_BUS_VER2_COMP_GRP_4:
1463 case CAM_VFE_BUS_VER2_COMP_GRP_5:
Harsh Shah23557ae2017-05-13 18:14:34 -07001464 comp_grp_id = (rsrc_data->comp_grp_type -
Harsh Shaha1af8822017-05-11 22:06:36 -07001465 CAM_VFE_BUS_VER2_COMP_GRP_0);
1466
1467 /* Check for Regular composite error */
1468 status_reg = cam_ife_irq_regs[CAM_IFE_IRQ_BUS_REG_STATUS0];
1469
1470 comp_err_reg = cam_ife_irq_regs[CAM_IFE_IRQ_BUS_REG_COMP_ERR];
1471 if ((status_reg & BIT(11)) &&
1472 (comp_err_reg & rsrc_data->composite_mask)) {
1473 /* Check for Regular composite error */
1474 rc = CAM_VFE_IRQ_STATUS_ERR_COMP;
1475 break;
1476 }
1477
1478 comp_err_reg = cam_ife_irq_regs[CAM_IFE_IRQ_BUS_REG_COMP_OWRT];
1479 /* Check for Regular composite Overwrite */
1480 if ((status_reg & BIT(12)) &&
1481 (comp_err_reg & rsrc_data->composite_mask)) {
1482 rc = CAM_VFE_IRQ_STATUS_COMP_OWRT;
1483 break;
1484 }
1485
Harsh Shah23557ae2017-05-13 18:14:34 -07001486 /* Regular Composite SUCCESS */
1487 if (status_reg & BIT(comp_grp_id + 5)) {
1488 cam_ife_irq_regs[CAM_IFE_IRQ_BUS_REG_STATUS0] &=
1489 ~BIT(comp_grp_id + 5);
Harsh Shaha1af8822017-05-11 22:06:36 -07001490 rc = CAM_VFE_IRQ_STATUS_SUCCESS;
Harsh Shah23557ae2017-05-13 18:14:34 -07001491 }
Harsh Shaha1af8822017-05-11 22:06:36 -07001492
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07001493 CAM_DBG(CAM_ISP, "status reg = 0x%x, bit index = %d rc %d",
Harsh Shah19f55812017-06-26 18:58:49 -07001494 status_reg, (comp_grp_id + 5), rc);
Harsh Shaha1af8822017-05-11 22:06:36 -07001495 break;
1496
1497 case CAM_VFE_BUS_VER2_COMP_GRP_DUAL_0:
1498 case CAM_VFE_BUS_VER2_COMP_GRP_DUAL_1:
1499 case CAM_VFE_BUS_VER2_COMP_GRP_DUAL_2:
1500 case CAM_VFE_BUS_VER2_COMP_GRP_DUAL_3:
1501 case CAM_VFE_BUS_VER2_COMP_GRP_DUAL_4:
1502 case CAM_VFE_BUS_VER2_COMP_GRP_DUAL_5:
Harsh Shah23557ae2017-05-13 18:14:34 -07001503 comp_grp_id = (rsrc_data->comp_grp_type -
Harsh Shaha1af8822017-05-11 22:06:36 -07001504 CAM_VFE_BUS_VER2_COMP_GRP_DUAL_0);
1505
1506 /* Check for DUAL composite error */
1507 status_reg = cam_ife_irq_regs[CAM_IFE_IRQ_BUS_REG_STATUS2];
1508
1509 comp_err_reg = cam_ife_irq_regs[CAM_IFE_IRQ_BUS_DUAL_COMP_ERR];
1510 if ((status_reg & BIT(6)) &&
1511 (comp_err_reg & rsrc_data->composite_mask)) {
1512 /* Check for DUAL composite error */
1513 rc = CAM_VFE_IRQ_STATUS_ERR_COMP;
1514 break;
1515 }
1516
1517 /* Check for Dual composite Overwrite */
1518 comp_err_reg = cam_ife_irq_regs[CAM_IFE_IRQ_BUS_DUAL_COMP_OWRT];
1519 if ((status_reg & BIT(7)) &&
1520 (comp_err_reg & rsrc_data->composite_mask)) {
1521 rc = CAM_VFE_IRQ_STATUS_COMP_OWRT;
1522 break;
1523 }
1524
Harsh Shah23557ae2017-05-13 18:14:34 -07001525 /* DUAL Composite SUCCESS */
1526 if (status_reg & BIT(comp_grp_id)) {
1527 cam_ife_irq_regs[CAM_IFE_IRQ_BUS_REG_STATUS2] &=
1528 ~BIT(comp_grp_id + 5);
Harsh Shaha1af8822017-05-11 22:06:36 -07001529 rc = CAM_VFE_IRQ_STATUS_SUCCESS;
Harsh Shah23557ae2017-05-13 18:14:34 -07001530 }
Harsh Shaha1af8822017-05-11 22:06:36 -07001531
1532 break;
Harsh Shaha1af8822017-05-11 22:06:36 -07001533 default:
1534 rc = CAM_VFE_IRQ_STATUS_ERR;
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07001535 CAM_ERR(CAM_ISP, "Error! Invalid comp_grp_type %u",
Harsh Shah19f55812017-06-26 18:58:49 -07001536 rsrc_data->comp_grp_type);
Harsh Shaha1af8822017-05-11 22:06:36 -07001537 break;
1538 }
1539
1540 if (rc == CAM_VFE_IRQ_STATUS_SUCCESS)
Harsh Shah19f55812017-06-26 18:58:49 -07001541 cam_vfe_bus_put_evt_payload(rsrc_data->common_data,
Harsh Shaha1af8822017-05-11 22:06:36 -07001542 &evt_payload);
1543
1544 return rc;
1545}
1546
1547static int cam_vfe_bus_init_comp_grp(uint32_t index,
1548 struct cam_vfe_bus_ver2_priv *ver2_bus_priv,
1549 struct cam_vfe_bus_ver2_hw_info *ver2_hw_info,
1550 struct cam_isp_resource_node *comp_grp)
1551{
Harsh Shah545df9a2017-06-16 16:43:17 -07001552 struct cam_vfe_bus_ver2_comp_grp_data *rsrc_data = NULL;
Harsh Shaha1af8822017-05-11 22:06:36 -07001553
1554 rsrc_data = kzalloc(sizeof(struct cam_vfe_bus_ver2_comp_grp_data),
1555 GFP_KERNEL);
1556 if (!rsrc_data) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07001557 CAM_DBG(CAM_ISP, "Failed to alloc for comp_grp_priv");
Harsh Shaha1af8822017-05-11 22:06:36 -07001558 return -ENOMEM;
1559 }
1560 comp_grp->res_priv = rsrc_data;
1561
1562 comp_grp->res_state = CAM_ISP_RESOURCE_STATE_AVAILABLE;
1563 INIT_LIST_HEAD(&comp_grp->list);
1564
1565 rsrc_data->comp_grp_type = index;
1566 rsrc_data->common_data = &ver2_bus_priv->common_data;
1567 rsrc_data->hw_regs = &ver2_hw_info->comp_grp_reg[index];
1568 rsrc_data->dual_slave_core = CAM_VFE_BUS_VER2_VFE_CORE_MAX;
1569
Harsh Shaha1af8822017-05-11 22:06:36 -07001570 if (rsrc_data->comp_grp_type >= CAM_VFE_BUS_VER2_COMP_GRP_DUAL_0 &&
1571 rsrc_data->comp_grp_type <= CAM_VFE_BUS_VER2_COMP_GRP_DUAL_5)
1572 list_add_tail(&comp_grp->list,
1573 &ver2_bus_priv->free_dual_comp_grp);
1574 else if (rsrc_data->comp_grp_type >= CAM_VFE_BUS_VER2_COMP_GRP_0
1575 && rsrc_data->comp_grp_type <= CAM_VFE_BUS_VER2_COMP_GRP_5)
1576 list_add_tail(&comp_grp->list, &ver2_bus_priv->free_comp_grp);
1577
1578 comp_grp->start = cam_vfe_bus_start_comp_grp;
1579 comp_grp->stop = cam_vfe_bus_stop_comp_grp;
1580 comp_grp->top_half_handler = cam_vfe_bus_handle_comp_done_top_half;
1581 comp_grp->bottom_half_handler =
1582 cam_vfe_bus_handle_comp_done_bottom_half;
1583 comp_grp->hw_intf = ver2_bus_priv->common_data.hw_intf;
1584
1585 return 0;
1586}
1587
Harsh Shah545df9a2017-06-16 16:43:17 -07001588static int cam_vfe_bus_deinit_comp_grp(
1589 struct cam_isp_resource_node *comp_grp)
1590{
1591 struct cam_vfe_bus_ver2_comp_grp_data *rsrc_data =
1592 comp_grp->res_priv;
1593
1594 comp_grp->start = NULL;
1595 comp_grp->stop = NULL;
1596 comp_grp->top_half_handler = NULL;
1597 comp_grp->bottom_half_handler = NULL;
1598 comp_grp->hw_intf = NULL;
1599
1600 list_del_init(&comp_grp->list);
1601 comp_grp->res_state = CAM_ISP_RESOURCE_STATE_UNAVAILABLE;
1602
1603 comp_grp->res_priv = NULL;
1604
1605 if (!rsrc_data) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07001606 CAM_ERR(CAM_ISP, "Error! comp_grp_priv is NULL");
Harsh Shah545df9a2017-06-16 16:43:17 -07001607 return -ENODEV;
1608 }
1609 kfree(rsrc_data);
1610
1611 return 0;
1612}
1613
Harsh Shah19f55812017-06-26 18:58:49 -07001614static int cam_vfe_bus_acquire_vfe_out(void *bus_priv, void *acquire_args,
1615 uint32_t args_size)
Harsh Shaha1af8822017-05-11 22:06:36 -07001616{
1617 int rc = -ENODEV;
1618 int i;
1619 enum cam_vfe_bus_ver2_vfe_out_type vfe_out_res_id;
1620 uint32_t format;
1621 uint32_t num_wm;
1622 uint32_t subscribe_irq;
1623 uint32_t client_done_mask;
1624 struct cam_vfe_bus_ver2_priv *ver2_bus_priv = bus_priv;
1625 struct cam_vfe_acquire_args *acq_args = acquire_args;
1626 struct cam_vfe_hw_vfe_out_acquire_args *out_acquire_args;
1627 struct cam_isp_resource_node *rsrc_node = NULL;
1628 struct cam_vfe_bus_ver2_vfe_out_data *rsrc_data = NULL;
1629
1630 if (!bus_priv || !acquire_args) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07001631 CAM_ERR(CAM_ISP, "Invalid Param");
Harsh Shaha1af8822017-05-11 22:06:36 -07001632 return -EINVAL;
1633 }
1634
1635 out_acquire_args = &acq_args->vfe_out;
1636 format = out_acquire_args->out_port_info->format;
1637
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07001638 CAM_DBG(CAM_ISP, "Acquiring resource type 0x%x",
Harsh Shaha1af8822017-05-11 22:06:36 -07001639 out_acquire_args->out_port_info->res_type);
1640
1641 vfe_out_res_id = cam_vfe_bus_get_out_res_id(
1642 out_acquire_args->out_port_info->res_type);
1643 if (vfe_out_res_id == CAM_VFE_BUS_VER2_VFE_OUT_MAX)
1644 return -ENODEV;
1645
1646 num_wm = cam_vfe_bus_get_num_wm(vfe_out_res_id, format);
1647 if (num_wm < 1)
1648 return -EINVAL;
1649
1650 rsrc_node = &ver2_bus_priv->vfe_out[vfe_out_res_id];
1651 if (rsrc_node->res_state != CAM_ISP_RESOURCE_STATE_AVAILABLE) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07001652 CAM_ERR(CAM_ISP, "Resource not available: Res_id %d state:%d",
Harsh Shaha1af8822017-05-11 22:06:36 -07001653 vfe_out_res_id, rsrc_node->res_state);
1654 return -EBUSY;
1655 }
1656
1657 rsrc_data = rsrc_node->res_priv;
1658 rsrc_data->num_wm = num_wm;
1659 rsrc_node->res_id = out_acquire_args->out_port_info->res_type;
1660 rsrc_node->tasklet_info = acq_args->tasklet;
1661 rsrc_node->cdm_ops = out_acquire_args->cdm_ops;
1662 rsrc_data->cdm_util_ops = out_acquire_args->cdm_ops;
1663
1664 /* Reserve Composite Group */
1665 if (num_wm > 1 || (out_acquire_args->out_port_info->comp_grp_id >
1666 CAM_ISP_RES_COMP_GROUP_NONE &&
1667 out_acquire_args->out_port_info->comp_grp_id <
1668 CAM_ISP_RES_COMP_GROUP_ID_MAX)) {
1669 rc = cam_vfe_bus_acquire_comp_grp(ver2_bus_priv,
1670 out_acquire_args->out_port_info,
Harsh Shah19f55812017-06-26 18:58:49 -07001671 acq_args->tasklet,
1672 out_acquire_args->ctx,
Harsh Shaha1af8822017-05-11 22:06:36 -07001673 out_acquire_args->unique_id,
1674 out_acquire_args->is_dual,
1675 out_acquire_args->is_master,
1676 out_acquire_args->dual_slave_core,
1677 &rsrc_data->comp_grp);
Harsh Shah19f55812017-06-26 18:58:49 -07001678 if (rc) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07001679 CAM_ERR(CAM_ISP,
1680 "VFE%d Comp_Grp acquire fail for Out %d rc=%d",
Harsh Shah19f55812017-06-26 18:58:49 -07001681 rsrc_data->common_data->core_index,
1682 vfe_out_res_id, rc);
Harsh Shaha1af8822017-05-11 22:06:36 -07001683 return rc;
Harsh Shah19f55812017-06-26 18:58:49 -07001684 }
Harsh Shaha1af8822017-05-11 22:06:36 -07001685
1686 subscribe_irq = 0;
Harsh Shah19f55812017-06-26 18:58:49 -07001687 } else {
Harsh Shaha1af8822017-05-11 22:06:36 -07001688 subscribe_irq = 1;
Harsh Shah19f55812017-06-26 18:58:49 -07001689 }
Harsh Shaha1af8822017-05-11 22:06:36 -07001690
1691 /* Reserve WM */
1692 for (i = 0; i < num_wm; i++) {
1693 rc = cam_vfe_bus_acquire_wm(ver2_bus_priv,
1694 out_acquire_args->out_port_info,
Harsh Shah19f55812017-06-26 18:58:49 -07001695 acq_args->tasklet,
1696 out_acquire_args->ctx,
Harsh Shaha1af8822017-05-11 22:06:36 -07001697 vfe_out_res_id,
1698 i,
1699 out_acquire_args->split_id,
1700 subscribe_irq,
1701 &rsrc_data->wm_res[i],
1702 &client_done_mask);
Harsh Shah19f55812017-06-26 18:58:49 -07001703 if (rc) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07001704 CAM_ERR(CAM_ISP,
1705 "VFE%d WM acquire failed for Out %d rc=%d",
Harsh Shah19f55812017-06-26 18:58:49 -07001706 rsrc_data->common_data->core_index,
1707 vfe_out_res_id, rc);
Harsh Shaha1af8822017-05-11 22:06:36 -07001708 goto release_wm;
Harsh Shah19f55812017-06-26 18:58:49 -07001709 }
Harsh Shaha1af8822017-05-11 22:06:36 -07001710
1711 if (rsrc_data->comp_grp)
1712 cam_vfe_bus_add_wm_to_comp_grp(rsrc_data->comp_grp,
1713 client_done_mask);
1714 }
1715
1716 rsrc_node->res_state = CAM_ISP_RESOURCE_STATE_RESERVED;
1717 out_acquire_args->rsrc_node = rsrc_node;
1718
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07001719 CAM_DBG(CAM_ISP, "Acquire successful");
Harsh Shaha1af8822017-05-11 22:06:36 -07001720 return rc;
1721
1722release_wm:
1723 for (i--; i >= 0; i--)
1724 cam_vfe_bus_release_wm(ver2_bus_priv, rsrc_data->wm_res[i]);
1725
1726 cam_vfe_bus_release_comp_grp(ver2_bus_priv,
1727 rsrc_data->comp_grp);
1728
1729 return rc;
1730}
1731
Harsh Shah19f55812017-06-26 18:58:49 -07001732static int cam_vfe_bus_release_vfe_out(void *bus_priv, void *release_args,
1733 uint32_t args_size)
Harsh Shaha1af8822017-05-11 22:06:36 -07001734{
Jing Zhoue71fd4a2017-05-15 19:44:34 -07001735 uint32_t i;
Harsh Shah19f55812017-06-26 18:58:49 -07001736 struct cam_isp_resource_node *vfe_out = NULL;
1737 struct cam_vfe_bus_ver2_vfe_out_data *rsrc_data = NULL;
1738
1739 if (!bus_priv || !release_args) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07001740 CAM_ERR(CAM_ISP, "Invalid input bus_priv %pK release_args %pK",
Harsh Shah19f55812017-06-26 18:58:49 -07001741 bus_priv, release_args);
1742 return -EINVAL;
1743 }
1744
1745 vfe_out = release_args;
1746 rsrc_data = vfe_out->res_priv;
Jing Zhoue71fd4a2017-05-15 19:44:34 -07001747
Harsh Shaha1af8822017-05-11 22:06:36 -07001748 if (vfe_out->res_state != CAM_ISP_RESOURCE_STATE_RESERVED) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07001749 CAM_ERR(CAM_ISP, "Error! Invalid resource state:%d",
Harsh Shaha1af8822017-05-11 22:06:36 -07001750 vfe_out->res_state);
1751 }
1752
Jing Zhoue71fd4a2017-05-15 19:44:34 -07001753 for (i = 0; i < rsrc_data->num_wm; i++)
1754 cam_vfe_bus_release_wm(bus_priv, rsrc_data->wm_res[i]);
1755 rsrc_data->num_wm = 0;
1756
1757 if (rsrc_data->comp_grp)
1758 cam_vfe_bus_release_comp_grp(bus_priv, rsrc_data->comp_grp);
1759 rsrc_data->comp_grp = NULL;
1760
1761 vfe_out->tasklet_info = NULL;
1762 vfe_out->cdm_ops = NULL;
1763 rsrc_data->cdm_util_ops = NULL;
1764
Harsh Shaha1af8822017-05-11 22:06:36 -07001765 if (vfe_out->res_state == CAM_ISP_RESOURCE_STATE_RESERVED)
1766 vfe_out->res_state = CAM_ISP_RESOURCE_STATE_AVAILABLE;
1767
1768 return 0;
1769}
1770
Harsh Shah19f55812017-06-26 18:58:49 -07001771static int cam_vfe_bus_start_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 struct cam_vfe_bus_ver2_common_data *common_data = NULL;
1777
1778 if (!vfe_out) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07001779 CAM_ERR(CAM_ISP, "Invalid input");
Harsh Shah19f55812017-06-26 18:58:49 -07001780 return -EINVAL;
1781 }
1782
1783 rsrc_data = vfe_out->res_priv;
1784 common_data = rsrc_data->common_data;
Harsh Shaha1af8822017-05-11 22:06:36 -07001785
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07001786 CAM_DBG(CAM_ISP, "Start resource index %d", rsrc_data->out_type);
Harsh Shaha1af8822017-05-11 22:06:36 -07001787
1788 if (vfe_out->res_state != CAM_ISP_RESOURCE_STATE_RESERVED) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07001789 CAM_ERR(CAM_ISP, "Error! Invalid resource state:%d",
Harsh Shaha1af8822017-05-11 22:06:36 -07001790 vfe_out->res_state);
1791 return -EACCES;
1792 }
1793
1794 for (i = 0; i < rsrc_data->num_wm; i++)
1795 rc = cam_vfe_bus_start_wm(rsrc_data->wm_res[i]);
1796
1797 if (rsrc_data->comp_grp)
1798 rc = cam_vfe_bus_start_comp_grp(rsrc_data->comp_grp);
1799
Harsh Shaha1af8822017-05-11 22:06:36 -07001800 /* BUS_WR_INPUT_IF_ADDR_SYNC_CFG */
1801 cam_io_w_mb(0x0, rsrc_data->common_data->mem_base + 0x0000207C);
1802 /* BUS_WR_INPUT_IF_ADDR_SYNC_FRAME_HEADER */
1803 cam_io_w_mb(0x0, rsrc_data->common_data->mem_base + 0x00002080);
1804 /* BUS_WR_INPUT_IF_ADDR_SYNC_NO_SYNC */
1805 cam_io_w_mb(0xFFFFF, rsrc_data->common_data->mem_base + 0x00002084);
Harsh Shaha1af8822017-05-11 22:06:36 -07001806 /* BUS_WR_INPUT_IF_ADDR_SYNC_0 */
1807 cam_io_w_mb(0x0, rsrc_data->common_data->mem_base + 0x00002088);
1808 cam_io_w_mb(0x0, rsrc_data->common_data->mem_base + 0x0000208c);
1809 cam_io_w_mb(0x0, rsrc_data->common_data->mem_base + 0x00002090);
1810 cam_io_w_mb(0x0, rsrc_data->common_data->mem_base + 0x00002094);
1811 cam_io_w_mb(0x0, rsrc_data->common_data->mem_base + 0x00002098);
1812 cam_io_w_mb(0x0, rsrc_data->common_data->mem_base + 0x0000209c);
1813 cam_io_w_mb(0x0, rsrc_data->common_data->mem_base + 0x000020a0);
1814 cam_io_w_mb(0x0, rsrc_data->common_data->mem_base + 0x000020a4);
1815
Harsh Shah23557ae2017-05-13 18:14:34 -07001816 /* no clock gating at bus input */
1817 cam_io_w_mb(0xFFFFF, rsrc_data->common_data->mem_base + 0x0000200C);
1818
1819 /* BUS_WR_TEST_BUS_CTRL */
1820 cam_io_w_mb(0x0, rsrc_data->common_data->mem_base + 0x0000211C);
1821
Abhishek Kondaveeti157ae882017-07-08 06:56:48 +05301822 vfe_out->res_state = CAM_ISP_RESOURCE_STATE_STREAMING;
Harsh Shaha1af8822017-05-11 22:06:36 -07001823 return rc;
1824}
1825
Harsh Shah19f55812017-06-26 18:58:49 -07001826static int cam_vfe_bus_stop_vfe_out(
1827 struct cam_isp_resource_node *vfe_out)
Harsh Shaha1af8822017-05-11 22:06:36 -07001828{
1829 int rc = 0, i;
Harsh Shah19f55812017-06-26 18:58:49 -07001830 struct cam_vfe_bus_ver2_vfe_out_data *rsrc_data = NULL;
1831
1832 if (!vfe_out) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07001833 CAM_ERR(CAM_ISP, "Invalid input");
Harsh Shah19f55812017-06-26 18:58:49 -07001834 return -EINVAL;
1835 }
1836
1837 rsrc_data = vfe_out->res_priv;
Harsh Shaha1af8822017-05-11 22:06:36 -07001838
1839 if (vfe_out->res_state == CAM_ISP_RESOURCE_STATE_AVAILABLE ||
1840 vfe_out->res_state == CAM_ISP_RESOURCE_STATE_RESERVED) {
1841 return rc;
1842 }
1843
1844 if (rsrc_data->comp_grp)
1845 rc = cam_vfe_bus_stop_comp_grp(rsrc_data->comp_grp);
1846
1847 for (i = 0; i < rsrc_data->num_wm; i++)
1848 rc = cam_vfe_bus_stop_wm(rsrc_data->wm_res[i]);
1849
Harsh Shaha1af8822017-05-11 22:06:36 -07001850
1851 vfe_out->res_state = CAM_ISP_RESOURCE_STATE_RESERVED;
1852 return rc;
1853}
1854
1855static int cam_vfe_bus_handle_vfe_out_done_top_half(uint32_t evt_id,
1856 struct cam_irq_th_payload *th_payload)
1857{
1858 return -EPERM;
1859}
1860
1861static int cam_vfe_bus_handle_vfe_out_done_bottom_half(
1862 void *handler_priv,
1863 void *evt_payload_priv)
1864{
1865 int rc = -EINVAL;
1866 struct cam_isp_resource_node *vfe_out = handler_priv;
1867 struct cam_vfe_bus_ver2_vfe_out_data *rsrc_data = vfe_out->res_priv;
1868
1869 /*
1870 * If this resource has Composite Group then we only handle
1871 * Composite done. We acquire Composite if number of WM > 1.
1872 * So Else case is only one individual buf_done = WM[0].
1873 */
1874 if (rsrc_data->comp_grp) {
1875 rc = rsrc_data->comp_grp->bottom_half_handler(
1876 rsrc_data->comp_grp, evt_payload_priv);
1877 } else {
1878 rc = rsrc_data->wm_res[0]->bottom_half_handler(
Harsh Shah23557ae2017-05-13 18:14:34 -07001879 rsrc_data->wm_res[0], evt_payload_priv);
Harsh Shaha1af8822017-05-11 22:06:36 -07001880 }
1881
1882 return rc;
1883}
1884
1885static int cam_vfe_bus_init_vfe_out_resource(uint32_t index,
1886 struct cam_vfe_bus_ver2_priv *ver2_bus_priv,
1887 struct cam_vfe_bus_ver2_hw_info *ver2_hw_info,
1888 struct cam_isp_resource_node *vfe_out)
1889{
1890 struct cam_vfe_bus_ver2_vfe_out_data *rsrc_data = NULL;
1891 int rc = 0;
1892
1893 rsrc_data = kzalloc(sizeof(struct cam_vfe_bus_ver2_vfe_out_data),
1894 GFP_KERNEL);
1895 if (!rsrc_data) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07001896 CAM_DBG(CAM_ISP, "Error! Failed to alloc for vfe out priv");
Harsh Shaha1af8822017-05-11 22:06:36 -07001897 rc = -ENOMEM;
1898 return rc;
1899 }
1900 vfe_out->res_priv = rsrc_data;
1901
1902 vfe_out->res_type = CAM_ISP_RESOURCE_VFE_OUT;
1903 vfe_out->res_state = CAM_ISP_RESOURCE_STATE_AVAILABLE;
1904 INIT_LIST_HEAD(&vfe_out->list);
1905
1906 rsrc_data->out_type = index;
1907 rsrc_data->common_data = &ver2_bus_priv->common_data;
1908 rsrc_data->max_width =
1909 ver2_hw_info->vfe_out_hw_info[index].max_width;
1910 rsrc_data->max_height =
1911 ver2_hw_info->vfe_out_hw_info[index].max_height;
1912
1913 vfe_out->start = cam_vfe_bus_start_vfe_out;
1914 vfe_out->stop = cam_vfe_bus_stop_vfe_out;
1915 vfe_out->top_half_handler = cam_vfe_bus_handle_vfe_out_done_top_half;
1916 vfe_out->bottom_half_handler =
1917 cam_vfe_bus_handle_vfe_out_done_bottom_half;
1918 vfe_out->hw_intf = ver2_bus_priv->common_data.hw_intf;
1919
1920 return 0;
1921}
1922
Harsh Shah545df9a2017-06-16 16:43:17 -07001923static int cam_vfe_bus_deinit_vfe_out_resource(
1924 struct cam_isp_resource_node *vfe_out)
1925{
1926 struct cam_vfe_bus_ver2_vfe_out_data *rsrc_data = vfe_out->res_priv;
1927
1928 vfe_out->start = NULL;
1929 vfe_out->stop = NULL;
1930 vfe_out->top_half_handler = NULL;
1931 vfe_out->bottom_half_handler = NULL;
1932 vfe_out->hw_intf = NULL;
1933
1934 vfe_out->res_state = CAM_ISP_RESOURCE_STATE_UNAVAILABLE;
1935 INIT_LIST_HEAD(&vfe_out->list);
1936 vfe_out->res_priv = NULL;
1937
1938 if (!rsrc_data) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07001939 CAM_ERR(CAM_ISP, "Error! vfe out priv is NULL");
Harsh Shah545df9a2017-06-16 16:43:17 -07001940 return -ENOMEM;
1941 }
1942 kfree(rsrc_data);
1943
1944 return 0;
1945}
1946
Harsh Shaha1af8822017-05-11 22:06:36 -07001947static int cam_vfe_bus_ver2_handle_irq(uint32_t evt_id,
1948 struct cam_irq_th_payload *th_payload)
1949{
Harsh Shaha1af8822017-05-11 22:06:36 -07001950 struct cam_vfe_bus_ver2_priv *bus_priv;
Harsh Shaha1af8822017-05-11 22:06:36 -07001951
Harsh Shah19f55812017-06-26 18:58:49 -07001952 bus_priv = th_payload->handler_priv;
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07001953 CAM_DBG(CAM_ISP, "Enter");
Harsh Shah19f55812017-06-26 18:58:49 -07001954 return cam_irq_controller_handle_irq(evt_id,
1955 bus_priv->common_data.bus_irq_controller);
Harsh Shaha1af8822017-05-11 22:06:36 -07001956}
1957
1958static int cam_vfe_bus_update_buf(void *priv, void *cmd_args,
1959 uint32_t arg_size)
1960{
1961 struct cam_vfe_bus_ver2_priv *bus_priv;
1962 struct cam_isp_hw_get_buf_update *update_buf;
Jing Zhoua4e9fbe2017-05-15 14:37:21 -07001963 struct cam_buf_io_cfg *io_cfg;
Harsh Shaha1af8822017-05-11 22:06:36 -07001964 struct cam_vfe_bus_ver2_vfe_out_data *vfe_out_data = NULL;
1965 struct cam_vfe_bus_ver2_wm_resource_data *wm_data = NULL;
Jing Zhoua4e9fbe2017-05-15 14:37:21 -07001966 uint32_t *reg_val_pair;
1967 uint32_t i, j, size = 0;
Junzhe Zou193d78c2017-05-16 15:10:54 -07001968 uint32_t frame_inc = 0;
Harsh Shaha1af8822017-05-11 22:06:36 -07001969
1970 /*
1971 * Need the entire buf io config so we can get the stride info
1972 * for the wm.
1973 */
1974
1975 bus_priv = (struct cam_vfe_bus_ver2_priv *) priv;
1976 update_buf = (struct cam_isp_hw_get_buf_update *) cmd_args;
1977
1978 vfe_out_data = (struct cam_vfe_bus_ver2_vfe_out_data *)
1979 update_buf->cdm.res->res_priv;
1980
1981 if (!vfe_out_data || !vfe_out_data->cdm_util_ops) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07001982 CAM_ERR(CAM_ISP, "Failed! Invalid data");
Harsh Shaha1af8822017-05-11 22:06:36 -07001983 return -EINVAL;
1984 }
1985
Jing Zhoua4e9fbe2017-05-15 14:37:21 -07001986 if (update_buf->num_buf != vfe_out_data->num_wm) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07001987 CAM_ERR(CAM_ISP,
1988 "Failed! Invalid number buffers:%d required:%d",
Harsh Shaha1af8822017-05-11 22:06:36 -07001989 update_buf->num_buf, vfe_out_data->num_wm);
Junzhe Zou193d78c2017-05-16 15:10:54 -07001990 return -EINVAL;
Harsh Shaha1af8822017-05-11 22:06:36 -07001991 }
1992
Jing Zhoua4e9fbe2017-05-15 14:37:21 -07001993 reg_val_pair = &vfe_out_data->common_data->io_buf_update[0];
1994 io_cfg = update_buf->io_cfg;
1995
1996 for (i = 0, j = 0; i < vfe_out_data->num_wm; i++) {
Junzhe Zou193d78c2017-05-16 15:10:54 -07001997 if (j >= (MAX_REG_VAL_PAIR_SIZE - MAX_BUF_UPDATE_REG_NUM * 2)) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07001998 CAM_ERR(CAM_ISP,
1999 "reg_val_pair %d exceeds the array limit %lu",
Junzhe Zou193d78c2017-05-16 15:10:54 -07002000 j, MAX_REG_VAL_PAIR_SIZE);
2001 return -ENOMEM;
2002 }
2003
Jing Zhoua4e9fbe2017-05-15 14:37:21 -07002004 wm_data = vfe_out_data->wm_res[i]->res_priv;
2005
2006 /* For initial configuration program all bus registers */
Ravikishore Pampanaad6bc902017-07-12 19:37:06 +05302007 if ((wm_data->stride != io_cfg->planes[i].plane_stride ||
2008 !wm_data->init_cfg_done) && (wm_data->index >= 3)) {
Jing Zhoua4e9fbe2017-05-15 14:37:21 -07002009 CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j,
2010 wm_data->hw_regs->stride,
2011 io_cfg->planes[i].plane_stride);
2012 wm_data->stride = io_cfg->planes[i].plane_stride;
2013 }
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07002014 CAM_DBG(CAM_ISP, "image stride 0x%x", wm_data->stride);
Jing Zhoua4e9fbe2017-05-15 14:37:21 -07002015
2016 if (wm_data->framedrop_pattern != io_cfg->framedrop_pattern ||
Pavan Kumar Chilamkurthi649cdf92017-08-15 01:40:57 -07002017 !wm_data->hfr_cfg_done) {
Jing Zhoua4e9fbe2017-05-15 14:37:21 -07002018 CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j,
2019 wm_data->hw_regs->framedrop_pattern,
2020 io_cfg->framedrop_pattern);
2021 wm_data->framedrop_pattern = io_cfg->framedrop_pattern;
2022 }
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07002023 CAM_DBG(CAM_ISP, "framedrop pattern 0x%x",
2024 wm_data->framedrop_pattern);
Jing Zhoua4e9fbe2017-05-15 14:37:21 -07002025
2026 if (wm_data->framedrop_period != io_cfg->framedrop_period ||
Pavan Kumar Chilamkurthi649cdf92017-08-15 01:40:57 -07002027 !wm_data->hfr_cfg_done) {
Jing Zhoua4e9fbe2017-05-15 14:37:21 -07002028 CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j,
2029 wm_data->hw_regs->framedrop_period,
2030 io_cfg->framedrop_period);
2031 wm_data->framedrop_period = io_cfg->framedrop_period;
2032 }
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07002033 CAM_DBG(CAM_ISP, "framedrop period 0x%x",
2034 wm_data->framedrop_period);
Jing Zhoua4e9fbe2017-05-15 14:37:21 -07002035
2036 if (wm_data->irq_subsample_period != io_cfg->subsample_period
Pavan Kumar Chilamkurthi649cdf92017-08-15 01:40:57 -07002037 || !wm_data->hfr_cfg_done) {
Jing Zhoua4e9fbe2017-05-15 14:37:21 -07002038 CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j,
2039 wm_data->hw_regs->irq_subsample_period,
2040 io_cfg->subsample_period);
2041 wm_data->irq_subsample_period =
2042 io_cfg->subsample_period;
2043 }
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07002044 CAM_DBG(CAM_ISP, "irq subsample period 0x%x",
Jing Zhoua4e9fbe2017-05-15 14:37:21 -07002045 wm_data->irq_subsample_period);
2046
2047 if (wm_data->irq_subsample_pattern != io_cfg->subsample_pattern
Pavan Kumar Chilamkurthi649cdf92017-08-15 01:40:57 -07002048 || !wm_data->hfr_cfg_done) {
Jing Zhoua4e9fbe2017-05-15 14:37:21 -07002049 CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j,
2050 wm_data->hw_regs->irq_subsample_pattern,
2051 io_cfg->subsample_pattern);
2052 wm_data->irq_subsample_pattern =
2053 io_cfg->subsample_pattern;
2054 }
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07002055 CAM_DBG(CAM_ISP, "irq subsample pattern 0x%x",
Jing Zhoua4e9fbe2017-05-15 14:37:21 -07002056 wm_data->irq_subsample_pattern);
2057
2058 if (wm_data->en_ubwc) {
2059 if (!wm_data->hw_regs->ubwc_regs) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07002060 CAM_ERR(CAM_ISP,
2061 "No UBWC register to configure.");
Jing Zhoua4e9fbe2017-05-15 14:37:21 -07002062 return -EINVAL;
2063 }
2064 if (wm_data->packer_cfg !=
2065 io_cfg->planes[i].packer_config ||
2066 !wm_data->init_cfg_done) {
2067 CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j,
2068 wm_data->hw_regs->packer_cfg,
2069 io_cfg->planes[i].packer_config);
2070 wm_data->packer_cfg =
2071 io_cfg->planes[i].packer_config;
2072 }
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07002073 CAM_DBG(CAM_ISP, "packer cfg 0x%x",
2074 wm_data->packer_cfg);
Jing Zhoua4e9fbe2017-05-15 14:37:21 -07002075
2076 if (wm_data->tile_cfg != io_cfg->planes[i].tile_config
2077 || !wm_data->init_cfg_done) {
2078 CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j,
2079 wm_data->hw_regs->ubwc_regs->tile_cfg,
2080 io_cfg->planes[i].tile_config);
2081 wm_data->tile_cfg =
2082 io_cfg->planes[i].tile_config;
2083 }
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07002084 CAM_DBG(CAM_ISP, "tile cfg 0x%x", wm_data->tile_cfg);
Jing Zhoua4e9fbe2017-05-15 14:37:21 -07002085
2086 if (wm_data->h_init != io_cfg->planes[i].h_init ||
2087 !wm_data->init_cfg_done) {
2088 CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j,
2089 wm_data->hw_regs->ubwc_regs->h_init,
2090 io_cfg->planes[i].h_init);
2091 wm_data->h_init = io_cfg->planes[i].h_init;
2092 }
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07002093 CAM_DBG(CAM_ISP, "h_init 0x%x", wm_data->h_init);
Jing Zhoua4e9fbe2017-05-15 14:37:21 -07002094
2095 if (wm_data->v_init != io_cfg->planes[i].v_init ||
2096 !wm_data->init_cfg_done) {
2097 CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j,
2098 wm_data->hw_regs->ubwc_regs->v_init,
2099 io_cfg->planes[i].v_init);
2100 wm_data->v_init = io_cfg->planes[i].v_init;
2101 }
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07002102 CAM_DBG(CAM_ISP, "v_init 0x%x", wm_data->v_init);
Jing Zhoua4e9fbe2017-05-15 14:37:21 -07002103
2104 if (wm_data->ubwc_meta_stride !=
2105 io_cfg->planes[i].meta_stride ||
2106 !wm_data->init_cfg_done) {
2107 CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j,
2108 wm_data->hw_regs->ubwc_regs->
2109 meta_stride,
2110 io_cfg->planes[i].meta_stride);
2111 wm_data->ubwc_meta_stride =
2112 io_cfg->planes[i].meta_stride;
2113 }
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07002114 CAM_DBG(CAM_ISP, "meta stride 0x%x",
2115 wm_data->ubwc_meta_stride);
Jing Zhoua4e9fbe2017-05-15 14:37:21 -07002116
2117 if (wm_data->ubwc_mode_cfg !=
2118 io_cfg->planes[i].mode_config ||
2119 !wm_data->init_cfg_done) {
2120 CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j,
2121 wm_data->hw_regs->ubwc_regs->mode_cfg,
2122 io_cfg->planes[i].mode_config);
2123 wm_data->ubwc_mode_cfg =
2124 io_cfg->planes[i].mode_config;
2125 }
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07002126 CAM_DBG(CAM_ISP, "ubwc mode cfg 0x%x",
2127 wm_data->ubwc_mode_cfg);
Jing Zhoua4e9fbe2017-05-15 14:37:21 -07002128
2129 if (wm_data->ubwc_meta_offset !=
2130 io_cfg->planes[i].meta_offset ||
2131 !wm_data->init_cfg_done) {
2132 CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j,
2133 wm_data->hw_regs->ubwc_regs->
2134 meta_offset,
2135 io_cfg->planes[i].meta_offset);
2136 wm_data->ubwc_meta_offset =
2137 io_cfg->planes[i].meta_offset;
2138 }
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07002139 CAM_DBG(CAM_ISP, "ubwc meta offset 0x%x",
Jing Zhoua4e9fbe2017-05-15 14:37:21 -07002140 wm_data->ubwc_meta_offset);
2141
2142 /* UBWC meta address */
2143 CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j,
2144 wm_data->hw_regs->ubwc_regs->meta_addr,
2145 update_buf->image_buf[i]);
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07002146 CAM_DBG(CAM_ISP, "ubwc meta addr 0x%llx",
Jing Zhoua4e9fbe2017-05-15 14:37:21 -07002147 update_buf->image_buf[i]);
2148 }
2149
2150 /* WM Image address */
2151 if (wm_data->en_ubwc)
2152 CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j,
2153 wm_data->hw_regs->image_addr,
2154 (update_buf->image_buf[i] +
2155 io_cfg->planes[i].meta_size));
2156 else
2157 CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j,
2158 wm_data->hw_regs->image_addr,
2159 update_buf->image_buf[i]);
2160
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07002161 CAM_DBG(CAM_ISP, "image address 0x%x", reg_val_pair[j-1]);
Jing Zhoua4e9fbe2017-05-15 14:37:21 -07002162
Junzhe Zou193d78c2017-05-16 15:10:54 -07002163 frame_inc = io_cfg->planes[i].plane_stride *
2164 io_cfg->planes[i].slice_height;
2165 CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j,
2166 wm_data->hw_regs->frame_inc, frame_inc);
2167
Jing Zhoua4e9fbe2017-05-15 14:37:21 -07002168 /* enable the WM */
2169 CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j,
2170 wm_data->hw_regs->cfg,
2171 wm_data->en_cfg);
2172
2173 /* set initial configuration done */
2174 if (!wm_data->init_cfg_done)
Pavan Kumar Chilamkurthi649cdf92017-08-15 01:40:57 -07002175 wm_data->init_cfg_done = true;
Jing Zhoua4e9fbe2017-05-15 14:37:21 -07002176 }
2177
2178 size = vfe_out_data->cdm_util_ops->cdm_required_size_reg_random(j/2);
Harsh Shaha1af8822017-05-11 22:06:36 -07002179
2180 /* cdm util returns dwords, need to convert to bytes */
2181 if ((size * 4) > update_buf->cdm.size) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07002182 CAM_ERR(CAM_ISP,
2183 "Failed! Buf size:%d insufficient, expected size:%d",
Harsh Shaha1af8822017-05-11 22:06:36 -07002184 update_buf->cdm.size, size);
2185 return -ENOMEM;
2186 }
2187
Harsh Shaha1af8822017-05-11 22:06:36 -07002188 vfe_out_data->cdm_util_ops->cdm_write_regrandom(
Jing Zhoua4e9fbe2017-05-15 14:37:21 -07002189 update_buf->cdm.cmd_buf_addr, j/2, reg_val_pair);
2190
Harsh Shaha1af8822017-05-11 22:06:36 -07002191 /* cdm util returns dwords, need to convert to bytes */
2192 update_buf->cdm.used_bytes = size * 4;
2193
2194 return 0;
2195}
2196
Pavan Kumar Chilamkurthi649cdf92017-08-15 01:40:57 -07002197static int cam_vfe_bus_update_hfr(void *priv, void *cmd_args,
2198 uint32_t arg_size)
2199{
2200 struct cam_vfe_bus_ver2_priv *bus_priv;
2201 struct cam_isp_hw_get_hfr_update *update_hfr;
2202 struct cam_vfe_bus_ver2_vfe_out_data *vfe_out_data = NULL;
2203 struct cam_vfe_bus_ver2_wm_resource_data *wm_data = NULL;
2204 struct cam_isp_port_hfr_config *hfr_cfg = NULL;
2205 uint32_t *reg_val_pair;
2206 uint32_t i, j, size = 0;
2207
2208 bus_priv = (struct cam_vfe_bus_ver2_priv *) priv;
2209 update_hfr = (struct cam_isp_hw_get_hfr_update *) cmd_args;
2210
2211 vfe_out_data = (struct cam_vfe_bus_ver2_vfe_out_data *)
2212 update_hfr->cdm.res->res_priv;
2213
2214 if (!vfe_out_data || !vfe_out_data->cdm_util_ops) {
2215 CAM_ERR(CAM_ISP, "Failed! Invalid data");
2216 return -EINVAL;
2217 }
2218
2219 reg_val_pair = &vfe_out_data->common_data->io_buf_update[0];
2220 hfr_cfg = update_hfr->io_hfr_cfg;
2221
2222 for (i = 0, j = 0; i < vfe_out_data->num_wm; i++) {
2223 if (j >= (MAX_REG_VAL_PAIR_SIZE - MAX_BUF_UPDATE_REG_NUM * 2)) {
2224 CAM_ERR(CAM_ISP,
2225 "reg_val_pair %d exceeds the array limit %lu",
2226 j, MAX_REG_VAL_PAIR_SIZE);
2227 return -ENOMEM;
2228 }
2229
2230 wm_data = vfe_out_data->wm_res[i]->res_priv;
2231
2232 if ((wm_data->framedrop_pattern !=
2233 hfr_cfg->framedrop_pattern) ||
2234 !wm_data->hfr_cfg_done) {
2235 CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j,
2236 wm_data->hw_regs->framedrop_pattern,
2237 hfr_cfg->framedrop_pattern);
2238 wm_data->framedrop_pattern = hfr_cfg->framedrop_pattern;
2239 }
2240 CAM_DBG(CAM_ISP, "framedrop pattern 0x%x",
2241 wm_data->framedrop_pattern);
2242
2243 if (wm_data->framedrop_period != hfr_cfg->framedrop_period ||
2244 !wm_data->hfr_cfg_done) {
2245 CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j,
2246 wm_data->hw_regs->framedrop_period,
2247 hfr_cfg->framedrop_period);
2248 wm_data->framedrop_period = hfr_cfg->framedrop_period;
2249 }
2250 CAM_DBG(CAM_ISP, "framedrop period 0x%x",
2251 wm_data->framedrop_period);
2252
2253 if (wm_data->irq_subsample_period != hfr_cfg->subsample_period
2254 || !wm_data->hfr_cfg_done) {
2255 CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j,
2256 wm_data->hw_regs->irq_subsample_period,
2257 hfr_cfg->subsample_period);
2258 wm_data->irq_subsample_period =
2259 hfr_cfg->subsample_period;
2260 }
2261 CAM_DBG(CAM_ISP, "irq subsample period 0x%x",
2262 wm_data->irq_subsample_period);
2263
2264 if (wm_data->irq_subsample_pattern != hfr_cfg->subsample_pattern
2265 || !wm_data->hfr_cfg_done) {
2266 CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j,
2267 wm_data->hw_regs->irq_subsample_pattern,
2268 hfr_cfg->subsample_pattern);
2269 wm_data->irq_subsample_pattern =
2270 hfr_cfg->subsample_pattern;
2271 }
2272 CAM_DBG(CAM_ISP, "irq subsample pattern 0x%x",
2273 wm_data->irq_subsample_pattern);
2274
2275 /* set initial configuration done */
2276 if (!wm_data->hfr_cfg_done)
2277 wm_data->hfr_cfg_done = true;
2278 }
2279
2280 size = vfe_out_data->cdm_util_ops->cdm_required_size_reg_random(j/2);
2281
2282 /* cdm util returns dwords, need to convert to bytes */
2283 if ((size * 4) > update_hfr->cdm.size) {
2284 CAM_ERR(CAM_ISP,
2285 "Failed! Buf size:%d insufficient, expected size:%d",
2286 update_hfr->cdm.size, size);
2287 return -ENOMEM;
2288 }
2289
2290 vfe_out_data->cdm_util_ops->cdm_write_regrandom(
2291 update_hfr->cdm.cmd_buf_addr, j/2, reg_val_pair);
2292
2293 /* cdm util returns dwords, need to convert to bytes */
2294 update_hfr->cdm.used_bytes = size * 4;
2295
2296 return 0;
2297}
2298
Harsh Shah19f55812017-06-26 18:58:49 -07002299static int cam_vfe_bus_start_hw(void *hw_priv,
2300 void *start_hw_args, uint32_t arg_size)
2301{
2302 return cam_vfe_bus_start_vfe_out(hw_priv);
2303}
2304
2305static int cam_vfe_bus_stop_hw(void *hw_priv,
2306 void *stop_hw_args, uint32_t arg_size)
2307{
2308 return cam_vfe_bus_stop_vfe_out(hw_priv);
2309}
2310
2311static int cam_vfe_bus_init_hw(void *hw_priv,
2312 void *init_hw_args, uint32_t arg_size)
2313{
2314 struct cam_vfe_bus_ver2_priv *bus_priv = hw_priv;
2315 uint32_t top_irq_reg_mask[2] = {0};
2316
2317 if (!bus_priv) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07002318 CAM_ERR(CAM_ISP, "Error! Invalid args");
Harsh Shah19f55812017-06-26 18:58:49 -07002319 return -EINVAL;
2320 }
2321
2322 top_irq_reg_mask[0] = (1 << 9);
2323
2324 bus_priv->irq_handle = cam_irq_controller_subscribe_irq(
2325 bus_priv->common_data.vfe_irq_controller,
2326 CAM_IRQ_PRIORITY_2,
2327 top_irq_reg_mask,
2328 bus_priv,
2329 cam_vfe_bus_ver2_handle_irq,
2330 NULL,
2331 NULL,
2332 NULL);
2333
2334 if (bus_priv->irq_handle <= 0) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07002335 CAM_ERR(CAM_ISP, "Failed to subscribe BUS IRQ");
Harsh Shah19f55812017-06-26 18:58:49 -07002336 return -EFAULT;
2337 }
2338
2339 return 0;
2340}
2341
2342static int cam_vfe_bus_deinit_hw(void *hw_priv,
2343 void *deinit_hw_args, uint32_t arg_size)
2344{
2345 struct cam_vfe_bus_ver2_priv *bus_priv = hw_priv;
2346 int rc;
2347
2348 if (!bus_priv || (bus_priv->irq_handle <= 0)) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07002349 CAM_ERR(CAM_ISP, "Error! Invalid args");
Harsh Shah19f55812017-06-26 18:58:49 -07002350 return -EINVAL;
2351 }
2352
2353 rc = cam_irq_controller_unsubscribe_irq(
2354 bus_priv->common_data.vfe_irq_controller,
2355 bus_priv->irq_handle);
2356 if (rc)
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07002357 CAM_ERR(CAM_ISP, "Failed to unsubscribe irq rc=%d", rc);
Harsh Shah19f55812017-06-26 18:58:49 -07002358
2359 return rc;
2360}
2361
Harsh Shaha1af8822017-05-11 22:06:36 -07002362static int cam_vfe_bus_process_cmd(void *priv,
2363 uint32_t cmd_type, void *cmd_args, uint32_t arg_size)
2364{
2365 int rc = -EINVAL;
2366
2367 if (!priv || !cmd_args) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07002368 CAM_ERR_RATE_LIMIT(CAM_ISP, "Error! Invalid input arguments\n");
Harsh Shaha1af8822017-05-11 22:06:36 -07002369 return -EINVAL;
2370 }
2371
2372 switch (cmd_type) {
2373 case CAM_VFE_HW_CMD_GET_BUF_UPDATE:
2374 rc = cam_vfe_bus_update_buf(priv, cmd_args, arg_size);
2375 break;
Pavan Kumar Chilamkurthi649cdf92017-08-15 01:40:57 -07002376 case CAM_VFE_HW_CMD_GET_HFR_UPDATE:
2377 rc = cam_vfe_bus_update_hfr(priv, cmd_args, arg_size);
2378 break;
Harsh Shaha1af8822017-05-11 22:06:36 -07002379 default:
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07002380 CAM_ERR_RATE_LIMIT(CAM_ISP, "Inval camif process command:%d\n",
Harsh Shaha1af8822017-05-11 22:06:36 -07002381 cmd_type);
2382 break;
2383 }
2384
2385 return rc;
2386}
2387
2388int cam_vfe_bus_ver2_init(
Harsh Shah19f55812017-06-26 18:58:49 -07002389 struct cam_hw_soc_info *soc_info,
Harsh Shaha1af8822017-05-11 22:06:36 -07002390 struct cam_hw_intf *hw_intf,
2391 void *bus_hw_info,
2392 void *vfe_irq_controller,
2393 struct cam_vfe_bus **vfe_bus)
2394{
2395 int i, rc = 0;
2396 struct cam_vfe_bus_ver2_priv *bus_priv = NULL;
2397 struct cam_vfe_bus *vfe_bus_local;
2398 struct cam_vfe_bus_ver2_hw_info *ver2_hw_info = bus_hw_info;
2399
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07002400 CAM_DBG(CAM_ISP, "Enter");
Harsh Shaha1af8822017-05-11 22:06:36 -07002401
Harsh Shah19f55812017-06-26 18:58:49 -07002402 if (!soc_info || !hw_intf || !bus_hw_info || !vfe_irq_controller) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07002403 CAM_ERR(CAM_ISP,
2404 "Inval_prms soc_info:%pK hw_intf:%pK hw_info%pK",
2405 soc_info, hw_intf, bus_hw_info);
2406 CAM_ERR(CAM_ISP, "controller: %pK", vfe_irq_controller);
Harsh Shah19f55812017-06-26 18:58:49 -07002407 rc = -EINVAL;
2408 goto end;
2409 }
2410
Harsh Shaha1af8822017-05-11 22:06:36 -07002411 vfe_bus_local = kzalloc(sizeof(struct cam_vfe_bus), GFP_KERNEL);
2412 if (!vfe_bus_local) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07002413 CAM_DBG(CAM_ISP, "Failed to alloc for vfe_bus");
Harsh Shaha1af8822017-05-11 22:06:36 -07002414 rc = -ENOMEM;
Harsh Shah545df9a2017-06-16 16:43:17 -07002415 goto end;
Harsh Shaha1af8822017-05-11 22:06:36 -07002416 }
2417
2418 bus_priv = kzalloc(sizeof(struct cam_vfe_bus_ver2_priv),
2419 GFP_KERNEL);
2420 if (!bus_priv) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07002421 CAM_DBG(CAM_ISP, "Failed to alloc for vfe_bus_priv");
Harsh Shaha1af8822017-05-11 22:06:36 -07002422 rc = -ENOMEM;
Harsh Shah545df9a2017-06-16 16:43:17 -07002423 goto free_bus_local;
Harsh Shaha1af8822017-05-11 22:06:36 -07002424 }
2425 vfe_bus_local->bus_priv = bus_priv;
2426
Harsh Shah19f55812017-06-26 18:58:49 -07002427 bus_priv->common_data.core_index = soc_info->index;
2428 bus_priv->common_data.mem_base =
2429 CAM_SOC_GET_REG_MAP_START(soc_info, VFE_CORE_BASE_IDX);
Harsh Shaha1af8822017-05-11 22:06:36 -07002430 bus_priv->common_data.hw_intf = hw_intf;
2431 bus_priv->common_data.vfe_irq_controller = vfe_irq_controller;
2432 bus_priv->common_data.common_reg = &ver2_hw_info->common_reg;
2433
Harsh Shah19f55812017-06-26 18:58:49 -07002434 rc = cam_irq_controller_init(drv_name, bus_priv->common_data.mem_base,
2435 &ver2_hw_info->common_reg.irq_reg_info,
2436 &bus_priv->common_data.bus_irq_controller);
2437 if (rc) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07002438 CAM_ERR(CAM_ISP, "Error! cam_irq_controller_init failed");
Harsh Shah19f55812017-06-26 18:58:49 -07002439 goto free_bus_priv;
2440 }
2441
Harsh Shaha1af8822017-05-11 22:06:36 -07002442 INIT_LIST_HEAD(&bus_priv->free_comp_grp);
2443 INIT_LIST_HEAD(&bus_priv->free_dual_comp_grp);
2444 INIT_LIST_HEAD(&bus_priv->used_comp_grp);
2445
2446 for (i = 0; i < CAM_VFE_BUS_VER2_MAX_CLIENTS; i++) {
2447 rc = cam_vfe_bus_init_wm_resource(i, bus_priv, bus_hw_info,
2448 &bus_priv->bus_client[i]);
2449 if (rc < 0) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07002450 CAM_ERR(CAM_ISP, "Error! Init WM failed rc=%d", rc);
Harsh Shah545df9a2017-06-16 16:43:17 -07002451 goto deinit_wm;
Harsh Shaha1af8822017-05-11 22:06:36 -07002452 }
2453 }
2454
2455 for (i = 0; i < CAM_VFE_BUS_VER2_COMP_GRP_MAX; i++) {
2456 rc = cam_vfe_bus_init_comp_grp(i, bus_priv, bus_hw_info,
2457 &bus_priv->comp_grp[i]);
2458 if (rc < 0) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07002459 CAM_ERR(CAM_ISP, "Init Comp Grp failed rc=%d", rc);
Harsh Shah545df9a2017-06-16 16:43:17 -07002460 goto deinit_comp_grp;
Harsh Shaha1af8822017-05-11 22:06:36 -07002461 }
2462 }
2463
2464 for (i = 0; i < CAM_VFE_BUS_VER2_VFE_OUT_MAX; i++) {
2465 rc = cam_vfe_bus_init_vfe_out_resource(i, bus_priv, bus_hw_info,
2466 &bus_priv->vfe_out[i]);
2467 if (rc < 0) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07002468 CAM_ERR(CAM_ISP, "Init VFE Out failed rc=%d", rc);
Harsh Shah545df9a2017-06-16 16:43:17 -07002469 goto deinit_vfe_out;
Harsh Shaha1af8822017-05-11 22:06:36 -07002470 }
2471 }
2472
Harsh Shah19f55812017-06-26 18:58:49 -07002473 INIT_LIST_HEAD(&bus_priv->common_data.free_payload_list);
2474 for (i = 0; i < CAM_VFE_BUS_VER2_PAYLOAD_MAX; i++) {
2475 INIT_LIST_HEAD(&bus_priv->common_data.evt_payload[i].list);
2476 list_add_tail(&bus_priv->common_data.evt_payload[i].list,
2477 &bus_priv->common_data.free_payload_list);
Harsh Shaha1af8822017-05-11 22:06:36 -07002478 }
2479
Harsh Shah19f55812017-06-26 18:58:49 -07002480 vfe_bus_local->hw_ops.reserve = cam_vfe_bus_acquire_vfe_out;
2481 vfe_bus_local->hw_ops.release = cam_vfe_bus_release_vfe_out;
2482 vfe_bus_local->hw_ops.start = cam_vfe_bus_start_hw;
2483 vfe_bus_local->hw_ops.stop = cam_vfe_bus_stop_hw;
2484 vfe_bus_local->hw_ops.init = cam_vfe_bus_init_hw;
2485 vfe_bus_local->hw_ops.deinit = cam_vfe_bus_deinit_hw;
2486 vfe_bus_local->top_half_handler = cam_vfe_bus_ver2_handle_irq;
Harsh Shaha1af8822017-05-11 22:06:36 -07002487 vfe_bus_local->bottom_half_handler = NULL;
Harsh Shah19f55812017-06-26 18:58:49 -07002488 vfe_bus_local->hw_ops.process_cmd = cam_vfe_bus_process_cmd;
Harsh Shaha1af8822017-05-11 22:06:36 -07002489
2490 *vfe_bus = vfe_bus_local;
2491
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07002492 CAM_DBG(CAM_ISP, "Exit");
Harsh Shaha1af8822017-05-11 22:06:36 -07002493 return rc;
2494
Harsh Shah545df9a2017-06-16 16:43:17 -07002495deinit_vfe_out:
2496 if (i < 0)
2497 i = CAM_VFE_BUS_VER2_VFE_OUT_MAX;
2498 for (--i; i >= 0; i--)
2499 cam_vfe_bus_deinit_vfe_out_resource(&bus_priv->vfe_out[i]);
2500
2501deinit_comp_grp:
2502 if (i < 0)
2503 i = CAM_VFE_BUS_VER2_COMP_GRP_MAX;
2504 for (--i; i >= 0; i--)
2505 cam_vfe_bus_deinit_comp_grp(&bus_priv->comp_grp[i]);
2506
2507deinit_wm:
2508 if (i < 0)
2509 i = CAM_VFE_BUS_VER2_MAX_CLIENTS;
2510 for (--i; i >= 0; i--)
2511 cam_vfe_bus_deinit_wm_resource(&bus_priv->bus_client[i]);
2512
Harsh Shah19f55812017-06-26 18:58:49 -07002513free_bus_priv:
Harsh Shaha1af8822017-05-11 22:06:36 -07002514 kfree(vfe_bus_local->bus_priv);
Harsh Shah545df9a2017-06-16 16:43:17 -07002515
2516free_bus_local:
Harsh Shaha1af8822017-05-11 22:06:36 -07002517 kfree(vfe_bus_local);
Harsh Shah545df9a2017-06-16 16:43:17 -07002518
2519end:
Harsh Shaha1af8822017-05-11 22:06:36 -07002520 return rc;
2521}
Harsh Shah545df9a2017-06-16 16:43:17 -07002522
2523int cam_vfe_bus_ver2_deinit(
2524 struct cam_vfe_bus **vfe_bus)
2525{
2526 int i, rc = 0;
2527 struct cam_vfe_bus_ver2_priv *bus_priv = NULL;
2528 struct cam_vfe_bus *vfe_bus_local;
2529
2530 if (!vfe_bus || !*vfe_bus) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07002531 CAM_ERR(CAM_ISP, "Error! Invalid input");
Harsh Shah545df9a2017-06-16 16:43:17 -07002532 return -EINVAL;
2533 }
2534 vfe_bus_local = *vfe_bus;
2535
2536 bus_priv = vfe_bus_local->bus_priv;
2537 if (!bus_priv) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07002538 CAM_ERR(CAM_ISP, "Error! bus_priv is NULL");
Harsh Shah545df9a2017-06-16 16:43:17 -07002539 rc = -ENODEV;
2540 goto free_bus_local;
2541 }
2542
Harsh Shah19f55812017-06-26 18:58:49 -07002543 INIT_LIST_HEAD(&bus_priv->common_data.free_payload_list);
2544 for (i = 0; i < CAM_VFE_BUS_VER2_PAYLOAD_MAX; i++)
2545 INIT_LIST_HEAD(&bus_priv->common_data.evt_payload[i].list);
Harsh Shah545df9a2017-06-16 16:43:17 -07002546
2547 for (i = 0; i < CAM_VFE_BUS_VER2_MAX_CLIENTS; i++) {
2548 rc = cam_vfe_bus_deinit_wm_resource(&bus_priv->bus_client[i]);
2549 if (rc < 0)
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07002550 CAM_ERR(CAM_ISP,
2551 "Error! Deinit WM failed rc=%d", rc);
Harsh Shah545df9a2017-06-16 16:43:17 -07002552 }
2553
2554 for (i = 0; i < CAM_VFE_BUS_VER2_COMP_GRP_MAX; i++) {
2555 rc = cam_vfe_bus_deinit_comp_grp(&bus_priv->comp_grp[i]);
2556 if (rc < 0)
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07002557 CAM_ERR(CAM_ISP,
2558 "Error! Deinit Comp Grp failed rc=%d", rc);
Harsh Shah545df9a2017-06-16 16:43:17 -07002559 }
2560
2561 for (i = 0; i < CAM_VFE_BUS_VER2_VFE_OUT_MAX; i++) {
2562 rc = cam_vfe_bus_deinit_vfe_out_resource(&bus_priv->vfe_out[i]);
2563 if (rc < 0)
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07002564 CAM_ERR(CAM_ISP,
2565 "Error! Deinit VFE Out failed rc=%d", rc);
Harsh Shah545df9a2017-06-16 16:43:17 -07002566 }
2567
2568 INIT_LIST_HEAD(&bus_priv->free_comp_grp);
2569 INIT_LIST_HEAD(&bus_priv->free_dual_comp_grp);
2570 INIT_LIST_HEAD(&bus_priv->used_comp_grp);
2571
Harsh Shah19f55812017-06-26 18:58:49 -07002572 rc = cam_irq_controller_deinit(
2573 &bus_priv->common_data.bus_irq_controller);
2574 if (rc)
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07002575 CAM_ERR(CAM_ISP,
2576 "Error! Deinit IRQ Controller failed rc=%d", rc);
Harsh Shah19f55812017-06-26 18:58:49 -07002577
Harsh Shah545df9a2017-06-16 16:43:17 -07002578 kfree(vfe_bus_local->bus_priv);
2579
2580free_bus_local:
2581 kfree(vfe_bus_local);
2582
2583 *vfe_bus = NULL;
2584
2585 return rc;
2586}
2587