blob: a2f773e17c6ce9d56ca9b90055a8820316de33b9 [file] [log] [blame]
Jing Zhouff57d862017-03-21 00:54:25 -07001/* Copyright (c) 2017, The Linux Foundation. All rights reserved.
2 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 and
5 * only version 2 as published by the Free Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 */
12
13#include <linux/iopoll.h>
14#include <linux/slab.h>
15#include <uapi/media/cam_isp.h>
16#include <uapi/media/cam_defs.h>
17
18#include "cam_ife_csid_core.h"
19#include "cam_isp_hw.h"
20#include "cam_soc_util.h"
21#include "cam_io_util.h"
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -070022#include "cam_debug_util.h"
Jing Zhouff57d862017-03-21 00:54:25 -070023
24/* Timeout value in msec */
25#define IFE_CSID_TIMEOUT 1000
26
27/* TPG VC/DT values */
28#define CAM_IFE_CSID_TPG_VC_VAL 0xA
29#define CAM_IFE_CSID_TPG_DT_VAL 0x2B
30
31/* Timeout values in usec */
32#define CAM_IFE_CSID_TIMEOUT_SLEEP_US 1000
33#define CAM_IFE_CSID_TIMEOUT_ALL_US 1000000
34
35static int cam_ife_csid_is_ipp_format_supported(
36 uint32_t decode_fmt)
37{
38 int rc = -EINVAL;
39
40 switch (decode_fmt) {
41 case CAM_FORMAT_MIPI_RAW_6:
42 case CAM_FORMAT_MIPI_RAW_8:
43 case CAM_FORMAT_MIPI_RAW_10:
44 case CAM_FORMAT_MIPI_RAW_12:
45 case CAM_FORMAT_MIPI_RAW_14:
46 case CAM_FORMAT_MIPI_RAW_16:
47 case CAM_FORMAT_MIPI_RAW_20:
48 case CAM_FORMAT_DPCM_10_6_10:
49 case CAM_FORMAT_DPCM_10_8_10:
50 case CAM_FORMAT_DPCM_12_6_12:
51 case CAM_FORMAT_DPCM_12_8_12:
52 case CAM_FORMAT_DPCM_14_8_14:
53 case CAM_FORMAT_DPCM_14_10_14:
54 rc = 0;
55 break;
56 default:
57 break;
58 }
59 return rc;
60}
61
Ravikishore Pampanaad6bc902017-07-12 19:37:06 +053062static int cam_ife_csid_get_format(uint32_t input_fmt,
63 uint32_t *path_fmt)
Jing Zhouff57d862017-03-21 00:54:25 -070064{
65 int rc = 0;
66
Ravikishore Pampanaad6bc902017-07-12 19:37:06 +053067 switch (input_fmt) {
Jing Zhouff57d862017-03-21 00:54:25 -070068 case CAM_FORMAT_MIPI_RAW_6:
69 *path_fmt = 0;
Jing Zhouff57d862017-03-21 00:54:25 -070070 break;
71 case CAM_FORMAT_MIPI_RAW_8:
72 *path_fmt = 1;
Jing Zhouff57d862017-03-21 00:54:25 -070073 break;
74 case CAM_FORMAT_MIPI_RAW_10:
75 *path_fmt = 2;
Jing Zhouff57d862017-03-21 00:54:25 -070076 break;
77 case CAM_FORMAT_MIPI_RAW_12:
78 *path_fmt = 3;
Jing Zhouff57d862017-03-21 00:54:25 -070079 break;
80 case CAM_FORMAT_MIPI_RAW_14:
81 *path_fmt = 4;
Jing Zhouff57d862017-03-21 00:54:25 -070082 break;
83 case CAM_FORMAT_MIPI_RAW_16:
84 *path_fmt = 5;
Jing Zhouff57d862017-03-21 00:54:25 -070085 break;
86 case CAM_FORMAT_MIPI_RAW_20:
87 *path_fmt = 6;
Jing Zhouff57d862017-03-21 00:54:25 -070088 break;
89 case CAM_FORMAT_DPCM_10_6_10:
90 *path_fmt = 7;
Jing Zhouff57d862017-03-21 00:54:25 -070091 break;
92 case CAM_FORMAT_DPCM_10_8_10:
93 *path_fmt = 8;
Jing Zhouff57d862017-03-21 00:54:25 -070094 break;
95 case CAM_FORMAT_DPCM_12_6_12:
96 *path_fmt = 9;
Jing Zhouff57d862017-03-21 00:54:25 -070097 break;
98 case CAM_FORMAT_DPCM_12_8_12:
99 *path_fmt = 0xA;
Jing Zhouff57d862017-03-21 00:54:25 -0700100 break;
101 case CAM_FORMAT_DPCM_14_8_14:
102 *path_fmt = 0xB;
Jing Zhouff57d862017-03-21 00:54:25 -0700103 break;
104 case CAM_FORMAT_DPCM_14_10_14:
105 *path_fmt = 0xC;
Jing Zhouff57d862017-03-21 00:54:25 -0700106 break;
107 default:
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -0700108 CAM_ERR(CAM_ISP, "CSID:%d un supported format",
109 input_fmt);
Jing Zhouff57d862017-03-21 00:54:25 -0700110 rc = -EINVAL;
111 }
112
113 return rc;
114}
115
Ravikishore Pampanaad6bc902017-07-12 19:37:06 +0530116static int cam_ife_csid_get_rdi_format(uint32_t input_fmt,
117 uint32_t output_fmt, uint32_t *path_fmt, uint32_t *plain_fmt)
118{
119 int rc = 0;
120
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -0700121 CAM_DBG(CAM_ISP, "input format:%d output format:%d",
122 input_fmt, output_fmt);
Ravikishore Pampanaad6bc902017-07-12 19:37:06 +0530123
124 switch (output_fmt) {
125 case CAM_FORMAT_MIPI_RAW_6:
126 case CAM_FORMAT_MIPI_RAW_8:
127 case CAM_FORMAT_MIPI_RAW_10:
128 case CAM_FORMAT_MIPI_RAW_12:
129 case CAM_FORMAT_MIPI_RAW_14:
130 case CAM_FORMAT_MIPI_RAW_16:
131 case CAM_FORMAT_MIPI_RAW_20:
132 case CAM_FORMAT_DPCM_10_6_10:
133 case CAM_FORMAT_DPCM_10_8_10:
134 case CAM_FORMAT_DPCM_12_6_12:
135 case CAM_FORMAT_DPCM_12_8_12:
136 case CAM_FORMAT_DPCM_14_8_14:
137 case CAM_FORMAT_DPCM_14_10_14:
138 *path_fmt = 0xF;
139 *plain_fmt = 0;
140 break;
141
142 case CAM_FORMAT_PLAIN8:
143 rc = cam_ife_csid_get_format(input_fmt, path_fmt);
144 if (rc)
145 goto error;
146
147 *plain_fmt = 0;
148 break;
149 case CAM_FORMAT_PLAIN16_8:
150 case CAM_FORMAT_PLAIN16_10:
151 case CAM_FORMAT_PLAIN16_12:
152 case CAM_FORMAT_PLAIN16_14:
153 case CAM_FORMAT_PLAIN16_16:
154 rc = cam_ife_csid_get_format(input_fmt, path_fmt);
155 if (rc)
156 goto error;
157
158 *plain_fmt = 1;
159 break;
160 case CAM_FORMAT_PLAIN32_20:
161 rc = cam_ife_csid_get_format(input_fmt, path_fmt);
162 if (rc)
163 goto error;
164
165 *plain_fmt = 2;
166 break;
167 default:
168 *path_fmt = 0xF;
169 *plain_fmt = 0;
170 break;
171 }
172
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -0700173 CAM_DBG(CAM_ISP, "path format value:%d plain format value:%d",
174 *path_fmt, *plain_fmt);
Ravikishore Pampanaad6bc902017-07-12 19:37:06 +0530175
176 return 0;
177error:
178 return rc;
179
180}
181
182
Jing Zhouff57d862017-03-21 00:54:25 -0700183static int cam_ife_csid_cid_get(struct cam_ife_csid_hw *csid_hw,
184 struct cam_isp_resource_node **res, int32_t vc, uint32_t dt,
185 uint32_t res_type)
186{
187 int rc = 0;
188 struct cam_ife_csid_cid_data *cid_data;
189 uint32_t i = 0, j = 0;
190
191 for (i = 0; i < CAM_IFE_CSID_CID_RES_MAX; i++) {
192 if (csid_hw->cid_res[i].res_state >=
193 CAM_ISP_RESOURCE_STATE_RESERVED) {
194 cid_data = (struct cam_ife_csid_cid_data *)
195 csid_hw->cid_res[i].res_priv;
196 if (res_type == CAM_ISP_IFE_IN_RES_TPG) {
197 if (cid_data->tpg_set) {
198 cid_data->cnt++;
199 *res = &csid_hw->cid_res[i];
200 break;
201 }
202 } else {
203 if (cid_data->vc == vc && cid_data->dt == dt) {
204 cid_data->cnt++;
205 *res = &csid_hw->cid_res[i];
206 break;
207 }
208 }
209 }
210 }
211
212 if (i == CAM_IFE_CSID_CID_RES_MAX) {
213 if (res_type == CAM_ISP_IFE_IN_RES_TPG) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -0700214 CAM_ERR(CAM_ISP, "CSID:%d TPG CID not available",
215 csid_hw->hw_intf->hw_idx);
Jing Zhouff57d862017-03-21 00:54:25 -0700216 rc = -EINVAL;
217 }
218
219 for (j = 0; j < CAM_IFE_CSID_CID_RES_MAX; j++) {
220 if (csid_hw->cid_res[j].res_state ==
221 CAM_ISP_RESOURCE_STATE_AVAILABLE) {
222 cid_data = (struct cam_ife_csid_cid_data *)
223 csid_hw->cid_res[j].res_priv;
224 cid_data->vc = vc;
225 cid_data->dt = dt;
226 cid_data->cnt = 1;
227 csid_hw->cid_res[j].res_state =
228 CAM_ISP_RESOURCE_STATE_RESERVED;
229 *res = &csid_hw->cid_res[j];
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -0700230 CAM_DBG(CAM_ISP, "CSID:%d CID %d allocated",
Jing Zhouff57d862017-03-21 00:54:25 -0700231 csid_hw->hw_intf->hw_idx,
232 csid_hw->cid_res[j].res_id);
233 break;
234 }
235 }
236
237 if (j == CAM_IFE_CSID_CID_RES_MAX) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -0700238 CAM_ERR(CAM_ISP, "CSID:%d Free cid is not available",
239 csid_hw->hw_intf->hw_idx);
Jing Zhouff57d862017-03-21 00:54:25 -0700240 rc = -EINVAL;
241 }
242 }
243
244 return rc;
245}
246
247
248static int cam_ife_csid_global_reset(struct cam_ife_csid_hw *csid_hw)
249{
250 struct cam_hw_soc_info *soc_info;
251 struct cam_ife_csid_reg_offset *csid_reg;
252 int rc = 0;
253 uint32_t i, irq_mask_rx, irq_mask_ipp = 0,
254 irq_mask_rdi[CAM_IFE_CSID_RDI_MAX];
255
256 soc_info = &csid_hw->hw_info->soc_info;
257 csid_reg = csid_hw->csid_info->csid_reg;
258
259 if (csid_hw->hw_info->hw_state != CAM_HW_STATE_POWER_UP) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -0700260 CAM_ERR(CAM_ISP, "CSID:%d Invalid HW State:%d",
261 csid_hw->hw_intf->hw_idx,
Jing Zhouff57d862017-03-21 00:54:25 -0700262 csid_hw->hw_info->hw_state);
263 return -EINVAL;
264 }
265
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -0700266 CAM_DBG(CAM_ISP, "CSID:%d Csid reset",
Jing Zhouff57d862017-03-21 00:54:25 -0700267 csid_hw->hw_intf->hw_idx);
268
269 init_completion(&csid_hw->csid_top_complete);
270
271 /* Save interrupt mask registers values*/
272 irq_mask_rx = cam_io_r_mb(soc_info->reg_map[0].mem_base +
273 csid_reg->csi2_reg->csid_csi2_rx_irq_mask_addr);
274
275 if (csid_reg->cmn_reg->no_pix)
276 irq_mask_ipp = cam_io_r_mb(soc_info->reg_map[0].mem_base +
277 csid_reg->ipp_reg->csid_ipp_irq_mask_addr);
278
279 for (i = 0; i < csid_reg->cmn_reg->no_rdis; i++) {
280 irq_mask_rdi[i] = cam_io_r_mb(soc_info->reg_map[0].mem_base +
281 csid_reg->rdi_reg[i]->csid_rdi_irq_mask_addr);
282 }
283
284 /* Mask all interrupts */
285 cam_io_w_mb(0, soc_info->reg_map[0].mem_base +
286 csid_reg->csi2_reg->csid_csi2_rx_irq_mask_addr);
287
288 if (csid_reg->cmn_reg->no_pix)
289 cam_io_w_mb(0, soc_info->reg_map[0].mem_base +
290 csid_reg->ipp_reg->csid_ipp_irq_mask_addr);
291
292 for (i = 0; i < csid_reg->cmn_reg->no_rdis; i++)
293 cam_io_w_mb(0, soc_info->reg_map[0].mem_base +
294 csid_reg->rdi_reg[i]->csid_rdi_irq_mask_addr);
295
296 /* clear all interrupts */
297 cam_io_w_mb(1, soc_info->reg_map[0].mem_base +
298 csid_reg->cmn_reg->csid_top_irq_clear_addr);
299
300 cam_io_w_mb(csid_reg->csi2_reg->csi2_irq_mask_all,
301 soc_info->reg_map[0].mem_base +
302 csid_reg->csi2_reg->csid_csi2_rx_irq_clear_addr);
303
304 if (csid_reg->cmn_reg->no_pix)
305 cam_io_w_mb(csid_reg->cmn_reg->ipp_irq_mask_all,
306 soc_info->reg_map[0].mem_base +
307 csid_reg->ipp_reg->csid_ipp_irq_clear_addr);
308
309 for (i = 0 ; i < csid_reg->cmn_reg->no_rdis; i++)
310 cam_io_w_mb(csid_reg->cmn_reg->rdi_irq_mask_all,
311 soc_info->reg_map[0].mem_base +
312 csid_reg->rdi_reg[i]->csid_rdi_irq_clear_addr);
313
314 cam_io_w_mb(1, soc_info->reg_map[0].mem_base +
315 csid_reg->cmn_reg->csid_irq_cmd_addr);
316
317 cam_io_w_mb(0x80, soc_info->reg_map[0].mem_base +
318 csid_hw->csid_info->csid_reg->csi2_reg->csid_csi2_rx_cfg1_addr);
319
320 /* enable the IPP and RDI format measure */
321 if (csid_reg->cmn_reg->no_pix)
322 cam_io_w_mb(0x1, soc_info->reg_map[0].mem_base +
323 csid_reg->ipp_reg->csid_ipp_cfg0_addr);
324
325 for (i = 0; i < csid_reg->cmn_reg->no_rdis; i++)
326 cam_io_w_mb(0x2, soc_info->reg_map[0].mem_base +
327 csid_reg->rdi_reg[i]->csid_rdi_cfg0_addr);
328
329 /* perform the top CSID HW reset */
330 cam_io_w_mb(csid_reg->cmn_reg->csid_rst_stb,
331 soc_info->reg_map[0].mem_base +
332 csid_reg->cmn_reg->csid_rst_strobes_addr);
333
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -0700334 CAM_DBG(CAM_ISP, " Waiting for reset complete from irq handler");
Jing Zhouff57d862017-03-21 00:54:25 -0700335 rc = wait_for_completion_timeout(&csid_hw->csid_top_complete,
336 msecs_to_jiffies(IFE_CSID_TIMEOUT));
337 if (rc <= 0) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -0700338 CAM_ERR(CAM_ISP, "CSID:%d reset completion in fail rc = %d",
339 csid_hw->hw_intf->hw_idx, rc);
Jing Zhouff57d862017-03-21 00:54:25 -0700340 if (rc == 0)
341 rc = -ETIMEDOUT;
342 } else {
343 rc = 0;
344 }
345
346 /*restore all interrupt masks */
347 cam_io_w_mb(irq_mask_rx, soc_info->reg_map[0].mem_base +
348 csid_reg->csi2_reg->csid_csi2_rx_irq_mask_addr);
349
350 if (csid_reg->cmn_reg->no_pix)
351 cam_io_w_mb(irq_mask_ipp, soc_info->reg_map[0].mem_base +
352 csid_reg->ipp_reg->csid_ipp_irq_mask_addr);
353
354 for (i = 0; i < csid_reg->cmn_reg->no_rdis; i++)
355 cam_io_w_mb(irq_mask_rdi[i], soc_info->reg_map[0].mem_base +
356 csid_reg->rdi_reg[i]->csid_rdi_irq_mask_addr);
357
358 return rc;
359}
360
361static int cam_ife_csid_path_reset(struct cam_ife_csid_hw *csid_hw,
362 struct cam_csid_reset_cfg_args *reset)
363{
364 int rc = 0;
365 struct cam_hw_soc_info *soc_info;
366 struct cam_isp_resource_node *res;
367 struct cam_ife_csid_reg_offset *csid_reg;
368 uint32_t reset_strb_addr, reset_strb_val, val, id;
369 struct completion *complete;
370
371 csid_reg = csid_hw->csid_info->csid_reg;
372 soc_info = &csid_hw->hw_info->soc_info;
373 res = reset->node_res;
374
375 if (csid_hw->hw_info->hw_state != CAM_HW_STATE_POWER_UP) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -0700376 CAM_ERR(CAM_ISP, "CSID:%d Invalid hw state :%d",
377 csid_hw->hw_intf->hw_idx,
Jing Zhouff57d862017-03-21 00:54:25 -0700378 csid_hw->hw_info->hw_state);
379 return -EINVAL;
380 }
381
382 if (res->res_id >= CAM_IFE_PIX_PATH_RES_MAX) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -0700383 CAM_DBG(CAM_ISP, "CSID:%d Invalid res id%d",
384 csid_hw->hw_intf->hw_idx, res->res_id);
Jing Zhouff57d862017-03-21 00:54:25 -0700385 rc = -EINVAL;
386 goto end;
387 }
388
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -0700389 CAM_DBG(CAM_ISP, "CSID:%d resource:%d",
Jing Zhouff57d862017-03-21 00:54:25 -0700390 csid_hw->hw_intf->hw_idx, res->res_id);
391
392 if (res->res_id == CAM_IFE_PIX_PATH_RES_IPP) {
393 if (!csid_reg->ipp_reg) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -0700394 CAM_ERR(CAM_ISP, "CSID:%d IPP not supported :%d",
395 csid_hw->hw_intf->hw_idx,
Jing Zhouff57d862017-03-21 00:54:25 -0700396 res->res_id);
397 return -EINVAL;
398 }
399
400 reset_strb_addr = csid_reg->ipp_reg->csid_ipp_rst_strobes_addr;
401 complete = &csid_hw->csid_ipp_complete;
402
403 /* Enable path reset done interrupt */
404 val = cam_io_r_mb(soc_info->reg_map[0].mem_base +
405 csid_reg->ipp_reg->csid_ipp_irq_mask_addr);
406 val |= CSID_PATH_INFO_RST_DONE;
407 cam_io_w_mb(val, soc_info->reg_map[0].mem_base +
408 csid_reg->ipp_reg->csid_ipp_irq_mask_addr);
409
410 } else {
411 id = res->res_id;
412 if (!csid_reg->rdi_reg[id]) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -0700413 CAM_ERR(CAM_ISP, "CSID:%d RDI res not supported :%d",
414 csid_hw->hw_intf->hw_idx,
Jing Zhouff57d862017-03-21 00:54:25 -0700415 res->res_id);
416 return -EINVAL;
417 }
418
419 reset_strb_addr =
420 csid_reg->rdi_reg[id]->csid_rdi_rst_strobes_addr;
421 complete =
422 &csid_hw->csid_rdin_complete[id];
423
424 /* Enable path reset done interrupt */
425 val = cam_io_r_mb(soc_info->reg_map[0].mem_base +
426 csid_reg->rdi_reg[id]->csid_rdi_irq_mask_addr);
427 val |= CSID_PATH_INFO_RST_DONE;
428 cam_io_w_mb(val, soc_info->reg_map[0].mem_base +
429 csid_reg->rdi_reg[id]->csid_rdi_irq_mask_addr);
430 }
431
432 init_completion(complete);
433 reset_strb_val = csid_reg->cmn_reg->path_rst_stb_all;
434
435 /* Enable the Test gen before reset */
436 cam_io_w_mb(1, csid_hw->hw_info->soc_info.reg_map[0].mem_base +
437 csid_reg->tpg_reg->csid_tpg_ctrl_addr);
438
439 /* Reset the corresponding ife csid path */
440 cam_io_w_mb(reset_strb_val, soc_info->reg_map[0].mem_base +
441 reset_strb_addr);
442
443 rc = wait_for_completion_timeout(complete,
444 msecs_to_jiffies(IFE_CSID_TIMEOUT));
445 if (rc <= 0) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -0700446 CAM_ERR(CAM_ISP, "CSID:%d Res id %d fail rc = %d",
447 csid_hw->hw_intf->hw_idx,
Jing Zhouff57d862017-03-21 00:54:25 -0700448 res->res_id, rc);
449 if (rc == 0)
450 rc = -ETIMEDOUT;
451 }
452
453 /* Disable Test Gen after reset*/
454 cam_io_w_mb(0, soc_info->reg_map[0].mem_base +
455 csid_reg->tpg_reg->csid_tpg_ctrl_addr);
456
457end:
458 return rc;
459
460}
461
462static int cam_ife_csid_cid_reserve(struct cam_ife_csid_hw *csid_hw,
463 struct cam_csid_hw_reserve_resource_args *cid_reserv)
464{
465 int rc = 0;
466 struct cam_ife_csid_cid_data *cid_data;
467
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -0700468 CAM_DBG(CAM_ISP,
469 "CSID:%d res_sel:%d Lane type:%d lane_num:%d dt:%d vc:%d",
470 csid_hw->hw_intf->hw_idx,
Jing Zhouff57d862017-03-21 00:54:25 -0700471 cid_reserv->in_port->res_type,
472 cid_reserv->in_port->lane_type,
473 cid_reserv->in_port->lane_num,
474 cid_reserv->in_port->dt,
475 cid_reserv->in_port->vc);
476
477 if (cid_reserv->in_port->res_type >= CAM_ISP_IFE_IN_RES_MAX) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -0700478 CAM_ERR(CAM_ISP, "CSID:%d Invalid phy sel %d",
479 csid_hw->hw_intf->hw_idx,
Jing Zhouff57d862017-03-21 00:54:25 -0700480 cid_reserv->in_port->res_type);
481 rc = -EINVAL;
482 goto end;
483 }
484
485 if (cid_reserv->in_port->lane_type >= CAM_ISP_LANE_TYPE_MAX &&
486 cid_reserv->in_port->res_type != CAM_ISP_IFE_IN_RES_TPG) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -0700487 CAM_ERR(CAM_ISP, "CSID:%d Invalid lane type %d",
488 csid_hw->hw_intf->hw_idx,
Jing Zhouff57d862017-03-21 00:54:25 -0700489 cid_reserv->in_port->lane_type);
490 rc = -EINVAL;
491 goto end;
492 }
493
494 if ((cid_reserv->in_port->lane_type == CAM_ISP_LANE_TYPE_DPHY &&
495 cid_reserv->in_port->lane_num > 4) &&
496 cid_reserv->in_port->res_type != CAM_ISP_IFE_IN_RES_TPG) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -0700497 CAM_ERR(CAM_ISP, "CSID:%d Invalid lane num %d",
498 csid_hw->hw_intf->hw_idx,
Jing Zhouff57d862017-03-21 00:54:25 -0700499 cid_reserv->in_port->lane_num);
500 rc = -EINVAL;
501 goto end;
502 }
503 if ((cid_reserv->in_port->lane_type == CAM_ISP_LANE_TYPE_CPHY &&
504 cid_reserv->in_port->lane_num > 3) &&
505 cid_reserv->in_port->res_type != CAM_ISP_IFE_IN_RES_TPG) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -0700506 CAM_ERR(CAM_ISP, " CSID:%d Invalid lane type %d & num %d",
507 csid_hw->hw_intf->hw_idx,
Jing Zhouff57d862017-03-21 00:54:25 -0700508 cid_reserv->in_port->lane_type,
509 cid_reserv->in_port->lane_num);
510 rc = -EINVAL;
511 goto end;
512 }
513
514 /* CSID CSI2 v2.0 supports 31 vc */
515 if (cid_reserv->in_port->dt > 0x3f ||
516 cid_reserv->in_port->vc > 0x1f) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -0700517 CAM_ERR(CAM_ISP, "CSID:%d Invalid vc:%d dt %d",
518 csid_hw->hw_intf->hw_idx,
Jing Zhouff57d862017-03-21 00:54:25 -0700519 cid_reserv->in_port->vc, cid_reserv->in_port->dt);
520 rc = -EINVAL;
521 goto end;
522 }
523
524 if (cid_reserv->in_port->res_type == CAM_ISP_IFE_IN_RES_TPG && (
525 (cid_reserv->in_port->format < CAM_FORMAT_MIPI_RAW_8 &&
526 cid_reserv->in_port->format > CAM_FORMAT_MIPI_RAW_16))) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -0700527 CAM_ERR(CAM_ISP, " CSID:%d Invalid tpg decode fmt %d",
528 csid_hw->hw_intf->hw_idx,
Jing Zhouff57d862017-03-21 00:54:25 -0700529 cid_reserv->in_port->format);
530 rc = -EINVAL;
531 goto end;
532 }
533
534 if (csid_hw->csi2_reserve_cnt) {
535 /* current configure res type should match requested res type */
536 if (csid_hw->res_type != cid_reserv->in_port->res_type) {
537 rc = -EINVAL;
538 goto end;
539 }
540
541 if (cid_reserv->in_port->res_type != CAM_ISP_IFE_IN_RES_TPG) {
542 if (csid_hw->csi2_rx_cfg.lane_cfg !=
543 cid_reserv->in_port->lane_cfg ||
544 csid_hw->csi2_rx_cfg.lane_type !=
545 cid_reserv->in_port->lane_type ||
546 csid_hw->csi2_rx_cfg.lane_num !=
547 cid_reserv->in_port->lane_num) {
548 rc = -EINVAL;
549 goto end;
550 }
551 } else {
552 if (csid_hw->tpg_cfg.decode_fmt !=
553 cid_reserv->in_port->format ||
554 csid_hw->tpg_cfg.width !=
555 cid_reserv->in_port->left_width ||
556 csid_hw->tpg_cfg.height !=
557 cid_reserv->in_port->height ||
558 csid_hw->tpg_cfg.test_pattern !=
559 cid_reserv->in_port->test_pattern) {
560 rc = -EINVAL;
561 goto end;
562 }
563 }
564 }
565
566 if (!csid_hw->csi2_reserve_cnt) {
567 csid_hw->res_type = cid_reserv->in_port->res_type;
568 /* Take the first CID resource*/
569 csid_hw->cid_res[0].res_state = CAM_ISP_RESOURCE_STATE_RESERVED;
570 cid_data = (struct cam_ife_csid_cid_data *)
571 csid_hw->cid_res[0].res_priv;
572
573 csid_hw->csi2_rx_cfg.lane_cfg =
574 cid_reserv->in_port->lane_cfg;
575 csid_hw->csi2_rx_cfg.lane_type =
576 cid_reserv->in_port->lane_type;
577 csid_hw->csi2_rx_cfg.lane_num =
578 cid_reserv->in_port->lane_num;
579
580 if (cid_reserv->in_port->res_type == CAM_ISP_IFE_IN_RES_TPG) {
581 csid_hw->csi2_rx_cfg.phy_sel = 0;
582 if (cid_reserv->in_port->format >
583 CAM_FORMAT_MIPI_RAW_16) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -0700584 CAM_ERR(CAM_ISP, " Wrong TPG format");
Jing Zhouff57d862017-03-21 00:54:25 -0700585 rc = -EINVAL;
586 goto end;
587 }
588 csid_hw->tpg_cfg.decode_fmt =
589 cid_reserv->in_port->format;
590 csid_hw->tpg_cfg.width =
591 cid_reserv->in_port->left_width;
592 csid_hw->tpg_cfg.height = cid_reserv->in_port->height;
593 csid_hw->tpg_cfg.test_pattern =
594 cid_reserv->in_port->test_pattern;
595 cid_data->tpg_set = 1;
596 } else {
597 csid_hw->csi2_rx_cfg.phy_sel =
598 (cid_reserv->in_port->res_type & 0xFF) - 1;
599 }
600
601 cid_data->vc = cid_reserv->in_port->vc;
602 cid_data->dt = cid_reserv->in_port->dt;
603 cid_data->cnt = 1;
604 cid_reserv->node_res = &csid_hw->cid_res[0];
605 csid_hw->csi2_reserve_cnt++;
606
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -0700607 CAM_DBG(CAM_ISP,
608 "CSID:%d CID :%d resource acquired successfully",
609 csid_hw->hw_intf->hw_idx,
Jing Zhouff57d862017-03-21 00:54:25 -0700610 cid_reserv->node_res->res_id);
611 } else {
612 rc = cam_ife_csid_cid_get(csid_hw, &cid_reserv->node_res,
613 cid_reserv->in_port->vc, cid_reserv->in_port->dt,
614 cid_reserv->in_port->res_type);
615 /* if success then increment the reserve count */
616 if (!rc) {
617 if (csid_hw->csi2_reserve_cnt == UINT_MAX) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -0700618 CAM_ERR(CAM_ISP,
619 "CSID%d reserve cnt reached max",
Jing Zhouff57d862017-03-21 00:54:25 -0700620 csid_hw->hw_intf->hw_idx);
621 rc = -EINVAL;
622 } else {
623 csid_hw->csi2_reserve_cnt++;
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -0700624 CAM_DBG(CAM_ISP, "CSID:%d CID:%d acquired",
Jing Zhouff57d862017-03-21 00:54:25 -0700625 csid_hw->hw_intf->hw_idx,
626 cid_reserv->node_res->res_id);
627 }
628 }
629 }
630
631end:
632 return rc;
633}
634
635
636static int cam_ife_csid_path_reserve(struct cam_ife_csid_hw *csid_hw,
637 struct cam_csid_hw_reserve_resource_args *reserve)
638{
639 int rc = 0;
640 struct cam_ife_csid_path_cfg *path_data;
641 struct cam_isp_resource_node *res;
642
643 /* CSID CSI2 v2.0 supports 31 vc */
644 if (reserve->in_port->dt > 0x3f || reserve->in_port->vc > 0x1f ||
645 (reserve->sync_mode >= CAM_ISP_HW_SYNC_MAX)) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -0700646 CAM_ERR(CAM_ISP, "CSID:%d Invalid vc:%d dt %d mode:%d",
647 csid_hw->hw_intf->hw_idx,
Jing Zhouff57d862017-03-21 00:54:25 -0700648 reserve->in_port->vc, reserve->in_port->dt,
649 reserve->sync_mode);
650 rc = -EINVAL;
651 goto end;
652 }
653
654 switch (reserve->res_id) {
655 case CAM_IFE_PIX_PATH_RES_IPP:
656 if (csid_hw->ipp_res.res_state !=
657 CAM_ISP_RESOURCE_STATE_AVAILABLE) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -0700658 CAM_DBG(CAM_ISP,
659 "CSID:%d IPP resource not available %d",
660 csid_hw->hw_intf->hw_idx,
Jing Zhouff57d862017-03-21 00:54:25 -0700661 csid_hw->ipp_res.res_state);
662 rc = -EINVAL;
663 goto end;
664 }
665
666 if (cam_ife_csid_is_ipp_format_supported(
667 reserve->in_port->format)) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -0700668 CAM_ERR(CAM_ISP,
669 "CSID:%d res id:%d un support format %d",
Jing Zhouff57d862017-03-21 00:54:25 -0700670 csid_hw->hw_intf->hw_idx, reserve->res_id,
671 reserve->in_port->format);
672 rc = -EINVAL;
673 goto end;
674 }
675
676 /* assign the IPP resource */
677 res = &csid_hw->ipp_res;
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -0700678 CAM_DBG(CAM_ISP,
679 "CSID:%d IPP resource:%d acquired successfully",
Jing Zhouff57d862017-03-21 00:54:25 -0700680 csid_hw->hw_intf->hw_idx, res->res_id);
681
682 break;
683 case CAM_IFE_PIX_PATH_RES_RDI_0:
684 case CAM_IFE_PIX_PATH_RES_RDI_1:
685 case CAM_IFE_PIX_PATH_RES_RDI_2:
686 case CAM_IFE_PIX_PATH_RES_RDI_3:
687 if (csid_hw->rdi_res[reserve->res_id].res_state !=
688 CAM_ISP_RESOURCE_STATE_AVAILABLE) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -0700689 CAM_DBG(CAM_ISP,
690 "CSID:%d RDI:%d resource not available %d",
691 csid_hw->hw_intf->hw_idx,
Jing Zhouff57d862017-03-21 00:54:25 -0700692 reserve->res_id,
693 csid_hw->rdi_res[reserve->res_id].res_state);
694 rc = -EINVAL;
695 goto end;
696 } else {
697 res = &csid_hw->rdi_res[reserve->res_id];
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -0700698 CAM_DBG(CAM_ISP,
699 "CSID:%d RDI resource:%d acquire success",
700 csid_hw->hw_intf->hw_idx,
Jing Zhouff57d862017-03-21 00:54:25 -0700701 res->res_id);
702 }
703
704 break;
705 default:
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -0700706 CAM_ERR(CAM_ISP, "CSID:%d Invalid res id:%d",
Jing Zhouff57d862017-03-21 00:54:25 -0700707 csid_hw->hw_intf->hw_idx, reserve->res_id);
708 rc = -EINVAL;
709 goto end;
710 }
711
712 res->res_state = CAM_ISP_RESOURCE_STATE_RESERVED;
713 path_data = (struct cam_ife_csid_path_cfg *)res->res_priv;
714
Ravikishore Pampanaad6bc902017-07-12 19:37:06 +0530715 /* store the output format for RDI */
716 switch (reserve->res_id) {
717 case CAM_IFE_PIX_PATH_RES_RDI_0:
718 case CAM_IFE_PIX_PATH_RES_RDI_1:
719 case CAM_IFE_PIX_PATH_RES_RDI_2:
720 case CAM_IFE_PIX_PATH_RES_RDI_3:
721 path_data->output_fmt = reserve->out_port->format;
722 break;
723 default:
724 break;
725 }
726
Jing Zhouff57d862017-03-21 00:54:25 -0700727 path_data->cid = reserve->cid;
728 path_data->decode_fmt = reserve->in_port->format;
729 path_data->master_idx = reserve->master_idx;
730 path_data->sync_mode = reserve->sync_mode;
731 path_data->height = reserve->in_port->height;
732 path_data->start_line = reserve->in_port->line_start;
733 if (reserve->in_port->res_type == CAM_ISP_IFE_IN_RES_TPG) {
734 path_data->dt = CAM_IFE_CSID_TPG_DT_VAL;
735 path_data->vc = CAM_IFE_CSID_TPG_VC_VAL;
736 } else {
737 path_data->dt = reserve->in_port->dt;
738 path_data->vc = reserve->in_port->vc;
739 }
740
741 if (reserve->sync_mode == CAM_ISP_HW_SYNC_MASTER) {
742 path_data->crop_enable = 1;
743 path_data->start_pixel = reserve->in_port->left_start;
744 path_data->width = reserve->in_port->left_width;
745 } else if (reserve->sync_mode == CAM_ISP_HW_SYNC_SLAVE) {
746 path_data->crop_enable = 1;
747 path_data->start_pixel = reserve->in_port->right_start;
748 path_data->width = reserve->in_port->right_width;
749 } else
750 path_data->crop_enable = 0;
751
752 reserve->node_res = res;
753
754end:
755 return rc;
756}
757
758static int cam_ife_csid_enable_hw(struct cam_ife_csid_hw *csid_hw)
759{
760 int rc = 0;
761 struct cam_ife_csid_reg_offset *csid_reg;
762 struct cam_hw_soc_info *soc_info;
763 uint32_t i, status, val;
764
765 csid_reg = csid_hw->csid_info->csid_reg;
766 soc_info = &csid_hw->hw_info->soc_info;
767
768 /* overflow check before increment */
769 if (csid_hw->hw_info->open_count == UINT_MAX) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -0700770 CAM_ERR(CAM_ISP, "CSID:%d Open count reached max",
771 csid_hw->hw_intf->hw_idx);
Jing Zhouff57d862017-03-21 00:54:25 -0700772 return -EINVAL;
773 }
774
775 /* Increment ref Count */
776 csid_hw->hw_info->open_count++;
777 if (csid_hw->hw_info->open_count > 1) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -0700778 CAM_DBG(CAM_ISP, "CSID hw has already been enabled");
Jing Zhouff57d862017-03-21 00:54:25 -0700779 return rc;
780 }
781
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -0700782 CAM_DBG(CAM_ISP, "CSID:%d init CSID HW",
Jing Zhouff57d862017-03-21 00:54:25 -0700783 csid_hw->hw_intf->hw_idx);
784
785 rc = cam_ife_csid_enable_soc_resources(soc_info);
786 if (rc) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -0700787 CAM_ERR(CAM_ISP, "CSID:%d Enable SOC failed",
Jing Zhouff57d862017-03-21 00:54:25 -0700788 csid_hw->hw_intf->hw_idx);
789 goto err;
790 }
791
792
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -0700793 CAM_DBG(CAM_ISP, "CSID:%d enable top irq interrupt",
Jing Zhouff57d862017-03-21 00:54:25 -0700794 csid_hw->hw_intf->hw_idx);
795
796 csid_hw->hw_info->hw_state = CAM_HW_STATE_POWER_UP;
797 /* Enable the top IRQ interrupt */
798 cam_io_w_mb(1, soc_info->reg_map[0].mem_base +
799 csid_reg->cmn_reg->csid_top_irq_mask_addr);
800
801 rc = cam_ife_csid_global_reset(csid_hw);
802 if (rc) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -0700803 CAM_ERR(CAM_ISP, "CSID:%d csid_reset fail rc = %d",
804 csid_hw->hw_intf->hw_idx, rc);
Jing Zhouff57d862017-03-21 00:54:25 -0700805 rc = -ETIMEDOUT;
806 goto disable_soc;
807 }
808
809 /*
810 * Reset the SW registers
811 * SW register reset also reset the mask irq, so poll the irq status
812 * to check the reset complete.
813 */
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -0700814 CAM_DBG(CAM_ISP, "CSID:%d Reset Software registers",
Jing Zhouff57d862017-03-21 00:54:25 -0700815 csid_hw->hw_intf->hw_idx);
816
817 cam_io_w_mb(csid_reg->cmn_reg->csid_rst_stb_sw_all,
818 soc_info->reg_map[0].mem_base +
819 csid_reg->cmn_reg->csid_rst_strobes_addr);
820
821 rc = readl_poll_timeout(soc_info->reg_map[0].mem_base +
822 csid_reg->cmn_reg->csid_top_irq_status_addr,
823 status, (status & 0x1) == 0x1,
824 CAM_IFE_CSID_TIMEOUT_SLEEP_US, CAM_IFE_CSID_TIMEOUT_ALL_US);
825 if (rc < 0) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -0700826 CAM_ERR(CAM_ISP, "software register reset timeout.....");
Jing Zhouff57d862017-03-21 00:54:25 -0700827 rc = -ETIMEDOUT;
828 goto disable_soc;
829 }
830
831 /* clear all interrupts */
832 cam_io_w_mb(1, soc_info->reg_map[0].mem_base +
833 csid_reg->cmn_reg->csid_top_irq_clear_addr);
834
835 cam_io_w_mb(csid_reg->csi2_reg->csi2_irq_mask_all,
836 soc_info->reg_map[0].mem_base +
837 csid_reg->csi2_reg->csid_csi2_rx_irq_clear_addr);
838
839 if (csid_reg->cmn_reg->no_pix)
840 cam_io_w_mb(csid_reg->cmn_reg->ipp_irq_mask_all,
841 soc_info->reg_map[0].mem_base +
842 csid_reg->ipp_reg->csid_ipp_irq_clear_addr);
843
844 for (i = 0; i < csid_reg->cmn_reg->no_rdis; i++)
845 cam_io_w_mb(csid_reg->cmn_reg->rdi_irq_mask_all,
846 soc_info->reg_map[0].mem_base +
847 csid_reg->rdi_reg[i]->csid_rdi_irq_clear_addr);
848
849 cam_io_w_mb(1, soc_info->reg_map[0].mem_base +
850 csid_reg->cmn_reg->csid_irq_cmd_addr);
851
852 /* Enable the top IRQ interrupt */
853 cam_io_w_mb(1, soc_info->reg_map[0].mem_base +
854 csid_reg->cmn_reg->csid_top_irq_mask_addr);
855
856 val = cam_io_r_mb(soc_info->reg_map[0].mem_base +
857 csid_reg->cmn_reg->csid_hw_version_addr);
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -0700858 CAM_DBG(CAM_ISP, "CSID:%d CSID HW version: 0x%x",
Jing Zhouff57d862017-03-21 00:54:25 -0700859 csid_hw->hw_intf->hw_idx, val);
860
861 return 0;
862
863disable_soc:
864 cam_ife_csid_disable_soc_resources(soc_info);
865 csid_hw->hw_info->hw_state = CAM_HW_STATE_POWER_DOWN;
866err:
867 csid_hw->hw_info->open_count--;
868 return rc;
869}
870
871static int cam_ife_csid_disable_hw(struct cam_ife_csid_hw *csid_hw)
872{
873 int rc = 0;
874 struct cam_hw_soc_info *soc_info;
875 struct cam_ife_csid_reg_offset *csid_reg;
876
877
878 /* Decrement ref Count */
879 if (csid_hw->hw_info->open_count)
880 csid_hw->hw_info->open_count--;
881 if (csid_hw->hw_info->open_count)
882 return rc;
883
884 soc_info = &csid_hw->hw_info->soc_info;
885 csid_reg = csid_hw->csid_info->csid_reg;
886
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -0700887 CAM_DBG(CAM_ISP, "CSID:%d De-init CSID HW",
Jing Zhouff57d862017-03-21 00:54:25 -0700888 csid_hw->hw_intf->hw_idx);
889
890 /*disable the top IRQ interrupt */
891 cam_io_w_mb(0, soc_info->reg_map[0].mem_base +
892 csid_reg->cmn_reg->csid_top_irq_mask_addr);
893
894 rc = cam_ife_csid_disable_soc_resources(soc_info);
895 if (rc)
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -0700896 CAM_ERR(CAM_ISP, "CSID:%d Disable CSID SOC failed",
897 csid_hw->hw_intf->hw_idx);
Jing Zhouff57d862017-03-21 00:54:25 -0700898
899 csid_hw->hw_info->hw_state = CAM_HW_STATE_POWER_DOWN;
900 return rc;
901}
902
903
904static int cam_ife_csid_tpg_start(struct cam_ife_csid_hw *csid_hw,
905 struct cam_isp_resource_node *res)
906{
907 uint32_t val = 0;
908 struct cam_hw_soc_info *soc_info;
909
910 csid_hw->tpg_start_cnt++;
911 if (csid_hw->tpg_start_cnt == 1) {
912 /*Enable the TPG */
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -0700913 CAM_DBG(CAM_ISP, "CSID:%d start CSID TPG",
914 csid_hw->hw_intf->hw_idx);
Jing Zhouff57d862017-03-21 00:54:25 -0700915
916 soc_info = &csid_hw->hw_info->soc_info;
917 {
918 uint32_t val;
919 uint32_t i;
920 uint32_t base = 0x600;
921
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -0700922 CAM_DBG(CAM_ISP, "================ TPG ============");
Jing Zhouff57d862017-03-21 00:54:25 -0700923 for (i = 0; i < 16; i++) {
924 val = cam_io_r_mb(
925 soc_info->reg_map[0].mem_base +
926 base + i * 4);
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -0700927 CAM_DBG(CAM_ISP, "reg 0x%x = 0x%x",
Jing Zhouff57d862017-03-21 00:54:25 -0700928 (base + i*4), val);
929 }
930
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -0700931 CAM_DBG(CAM_ISP, "================ IPP =============");
Jing Zhouff57d862017-03-21 00:54:25 -0700932 base = 0x200;
933 for (i = 0; i < 10; i++) {
934 val = cam_io_r_mb(
935 soc_info->reg_map[0].mem_base +
936 base + i * 4);
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -0700937 CAM_DBG(CAM_ISP, "reg 0x%x = 0x%x",
Jing Zhouff57d862017-03-21 00:54:25 -0700938 (base + i*4), val);
939 }
940
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -0700941 CAM_DBG(CAM_ISP, "================ RX =============");
Jing Zhouff57d862017-03-21 00:54:25 -0700942 base = 0x100;
943 for (i = 0; i < 5; i++) {
944 val = cam_io_r_mb(
945 soc_info->reg_map[0].mem_base +
946 base + i * 4);
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -0700947 CAM_DBG(CAM_ISP, "reg 0x%x = 0x%x",
Jing Zhouff57d862017-03-21 00:54:25 -0700948 (base + i*4), val);
949 }
950 }
951
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -0700952 CAM_DBG(CAM_ISP, "============ TPG control ============");
Jing Zhouff57d862017-03-21 00:54:25 -0700953 val = (4 << 20);
954 val |= (0x80 << 8);
955 val |= (((csid_hw->csi2_rx_cfg.lane_num - 1) & 0x3) << 4);
956 val |= 7;
957 cam_io_w_mb(val, soc_info->reg_map[0].mem_base +
958 csid_hw->csid_info->csid_reg->tpg_reg->
959 csid_tpg_ctrl_addr);
960
961 val = cam_io_r_mb(soc_info->reg_map[0].mem_base + 0x600);
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -0700962 CAM_DBG(CAM_ISP, "reg 0x%x = 0x%x", 0x600, val);
Jing Zhouff57d862017-03-21 00:54:25 -0700963 }
964
965 return 0;
966}
967
968static int cam_ife_csid_tpg_stop(struct cam_ife_csid_hw *csid_hw,
969 struct cam_isp_resource_node *res)
970{
971 struct cam_hw_soc_info *soc_info;
972
973 if (csid_hw->tpg_start_cnt)
974 csid_hw->tpg_start_cnt--;
975
976 if (csid_hw->tpg_start_cnt)
977 return 0;
978
979 soc_info = &csid_hw->hw_info->soc_info;
980
981 /* disable the TPG */
982 if (!csid_hw->tpg_start_cnt) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -0700983 CAM_DBG(CAM_ISP, "CSID:%d stop CSID TPG",
984 csid_hw->hw_intf->hw_idx);
Jing Zhouff57d862017-03-21 00:54:25 -0700985
986 /*stop the TPG */
987 cam_io_w_mb(0, soc_info->reg_map[0].mem_base +
988 csid_hw->csid_info->csid_reg->tpg_reg->csid_tpg_ctrl_addr);
989 }
990
991 return 0;
992}
993
994
995static int cam_ife_csid_config_tpg(struct cam_ife_csid_hw *csid_hw,
996 struct cam_isp_resource_node *res)
997{
998 struct cam_ife_csid_reg_offset *csid_reg;
999 struct cam_hw_soc_info *soc_info;
1000 uint32_t val = 0;
1001
1002 csid_reg = csid_hw->csid_info->csid_reg;
1003 soc_info = &csid_hw->hw_info->soc_info;
1004
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07001005 CAM_DBG(CAM_ISP, "CSID:%d TPG config",
1006 csid_hw->hw_intf->hw_idx);
Jing Zhouff57d862017-03-21 00:54:25 -07001007
1008 /* configure one DT, infinite frames */
1009 val = (0 << 16) | (1 << 10) | CAM_IFE_CSID_TPG_VC_VAL;
1010 cam_io_w_mb(val, soc_info->reg_map[0].mem_base +
1011 csid_reg->tpg_reg->csid_tpg_vc_cfg0_addr);
1012
1013 /* vertical blanking count = 0x740, horzontal blanking count = 0x740*/
1014 val = (0x740 << 12) | 0x740;
1015 cam_io_w_mb(val, soc_info->reg_map[0].mem_base +
1016 csid_reg->tpg_reg->csid_tpg_vc_cfg1_addr);
1017
1018 cam_io_w_mb(0x12345678, soc_info->reg_map[0].mem_base +
1019 csid_hw->csid_info->csid_reg->tpg_reg->csid_tpg_lfsr_seed_addr);
1020
1021 val = csid_hw->tpg_cfg.width << 16 |
1022 csid_hw->tpg_cfg.height;
1023 cam_io_w_mb(val, soc_info->reg_map[0].mem_base +
1024 csid_reg->tpg_reg->csid_tpg_dt_n_cfg_0_addr);
1025
1026 cam_io_w_mb(CAM_IFE_CSID_TPG_DT_VAL, soc_info->reg_map[0].mem_base +
1027 csid_reg->tpg_reg->csid_tpg_dt_n_cfg_1_addr);
1028
1029 /*
1030 * decode_fmt is the same as the input resource format.
1031 * it is one larger than the register spec format.
1032 */
1033 val = ((csid_hw->tpg_cfg.decode_fmt - 1) << 16) | 0x8;
1034 cam_io_w_mb(val, soc_info->reg_map[0].mem_base +
1035 csid_reg->tpg_reg->csid_tpg_dt_n_cfg_2_addr);
1036
Jing Zhoua4e9fbe2017-05-15 14:37:21 -07001037 /* static frame with split color bar */
1038 val = 1 << 5;
Jing Zhouff57d862017-03-21 00:54:25 -07001039 cam_io_w_mb(val, soc_info->reg_map[0].mem_base +
1040 csid_reg->tpg_reg->csid_tpg_color_bars_cfg_addr);
1041 /* config pix pattern */
1042 cam_io_w_mb(csid_hw->tpg_cfg.test_pattern,
1043 soc_info->reg_map[0].mem_base +
1044 csid_reg->tpg_reg->csid_tpg_common_gen_cfg_addr);
1045
1046 return 0;
1047}
1048
1049static int cam_ife_csid_enable_csi2(
1050 struct cam_ife_csid_hw *csid_hw,
1051 struct cam_isp_resource_node *res)
1052{
1053 int rc = 0;
1054 struct cam_ife_csid_reg_offset *csid_reg;
1055 struct cam_hw_soc_info *soc_info;
1056 struct cam_ife_csid_cid_data *cid_data;
1057 uint32_t val = 0;
1058
1059 csid_reg = csid_hw->csid_info->csid_reg;
1060 soc_info = &csid_hw->hw_info->soc_info;
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07001061 CAM_DBG(CAM_ISP, "CSID:%d count:%d config csi2 rx",
1062 csid_hw->hw_intf->hw_idx, csid_hw->csi2_cfg_cnt);
Jing Zhouff57d862017-03-21 00:54:25 -07001063
1064 /* overflow check before increment */
1065 if (csid_hw->csi2_cfg_cnt == UINT_MAX) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07001066 CAM_ERR(CAM_ISP, "CSID:%d Open count reached max",
1067 csid_hw->hw_intf->hw_idx);
Jing Zhouff57d862017-03-21 00:54:25 -07001068 return -EINVAL;
1069 }
1070
1071 cid_data = (struct cam_ife_csid_cid_data *)res->res_priv;
1072
1073 res->res_state = CAM_ISP_RESOURCE_STATE_STREAMING;
1074 csid_hw->csi2_cfg_cnt++;
1075 if (csid_hw->csi2_cfg_cnt > 1)
1076 return rc;
1077
1078 /* rx cfg0 */
1079 val = (csid_hw->csi2_rx_cfg.lane_num - 1) |
1080 (csid_hw->csi2_rx_cfg.lane_cfg << 4) |
1081 (csid_hw->csi2_rx_cfg.lane_type << 24);
Alex Wong78578602017-07-07 19:51:43 -07001082 val |= (csid_hw->csi2_rx_cfg.phy_sel & 0x3) << 20;
Jing Zhouff57d862017-03-21 00:54:25 -07001083 cam_io_w_mb(val, soc_info->reg_map[0].mem_base +
1084 csid_reg->csi2_reg->csid_csi2_rx_cfg0_addr);
1085
1086 /* rx cfg1*/
1087 val = (1 << csid_reg->csi2_reg->csi2_misr_enable_shift_val);
1088 /* if VC value is more than 3 than set full width of VC */
1089 if (cid_data->vc > 3)
1090 val |= (1 << csid_reg->csi2_reg->csi2_vc_mode_shift_val);
1091
1092 /* enable packet ecc correction */
1093 val |= 1;
1094 cam_io_w_mb(val, soc_info->reg_map[0].mem_base +
1095 csid_reg->csi2_reg->csid_csi2_rx_cfg1_addr);
1096
1097 if (csid_hw->res_type == CAM_ISP_IFE_IN_RES_TPG) {
1098 /* Config the TPG */
1099 rc = cam_ife_csid_config_tpg(csid_hw, res);
1100 if (rc) {
1101 res->res_state = CAM_ISP_RESOURCE_STATE_RESERVED;
1102 return rc;
1103 }
1104 }
1105
1106 /*Enable the CSI2 rx inerrupts */
1107 val = CSID_CSI2_RX_INFO_RST_DONE |
1108 CSID_CSI2_RX_ERROR_TG_FIFO_OVERFLOW |
1109 CSID_CSI2_RX_ERROR_LANE0_FIFO_OVERFLOW |
1110 CSID_CSI2_RX_ERROR_LANE1_FIFO_OVERFLOW |
1111 CSID_CSI2_RX_ERROR_LANE2_FIFO_OVERFLOW |
1112 CSID_CSI2_RX_ERROR_LANE3_FIFO_OVERFLOW |
1113 CSID_CSI2_RX_ERROR_CPHY_EOT_RECEPTION |
1114 CSID_CSI2_RX_ERROR_CPHY_SOT_RECEPTION |
1115 CSID_CSI2_RX_ERROR_CPHY_PH_CRC;
1116 cam_io_w_mb(val, soc_info->reg_map[0].mem_base +
1117 csid_reg->csi2_reg->csid_csi2_rx_irq_mask_addr);
1118
1119 return 0;
1120}
1121
1122static int cam_ife_csid_disable_csi2(
1123 struct cam_ife_csid_hw *csid_hw,
1124 struct cam_isp_resource_node *res)
1125{
1126 struct cam_ife_csid_reg_offset *csid_reg;
1127 struct cam_hw_soc_info *soc_info;
1128
1129 if (res->res_id >= CAM_IFE_CSID_CID_MAX) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07001130 CAM_ERR(CAM_ISP, "CSID:%d Invalid res id :%d",
1131 csid_hw->hw_intf->hw_idx, res->res_id);
Jing Zhouff57d862017-03-21 00:54:25 -07001132 return -EINVAL;
1133 }
1134
1135 csid_reg = csid_hw->csid_info->csid_reg;
1136 soc_info = &csid_hw->hw_info->soc_info;
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07001137 CAM_DBG(CAM_ISP, "CSID:%d cnt : %d Disable csi2 rx",
1138 csid_hw->hw_intf->hw_idx, csid_hw->csi2_cfg_cnt);
Jing Zhouff57d862017-03-21 00:54:25 -07001139
1140 if (csid_hw->csi2_cfg_cnt)
1141 csid_hw->csi2_cfg_cnt--;
1142
1143 if (csid_hw->csi2_cfg_cnt)
1144 return 0;
1145
1146 /*Disable the CSI2 rx inerrupts */
1147 cam_io_w_mb(0, soc_info->reg_map[0].mem_base +
1148 csid_reg->csi2_reg->csid_csi2_rx_irq_mask_addr);
1149
1150 res->res_state = CAM_ISP_RESOURCE_STATE_RESERVED;
1151
1152 return 0;
1153}
1154
1155static int cam_ife_csid_init_config_ipp_path(
1156 struct cam_ife_csid_hw *csid_hw,
1157 struct cam_isp_resource_node *res)
1158{
1159 int rc = 0;
1160 struct cam_ife_csid_path_cfg *path_data;
1161 struct cam_ife_csid_reg_offset *csid_reg;
1162 struct cam_hw_soc_info *soc_info;
Ravikishore Pampanaad6bc902017-07-12 19:37:06 +05301163 uint32_t path_format = 0, val = 0;
Jing Zhouff57d862017-03-21 00:54:25 -07001164
1165 path_data = (struct cam_ife_csid_path_cfg *) res->res_priv;
1166 csid_reg = csid_hw->csid_info->csid_reg;
1167 soc_info = &csid_hw->hw_info->soc_info;
1168
1169 if (!csid_reg->ipp_reg) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07001170 CAM_ERR(CAM_ISP, "CSID:%d IPP:%d is not supported on HW",
1171 csid_hw->hw_intf->hw_idx,
Jing Zhouff57d862017-03-21 00:54:25 -07001172 res->res_id);
1173 return -EINVAL;
1174 }
1175
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07001176 CAM_DBG(CAM_ISP, "Enabled IPP Path.......");
Ravikishore Pampanaad6bc902017-07-12 19:37:06 +05301177 rc = cam_ife_csid_get_format(path_data->decode_fmt, &path_format);
Jing Zhouff57d862017-03-21 00:54:25 -07001178 if (rc)
1179 return rc;
1180
Jing Zhoubb536a82017-05-18 15:20:38 -07001181 /*
Jing Zhouff57d862017-03-21 00:54:25 -07001182 * configure the IPP and enable the time stamp capture.
1183 * enable the HW measrurement blocks
1184 */
1185 val = (path_data->vc << csid_reg->cmn_reg->vc_shift_val) |
1186 (path_data->dt << csid_reg->cmn_reg->dt_shift_val) |
1187 (path_data->cid << csid_reg->cmn_reg->dt_id_shift_val) |
1188 (path_format << csid_reg->cmn_reg->fmt_shift_val) |
1189 (path_data->crop_enable & 1 <<
1190 csid_reg->cmn_reg->crop_h_en_shift_val) |
1191 (path_data->crop_enable & 1 <<
1192 csid_reg->cmn_reg->crop_v_en_shift_val) |
1193 (1 << 1) | 1;
1194 val |= (1 << csid_reg->ipp_reg->pix_store_en_shift_val);
1195 cam_io_w_mb(val, soc_info->reg_map[0].mem_base +
1196 csid_reg->ipp_reg->csid_ipp_cfg0_addr);
1197
Jing Zhoudedc4762017-06-19 17:45:36 +05301198 /* select the post irq sub sample strobe for time stamp capture */
1199 cam_io_w_mb(CSID_TIMESTAMP_STB_POST_IRQ, soc_info->reg_map[0].mem_base +
1200 csid_reg->ipp_reg->csid_ipp_cfg1_addr);
1201
Jing Zhouff57d862017-03-21 00:54:25 -07001202 if (path_data->crop_enable) {
1203 val = ((path_data->width +
1204 path_data->start_pixel) & 0xFFFF <<
1205 csid_reg->cmn_reg->crop_shift) |
1206 (path_data->start_pixel & 0xFFFF);
1207
1208 cam_io_w_mb(val, soc_info->reg_map[0].mem_base +
1209 csid_reg->ipp_reg->csid_ipp_hcrop_addr);
1210
1211 val = ((path_data->height +
1212 path_data->start_line) & 0xFFFF <<
1213 csid_reg->cmn_reg->crop_shift) |
1214 (path_data->start_line & 0xFFFF);
1215
1216 cam_io_w_mb(val, soc_info->reg_map[0].mem_base +
1217 csid_reg->ipp_reg->csid_ipp_vcrop_addr);
1218 }
1219
1220 /* set frame drop pattern to 0 and period to 1 */
1221 cam_io_w_mb(1, soc_info->reg_map[0].mem_base +
1222 csid_reg->ipp_reg->csid_ipp_frm_drop_period_addr);
1223 cam_io_w_mb(0, soc_info->reg_map[0].mem_base +
1224 csid_reg->ipp_reg->csid_ipp_frm_drop_pattern_addr);
1225 /* set irq sub sample pattern to 0 and period to 1 */
1226 cam_io_w_mb(1, soc_info->reg_map[0].mem_base +
1227 csid_reg->ipp_reg->csid_ipp_irq_subsample_period_addr);
1228 cam_io_w_mb(0, soc_info->reg_map[0].mem_base +
1229 csid_reg->ipp_reg->csid_ipp_irq_subsample_pattern_addr);
1230 /* set pixel drop pattern to 0 and period to 1 */
1231 cam_io_w_mb(0, soc_info->reg_map[0].mem_base +
1232 csid_reg->ipp_reg->csid_ipp_pix_drop_pattern_addr);
1233 cam_io_w_mb(1, soc_info->reg_map[0].mem_base +
1234 csid_reg->ipp_reg->csid_ipp_pix_drop_period_addr);
1235 /* set line drop pattern to 0 and period to 1 */
1236 cam_io_w_mb(0, soc_info->reg_map[0].mem_base +
1237 csid_reg->ipp_reg->csid_ipp_line_drop_pattern_addr);
1238 cam_io_w_mb(1, soc_info->reg_map[0].mem_base +
1239 csid_reg->ipp_reg->csid_ipp_line_drop_period_addr);
1240
1241 /*Set master or slave IPP */
1242 if (path_data->sync_mode == CAM_ISP_HW_SYNC_MASTER)
1243 /*Set halt mode as master */
1244 val = CSID_HALT_MODE_MASTER << 2;
1245 else if (path_data->sync_mode == CAM_ISP_HW_SYNC_SLAVE)
1246 /*Set halt mode as slave and set master idx */
1247 val = path_data->master_idx << 4 | CSID_HALT_MODE_SLAVE << 2;
1248 else
1249 /* Default is internal halt mode */
1250 val = 0;
1251
1252 cam_io_w_mb(val, soc_info->reg_map[0].mem_base +
1253 csid_reg->ipp_reg->csid_ipp_ctrl_addr);
1254
1255 /* Enable the IPP path */
1256 val = cam_io_r_mb(soc_info->reg_map[0].mem_base +
1257 csid_reg->ipp_reg->csid_ipp_cfg0_addr);
1258 val |= (1 << csid_reg->cmn_reg->path_en_shift_val);
1259 cam_io_w_mb(val, soc_info->reg_map[0].mem_base +
1260 csid_reg->ipp_reg->csid_ipp_cfg0_addr);
1261
1262 res->res_state = CAM_ISP_RESOURCE_STATE_INIT_HW;
1263
1264 return rc;
1265}
1266
1267static int cam_ife_csid_deinit_ipp_path(
1268 struct cam_ife_csid_hw *csid_hw,
1269 struct cam_isp_resource_node *res)
1270{
1271 int rc = 0;
1272 struct cam_ife_csid_reg_offset *csid_reg;
1273 struct cam_hw_soc_info *soc_info;
1274 uint32_t val = 0;
1275
1276 csid_reg = csid_hw->csid_info->csid_reg;
1277 soc_info = &csid_hw->hw_info->soc_info;
1278
1279 if (res->res_state != CAM_ISP_RESOURCE_STATE_INIT_HW) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07001280 CAM_ERR(CAM_ISP,
1281 "CSID:%d Res type %d res_id:%d in wrong state %d",
1282 csid_hw->hw_intf->hw_idx,
Jing Zhouff57d862017-03-21 00:54:25 -07001283 res->res_type, res->res_id, res->res_state);
1284 rc = -EINVAL;
1285 }
1286
1287 if (!csid_reg->ipp_reg) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07001288 CAM_ERR(CAM_ISP, "CSID:%d IPP %d is not supported on HW",
1289 csid_hw->hw_intf->hw_idx,
Jing Zhouff57d862017-03-21 00:54:25 -07001290 res->res_id);
1291 rc = -EINVAL;
1292 }
1293
1294 /* Disable the IPP path */
1295 val = cam_io_r_mb(soc_info->reg_map[0].mem_base +
1296 csid_reg->ipp_reg->csid_ipp_cfg0_addr);
1297 val &= ~(1 << csid_reg->cmn_reg->path_en_shift_val);
1298 cam_io_w_mb(val, soc_info->reg_map[0].mem_base +
1299 csid_reg->ipp_reg->csid_ipp_cfg0_addr);
1300
1301 res->res_state = CAM_ISP_RESOURCE_STATE_RESERVED;
1302 return rc;
1303}
1304
1305static int cam_ife_csid_enable_ipp_path(
1306 struct cam_ife_csid_hw *csid_hw,
1307 struct cam_isp_resource_node *res)
1308{
1309 struct cam_ife_csid_reg_offset *csid_reg;
1310 struct cam_hw_soc_info *soc_info;
1311 struct cam_ife_csid_path_cfg *path_data;
1312 uint32_t val = 0;
1313
1314 path_data = (struct cam_ife_csid_path_cfg *) res->res_priv;
1315 csid_reg = csid_hw->csid_info->csid_reg;
1316 soc_info = &csid_hw->hw_info->soc_info;
1317
1318 if (res->res_state != CAM_ISP_RESOURCE_STATE_INIT_HW) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07001319 CAM_ERR(CAM_ISP,
1320 "CSID:%d res type:%d res_id:%d Invalid state%d",
1321 csid_hw->hw_intf->hw_idx,
Jing Zhouff57d862017-03-21 00:54:25 -07001322 res->res_type, res->res_id, res->res_state);
1323 return -EINVAL;
1324 }
1325
1326 if (!csid_reg->ipp_reg) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07001327 CAM_ERR(CAM_ISP, "CSID:%d IPP %d not supported on HW",
1328 csid_hw->hw_intf->hw_idx,
Jing Zhouff57d862017-03-21 00:54:25 -07001329 res->res_id);
1330 return -EINVAL;
1331 }
1332
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07001333 CAM_DBG(CAM_ISP, "enable IPP path.......");
Jing Zhouff57d862017-03-21 00:54:25 -07001334
1335 /*Resume at frame boundary */
1336 if (path_data->sync_mode == CAM_ISP_HW_SYNC_MASTER) {
1337 val = cam_io_r_mb(soc_info->reg_map[0].mem_base +
1338 csid_reg->ipp_reg->csid_ipp_ctrl_addr);
1339 val |= CAM_CSID_RESUME_AT_FRAME_BOUNDARY;
1340 cam_io_w_mb(val, soc_info->reg_map[0].mem_base +
1341 csid_reg->ipp_reg->csid_ipp_ctrl_addr);
1342 } else if (path_data->sync_mode == CAM_ISP_HW_SYNC_NONE) {
1343 cam_io_w_mb(CAM_CSID_RESUME_AT_FRAME_BOUNDARY,
1344 soc_info->reg_map[0].mem_base +
1345 csid_reg->ipp_reg->csid_ipp_ctrl_addr);
1346 }
1347 /* for slave mode, not need to resume for slave device */
1348
1349 /* Enable the required ipp interrupts */
Ravikishore Pampanaad6bc902017-07-12 19:37:06 +05301350 val = CSID_PATH_INFO_RST_DONE | CSID_PATH_ERROR_FIFO_OVERFLOW;
Jing Zhouff57d862017-03-21 00:54:25 -07001351 cam_io_w_mb(val, soc_info->reg_map[0].mem_base +
1352 csid_reg->ipp_reg->csid_ipp_irq_mask_addr);
1353
1354 res->res_state = CAM_ISP_RESOURCE_STATE_STREAMING;
1355
1356 return 0;
1357}
1358
1359static int cam_ife_csid_disable_ipp_path(
1360 struct cam_ife_csid_hw *csid_hw,
1361 struct cam_isp_resource_node *res,
1362 enum cam_ife_csid_halt_cmd stop_cmd)
1363{
1364 int rc = 0;
1365 struct cam_ife_csid_reg_offset *csid_reg;
1366 struct cam_hw_soc_info *soc_info;
1367 struct cam_ife_csid_path_cfg *path_data;
1368 uint32_t val = 0;
1369
1370 path_data = (struct cam_ife_csid_path_cfg *) res->res_priv;
1371 csid_reg = csid_hw->csid_info->csid_reg;
1372 soc_info = &csid_hw->hw_info->soc_info;
1373
1374 if (res->res_id >= CAM_IFE_PIX_PATH_RES_MAX) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07001375 CAM_DBG(CAM_ISP, "CSID:%d Invalid res id%d",
1376 csid_hw->hw_intf->hw_idx, res->res_id);
Jing Zhouff57d862017-03-21 00:54:25 -07001377 return -EINVAL;
1378 }
1379
1380 if (res->res_state == CAM_ISP_RESOURCE_STATE_INIT_HW ||
1381 res->res_state == CAM_ISP_RESOURCE_STATE_RESERVED) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07001382 CAM_DBG(CAM_ISP, "CSID:%d Res:%d already in stopped state:%d",
1383 csid_hw->hw_intf->hw_idx,
Jing Zhouff57d862017-03-21 00:54:25 -07001384 res->res_id, res->res_state);
1385 return rc;
1386 }
1387
1388 if (res->res_state != CAM_ISP_RESOURCE_STATE_STREAMING) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07001389 CAM_DBG(CAM_ISP, "CSID:%d Res:%d Invalid state%d",
1390 csid_hw->hw_intf->hw_idx, res->res_id,
Jing Zhouff57d862017-03-21 00:54:25 -07001391 res->res_state);
1392 return -EINVAL;
1393 }
1394
1395 if (!csid_reg->ipp_reg) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07001396 CAM_ERR(CAM_ISP, "CSID:%d IPP%d is not supported on HW",
1397 csid_hw->hw_intf->hw_idx, res->res_id);
Jing Zhouff57d862017-03-21 00:54:25 -07001398 return -EINVAL;
1399 }
1400
1401 if (stop_cmd != CAM_CSID_HALT_AT_FRAME_BOUNDARY &&
1402 stop_cmd != CAM_CSID_HALT_IMMEDIATELY) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07001403 CAM_ERR(CAM_ISP, "CSID:%d un supported stop command:%d",
1404 csid_hw->hw_intf->hw_idx, stop_cmd);
Jing Zhouff57d862017-03-21 00:54:25 -07001405 return -EINVAL;
1406 }
1407
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07001408 CAM_DBG(CAM_ISP, "CSID:%d res_id:%d",
Jing Zhouff57d862017-03-21 00:54:25 -07001409 csid_hw->hw_intf->hw_idx, res->res_id);
1410
1411 if (path_data->sync_mode == CAM_ISP_HW_SYNC_MASTER) {
1412 /* configure Halt */
1413 val = cam_io_r_mb(soc_info->reg_map[0].mem_base +
1414 csid_reg->ipp_reg->csid_ipp_ctrl_addr);
1415 val &= ~0x3;
1416 val |= stop_cmd;
1417 cam_io_w_mb(val, soc_info->reg_map[0].mem_base +
1418 csid_reg->ipp_reg->csid_ipp_ctrl_addr);
1419 } else if (path_data->sync_mode == CAM_ISP_HW_SYNC_NONE)
1420 cam_io_w_mb(stop_cmd, soc_info->reg_map[0].mem_base +
1421 csid_reg->ipp_reg->csid_ipp_ctrl_addr);
1422
1423 /* For slave mode, halt command should take it from master */
1424
1425 /* Enable the EOF interrupt for resume at boundary case */
1426 if (stop_cmd != CAM_CSID_HALT_IMMEDIATELY) {
1427 init_completion(&csid_hw->csid_ipp_complete);
1428 val = cam_io_r_mb(soc_info->reg_map[0].mem_base +
1429 csid_reg->ipp_reg->csid_ipp_irq_mask_addr);
1430 val |= CSID_PATH_INFO_INPUT_EOF;
1431 cam_io_w_mb(val, soc_info->reg_map[0].mem_base +
1432 csid_reg->ipp_reg->csid_ipp_irq_mask_addr);
1433 } else {
1434 val &= ~(CSID_PATH_INFO_RST_DONE |
1435 CSID_PATH_ERROR_FIFO_OVERFLOW);
1436 cam_io_w_mb(val, soc_info->reg_map[0].mem_base +
1437 csid_reg->ipp_reg->csid_ipp_irq_mask_addr);
1438 }
1439
1440 return rc;
1441}
1442
1443
1444static int cam_ife_csid_init_config_rdi_path(
1445 struct cam_ife_csid_hw *csid_hw,
1446 struct cam_isp_resource_node *res)
1447{
1448 int rc = 0;
1449 struct cam_ife_csid_path_cfg *path_data;
1450 struct cam_ife_csid_reg_offset *csid_reg;
1451 struct cam_hw_soc_info *soc_info;
1452 uint32_t path_format = 0, plain_fmt = 0, val = 0, id;
1453
1454 path_data = (struct cam_ife_csid_path_cfg *) res->res_priv;
1455 csid_reg = csid_hw->csid_info->csid_reg;
1456 soc_info = &csid_hw->hw_info->soc_info;
1457
1458 id = res->res_id;
1459 if (!csid_reg->rdi_reg[id]) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07001460 CAM_ERR(CAM_ISP, "CSID:%d RDI:%d is not supported on HW",
1461 csid_hw->hw_intf->hw_idx, id);
Jing Zhouff57d862017-03-21 00:54:25 -07001462 return -EINVAL;
1463 }
1464
Ravikishore Pampanaad6bc902017-07-12 19:37:06 +05301465 rc = cam_ife_csid_get_rdi_format(path_data->decode_fmt,
1466 path_data->output_fmt, &path_format, &plain_fmt);
Jing Zhouff57d862017-03-21 00:54:25 -07001467 if (rc)
1468 return rc;
1469
Jing Zhoubb536a82017-05-18 15:20:38 -07001470 /*
Jing Zhouff57d862017-03-21 00:54:25 -07001471 * RDI path config and enable the time stamp capture
1472 * Enable the measurement blocks
1473 */
1474 val = (path_data->vc << csid_reg->cmn_reg->vc_shift_val) |
1475 (path_data->dt << csid_reg->cmn_reg->dt_shift_val) |
1476 (path_data->cid << csid_reg->cmn_reg->dt_id_shift_val) |
1477 (path_format << csid_reg->cmn_reg->fmt_shift_val) |
1478 (plain_fmt << csid_reg->cmn_reg->plain_fmt_shit_val) |
1479 (path_data->crop_enable & 1 <<
1480 csid_reg->cmn_reg->crop_h_en_shift_val) |
1481 (path_data->crop_enable & 1 <<
1482 csid_reg->cmn_reg->crop_v_en_shift_val) |
1483 (1 << 2) | 3;
1484
1485 cam_io_w_mb(val, soc_info->reg_map[0].mem_base +
1486 csid_reg->rdi_reg[id]->csid_rdi_cfg0_addr);
1487
Jing Zhoudedc4762017-06-19 17:45:36 +05301488 /* select the post irq sub sample strobe for time stamp capture */
1489 cam_io_w_mb(CSID_TIMESTAMP_STB_POST_IRQ, soc_info->reg_map[0].mem_base +
1490 csid_reg->rdi_reg[id]->csid_rdi_cfg1_addr);
1491
Jing Zhouff57d862017-03-21 00:54:25 -07001492 if (path_data->crop_enable) {
1493 val = ((path_data->width +
1494 path_data->start_pixel) & 0xFFFF <<
1495 csid_reg->cmn_reg->crop_shift) |
1496 (path_data->start_pixel & 0xFFFF);
1497
1498 cam_io_w_mb(val, soc_info->reg_map[0].mem_base +
1499 csid_reg->rdi_reg[id]->csid_rdi_rpp_hcrop_addr);
1500
1501 val = ((path_data->height +
1502 path_data->start_line) & 0xFFFF <<
1503 csid_reg->cmn_reg->crop_shift) |
1504 (path_data->start_line & 0xFFFF);
1505
1506 cam_io_w_mb(val, soc_info->reg_map[0].mem_base +
1507 csid_reg->rdi_reg[id]->csid_rdi_rpp_vcrop_addr);
1508 }
1509 /* set frame drop pattern to 0 and period to 1 */
1510 cam_io_w_mb(1, soc_info->reg_map[0].mem_base +
1511 csid_reg->rdi_reg[id]->csid_rdi_frm_drop_period_addr);
1512 cam_io_w_mb(0, soc_info->reg_map[0].mem_base +
1513 csid_reg->rdi_reg[id]->csid_rdi_frm_drop_pattern_addr);
1514 /* set IRQ sum sabmple */
1515 cam_io_w_mb(1, soc_info->reg_map[0].mem_base +
1516 csid_reg->rdi_reg[id]->csid_rdi_irq_subsample_period_addr);
1517 cam_io_w_mb(0, soc_info->reg_map[0].mem_base +
1518 csid_reg->rdi_reg[id]->csid_rdi_irq_subsample_pattern_addr);
1519
1520 /* set pixel drop pattern to 0 and period to 1 */
1521 cam_io_w_mb(0, soc_info->reg_map[0].mem_base +
1522 csid_reg->rdi_reg[id]->csid_rdi_rpp_pix_drop_pattern_addr);
1523 cam_io_w_mb(1, soc_info->reg_map[0].mem_base +
1524 csid_reg->rdi_reg[id]->csid_rdi_rpp_pix_drop_period_addr);
1525 /* set line drop pattern to 0 and period to 1 */
1526 cam_io_w_mb(0, soc_info->reg_map[0].mem_base +
1527 csid_reg->rdi_reg[id]->csid_rdi_rpp_line_drop_pattern_addr);
1528 cam_io_w_mb(1, soc_info->reg_map[0].mem_base +
1529 csid_reg->rdi_reg[id]->csid_rdi_rpp_line_drop_period_addr);
1530
1531 /* Configure the halt mode */
1532 cam_io_w_mb(0, soc_info->reg_map[0].mem_base +
1533 csid_reg->rdi_reg[id]->csid_rdi_ctrl_addr);
1534
1535 /* Enable the RPP path */
1536 val = cam_io_r_mb(soc_info->reg_map[0].mem_base +
1537 csid_reg->rdi_reg[id]->csid_rdi_cfg0_addr);
1538 val |= (1 << csid_reg->cmn_reg->path_en_shift_val);
1539 cam_io_w_mb(val, soc_info->reg_map[0].mem_base +
1540 csid_reg->rdi_reg[id]->csid_rdi_cfg0_addr);
1541
1542 res->res_state = CAM_ISP_RESOURCE_STATE_INIT_HW;
1543
1544 return rc;
1545}
1546
1547static int cam_ife_csid_deinit_rdi_path(
1548 struct cam_ife_csid_hw *csid_hw,
1549 struct cam_isp_resource_node *res)
1550{
1551 int rc = 0;
1552 struct cam_ife_csid_reg_offset *csid_reg;
1553 struct cam_hw_soc_info *soc_info;
1554 uint32_t val = 0, id;
1555
1556 csid_reg = csid_hw->csid_info->csid_reg;
1557 soc_info = &csid_hw->hw_info->soc_info;
1558 id = res->res_id;
1559
1560 if (res->res_id > CAM_IFE_PIX_PATH_RES_RDI_3 ||
1561 res->res_state != CAM_ISP_RESOURCE_STATE_INIT_HW ||
1562 !csid_reg->rdi_reg[id]) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07001563 CAM_ERR(CAM_ISP, "CSID:%d Invalid res id%d state:%d",
1564 csid_hw->hw_intf->hw_idx, res->res_id,
Jing Zhouff57d862017-03-21 00:54:25 -07001565 res->res_state);
1566 return -EINVAL;
1567 }
1568
1569 /* Disable the RDI path */
1570 val = cam_io_r_mb(soc_info->reg_map[0].mem_base +
1571 csid_reg->rdi_reg[id]->csid_rdi_cfg0_addr);
1572 val &= ~(1 << csid_reg->cmn_reg->path_en_shift_val);
1573 cam_io_w_mb(val, soc_info->reg_map[0].mem_base +
1574 csid_reg->rdi_reg[id]->csid_rdi_cfg0_addr);
1575
1576 res->res_state = CAM_ISP_RESOURCE_STATE_RESERVED;
1577 return rc;
1578}
1579
1580static int cam_ife_csid_enable_rdi_path(
1581 struct cam_ife_csid_hw *csid_hw,
1582 struct cam_isp_resource_node *res)
1583{
1584 struct cam_ife_csid_reg_offset *csid_reg;
1585 struct cam_hw_soc_info *soc_info;
1586 uint32_t id, val;
1587
1588 csid_reg = csid_hw->csid_info->csid_reg;
1589 soc_info = &csid_hw->hw_info->soc_info;
1590 id = res->res_id;
1591
1592 if (res->res_state != CAM_ISP_RESOURCE_STATE_INIT_HW ||
1593 res->res_id > CAM_IFE_PIX_PATH_RES_RDI_3 ||
1594 !csid_reg->rdi_reg[id]) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07001595 CAM_ERR(CAM_ISP,
1596 "CSID:%d invalid res type:%d res_id:%d state%d",
1597 csid_hw->hw_intf->hw_idx,
Jing Zhouff57d862017-03-21 00:54:25 -07001598 res->res_type, res->res_id, res->res_state);
1599 return -EINVAL;
1600 }
1601
1602 /*resume at frame boundary */
1603 cam_io_w_mb(CAM_CSID_RESUME_AT_FRAME_BOUNDARY,
1604 soc_info->reg_map[0].mem_base +
1605 csid_reg->rdi_reg[id]->csid_rdi_ctrl_addr);
1606
1607 /* Enable the required RDI interrupts */
Ravikishore Pampanaad6bc902017-07-12 19:37:06 +05301608 val = CSID_PATH_INFO_RST_DONE | CSID_PATH_ERROR_FIFO_OVERFLOW;
Jing Zhouff57d862017-03-21 00:54:25 -07001609 cam_io_w_mb(val, soc_info->reg_map[0].mem_base +
1610 csid_reg->rdi_reg[id]->csid_rdi_irq_mask_addr);
1611
1612 res->res_state = CAM_ISP_RESOURCE_STATE_STREAMING;
1613
1614 return 0;
1615}
1616
1617
1618static int cam_ife_csid_disable_rdi_path(
1619 struct cam_ife_csid_hw *csid_hw,
1620 struct cam_isp_resource_node *res,
1621 enum cam_ife_csid_halt_cmd stop_cmd)
1622{
1623 int rc = 0;
1624 struct cam_ife_csid_reg_offset *csid_reg;
1625 struct cam_hw_soc_info *soc_info;
1626 uint32_t val = 0, id;
1627
1628 csid_reg = csid_hw->csid_info->csid_reg;
1629 soc_info = &csid_hw->hw_info->soc_info;
1630 id = res->res_id;
1631
1632 if (res->res_id >= CAM_IFE_PIX_PATH_RES_MAX ||
1633 !csid_reg->rdi_reg[res->res_id]) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07001634 CAM_DBG(CAM_ISP, "CSID:%d Invalid res id%d",
1635 csid_hw->hw_intf->hw_idx, res->res_id);
Jing Zhouff57d862017-03-21 00:54:25 -07001636 return -EINVAL;
1637 }
1638
1639 if (res->res_state == CAM_ISP_RESOURCE_STATE_INIT_HW ||
1640 res->res_state == CAM_ISP_RESOURCE_STATE_RESERVED) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07001641 CAM_DBG(CAM_ISP, "CSID:%d Res:%d already in stopped state:%d",
1642 csid_hw->hw_intf->hw_idx,
Jing Zhouff57d862017-03-21 00:54:25 -07001643 res->res_id, res->res_state);
1644 return rc;
1645 }
1646
1647 if (res->res_state != CAM_ISP_RESOURCE_STATE_STREAMING) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07001648 CAM_DBG(CAM_ISP, "CSID:%d Res:%d Invalid res_state%d",
1649 csid_hw->hw_intf->hw_idx, res->res_id,
Jing Zhouff57d862017-03-21 00:54:25 -07001650 res->res_state);
1651 return -EINVAL;
1652 }
1653
1654 if (stop_cmd != CAM_CSID_HALT_AT_FRAME_BOUNDARY &&
1655 stop_cmd != CAM_CSID_HALT_IMMEDIATELY) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07001656 CAM_ERR(CAM_ISP, "CSID:%d un supported stop command:%d",
1657 csid_hw->hw_intf->hw_idx, stop_cmd);
Jing Zhouff57d862017-03-21 00:54:25 -07001658 return -EINVAL;
1659 }
1660
1661
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07001662 CAM_DBG(CAM_ISP, "CSID:%d res_id:%d",
Jing Zhouff57d862017-03-21 00:54:25 -07001663 csid_hw->hw_intf->hw_idx, res->res_id);
1664
1665 init_completion(&csid_hw->csid_rdin_complete[id]);
1666
1667 if (stop_cmd != CAM_CSID_HALT_IMMEDIATELY) {
1668 val = cam_io_r_mb(soc_info->reg_map[0].mem_base +
1669 csid_reg->rdi_reg[id]->csid_rdi_irq_mask_addr);
1670 val |= CSID_PATH_INFO_INPUT_EOF;
1671 cam_io_w_mb(val, soc_info->reg_map[0].mem_base +
1672 csid_reg->rdi_reg[id]->csid_rdi_irq_mask_addr);
1673 } else {
1674 val &= ~(CSID_PATH_INFO_RST_DONE |
1675 CSID_PATH_ERROR_FIFO_OVERFLOW);
1676 cam_io_w_mb(val, soc_info->reg_map[0].mem_base +
1677 csid_reg->rdi_reg[id]->csid_rdi_irq_mask_addr);
1678 }
1679
1680 /*Halt the RDI path */
1681 cam_io_w_mb(stop_cmd, soc_info->reg_map[0].mem_base +
1682 csid_reg->rdi_reg[id]->csid_rdi_ctrl_addr);
1683
1684 return rc;
1685}
1686
1687static int cam_ife_csid_get_time_stamp(
1688 struct cam_ife_csid_hw *csid_hw, void *cmd_args)
1689{
1690 struct cam_csid_get_time_stamp_args *time_stamp;
1691 struct cam_isp_resource_node *res;
1692 struct cam_ife_csid_reg_offset *csid_reg;
1693 struct cam_hw_soc_info *soc_info;
1694 uint32_t time_32, id;
1695
1696 time_stamp = (struct cam_csid_get_time_stamp_args *)cmd_args;
1697 res = time_stamp->node_res;
1698 csid_reg = csid_hw->csid_info->csid_reg;
1699 soc_info = &csid_hw->hw_info->soc_info;
1700
1701 if (res->res_type != CAM_ISP_RESOURCE_PIX_PATH ||
1702 res->res_id >= CAM_IFE_PIX_PATH_RES_MAX) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07001703 CAM_DBG(CAM_ISP, "CSID:%d Invalid res_type:%d res id%d",
1704 csid_hw->hw_intf->hw_idx, res->res_type,
Jing Zhouff57d862017-03-21 00:54:25 -07001705 res->res_id);
1706 return -EINVAL;
1707 }
1708
1709 if (csid_hw->hw_info->hw_state != CAM_HW_STATE_POWER_UP) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07001710 CAM_ERR(CAM_ISP, "CSID:%d Invalid dev state :%d",
1711 csid_hw->hw_intf->hw_idx,
Jing Zhouff57d862017-03-21 00:54:25 -07001712 csid_hw->hw_info->hw_state);
1713 return -EINVAL;
1714 }
1715
1716 if (res->res_id == CAM_IFE_PIX_PATH_RES_IPP) {
1717 time_32 = cam_io_r_mb(soc_info->reg_map[0].mem_base +
1718 csid_reg->ipp_reg->csid_ipp_timestamp_curr1_sof_addr);
1719 time_stamp->time_stamp_val = time_32;
1720 time_stamp->time_stamp_val = time_stamp->time_stamp_val << 32;
1721 time_32 = cam_io_r_mb(soc_info->reg_map[0].mem_base +
1722 csid_reg->ipp_reg->csid_ipp_timestamp_curr0_sof_addr);
1723 time_stamp->time_stamp_val |= time_32;
1724 } else {
1725 id = res->res_id;
1726 time_32 = cam_io_r_mb(soc_info->reg_map[0].mem_base +
1727 csid_reg->rdi_reg[id]->
1728 csid_rdi_timestamp_curr1_sof_addr);
1729 time_stamp->time_stamp_val = time_32;
1730 time_stamp->time_stamp_val = time_stamp->time_stamp_val << 32;
1731
1732 time_32 = cam_io_r_mb(soc_info->reg_map[0].mem_base +
1733 csid_reg->rdi_reg[id]->
1734 csid_rdi_timestamp_curr0_sof_addr);
1735 time_stamp->time_stamp_val |= time_32;
1736 }
1737
1738 return 0;
1739}
1740static int cam_ife_csid_res_wait_for_halt(
1741 struct cam_ife_csid_hw *csid_hw,
1742 struct cam_isp_resource_node *res)
1743{
1744 int rc = 0;
1745 struct cam_ife_csid_reg_offset *csid_reg;
1746 struct cam_hw_soc_info *soc_info;
1747
1748 struct completion *complete;
1749 uint32_t val = 0, id;
1750
1751 csid_reg = csid_hw->csid_info->csid_reg;
1752 soc_info = &csid_hw->hw_info->soc_info;
1753
1754 if (res->res_id >= CAM_IFE_PIX_PATH_RES_MAX) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07001755 CAM_DBG(CAM_ISP, "CSID:%d Invalid res id%d",
1756 csid_hw->hw_intf->hw_idx, res->res_id);
Jing Zhouff57d862017-03-21 00:54:25 -07001757 return -EINVAL;
1758 }
1759
1760 if (res->res_state == CAM_ISP_RESOURCE_STATE_INIT_HW ||
1761 res->res_state == CAM_ISP_RESOURCE_STATE_RESERVED) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07001762 CAM_DBG(CAM_ISP, "CSID:%d Res:%d already in stopped state:%d",
1763 csid_hw->hw_intf->hw_idx,
Jing Zhouff57d862017-03-21 00:54:25 -07001764 res->res_id, res->res_state);
1765 return rc;
1766 }
1767
1768 if (res->res_state != CAM_ISP_RESOURCE_STATE_STREAMING) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07001769 CAM_DBG(CAM_ISP, "CSID:%d Res:%d Invalid state%d",
1770 csid_hw->hw_intf->hw_idx, res->res_id,
Jing Zhouff57d862017-03-21 00:54:25 -07001771 res->res_state);
1772 return -EINVAL;
1773 }
1774
1775 if (res->res_id == CAM_IFE_PIX_PATH_RES_IPP)
1776 complete = &csid_hw->csid_ipp_complete;
1777 else
1778 complete = &csid_hw->csid_rdin_complete[res->res_id];
1779
1780 rc = wait_for_completion_timeout(complete,
1781 msecs_to_jiffies(IFE_CSID_TIMEOUT));
1782 if (rc <= 0) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07001783 CAM_ERR(CAM_ISP, "CSID%d stop at frame boundary failid:%drc:%d",
1784 csid_hw->hw_intf->hw_idx,
Jing Zhouff57d862017-03-21 00:54:25 -07001785 res->res_id, rc);
1786 if (rc == 0)
1787 /* continue even have timeout */
1788 rc = -ETIMEDOUT;
1789 }
1790
1791 /* Disable the interrupt */
1792 if (res->res_id == CAM_IFE_PIX_PATH_RES_IPP) {
1793 val = cam_io_r_mb(soc_info->reg_map[0].mem_base +
1794 csid_reg->ipp_reg->csid_ipp_irq_mask_addr);
1795 val &= ~(CSID_PATH_INFO_INPUT_EOF | CSID_PATH_INFO_RST_DONE |
1796 CSID_PATH_ERROR_FIFO_OVERFLOW);
1797 cam_io_w_mb(val, soc_info->reg_map[0].mem_base +
1798 csid_reg->ipp_reg->csid_ipp_irq_mask_addr);
1799 } else {
1800 id = res->res_id;
1801 val = cam_io_r_mb(soc_info->reg_map[0].mem_base +
1802 csid_reg->rdi_reg[id]->csid_rdi_irq_mask_addr);
1803 val &= ~(CSID_PATH_INFO_INPUT_EOF | CSID_PATH_INFO_RST_DONE |
1804 CSID_PATH_ERROR_FIFO_OVERFLOW);
1805 cam_io_w_mb(val, soc_info->reg_map[0].mem_base +
1806 csid_reg->rdi_reg[id]->csid_rdi_irq_mask_addr);
1807 }
1808 /* set state to init HW */
1809 res->res_state = CAM_ISP_RESOURCE_STATE_INIT_HW;
1810 return rc;
1811}
1812
1813static int cam_ife_csid_get_hw_caps(void *hw_priv,
1814 void *get_hw_cap_args, uint32_t arg_size)
1815{
1816 int rc = 0;
1817 struct cam_ife_csid_hw_caps *hw_caps;
1818 struct cam_ife_csid_hw *csid_hw;
1819 struct cam_hw_info *csid_hw_info;
1820 struct cam_ife_csid_reg_offset *csid_reg;
1821
1822 if (!hw_priv || !get_hw_cap_args) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07001823 CAM_ERR(CAM_ISP, "CSID: Invalid args");
Jing Zhouff57d862017-03-21 00:54:25 -07001824 return -EINVAL;
1825 }
1826
1827 csid_hw_info = (struct cam_hw_info *)hw_priv;
1828 csid_hw = (struct cam_ife_csid_hw *)csid_hw_info->core_info;
1829 csid_reg = csid_hw->csid_info->csid_reg;
1830 hw_caps = (struct cam_ife_csid_hw_caps *) get_hw_cap_args;
1831
1832 hw_caps->no_rdis = csid_reg->cmn_reg->no_rdis;
1833 hw_caps->no_pix = csid_reg->cmn_reg->no_pix;
1834 hw_caps->major_version = csid_reg->cmn_reg->major_version;
1835 hw_caps->minor_version = csid_reg->cmn_reg->minor_version;
1836 hw_caps->version_incr = csid_reg->cmn_reg->version_incr;
1837
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07001838 CAM_DBG(CAM_ISP,
1839 "CSID:%d No rdis:%d, no pix:%d, major:%d minor:%d ver :%d",
1840 csid_hw->hw_intf->hw_idx, hw_caps->no_rdis,
Jing Zhouff57d862017-03-21 00:54:25 -07001841 hw_caps->no_pix, hw_caps->major_version, hw_caps->minor_version,
1842 hw_caps->version_incr);
1843
1844 return rc;
1845}
1846
1847static int cam_ife_csid_reset(void *hw_priv,
1848 void *reset_args, uint32_t arg_size)
1849{
1850 struct cam_ife_csid_hw *csid_hw;
1851 struct cam_hw_info *csid_hw_info;
1852 struct cam_csid_reset_cfg_args *reset;
1853 int rc = 0;
1854
1855 if (!hw_priv || !reset_args || (arg_size !=
1856 sizeof(struct cam_csid_reset_cfg_args))) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07001857 CAM_ERR(CAM_ISP, "CSID:Invalid args");
Jing Zhouff57d862017-03-21 00:54:25 -07001858 return -EINVAL;
1859 }
1860
1861 csid_hw_info = (struct cam_hw_info *)hw_priv;
1862 csid_hw = (struct cam_ife_csid_hw *)csid_hw_info->core_info;
1863 reset = (struct cam_csid_reset_cfg_args *)reset_args;
1864
1865 switch (reset->reset_type) {
1866 case CAM_IFE_CSID_RESET_GLOBAL:
1867 rc = cam_ife_csid_global_reset(csid_hw);
1868 break;
1869 case CAM_IFE_CSID_RESET_PATH:
1870 rc = cam_ife_csid_path_reset(csid_hw, reset);
1871 break;
1872 default:
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07001873 CAM_ERR(CAM_ISP, "CSID:Invalid reset type :%d",
1874 reset->reset_type);
Jing Zhouff57d862017-03-21 00:54:25 -07001875 rc = -EINVAL;
1876 break;
1877 }
1878
1879 return rc;
1880}
1881
1882static int cam_ife_csid_reserve(void *hw_priv,
1883 void *reserve_args, uint32_t arg_size)
1884{
1885 int rc = 0;
1886 struct cam_ife_csid_hw *csid_hw;
1887 struct cam_hw_info *csid_hw_info;
1888 struct cam_csid_hw_reserve_resource_args *reserv;
1889
1890 if (!hw_priv || !reserve_args || (arg_size !=
1891 sizeof(struct cam_csid_hw_reserve_resource_args))) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07001892 CAM_ERR(CAM_ISP, "CSID: Invalid args");
Jing Zhouff57d862017-03-21 00:54:25 -07001893 return -EINVAL;
1894 }
1895
1896 csid_hw_info = (struct cam_hw_info *)hw_priv;
1897 csid_hw = (struct cam_ife_csid_hw *)csid_hw_info->core_info;
1898 reserv = (struct cam_csid_hw_reserve_resource_args *)reserve_args;
1899
1900 mutex_lock(&csid_hw->hw_info->hw_mutex);
1901 switch (reserv->res_type) {
1902 case CAM_ISP_RESOURCE_CID:
1903 rc = cam_ife_csid_cid_reserve(csid_hw, reserv);
1904 break;
1905 case CAM_ISP_RESOURCE_PIX_PATH:
1906 rc = cam_ife_csid_path_reserve(csid_hw, reserv);
1907 break;
1908 default:
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07001909 CAM_ERR(CAM_ISP, "CSID:%d Invalid res type :%d",
1910 csid_hw->hw_intf->hw_idx, reserv->res_type);
Jing Zhouff57d862017-03-21 00:54:25 -07001911 rc = -EINVAL;
1912 break;
1913 }
1914 mutex_unlock(&csid_hw->hw_info->hw_mutex);
1915 return rc;
1916}
1917
1918static int cam_ife_csid_release(void *hw_priv,
1919 void *release_args, uint32_t arg_size)
1920{
1921 int rc = 0;
1922 struct cam_ife_csid_hw *csid_hw;
1923 struct cam_hw_info *csid_hw_info;
1924 struct cam_isp_resource_node *res;
1925 struct cam_ife_csid_cid_data *cid_data;
1926
1927 if (!hw_priv || !release_args ||
1928 (arg_size != sizeof(struct cam_isp_resource_node))) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07001929 CAM_ERR(CAM_ISP, "CSID: Invalid args");
Jing Zhouff57d862017-03-21 00:54:25 -07001930 return -EINVAL;
1931 }
1932
1933 csid_hw_info = (struct cam_hw_info *)hw_priv;
1934 csid_hw = (struct cam_ife_csid_hw *)csid_hw_info->core_info;
1935 res = (struct cam_isp_resource_node *)release_args;
1936
1937 mutex_lock(&csid_hw->hw_info->hw_mutex);
1938 if ((res->res_type == CAM_ISP_RESOURCE_CID &&
1939 res->res_id >= CAM_IFE_CSID_CID_MAX) ||
1940 (res->res_type == CAM_ISP_RESOURCE_PIX_PATH &&
1941 res->res_id >= CAM_IFE_PIX_PATH_RES_MAX)) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07001942 CAM_ERR(CAM_ISP, "CSID:%d Invalid res type:%d res id%d",
1943 csid_hw->hw_intf->hw_idx, res->res_type,
Jing Zhouff57d862017-03-21 00:54:25 -07001944 res->res_id);
1945 rc = -EINVAL;
1946 goto end;
1947 }
1948
1949 if (res->res_state == CAM_ISP_RESOURCE_STATE_AVAILABLE) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07001950 CAM_DBG(CAM_ISP,
1951 "CSID:%d res type:%d Res %d in released state",
1952 csid_hw->hw_intf->hw_idx,
Jing Zhouff57d862017-03-21 00:54:25 -07001953 res->res_type, res->res_id);
1954 goto end;
1955 }
1956
1957 if (res->res_type == CAM_ISP_RESOURCE_PIX_PATH &&
1958 res->res_state != CAM_ISP_RESOURCE_STATE_RESERVED) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07001959 CAM_DBG(CAM_ISP,
1960 "CSID:%d res type:%d Res id:%d invalid state:%d",
1961 csid_hw->hw_intf->hw_idx,
Jing Zhouff57d862017-03-21 00:54:25 -07001962 res->res_type, res->res_id, res->res_state);
1963 rc = -EINVAL;
1964 goto end;
1965 }
1966
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07001967 CAM_DBG(CAM_ISP, "CSID:%d res type :%d Resource id:%d",
1968 csid_hw->hw_intf->hw_idx, res->res_type, res->res_id);
Jing Zhouff57d862017-03-21 00:54:25 -07001969
1970 switch (res->res_type) {
1971 case CAM_ISP_RESOURCE_CID:
1972 cid_data = (struct cam_ife_csid_cid_data *) res->res_priv;
1973 if (cid_data->cnt)
1974 cid_data->cnt--;
1975
1976 if (!cid_data->cnt)
1977 res->res_state = CAM_ISP_RESOURCE_STATE_AVAILABLE;
1978
1979 if (csid_hw->csi2_reserve_cnt)
1980 csid_hw->csi2_reserve_cnt--;
1981
1982 if (!csid_hw->csi2_reserve_cnt)
1983 memset(&csid_hw->csi2_rx_cfg, 0,
1984 sizeof(struct cam_ife_csid_csi2_rx_cfg));
1985
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07001986 CAM_DBG(CAM_ISP, "CSID:%d res id :%d cnt:%d reserv cnt:%d",
1987 csid_hw->hw_intf->hw_idx,
Jing Zhouff57d862017-03-21 00:54:25 -07001988 res->res_id, cid_data->cnt, csid_hw->csi2_reserve_cnt);
1989
1990 break;
1991 case CAM_ISP_RESOURCE_PIX_PATH:
1992 res->res_state = CAM_ISP_RESOURCE_STATE_AVAILABLE;
1993 break;
1994 default:
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07001995 CAM_ERR(CAM_ISP, "CSID:%d Invalid res type:%d res id%d",
1996 csid_hw->hw_intf->hw_idx, res->res_type,
Jing Zhouff57d862017-03-21 00:54:25 -07001997 res->res_id);
1998 rc = -EINVAL;
1999 break;
2000 }
2001
2002end:
2003 mutex_unlock(&csid_hw->hw_info->hw_mutex);
2004 return rc;
2005}
2006
2007static int cam_ife_csid_init_hw(void *hw_priv,
2008 void *init_args, uint32_t arg_size)
2009{
2010 int rc = 0;
2011 struct cam_ife_csid_hw *csid_hw;
2012 struct cam_hw_info *csid_hw_info;
2013 struct cam_isp_resource_node *res;
2014 struct cam_ife_csid_reg_offset *csid_reg;
2015
2016 if (!hw_priv || !init_args ||
2017 (arg_size != sizeof(struct cam_isp_resource_node))) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07002018 CAM_ERR(CAM_ISP, "CSID: Invalid args");
Jing Zhouff57d862017-03-21 00:54:25 -07002019 return -EINVAL;
2020 }
2021
2022 csid_hw_info = (struct cam_hw_info *)hw_priv;
2023 csid_hw = (struct cam_ife_csid_hw *)csid_hw_info->core_info;
2024 res = (struct cam_isp_resource_node *)init_args;
2025 csid_reg = csid_hw->csid_info->csid_reg;
2026
2027 mutex_lock(&csid_hw->hw_info->hw_mutex);
2028 if ((res->res_type == CAM_ISP_RESOURCE_CID &&
2029 res->res_id >= CAM_IFE_CSID_CID_MAX) ||
2030 (res->res_type == CAM_ISP_RESOURCE_PIX_PATH &&
2031 res->res_id >= CAM_IFE_PIX_PATH_RES_MAX)) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07002032 CAM_ERR(CAM_ISP, "CSID:%d Invalid res tpe:%d res id%d",
2033 csid_hw->hw_intf->hw_idx, res->res_type,
Jing Zhouff57d862017-03-21 00:54:25 -07002034 res->res_id);
2035 rc = -EINVAL;
2036 goto end;
2037 }
2038
2039
2040 if ((res->res_type == CAM_ISP_RESOURCE_PIX_PATH) &&
2041 (res->res_state != CAM_ISP_RESOURCE_STATE_RESERVED)) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07002042 CAM_ERR(CAM_ISP,
2043 "CSID:%d res type:%d res_id:%dInvalid state %d",
2044 csid_hw->hw_intf->hw_idx,
Jing Zhouff57d862017-03-21 00:54:25 -07002045 res->res_type, res->res_id, res->res_state);
2046 rc = -EINVAL;
2047 goto end;
2048 }
2049
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07002050 CAM_DBG(CAM_ISP, "CSID:%d res type :%d res_id:%d",
Jing Zhouff57d862017-03-21 00:54:25 -07002051 csid_hw->hw_intf->hw_idx, res->res_type, res->res_id);
2052
2053
2054 /* Initialize the csid hardware */
2055 rc = cam_ife_csid_enable_hw(csid_hw);
2056 if (rc)
2057 goto end;
2058
2059 switch (res->res_type) {
2060 case CAM_ISP_RESOURCE_CID:
2061 rc = cam_ife_csid_enable_csi2(csid_hw, res);
2062 break;
2063 case CAM_ISP_RESOURCE_PIX_PATH:
2064 if (res->res_id == CAM_IFE_PIX_PATH_RES_IPP)
2065 rc = cam_ife_csid_init_config_ipp_path(csid_hw, res);
2066 else
2067 rc = cam_ife_csid_init_config_rdi_path(csid_hw, res);
2068
2069 break;
2070 default:
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07002071 CAM_ERR(CAM_ISP, "CSID:%d Invalid res type state %d",
2072 csid_hw->hw_intf->hw_idx,
Jing Zhouff57d862017-03-21 00:54:25 -07002073 res->res_type);
2074 break;
2075 }
2076
2077 if (rc)
2078 cam_ife_csid_disable_hw(csid_hw);
2079end:
2080 mutex_unlock(&csid_hw->hw_info->hw_mutex);
2081 return rc;
2082}
2083
2084static int cam_ife_csid_deinit_hw(void *hw_priv,
2085 void *deinit_args, uint32_t arg_size)
2086{
2087 int rc = 0;
2088 struct cam_ife_csid_hw *csid_hw;
2089 struct cam_hw_info *csid_hw_info;
2090 struct cam_isp_resource_node *res;
2091
2092 if (!hw_priv || !deinit_args ||
2093 (arg_size != sizeof(struct cam_isp_resource_node))) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07002094 CAM_ERR(CAM_ISP, "CSID:Invalid arguments");
Jing Zhouff57d862017-03-21 00:54:25 -07002095 return -EINVAL;
2096 }
2097
2098 res = (struct cam_isp_resource_node *)deinit_args;
2099 csid_hw_info = (struct cam_hw_info *)hw_priv;
2100 csid_hw = (struct cam_ife_csid_hw *)csid_hw_info->core_info;
2101
2102 mutex_lock(&csid_hw->hw_info->hw_mutex);
2103 if (res->res_state == CAM_ISP_RESOURCE_STATE_RESERVED) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07002104 CAM_DBG(CAM_ISP, "CSID:%d Res:%d already in De-init state",
2105 csid_hw->hw_intf->hw_idx,
Jing Zhouff57d862017-03-21 00:54:25 -07002106 res->res_id);
2107 goto end;
2108 }
2109
2110 switch (res->res_type) {
2111 case CAM_ISP_RESOURCE_CID:
2112 rc = cam_ife_csid_disable_csi2(csid_hw, res);
2113 break;
2114 case CAM_ISP_RESOURCE_PIX_PATH:
2115 if (res->res_id == CAM_IFE_PIX_PATH_RES_IPP)
2116 rc = cam_ife_csid_deinit_ipp_path(csid_hw, res);
2117 else
2118 rc = cam_ife_csid_deinit_rdi_path(csid_hw, res);
2119
2120 break;
2121 default:
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07002122 CAM_ERR(CAM_ISP, "CSID:%d Invalid Res type %d",
2123 csid_hw->hw_intf->hw_idx,
Jing Zhouff57d862017-03-21 00:54:25 -07002124 res->res_type);
2125 goto end;
2126 }
2127
2128 /* Disable CSID HW */
2129 cam_ife_csid_disable_hw(csid_hw);
2130
2131end:
2132 mutex_unlock(&csid_hw->hw_info->hw_mutex);
2133 return rc;
2134}
2135
2136static int cam_ife_csid_start(void *hw_priv, void *start_args,
2137 uint32_t arg_size)
2138{
2139 int rc = 0;
2140 struct cam_ife_csid_hw *csid_hw;
2141 struct cam_hw_info *csid_hw_info;
2142 struct cam_isp_resource_node *res;
2143 struct cam_ife_csid_reg_offset *csid_reg;
2144
2145 if (!hw_priv || !start_args ||
2146 (arg_size != sizeof(struct cam_isp_resource_node))) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07002147 CAM_ERR(CAM_ISP, "CSID: Invalid args");
Jing Zhouff57d862017-03-21 00:54:25 -07002148 return -EINVAL;
2149 }
2150
2151 csid_hw_info = (struct cam_hw_info *)hw_priv;
2152 csid_hw = (struct cam_ife_csid_hw *)csid_hw_info->core_info;
2153 res = (struct cam_isp_resource_node *)start_args;
2154 csid_reg = csid_hw->csid_info->csid_reg;
2155
Jing Zhouff57d862017-03-21 00:54:25 -07002156 if ((res->res_type == CAM_ISP_RESOURCE_CID &&
2157 res->res_id >= CAM_IFE_CSID_CID_MAX) ||
2158 (res->res_type == CAM_ISP_RESOURCE_PIX_PATH &&
2159 res->res_id >= CAM_IFE_PIX_PATH_RES_MAX)) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07002160 CAM_DBG(CAM_ISP, "CSID:%d Invalid res tpe:%d res id:%d",
2161 csid_hw->hw_intf->hw_idx, res->res_type,
Jing Zhouff57d862017-03-21 00:54:25 -07002162 res->res_id);
2163 rc = -EINVAL;
2164 goto end;
2165 }
2166
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07002167 CAM_DBG(CAM_ISP, "CSID:%d res_type :%d res_id:%d",
Jing Zhouff57d862017-03-21 00:54:25 -07002168 csid_hw->hw_intf->hw_idx, res->res_type, res->res_id);
2169
2170 switch (res->res_type) {
2171 case CAM_ISP_RESOURCE_CID:
2172 if (csid_hw->res_type == CAM_ISP_IFE_IN_RES_TPG)
2173 rc = cam_ife_csid_tpg_start(csid_hw, res);
2174 break;
2175 case CAM_ISP_RESOURCE_PIX_PATH:
2176 if (res->res_id == CAM_IFE_PIX_PATH_RES_IPP)
2177 rc = cam_ife_csid_enable_ipp_path(csid_hw, res);
2178 else
2179 rc = cam_ife_csid_enable_rdi_path(csid_hw, res);
2180 break;
2181 default:
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07002182 CAM_ERR(CAM_ISP, "CSID:%d Invalid res type%d",
2183 csid_hw->hw_intf->hw_idx,
Jing Zhouff57d862017-03-21 00:54:25 -07002184 res->res_type);
2185 break;
2186 }
2187end:
Jing Zhouff57d862017-03-21 00:54:25 -07002188 return rc;
2189}
2190
2191static int cam_ife_csid_stop(void *hw_priv,
2192 void *stop_args, uint32_t arg_size)
2193{
2194 int rc = 0;
2195 struct cam_ife_csid_hw *csid_hw;
2196 struct cam_hw_info *csid_hw_info;
2197 struct cam_isp_resource_node *res;
2198 struct cam_csid_hw_stop_args *csid_stop;
2199 uint32_t i;
2200
2201 if (!hw_priv || !stop_args ||
2202 (arg_size != sizeof(struct cam_csid_hw_stop_args))) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07002203 CAM_ERR(CAM_ISP, "CSID: Invalid args");
Jing Zhouff57d862017-03-21 00:54:25 -07002204 return -EINVAL;
2205 }
2206 csid_stop = (struct cam_csid_hw_stop_args *) stop_args;
2207 csid_hw_info = (struct cam_hw_info *)hw_priv;
2208 csid_hw = (struct cam_ife_csid_hw *)csid_hw_info->core_info;
2209
Jing Zhouff57d862017-03-21 00:54:25 -07002210 /* Stop the resource first */
2211 for (i = 0; i < csid_stop->num_res; i++) {
2212 res = csid_stop->node_res[i];
2213 switch (res->res_type) {
2214 case CAM_ISP_RESOURCE_CID:
2215 if (csid_hw->res_type == CAM_ISP_IFE_IN_RES_TPG)
2216 rc = cam_ife_csid_tpg_stop(csid_hw, res);
2217 break;
2218 case CAM_ISP_RESOURCE_PIX_PATH:
2219 if (res->res_id == CAM_IFE_PIX_PATH_RES_IPP)
2220 rc = cam_ife_csid_disable_ipp_path(csid_hw,
2221 res, csid_stop->stop_cmd);
2222 else
2223 rc = cam_ife_csid_disable_rdi_path(csid_hw,
2224 res, csid_stop->stop_cmd);
2225
2226 break;
2227 default:
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07002228 CAM_ERR(CAM_ISP, "CSID:%d Invalid res type%d",
2229 csid_hw->hw_intf->hw_idx,
Jing Zhouff57d862017-03-21 00:54:25 -07002230 res->res_type);
2231 break;
2232 }
2233 }
2234
2235 /*wait for the path to halt */
2236 for (i = 0; i < csid_stop->num_res; i++) {
2237 res = csid_stop->node_res[i];
2238 if (res->res_type == CAM_ISP_RESOURCE_PIX_PATH &&
2239 csid_stop->stop_cmd == CAM_CSID_HALT_AT_FRAME_BOUNDARY)
2240 rc = cam_ife_csid_res_wait_for_halt(csid_hw, res);
Ravikishore Pampanaad6bc902017-07-12 19:37:06 +05302241 else
2242 res->res_state = CAM_ISP_RESOURCE_STATE_INIT_HW;
Jing Zhouff57d862017-03-21 00:54:25 -07002243 }
2244
Jing Zhouff57d862017-03-21 00:54:25 -07002245 return rc;
2246
2247}
2248
2249static int cam_ife_csid_read(void *hw_priv,
2250 void *read_args, uint32_t arg_size)
2251{
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07002252 CAM_ERR(CAM_ISP, "CSID: un supported");
Jing Zhouff57d862017-03-21 00:54:25 -07002253
2254 return -EINVAL;
2255}
2256
2257static int cam_ife_csid_write(void *hw_priv,
2258 void *write_args, uint32_t arg_size)
2259{
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07002260 CAM_ERR(CAM_ISP, "CSID: un supported");
Jing Zhouff57d862017-03-21 00:54:25 -07002261 return -EINVAL;
2262}
2263
2264static int cam_ife_csid_process_cmd(void *hw_priv,
2265 uint32_t cmd_type, void *cmd_args, uint32_t arg_size)
2266{
2267 int rc = 0;
2268 struct cam_ife_csid_hw *csid_hw;
2269 struct cam_hw_info *csid_hw_info;
2270
2271 if (!hw_priv || !cmd_args) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07002272 CAM_ERR(CAM_ISP, "CSID: Invalid arguments");
Jing Zhouff57d862017-03-21 00:54:25 -07002273 return -EINVAL;
2274 }
2275
2276 csid_hw_info = (struct cam_hw_info *)hw_priv;
2277 csid_hw = (struct cam_ife_csid_hw *)csid_hw_info->core_info;
2278
Jing Zhouff57d862017-03-21 00:54:25 -07002279 switch (cmd_type) {
2280 case CAM_IFE_CSID_CMD_GET_TIME_STAMP:
2281 rc = cam_ife_csid_get_time_stamp(csid_hw, cmd_args);
2282 break;
2283 default:
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07002284 CAM_ERR(CAM_ISP, "CSID:%d un supported cmd:%d",
2285 csid_hw->hw_intf->hw_idx, cmd_type);
Jing Zhouff57d862017-03-21 00:54:25 -07002286 rc = -EINVAL;
2287 break;
2288 }
Jing Zhouff57d862017-03-21 00:54:25 -07002289
2290 return rc;
2291
2292}
2293
2294irqreturn_t cam_ife_csid_irq(int irq_num, void *data)
2295{
2296 struct cam_ife_csid_hw *csid_hw;
2297 struct cam_hw_soc_info *soc_info;
2298 struct cam_ife_csid_reg_offset *csid_reg;
2299 uint32_t i, irq_status_top, irq_status_rx, irq_status_ipp = 0,
2300 irq_status_rdi[4];
2301
2302 csid_hw = (struct cam_ife_csid_hw *)data;
2303
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07002304 CAM_DBG(CAM_ISP, "CSID %d IRQ Handling", csid_hw->hw_intf->hw_idx);
Jing Zhouff57d862017-03-21 00:54:25 -07002305
2306 if (!data) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07002307 CAM_ERR(CAM_ISP, "CSID: Invalid arguments");
Jing Zhouff57d862017-03-21 00:54:25 -07002308 return IRQ_HANDLED;
2309 }
2310
2311 csid_reg = csid_hw->csid_info->csid_reg;
2312 soc_info = &csid_hw->hw_info->soc_info;
2313
2314 /* read */
2315 irq_status_top = cam_io_r_mb(soc_info->reg_map[0].mem_base +
2316 csid_reg->cmn_reg->csid_top_irq_status_addr);
2317
2318 irq_status_rx = cam_io_r_mb(soc_info->reg_map[0].mem_base +
2319 csid_reg->csi2_reg->csid_csi2_rx_irq_status_addr);
2320
2321 if (csid_reg->cmn_reg->no_pix)
2322 irq_status_ipp = cam_io_r_mb(soc_info->reg_map[0].mem_base +
2323 csid_reg->ipp_reg->csid_ipp_irq_status_addr);
2324
2325
2326 for (i = 0; i < csid_reg->cmn_reg->no_rdis; i++)
2327 irq_status_rdi[i] = cam_io_r_mb(soc_info->reg_map[0].mem_base +
2328 csid_reg->rdi_reg[i]->csid_rdi_irq_status_addr);
2329
2330 /* clear */
2331 cam_io_w_mb(irq_status_top, soc_info->reg_map[0].mem_base +
2332 csid_reg->cmn_reg->csid_top_irq_clear_addr);
2333 cam_io_w_mb(irq_status_rx, soc_info->reg_map[0].mem_base +
2334 csid_reg->csi2_reg->csid_csi2_rx_irq_clear_addr);
2335 if (csid_reg->cmn_reg->no_pix)
2336 cam_io_w_mb(irq_status_ipp, soc_info->reg_map[0].mem_base +
2337 csid_reg->ipp_reg->csid_ipp_irq_clear_addr);
2338
2339 for (i = 0; i < csid_reg->cmn_reg->no_rdis; i++) {
2340 cam_io_w_mb(irq_status_rdi[i], soc_info->reg_map[0].mem_base +
2341 csid_reg->rdi_reg[i]->csid_rdi_irq_clear_addr);
2342 }
2343 cam_io_w_mb(1, soc_info->reg_map[0].mem_base +
2344 csid_reg->cmn_reg->csid_irq_cmd_addr);
2345
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07002346 CAM_DBG(CAM_ISP, "irq_status_rx = 0x%x", irq_status_rx);
2347 CAM_DBG(CAM_ISP, "irq_status_ipp = 0x%x", irq_status_ipp);
Jing Zhouff57d862017-03-21 00:54:25 -07002348
2349 if (irq_status_top) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07002350 CAM_DBG(CAM_ISP, "CSID global reset complete......Exit");
Jing Zhouff57d862017-03-21 00:54:25 -07002351 complete(&csid_hw->csid_top_complete);
2352 return IRQ_HANDLED;
2353 }
2354
2355
2356 if (irq_status_rx & BIT(csid_reg->csi2_reg->csi2_rst_done_shift_val)) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07002357 CAM_DBG(CAM_ISP, "csi rx reset complete");
Jing Zhouff57d862017-03-21 00:54:25 -07002358 complete(&csid_hw->csid_csi2_complete);
2359 }
2360
2361 if (irq_status_rx & CSID_CSI2_RX_ERROR_LANE0_FIFO_OVERFLOW) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07002362 pr_err_ratelimited("CSID:%d lane 0 over flow",
2363 csid_hw->hw_intf->hw_idx);
Jing Zhouff57d862017-03-21 00:54:25 -07002364 }
2365 if (irq_status_rx & CSID_CSI2_RX_ERROR_LANE1_FIFO_OVERFLOW) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07002366 pr_err_ratelimited("CSID:%d lane 1 over flow",
2367 csid_hw->hw_intf->hw_idx);
Jing Zhouff57d862017-03-21 00:54:25 -07002368 }
2369 if (irq_status_rx & CSID_CSI2_RX_ERROR_LANE2_FIFO_OVERFLOW) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07002370 pr_err_ratelimited("CSID:%d lane 2 over flow",
2371 csid_hw->hw_intf->hw_idx);
Jing Zhouff57d862017-03-21 00:54:25 -07002372 }
2373 if (irq_status_rx & CSID_CSI2_RX_ERROR_LANE3_FIFO_OVERFLOW) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07002374 pr_err_ratelimited("CSID:%d lane 3 over flow",
2375 csid_hw->hw_intf->hw_idx);
Jing Zhouff57d862017-03-21 00:54:25 -07002376 }
2377 if (irq_status_rx & CSID_CSI2_RX_ERROR_TG_FIFO_OVERFLOW) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07002378 pr_err_ratelimited("CSID:%d TG OVER FLOW",
2379 csid_hw->hw_intf->hw_idx);
Jing Zhouff57d862017-03-21 00:54:25 -07002380 }
2381 if (irq_status_rx & CSID_CSI2_RX_ERROR_CPHY_EOT_RECEPTION) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07002382 pr_err_ratelimited("CSID:%d CPHY_EOT_RECEPTION",
2383 csid_hw->hw_intf->hw_idx);
Jing Zhouff57d862017-03-21 00:54:25 -07002384 }
2385 if (irq_status_rx & CSID_CSI2_RX_ERROR_CPHY_SOT_RECEPTION) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07002386 pr_err_ratelimited("CSID:%d CPHY_SOT_RECEPTION",
2387 csid_hw->hw_intf->hw_idx);
Jing Zhouff57d862017-03-21 00:54:25 -07002388 }
2389 if (irq_status_rx & CSID_CSI2_RX_ERROR_CPHY_PH_CRC) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07002390 pr_err_ratelimited("CSID:%d CPHY_PH_CRC",
2391 csid_hw->hw_intf->hw_idx);
Jing Zhouff57d862017-03-21 00:54:25 -07002392 }
2393
2394 /*read the IPP errors */
2395 if (csid_reg->cmn_reg->no_pix) {
2396 /* IPP reset done bit */
2397 if (irq_status_ipp &
2398 BIT(csid_reg->cmn_reg->path_rst_done_shift_val)) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07002399 CAM_DBG(CAM_ISP, "CSID IPP reset complete");
Jing Zhouff57d862017-03-21 00:54:25 -07002400 complete(&csid_hw->csid_ipp_complete);
2401 }
2402 if (irq_status_ipp & CSID_PATH_INFO_INPUT_SOF)
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07002403 CAM_DBG(CAM_ISP, "CSID IPP SOF received");
Jing Zhouff57d862017-03-21 00:54:25 -07002404 if (irq_status_ipp & CSID_PATH_INFO_INPUT_SOL)
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07002405 CAM_DBG(CAM_ISP, "CSID IPP SOL received");
Jing Zhouff57d862017-03-21 00:54:25 -07002406 if (irq_status_ipp & CSID_PATH_INFO_INPUT_EOL)
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07002407 CAM_DBG(CAM_ISP, "CSID IPP EOL received");
Jing Zhouff57d862017-03-21 00:54:25 -07002408 if (irq_status_ipp & CSID_PATH_INFO_INPUT_EOF)
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07002409 CAM_DBG(CAM_ISP, "CSID IPP EOF received");
Jing Zhouff57d862017-03-21 00:54:25 -07002410
2411 if (irq_status_ipp & CSID_PATH_INFO_INPUT_EOF)
2412 complete(&csid_hw->csid_ipp_complete);
2413
2414 if (irq_status_ipp & CSID_PATH_ERROR_FIFO_OVERFLOW) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07002415 CAM_ERR(CAM_ISP, "CSID:%d IPP fifo over flow",
Jing Zhouff57d862017-03-21 00:54:25 -07002416 csid_hw->hw_intf->hw_idx);
2417 /*Stop IPP path immediately */
2418 cam_io_w_mb(CAM_CSID_HALT_IMMEDIATELY,
2419 soc_info->reg_map[0].mem_base +
2420 csid_reg->ipp_reg->csid_ipp_ctrl_addr);
2421 }
2422 }
2423
2424 for (i = 0; i < csid_reg->cmn_reg->no_rdis; i++) {
2425 if (irq_status_rdi[i] &
2426 BIT(csid_reg->cmn_reg->path_rst_done_shift_val)) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07002427 CAM_DBG(CAM_ISP, "CSID rdi%d reset complete", i);
Jing Zhouff57d862017-03-21 00:54:25 -07002428 complete(&csid_hw->csid_rdin_complete[i]);
2429 }
2430
Ravikishore Pampanaad6bc902017-07-12 19:37:06 +05302431 if (irq_status_rdi[i] & CSID_PATH_INFO_INPUT_SOF)
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07002432 CAM_DBG(CAM_ISP, "CSID RDI SOF received");
Ravikishore Pampanaad6bc902017-07-12 19:37:06 +05302433 if (irq_status_rdi[i] & CSID_PATH_INFO_INPUT_EOF)
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07002434 CAM_DBG(CAM_ISP, "CSID RDI EOF received");
Ravikishore Pampanaad6bc902017-07-12 19:37:06 +05302435
Jing Zhouff57d862017-03-21 00:54:25 -07002436 if (irq_status_rdi[i] & CSID_PATH_INFO_INPUT_EOF)
2437 complete(&csid_hw->csid_rdin_complete[i]);
2438
2439 if (irq_status_rdi[i] & CSID_PATH_ERROR_FIFO_OVERFLOW) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07002440 CAM_ERR(CAM_ISP, "CSID:%d RDI fifo over flow",
Jing Zhouff57d862017-03-21 00:54:25 -07002441 csid_hw->hw_intf->hw_idx);
2442 /*Stop RDI path immediately */
2443 cam_io_w_mb(CAM_CSID_HALT_IMMEDIATELY,
2444 soc_info->reg_map[0].mem_base +
2445 csid_reg->rdi_reg[i]->csid_rdi_ctrl_addr);
2446 }
2447 }
2448
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07002449 CAM_DBG(CAM_ISP, "IRQ Handling exit");
Jing Zhouff57d862017-03-21 00:54:25 -07002450 return IRQ_HANDLED;
2451}
2452
2453int cam_ife_csid_hw_probe_init(struct cam_hw_intf *csid_hw_intf,
2454 uint32_t csid_idx)
2455{
2456 int rc = -EINVAL;
2457 uint32_t i;
2458 struct cam_ife_csid_path_cfg *path_data;
2459 struct cam_ife_csid_cid_data *cid_data;
2460 struct cam_hw_info *csid_hw_info;
2461 struct cam_ife_csid_hw *ife_csid_hw = NULL;
2462
2463 if (csid_idx >= CAM_IFE_CSID_HW_RES_MAX) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07002464 CAM_ERR(CAM_ISP, "Invalid csid index:%d", csid_idx);
Jing Zhouff57d862017-03-21 00:54:25 -07002465 return rc;
2466 }
2467
2468 csid_hw_info = (struct cam_hw_info *) csid_hw_intf->hw_priv;
2469 ife_csid_hw = (struct cam_ife_csid_hw *) csid_hw_info->core_info;
2470
2471 ife_csid_hw->hw_intf = csid_hw_intf;
2472 ife_csid_hw->hw_info = csid_hw_info;
2473
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07002474 CAM_DBG(CAM_ISP, "type %d index %d",
Jing Zhouff57d862017-03-21 00:54:25 -07002475 ife_csid_hw->hw_intf->hw_type, csid_idx);
2476
2477
2478 ife_csid_hw->hw_info->hw_state = CAM_HW_STATE_POWER_DOWN;
2479 mutex_init(&ife_csid_hw->hw_info->hw_mutex);
2480 spin_lock_init(&ife_csid_hw->hw_info->hw_lock);
2481 init_completion(&ife_csid_hw->hw_info->hw_complete);
2482
2483 init_completion(&ife_csid_hw->csid_top_complete);
2484 init_completion(&ife_csid_hw->csid_csi2_complete);
2485 init_completion(&ife_csid_hw->csid_ipp_complete);
2486 for (i = 0; i < CAM_IFE_CSID_RDI_MAX; i++)
2487 init_completion(&ife_csid_hw->csid_rdin_complete[i]);
2488
2489
2490 rc = cam_ife_csid_init_soc_resources(&ife_csid_hw->hw_info->soc_info,
2491 cam_ife_csid_irq, ife_csid_hw);
2492 if (rc < 0) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07002493 CAM_ERR(CAM_ISP, "CSID:%d Failed to init_soc", csid_idx);
Jing Zhouff57d862017-03-21 00:54:25 -07002494 goto err;
2495 }
2496
2497 ife_csid_hw->hw_intf->hw_ops.get_hw_caps = cam_ife_csid_get_hw_caps;
2498 ife_csid_hw->hw_intf->hw_ops.init = cam_ife_csid_init_hw;
2499 ife_csid_hw->hw_intf->hw_ops.deinit = cam_ife_csid_deinit_hw;
2500 ife_csid_hw->hw_intf->hw_ops.reset = cam_ife_csid_reset;
2501 ife_csid_hw->hw_intf->hw_ops.reserve = cam_ife_csid_reserve;
2502 ife_csid_hw->hw_intf->hw_ops.release = cam_ife_csid_release;
2503 ife_csid_hw->hw_intf->hw_ops.start = cam_ife_csid_start;
2504 ife_csid_hw->hw_intf->hw_ops.stop = cam_ife_csid_stop;
2505 ife_csid_hw->hw_intf->hw_ops.read = cam_ife_csid_read;
2506 ife_csid_hw->hw_intf->hw_ops.write = cam_ife_csid_write;
2507 ife_csid_hw->hw_intf->hw_ops.process_cmd = cam_ife_csid_process_cmd;
2508
2509 /*Initialize the CID resoure */
2510 for (i = 0; i < CAM_IFE_CSID_CID_RES_MAX; i++) {
2511 ife_csid_hw->cid_res[i].res_type = CAM_ISP_RESOURCE_CID;
2512 ife_csid_hw->cid_res[i].res_id = i;
2513 ife_csid_hw->cid_res[i].res_state =
2514 CAM_ISP_RESOURCE_STATE_AVAILABLE;
2515 ife_csid_hw->cid_res[i].hw_intf = ife_csid_hw->hw_intf;
2516
2517 cid_data = kzalloc(sizeof(struct cam_ife_csid_cid_data),
2518 GFP_KERNEL);
2519 if (!cid_data) {
2520 rc = -ENOMEM;
2521 goto err;
2522 }
2523 ife_csid_hw->cid_res[i].res_priv = cid_data;
2524 }
2525
2526 /* Initialize the IPP resources */
2527 if (ife_csid_hw->csid_info->csid_reg->cmn_reg->no_pix) {
2528 ife_csid_hw->ipp_res.res_type = CAM_ISP_RESOURCE_PIX_PATH;
2529 ife_csid_hw->ipp_res.res_id = CAM_IFE_PIX_PATH_RES_IPP;
2530 ife_csid_hw->ipp_res.res_state =
2531 CAM_ISP_RESOURCE_STATE_AVAILABLE;
2532 ife_csid_hw->ipp_res.hw_intf = ife_csid_hw->hw_intf;
2533 path_data = kzalloc(sizeof(struct cam_ife_csid_path_cfg),
2534 GFP_KERNEL);
2535 if (!path_data) {
2536 rc = -ENOMEM;
2537 goto err;
2538 }
2539 ife_csid_hw->ipp_res.res_priv = path_data;
2540 }
2541
2542 /* Initialize the RDI resource */
2543 for (i = 0; i < ife_csid_hw->csid_info->csid_reg->cmn_reg->no_rdis;
2544 i++) {
2545 /* res type is from RDI 0 to RDI3 */
2546 ife_csid_hw->rdi_res[i].res_type =
2547 CAM_ISP_RESOURCE_PIX_PATH;
2548 ife_csid_hw->rdi_res[i].res_id = i;
2549 ife_csid_hw->rdi_res[i].res_state =
2550 CAM_ISP_RESOURCE_STATE_AVAILABLE;
2551 ife_csid_hw->rdi_res[i].hw_intf = ife_csid_hw->hw_intf;
2552
2553 path_data = kzalloc(sizeof(struct cam_ife_csid_path_cfg),
2554 GFP_KERNEL);
2555 if (!path_data) {
2556 rc = -ENOMEM;
2557 goto err;
2558 }
2559 ife_csid_hw->rdi_res[i].res_priv = path_data;
2560 }
2561
2562 return 0;
2563err:
2564 if (rc) {
2565 kfree(ife_csid_hw->ipp_res.res_priv);
2566 for (i = 0; i <
2567 ife_csid_hw->csid_info->csid_reg->cmn_reg->no_rdis; i++)
2568 kfree(ife_csid_hw->rdi_res[i].res_priv);
2569
2570 for (i = 0; i < CAM_IFE_CSID_CID_RES_MAX; i++)
2571 kfree(ife_csid_hw->cid_res[i].res_priv);
2572
2573 }
2574
2575 return rc;
2576}
2577
2578
2579int cam_ife_csid_hw_deinit(struct cam_ife_csid_hw *ife_csid_hw)
2580{
2581 int rc = -EINVAL;
2582 uint32_t i;
2583
2584 if (!ife_csid_hw) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07002585 CAM_ERR(CAM_ISP, "Invalid param");
Jing Zhouff57d862017-03-21 00:54:25 -07002586 return rc;
2587 }
2588
2589 /* release the privdate data memory from resources */
2590 kfree(ife_csid_hw->ipp_res.res_priv);
2591 for (i = 0; i <
2592 ife_csid_hw->csid_info->csid_reg->cmn_reg->no_rdis;
2593 i++) {
2594 kfree(ife_csid_hw->rdi_res[i].res_priv);
2595 }
2596 for (i = 0; i < CAM_IFE_CSID_CID_RES_MAX; i++)
2597 kfree(ife_csid_hw->cid_res[i].res_priv);
2598
Ravikishore Pampanaad6bc902017-07-12 19:37:06 +05302599 cam_ife_csid_deinit_soc_resources(&ife_csid_hw->hw_info->soc_info);
Jing Zhouff57d862017-03-21 00:54:25 -07002600
2601 return 0;
2602}