blob: 14d32ad57292841d9fa899723c78ba26b9ea6194 [file] [log] [blame]
Jing Zhoud352ed12017-03-20 23:59:56 -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/debugfs.h>
14#include <linux/videodev2.h>
15#include <linux/slab.h>
16#include <linux/uaccess.h>
Jing Zhoub524a852017-05-16 15:47:30 +053017#include <linux/ratelimit.h>
Jing Zhoud352ed12017-03-20 23:59:56 -070018
19#include "cam_isp_context.h"
20#include "cam_isp_log.h"
21#include "cam_mem_mgr.h"
22#include "cam_sync_api.h"
Jing Zhoub524a852017-05-16 15:47:30 +053023#include "cam_req_mgr_dev.h"
Gregory Bergschneider5164f3a2017-07-07 10:26:17 -060024#include "cam_trace.h"
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -070025#include "cam_debug_util.h"
Jing Zhoud352ed12017-03-20 23:59:56 -070026
Jing Zhou77962c52017-09-18 19:13:34 -070027static int __cam_isp_ctx_enqueue_request_in_order(
28 struct cam_context *ctx, struct cam_ctx_request *req)
29{
30 struct cam_ctx_request *req_current;
31 struct cam_ctx_request *req_prev;
32 struct list_head temp_list;
33
34 INIT_LIST_HEAD(&temp_list);
35 spin_lock_bh(&ctx->lock);
36 if (list_empty(&ctx->pending_req_list)) {
37 list_add_tail(&req->list, &ctx->pending_req_list);
38 } else {
39 list_for_each_entry_safe_reverse(
40 req_current, req_prev, &ctx->pending_req_list, list) {
41 if (req->request_id < req_current->request_id) {
42 list_del_init(&req_current->list);
43 list_add(&req_current->list, &temp_list);
44 continue;
45 } else if (req->request_id == req_current->request_id) {
46 CAM_WARN(CAM_ISP,
47 "Received duplicated request %lld",
48 req->request_id);
49 }
50 break;
51 }
52 list_add_tail(&req->list, &ctx->pending_req_list);
53
54 if (!list_empty(&temp_list)) {
55 list_for_each_entry_safe(
56 req_current, req_prev, &temp_list, list) {
57 list_del_init(&req_current->list);
58 list_add_tail(&req_current->list,
59 &ctx->pending_req_list);
60 }
61 }
62 }
63 spin_unlock_bh(&ctx->lock);
64 return 0;
65}
66
Karthik Anantha Ramba3bd972017-09-25 15:35:26 -070067static const char *__cam_isp_resource_handle_id_to_type
68 (uint32_t resource_handle)
69{
70 switch (resource_handle) {
71 case CAM_ISP_IFE_OUT_RES_FULL:
72 return "CAM_ISP_IFE_OUT_RES_FULL";
73 case CAM_ISP_IFE_OUT_RES_DS4:
74 return "CAM_ISP_IFE_OUT_RES_DS4";
75 case CAM_ISP_IFE_OUT_RES_DS16:
76 return "CAM_ISP_IFE_OUT_RES_DS16";
77 case CAM_ISP_IFE_OUT_RES_RAW_DUMP:
78 return "CAM_ISP_IFE_OUT_RES_RAW_DUMP";
79 case CAM_ISP_IFE_OUT_RES_FD:
80 return "CAM_ISP_IFE_OUT_RES_FD";
81 case CAM_ISP_IFE_OUT_RES_PDAF:
82 return "CAM_ISP_IFE_OUT_RES_PDAF";
83 case CAM_ISP_IFE_OUT_RES_RDI_0:
84 return "CAM_ISP_IFE_OUT_RES_RDI_0";
85 case CAM_ISP_IFE_OUT_RES_RDI_1:
86 return "CAM_ISP_IFE_OUT_RES_RDI_1";
87 case CAM_ISP_IFE_OUT_RES_RDI_2:
88 return "CAM_ISP_IFE_OUT_RES_RDI_2";
89 case CAM_ISP_IFE_OUT_RES_RDI_3:
90 return "CAM_ISP_IFE_OUT_RES_RDI_3";
91 case CAM_ISP_IFE_OUT_RES_STATS_HDR_BE:
92 return "CAM_ISP_IFE_OUT_RES_STATS_HDR_BE";
93 case CAM_ISP_IFE_OUT_RES_STATS_HDR_BHIST:
94 return "CAM_ISP_IFE_OUT_RES_STATS_HDR_BHIST";
95 case CAM_ISP_IFE_OUT_RES_STATS_TL_BG:
96 return "CAM_ISP_IFE_OUT_RES_STATS_TL_BG";
97 case CAM_ISP_IFE_OUT_RES_STATS_BF:
98 return "CAM_ISP_IFE_OUT_RES_STATS_BF";
99 case CAM_ISP_IFE_OUT_RES_STATS_AWB_BG:
100 return "CAM_ISP_IFE_OUT_RES_STATS_AWB_BG";
101 case CAM_ISP_IFE_OUT_RES_STATS_BHIST:
102 return "CAM_ISP_IFE_OUT_RES_STATS_BHIST";
103 case CAM_ISP_IFE_OUT_RES_STATS_RS:
104 return "CAM_ISP_IFE_OUT_RES_STATS_RS";
105 case CAM_ISP_IFE_OUT_RES_STATS_CS:
106 return "CAM_ISP_IFE_OUT_RES_STATS_CS";
107 default:
108 return "CAM_ISP_Invalid_Resource_Type";
109 }
110}
111
Gregory Bergschneider5164f3a2017-07-07 10:26:17 -0600112static uint64_t __cam_isp_ctx_get_event_ts(uint32_t evt_id, void *evt_data)
113{
114 uint64_t ts = 0;
115
116 if (!evt_data)
117 return 0;
118
119 switch (evt_id) {
120 case CAM_ISP_HW_EVENT_ERROR:
121 ts = ((struct cam_isp_hw_error_event_data *)evt_data)->
122 timestamp;
123 break;
124 case CAM_ISP_HW_EVENT_SOF:
125 ts = ((struct cam_isp_hw_sof_event_data *)evt_data)->
126 timestamp;
127 break;
128 case CAM_ISP_HW_EVENT_REG_UPDATE:
129 ts = ((struct cam_isp_hw_reg_update_event_data *)evt_data)->
130 timestamp;
131 break;
132 case CAM_ISP_HW_EVENT_EPOCH:
133 ts = ((struct cam_isp_hw_epoch_event_data *)evt_data)->
134 timestamp;
135 break;
136 case CAM_ISP_HW_EVENT_EOF:
137 ts = ((struct cam_isp_hw_eof_event_data *)evt_data)->
138 timestamp;
139 break;
140 case CAM_ISP_HW_EVENT_DONE:
141 break;
142 default:
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -0700143 CAM_DBG(CAM_ISP, "Invalid Event Type %d", evt_id);
Gregory Bergschneider5164f3a2017-07-07 10:26:17 -0600144 }
145
146 return ts;
147}
148
Karthik Anantha Ramba3bd972017-09-25 15:35:26 -0700149static void __cam_isp_ctx_handle_buf_done_fail_log(
150 struct cam_isp_ctx_req *req_isp)
151{
152 int i;
153
Harsh Shah1b8eb232017-10-09 19:20:52 -0700154 if (req_isp->num_fence_map_out >= CAM_ISP_CTX_RES_MAX) {
155 CAM_ERR_RATE_LIMIT(CAM_ISP,
156 "Num Resources exceed mMAX %d >= %d ",
157 req_isp->num_fence_map_out, CAM_ISP_CTX_RES_MAX);
158 return;
159 }
160
Karthik Anantha Ramba3bd972017-09-25 15:35:26 -0700161 CAM_ERR_RATE_LIMIT(CAM_ISP,
162 "Resource Handles that fail to generate buf_done in prev frame");
163 for (i = 0; i < req_isp->num_fence_map_out; i++) {
164 if (req_isp->fence_map_out[i].sync_id != -1)
165 CAM_ERR_RATE_LIMIT(CAM_ISP,
166 "Resource_Handle: [%s] Sync_ID: [0x%x]",
167 __cam_isp_resource_handle_id_to_type(
168 req_isp->fence_map_out[i].resource_handle),
169 req_isp->fence_map_out[i].sync_id);
170 }
171}
172
Jing Zhoud352ed12017-03-20 23:59:56 -0700173static int __cam_isp_ctx_handle_buf_done_in_activated_state(
174 struct cam_isp_context *ctx_isp,
175 struct cam_isp_hw_done_event_data *done,
176 uint32_t bubble_state)
177{
178 int rc = 0;
179 int i, j;
180 struct cam_ctx_request *req;
181 struct cam_isp_ctx_req *req_isp;
182 struct cam_context *ctx = ctx_isp->base;
183
184 if (list_empty(&ctx->active_req_list)) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -0700185 CAM_DBG(CAM_ISP, "Buf done with no active request!");
Jing Zhoud352ed12017-03-20 23:59:56 -0700186 goto end;
187 }
188
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -0700189 CAM_DBG(CAM_ISP, "Enter with bubble_state %d", bubble_state);
Jing Zhoud352ed12017-03-20 23:59:56 -0700190
191 req = list_first_entry(&ctx->active_req_list,
192 struct cam_ctx_request, list);
Gregory Bergschneider5164f3a2017-07-07 10:26:17 -0600193
194 trace_cam_buf_done("ISP", ctx, req);
195
Jing Zhoud352ed12017-03-20 23:59:56 -0700196 req_isp = (struct cam_isp_ctx_req *) req->req_priv;
197 for (i = 0; i < done->num_handles; i++) {
198 for (j = 0; j < req_isp->num_fence_map_out; j++) {
199 if (done->resource_handle[i] ==
200 req_isp->fence_map_out[j].resource_handle)
201 break;
202 }
203
204 if (j == req_isp->num_fence_map_out) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -0700205 CAM_ERR(CAM_ISP,
206 "Can not find matching lane handle 0x%x!",
Jing Zhoud352ed12017-03-20 23:59:56 -0700207 done->resource_handle[i]);
208 rc = -EINVAL;
209 continue;
210 }
211
Harsh Shah1b8eb232017-10-09 19:20:52 -0700212 if (req_isp->fence_map_out[j].sync_id == -1) {
213 __cam_isp_ctx_handle_buf_done_fail_log(req_isp);
214 continue;
215 }
Jing Zhoubb536a82017-05-18 15:20:38 -0700216
Harsh Shah1b8eb232017-10-09 19:20:52 -0700217 if (!bubble_state) {
218 CAM_DBG(CAM_ISP,
219 "Sync with success: req %lld res 0x%x fd 0x%x",
220 req->request_id,
221 req_isp->fence_map_out[j].resource_handle,
222 req_isp->fence_map_out[j].sync_id);
223
224 rc = cam_sync_signal(req_isp->fence_map_out[j].sync_id,
225 CAM_SYNC_STATE_SIGNALED_SUCCESS);
226 if (rc)
227 CAM_DBG(CAM_ISP, "Sync failed with rc = %d",
228 rc);
Jing Zhoud352ed12017-03-20 23:59:56 -0700229 } else if (!req_isp->bubble_report) {
Harsh Shah1b8eb232017-10-09 19:20:52 -0700230 CAM_DBG(CAM_ISP,
231 "Sync with failure: req %lld res 0x%x fd 0x%x",
232 req->request_id,
233 req_isp->fence_map_out[j].resource_handle,
234 req_isp->fence_map_out[j].sync_id);
235
Jing Zhoubb536a82017-05-18 15:20:38 -0700236 rc = cam_sync_signal(req_isp->fence_map_out[j].sync_id,
Jing Zhoud352ed12017-03-20 23:59:56 -0700237 CAM_SYNC_STATE_SIGNALED_ERROR);
Jing Zhoubb536a82017-05-18 15:20:38 -0700238 if (rc)
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -0700239 CAM_ERR(CAM_ISP, "Sync failed with rc = %d",
Harsh Shah1b8eb232017-10-09 19:20:52 -0700240 rc);
Jing Zhoud352ed12017-03-20 23:59:56 -0700241 } else {
242 /*
243 * Ignore the buffer done if bubble detect is on
244 * In most case, active list should be empty when
245 * bubble detects. But for safety, we just move the
246 * current active request to the pending list here.
247 */
Harsh Shah1b8eb232017-10-09 19:20:52 -0700248 CAM_DBG(CAM_ISP,
249 "buf done with bubble state %d recovery %d",
250 bubble_state, req_isp->bubble_report);
Jing Zhoud352ed12017-03-20 23:59:56 -0700251 list_del_init(&req->list);
252 list_add(&req->list, &ctx->pending_req_list);
253 continue;
254 }
255
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -0700256 CAM_DBG(CAM_ISP, "req %lld, reset sync id 0x%x",
Harsh Shah1b8eb232017-10-09 19:20:52 -0700257 req->request_id,
258 req_isp->fence_map_out[j].sync_id);
259 if (!rc) {
260 req_isp->num_acked++;
261 req_isp->fence_map_out[j].sync_id = -1;
262 }
Jing Zhoud352ed12017-03-20 23:59:56 -0700263 }
264
Harsh Shah1b8eb232017-10-09 19:20:52 -0700265 if (req_isp->num_acked > req_isp->num_fence_map_out) {
266 /* Should not happen */
267 CAM_ERR(CAM_ISP,
268 "WARNING: req_id %lld num_acked %d > map_out %d",
269 req->request_id, req_isp->num_acked,
270 req_isp->num_fence_map_out);
271 WARN_ON(req_isp->num_acked > req_isp->num_fence_map_out);
272 }
Jing Zhoud352ed12017-03-20 23:59:56 -0700273 if (req_isp->num_acked == req_isp->num_fence_map_out) {
274 list_del_init(&req->list);
275 list_add_tail(&req->list, &ctx->free_req_list);
Jing Zhoudedc4762017-06-19 17:45:36 +0530276 ctx_isp->active_req_cnt--;
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -0700277 CAM_DBG(CAM_ISP,
278 "Move active request %lld to free list(cnt = %d)",
279 req->request_id, ctx_isp->active_req_cnt);
Jing Zhoud352ed12017-03-20 23:59:56 -0700280 }
281
282end:
283 return rc;
284}
285
Jing Zhoudedc4762017-06-19 17:45:36 +0530286static void __cam_isp_ctx_send_sof_timestamp(
287 struct cam_isp_context *ctx_isp, uint64_t request_id,
288 uint32_t sof_event_status)
289{
290 struct cam_req_mgr_message req_msg;
291
292 req_msg.session_hdl = ctx_isp->base->session_hdl;
293 req_msg.u.frame_msg.frame_id = ctx_isp->frame_id;
294 req_msg.u.frame_msg.request_id = request_id;
295 req_msg.u.frame_msg.timestamp = ctx_isp->sof_timestamp_val;
296 req_msg.u.frame_msg.link_hdl = ctx_isp->base->link_hdl;
297 req_msg.u.frame_msg.sof_status = sof_event_status;
298
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -0700299 CAM_DBG(CAM_ISP,
300 "request id:%lld frame number:%lld SOF time stamp:0x%llx",
301 request_id, ctx_isp->frame_id,
Jing Zhoudedc4762017-06-19 17:45:36 +0530302 ctx_isp->sof_timestamp_val);
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -0700303 CAM_DBG(CAM_ISP, " sof status:%d", sof_event_status);
Jing Zhoudedc4762017-06-19 17:45:36 +0530304
305 if (cam_req_mgr_notify_frame_message(&req_msg,
306 V4L_EVENT_CAM_REQ_MGR_SOF, V4L_EVENT_CAM_REQ_MGR_EVENT))
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -0700307 CAM_ERR(CAM_ISP,
308 "Error in notifying the sof time for req id:%lld",
309 request_id);
Jing Zhoudedc4762017-06-19 17:45:36 +0530310}
311
Jing Zhoud352ed12017-03-20 23:59:56 -0700312static int __cam_isp_ctx_reg_upd_in_activated_state(
313 struct cam_isp_context *ctx_isp, void *evt_data)
314{
315 int rc = 0;
316 struct cam_ctx_request *req;
317 struct cam_context *ctx = ctx_isp->base;
318 struct cam_isp_ctx_req *req_isp;
319
320 if (list_empty(&ctx->pending_req_list)) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -0700321 CAM_ERR(CAM_ISP, "Reg upd ack with no pending request");
Jing Zhoud352ed12017-03-20 23:59:56 -0700322 goto end;
323 }
324 req = list_first_entry(&ctx->pending_req_list,
325 struct cam_ctx_request, list);
326 list_del_init(&req->list);
327
328 req_isp = (struct cam_isp_ctx_req *) req->req_priv;
329 if (req_isp->num_fence_map_out != 0) {
Jing Zhoud352ed12017-03-20 23:59:56 -0700330 list_add_tail(&req->list, &ctx->active_req_list);
Jing Zhoudedc4762017-06-19 17:45:36 +0530331 ctx_isp->active_req_cnt++;
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -0700332 CAM_DBG(CAM_ISP, "move request %lld to active list(cnt = %d)",
333 req->request_id, ctx_isp->active_req_cnt);
Jing Zhoud352ed12017-03-20 23:59:56 -0700334 } else {
335 /* no io config, so the request is completed. */
336 list_add_tail(&req->list, &ctx->free_req_list);
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -0700337 CAM_DBG(CAM_ISP,
338 "move active request %lld to free list(cnt = %d)",
339 req->request_id, ctx_isp->active_req_cnt);
Jing Zhoud352ed12017-03-20 23:59:56 -0700340 }
341
342 /*
343 * This function only called directly from applied and bubble applied
344 * state so change substate here.
345 */
346 ctx_isp->substate_activated = CAM_ISP_CTX_ACTIVATED_EPOCH;
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -0700347 CAM_DBG(CAM_ISP, "next substate %d", ctx_isp->substate_activated);
Jing Zhoud352ed12017-03-20 23:59:56 -0700348
349end:
350 return rc;
351}
352
353static int __cam_isp_ctx_notify_sof_in_actived_state(
354 struct cam_isp_context *ctx_isp, void *evt_data)
355{
Junzhe Zou2df84502017-05-26 13:20:23 -0700356 int rc = 0;
357 struct cam_req_mgr_trigger_notify notify;
Jing Zhoud352ed12017-03-20 23:59:56 -0700358 struct cam_context *ctx = ctx_isp->base;
Jing Zhoudedc4762017-06-19 17:45:36 +0530359 struct cam_ctx_request *req;
360 uint64_t request_id = 0;
Jing Zhoud352ed12017-03-20 23:59:56 -0700361
Jing Zhoudedc4762017-06-19 17:45:36 +0530362 /*
363 * notify reqmgr with sof signal. Note, due to scheduling delay
364 * we can run into situation that two active requests has already
365 * be in the active queue while we try to do the notification.
366 * In this case, we need to skip the current notification. This
367 * helps the state machine to catch up the delay.
368 */
Junzhe Zou2df84502017-05-26 13:20:23 -0700369 if (ctx->ctx_crm_intf && ctx->ctx_crm_intf->notify_trigger &&
Jing Zhoudedc4762017-06-19 17:45:36 +0530370 ctx_isp->active_req_cnt <= 2) {
Junzhe Zou2df84502017-05-26 13:20:23 -0700371 if (ctx_isp->subscribe_event & CAM_TRIGGER_POINT_SOF) {
372 notify.link_hdl = ctx->link_hdl;
373 notify.dev_hdl = ctx->dev_hdl;
374 notify.frame_id = ctx_isp->frame_id;
375 notify.trigger = CAM_TRIGGER_POINT_SOF;
Jing Zhoud352ed12017-03-20 23:59:56 -0700376
Junzhe Zou2df84502017-05-26 13:20:23 -0700377 ctx->ctx_crm_intf->notify_trigger(&notify);
378 CAM_DBG(CAM_ISP, "Notify CRM SOF frame %lld",
379 ctx_isp->frame_id);
380 }
Jing Zhoudedc4762017-06-19 17:45:36 +0530381
382 list_for_each_entry(req, &ctx->active_req_list, list) {
383 if (req->request_id > ctx_isp->reported_req_id) {
384 request_id = req->request_id;
385 ctx_isp->reported_req_id = request_id;
386 break;
387 }
388 }
389
390 __cam_isp_ctx_send_sof_timestamp(ctx_isp, request_id,
391 CAM_REQ_MGR_SOF_EVENT_SUCCESS);
Jing Zhoud352ed12017-03-20 23:59:56 -0700392 } else {
Harsh Shahcb0072c2017-09-26 19:22:10 -0700393 CAM_ERR_RATE_LIMIT(CAM_ISP, "Can not notify SOF to CRM");
Junzhe Zou2df84502017-05-26 13:20:23 -0700394 rc = -EFAULT;
Jing Zhoud352ed12017-03-20 23:59:56 -0700395 }
396
Jing Zhoudedc4762017-06-19 17:45:36 +0530397 return 0;
Jing Zhoud352ed12017-03-20 23:59:56 -0700398}
399
Junzhe Zou2df84502017-05-26 13:20:23 -0700400static int __cam_isp_ctx_notify_eof_in_actived_state(
401 struct cam_isp_context *ctx_isp, void *evt_data)
402{
403 int rc = 0;
404 struct cam_req_mgr_trigger_notify notify;
405 struct cam_context *ctx = ctx_isp->base;
406
407 if (!(ctx_isp->subscribe_event & CAM_TRIGGER_POINT_EOF))
408 return rc;
409
410 /* notify reqmgr with eof signal */
411 if (ctx->ctx_crm_intf && ctx->ctx_crm_intf->notify_trigger) {
412 notify.link_hdl = ctx->link_hdl;
413 notify.dev_hdl = ctx->dev_hdl;
414 notify.frame_id = ctx_isp->frame_id;
415 notify.trigger = CAM_TRIGGER_POINT_EOF;
416
417 ctx->ctx_crm_intf->notify_trigger(&notify);
418 CAM_DBG(CAM_ISP, "Notify CRM EOF frame %lld\n",
419 ctx_isp->frame_id);
420 } else {
421 CAM_ERR(CAM_ISP, "Can not notify EOF to CRM");
422 rc = -EFAULT;
423 }
424
425 return rc;
426}
Jing Zhoud352ed12017-03-20 23:59:56 -0700427
Jing Zhoudedc4762017-06-19 17:45:36 +0530428static int __cam_isp_ctx_sof_in_activated_state(
429 struct cam_isp_context *ctx_isp, void *evt_data)
Jing Zhoud352ed12017-03-20 23:59:56 -0700430{
431 int rc = 0;
Jing Zhoudedc4762017-06-19 17:45:36 +0530432 struct cam_isp_hw_sof_event_data *sof_event_data = evt_data;
Jing Zhoud352ed12017-03-20 23:59:56 -0700433
Jing Zhoudedc4762017-06-19 17:45:36 +0530434 if (!evt_data) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -0700435 CAM_ERR(CAM_ISP, "in valid sof event data");
Jing Zhoudedc4762017-06-19 17:45:36 +0530436 return -EINVAL;
437 }
438
Jing Zhoud352ed12017-03-20 23:59:56 -0700439 ctx_isp->frame_id++;
Jing Zhoudedc4762017-06-19 17:45:36 +0530440 ctx_isp->sof_timestamp_val = sof_event_data->timestamp;
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -0700441 CAM_DBG(CAM_ISP, "frame id: %lld time stamp:0x%llx",
Jing Zhoudedc4762017-06-19 17:45:36 +0530442 ctx_isp->frame_id, ctx_isp->sof_timestamp_val);
Jing Zhoud352ed12017-03-20 23:59:56 -0700443
444 return rc;
445}
446
447static int __cam_isp_ctx_reg_upd_in_sof(struct cam_isp_context *ctx_isp,
448 void *evt_data)
449{
450 int rc = 0;
451 struct cam_ctx_request *req;
452 struct cam_isp_ctx_req *req_isp;
453 struct cam_context *ctx = ctx_isp->base;
454
455 if (ctx->state != CAM_CTX_ACTIVATED) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -0700456 CAM_DBG(CAM_ISP, "invalid RUP");
Jing Zhoud352ed12017-03-20 23:59:56 -0700457 goto end;
458 }
459
460 /*
461 * This is for the first update. The initial setting will
462 * cause the reg_upd in the first frame.
463 */
464 if (!list_empty(&ctx->pending_req_list)) {
465 req = list_first_entry(&ctx->pending_req_list,
466 struct cam_ctx_request, list);
467 list_del_init(&req->list);
468 req_isp = (struct cam_isp_ctx_req *) req->req_priv;
Jing Zhoudedc4762017-06-19 17:45:36 +0530469 if (req_isp->num_fence_map_out == req_isp->num_acked) {
Jing Zhoud352ed12017-03-20 23:59:56 -0700470 list_add_tail(&req->list, &ctx->free_req_list);
Jing Zhoudedc4762017-06-19 17:45:36 +0530471 } else {
Jing Zhoud352ed12017-03-20 23:59:56 -0700472 /* need to handle the buf done */
473 list_add_tail(&req->list, &ctx->active_req_list);
Jing Zhoudedc4762017-06-19 17:45:36 +0530474 ctx_isp->active_req_cnt++;
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -0700475 CAM_DBG(CAM_ISP,
476 "move request %lld to active list(cnt = %d)",
477 req->request_id,
Jing Zhoudedc4762017-06-19 17:45:36 +0530478 ctx_isp->active_req_cnt);
Jing Zhoud352ed12017-03-20 23:59:56 -0700479 ctx_isp->substate_activated =
480 CAM_ISP_CTX_ACTIVATED_EPOCH;
481 }
482 }
483end:
484 return rc;
485}
486
487static int __cam_isp_ctx_epoch_in_applied(struct cam_isp_context *ctx_isp,
488 void *evt_data)
489{
Jing Zhoud352ed12017-03-20 23:59:56 -0700490 struct cam_ctx_request *req;
491 struct cam_isp_ctx_req *req_isp;
492 struct cam_context *ctx = ctx_isp->base;
Jing Zhoudedc4762017-06-19 17:45:36 +0530493 uint64_t request_id = 0;
Jing Zhoud352ed12017-03-20 23:59:56 -0700494
495 if (list_empty(&ctx->pending_req_list)) {
496 /*
497 * If no pending req in epoch, this is an error case.
498 * The recovery is to go back to sof state
499 */
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -0700500 CAM_ERR(CAM_ISP, "No pending request");
Jing Zhoud352ed12017-03-20 23:59:56 -0700501 ctx_isp->substate_activated = CAM_ISP_CTX_ACTIVATED_SOF;
Jing Zhoudedc4762017-06-19 17:45:36 +0530502
503 /* Send SOF event as empty frame*/
504 __cam_isp_ctx_send_sof_timestamp(ctx_isp, request_id,
505 CAM_REQ_MGR_SOF_EVENT_SUCCESS);
506
Jing Zhoud352ed12017-03-20 23:59:56 -0700507 goto end;
508 }
509
510 req = list_first_entry(&ctx->pending_req_list, struct cam_ctx_request,
511 list);
512 req_isp = (struct cam_isp_ctx_req *)req->req_priv;
513
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -0700514 CAM_DBG(CAM_ISP, "Report Bubble flag %d", req_isp->bubble_report);
Jing Zhoud352ed12017-03-20 23:59:56 -0700515 if (req_isp->bubble_report && ctx->ctx_crm_intf &&
516 ctx->ctx_crm_intf->notify_err) {
517 struct cam_req_mgr_error_notify notify;
518
519 notify.link_hdl = ctx->link_hdl;
520 notify.dev_hdl = ctx->dev_hdl;
521 notify.req_id = req->request_id;
522 notify.error = CRM_KMD_ERR_BUBBLE;
523 ctx->ctx_crm_intf->notify_err(&notify);
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -0700524 CAM_DBG(CAM_ISP, "Notify CRM about Bubble frame %lld",
Jing Zhoud352ed12017-03-20 23:59:56 -0700525 ctx_isp->frame_id);
Jing Zhou45b55cc2017-05-16 17:27:18 -0700526 } else {
527 /*
528 * Since can not bubble report, always move the request to
529 * active list.
530 */
531 list_del_init(&req->list);
532 list_add_tail(&req->list, &ctx->active_req_list);
Jing Zhoudedc4762017-06-19 17:45:36 +0530533 ctx_isp->active_req_cnt++;
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -0700534 CAM_DBG(CAM_ISP, "move request %lld to active list(cnt = %d)",
535 req->request_id, ctx_isp->active_req_cnt);
Jing Zhou45b55cc2017-05-16 17:27:18 -0700536 req_isp->bubble_report = 0;
Jing Zhoud352ed12017-03-20 23:59:56 -0700537 }
538
Jing Zhoudedc4762017-06-19 17:45:36 +0530539 request_id = req->request_id;
540 __cam_isp_ctx_send_sof_timestamp(ctx_isp, request_id,
541 CAM_REQ_MGR_SOF_EVENT_ERROR);
542
Jing Zhoud352ed12017-03-20 23:59:56 -0700543 ctx_isp->substate_activated = CAM_ISP_CTX_ACTIVATED_BUBBLE;
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -0700544 CAM_DBG(CAM_ISP, "next substate %d",
Jing Zhoud352ed12017-03-20 23:59:56 -0700545 ctx_isp->substate_activated);
546end:
Jing Zhoudedc4762017-06-19 17:45:36 +0530547 return 0;
Jing Zhoud352ed12017-03-20 23:59:56 -0700548}
549
550
551static int __cam_isp_ctx_buf_done_in_applied(struct cam_isp_context *ctx_isp,
552 void *evt_data)
553{
554 int rc = 0;
555 struct cam_isp_hw_done_event_data *done =
556 (struct cam_isp_hw_done_event_data *) evt_data;
557
558 rc = __cam_isp_ctx_handle_buf_done_in_activated_state(ctx_isp, done, 0);
559 return rc;
560}
561
562
563static int __cam_isp_ctx_sof_in_epoch(struct cam_isp_context *ctx_isp,
564 void *evt_data)
565{
566 int rc = 0;
Jing Zhoudedc4762017-06-19 17:45:36 +0530567 struct cam_context *ctx = ctx_isp->base;
568 struct cam_isp_hw_sof_event_data *sof_event_data = evt_data;
Jing Zhou93b3ec12017-06-15 17:43:39 -0700569
Jing Zhoudedc4762017-06-19 17:45:36 +0530570 if (!evt_data) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -0700571 CAM_ERR(CAM_ISP, "in valid sof event data");
Jing Zhoudedc4762017-06-19 17:45:36 +0530572 return -EINVAL;
573 }
Jing Zhoud352ed12017-03-20 23:59:56 -0700574
575 ctx_isp->frame_id++;
Jing Zhoudedc4762017-06-19 17:45:36 +0530576 ctx_isp->sof_timestamp_val = sof_event_data->timestamp;
577
Jing Zhou93b3ec12017-06-15 17:43:39 -0700578 if (list_empty(&ctx->active_req_list))
579 ctx_isp->substate_activated = CAM_ISP_CTX_ACTIVATED_SOF;
580 else
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -0700581 CAM_DBG(CAM_ISP, "Still need to wait for the buf done");
Jing Zhoudedc4762017-06-19 17:45:36 +0530582
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -0700583 CAM_DBG(CAM_ISP, "next substate %d",
Jing Zhoud352ed12017-03-20 23:59:56 -0700584 ctx_isp->substate_activated);
585
586 return rc;
587}
588
589static int __cam_isp_ctx_buf_done_in_epoch(struct cam_isp_context *ctx_isp,
590 void *evt_data)
591{
592 int rc = 0;
593 struct cam_isp_hw_done_event_data *done =
594 (struct cam_isp_hw_done_event_data *) evt_data;
595
596 rc = __cam_isp_ctx_handle_buf_done_in_activated_state(ctx_isp, done, 0);
597 return rc;
598}
599
Jing Zhoud352ed12017-03-20 23:59:56 -0700600static int __cam_isp_ctx_buf_done_in_bubble(
601 struct cam_isp_context *ctx_isp, void *evt_data)
602{
603 int rc = 0;
604 struct cam_isp_hw_done_event_data *done =
605 (struct cam_isp_hw_done_event_data *) evt_data;
606
607 rc = __cam_isp_ctx_handle_buf_done_in_activated_state(ctx_isp, done, 1);
608 return rc;
609}
610
Jing Zhoud352ed12017-03-20 23:59:56 -0700611static int __cam_isp_ctx_epoch_in_bubble_applied(
612 struct cam_isp_context *ctx_isp, void *evt_data)
613{
614 struct cam_ctx_request *req;
615 struct cam_isp_ctx_req *req_isp;
616 struct cam_context *ctx = ctx_isp->base;
Jing Zhoudedc4762017-06-19 17:45:36 +0530617 uint64_t request_id = 0;
Jing Zhoud352ed12017-03-20 23:59:56 -0700618
619 /*
620 * This means we missed the reg upd ack. So we need to
621 * transition to BUBBLE state again.
622 */
623
624 if (list_empty(&ctx->pending_req_list)) {
625 /*
626 * If no pending req in epoch, this is an error case.
627 * Just go back to the bubble state.
628 */
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -0700629 CAM_ERR(CAM_ISP, "No pending request.");
Jing Zhoudedc4762017-06-19 17:45:36 +0530630 __cam_isp_ctx_send_sof_timestamp(ctx_isp, request_id,
631 CAM_REQ_MGR_SOF_EVENT_SUCCESS);
632
Jing Zhoud352ed12017-03-20 23:59:56 -0700633 ctx_isp->substate_activated = CAM_ISP_CTX_ACTIVATED_BUBBLE;
634 goto end;
635 }
636
637 req = list_first_entry(&ctx->pending_req_list, struct cam_ctx_request,
638 list);
639 req_isp = (struct cam_isp_ctx_req *)req->req_priv;
640
641 if (req_isp->bubble_report && ctx->ctx_crm_intf &&
642 ctx->ctx_crm_intf->notify_err) {
643 struct cam_req_mgr_error_notify notify;
644
645 notify.link_hdl = ctx->link_hdl;
646 notify.dev_hdl = ctx->dev_hdl;
647 notify.req_id = req->request_id;
648 notify.error = CRM_KMD_ERR_BUBBLE;
649 ctx->ctx_crm_intf->notify_err(&notify);
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -0700650 CAM_DBG(CAM_ISP, "Notify CRM about Bubble frame %lld",
Jing Zhoud352ed12017-03-20 23:59:56 -0700651 ctx_isp->frame_id);
Jing Zhou45b55cc2017-05-16 17:27:18 -0700652 } else {
653 /*
654 * If we can not report bubble, then treat it as if no bubble
655 * report. Just move the req to active list.
656 */
657 list_del_init(&req->list);
658 list_add_tail(&req->list, &ctx->active_req_list);
Jing Zhoudedc4762017-06-19 17:45:36 +0530659 ctx_isp->active_req_cnt++;
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -0700660 CAM_DBG(CAM_ISP, "move request %lld to active list(cnt = %d)",
661 req->request_id, ctx_isp->active_req_cnt);
Jing Zhou45b55cc2017-05-16 17:27:18 -0700662 req_isp->bubble_report = 0;
Jing Zhoud352ed12017-03-20 23:59:56 -0700663 }
664
Jing Zhoudedc4762017-06-19 17:45:36 +0530665 request_id = req->request_id;
666 __cam_isp_ctx_send_sof_timestamp(ctx_isp, request_id,
667 CAM_REQ_MGR_SOF_EVENT_ERROR);
668
Jing Zhoud352ed12017-03-20 23:59:56 -0700669 ctx_isp->substate_activated = CAM_ISP_CTX_ACTIVATED_BUBBLE;
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -0700670 CAM_DBG(CAM_ISP, "next substate %d", ctx_isp->substate_activated);
Jing Zhoud352ed12017-03-20 23:59:56 -0700671end:
672 return 0;
673}
674
675static int __cam_isp_ctx_buf_done_in_bubble_applied(
676 struct cam_isp_context *ctx_isp, void *evt_data)
677{
678 int rc = 0;
679 struct cam_isp_hw_done_event_data *done =
680 (struct cam_isp_hw_done_event_data *) evt_data;
681
682 rc = __cam_isp_ctx_handle_buf_done_in_activated_state(ctx_isp, done, 1);
683 return rc;
684}
685
686static int __cam_isp_ctx_handle_error(struct cam_isp_context *ctx_isp,
687 void *evt_data)
688{
689 int rc = 0;
690 struct cam_ctx_request *req;
691 struct cam_req_mgr_error_notify notify;
692
693 struct cam_context *ctx = ctx_isp->base;
694 struct cam_isp_hw_error_event_data *error_event_data =
695 (struct cam_isp_hw_error_event_data *)evt_data;
696
697 uint32_t error_type = error_event_data->error_type;
698
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -0700699 CAM_DBG(CAM_ISP, "Enter error_type = %d", error_type);
Jing Zhoud352ed12017-03-20 23:59:56 -0700700 if ((error_type == CAM_ISP_HW_ERROR_OVERFLOW) ||
701 (error_type == CAM_ISP_HW_ERROR_BUSIF_OVERFLOW))
702 notify.error = CRM_KMD_ERR_FATAL;
703
704 /*
705 * Need to check the active req
706 * move all of them to the pending request list
707 * Note this funciton need revisit!
708 */
709
710 if (list_empty(&ctx->active_req_list)) {
Harsh Shahcb0072c2017-09-26 19:22:10 -0700711 CAM_ERR_RATE_LIMIT(CAM_ISP,
712 "handling error with no active request");
Jing Zhoud352ed12017-03-20 23:59:56 -0700713 rc = -EINVAL;
714 goto end;
715 }
716
717 req = list_first_entry(&ctx->active_req_list,
718 struct cam_ctx_request, list);
719
720 if (ctx->ctx_crm_intf && ctx->ctx_crm_intf->notify_err) {
721 notify.link_hdl = ctx->link_hdl;
722 notify.dev_hdl = ctx->dev_hdl;
723 notify.req_id = req->request_id;
724
725 ctx->ctx_crm_intf->notify_err(&notify);
Harsh Shahcb0072c2017-09-26 19:22:10 -0700726 CAM_ERR_RATE_LIMIT(CAM_ISP, "Notify CRM about ERROR frame %lld",
Jing Zhoud352ed12017-03-20 23:59:56 -0700727 ctx_isp->frame_id);
728 } else {
Harsh Shahcb0072c2017-09-26 19:22:10 -0700729 CAM_ERR_RATE_LIMIT(CAM_ISP, "Can not notify ERRROR to CRM");
Jing Zhoud352ed12017-03-20 23:59:56 -0700730 rc = -EFAULT;
731 }
732
733 list_del_init(&req->list);
734 list_add(&req->list, &ctx->pending_req_list);
735 /* might need to check if active list is empty */
736
737end:
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -0700738 CAM_DBG(CAM_ISP, "Exit");
Jing Zhoud352ed12017-03-20 23:59:56 -0700739 return rc;
740}
741
742static struct cam_isp_ctx_irq_ops
743 cam_isp_ctx_activated_state_machine_irq[CAM_ISP_CTX_ACTIVATED_MAX] = {
744 /* SOF */
745 {
746 .irq_ops = {
747 NULL,
Jing Zhoudedc4762017-06-19 17:45:36 +0530748 __cam_isp_ctx_sof_in_activated_state,
Jing Zhoud352ed12017-03-20 23:59:56 -0700749 __cam_isp_ctx_reg_upd_in_sof,
750 __cam_isp_ctx_notify_sof_in_actived_state,
Junzhe Zou2df84502017-05-26 13:20:23 -0700751 __cam_isp_ctx_notify_eof_in_actived_state,
Jing Zhoud352ed12017-03-20 23:59:56 -0700752 NULL,
753 },
754 },
755 /* APPLIED */
756 {
757 .irq_ops = {
758 __cam_isp_ctx_handle_error,
Jing Zhoudedc4762017-06-19 17:45:36 +0530759 __cam_isp_ctx_sof_in_activated_state,
Jing Zhoud352ed12017-03-20 23:59:56 -0700760 __cam_isp_ctx_reg_upd_in_activated_state,
761 __cam_isp_ctx_epoch_in_applied,
Junzhe Zou2df84502017-05-26 13:20:23 -0700762 __cam_isp_ctx_notify_eof_in_actived_state,
Jing Zhoud352ed12017-03-20 23:59:56 -0700763 __cam_isp_ctx_buf_done_in_applied,
764 },
765 },
766 /* EPOCH */
767 {
768 .irq_ops = {
769 __cam_isp_ctx_handle_error,
770 __cam_isp_ctx_sof_in_epoch,
771 NULL,
772 __cam_isp_ctx_notify_sof_in_actived_state,
Junzhe Zou2df84502017-05-26 13:20:23 -0700773 __cam_isp_ctx_notify_eof_in_actived_state,
Jing Zhoud352ed12017-03-20 23:59:56 -0700774 __cam_isp_ctx_buf_done_in_epoch,
775 },
776 },
777 /* BUBBLE */
778 {
779 .irq_ops = {
780 NULL,
Jing Zhoudedc4762017-06-19 17:45:36 +0530781 __cam_isp_ctx_sof_in_activated_state,
Jing Zhoud352ed12017-03-20 23:59:56 -0700782 NULL,
783 __cam_isp_ctx_notify_sof_in_actived_state,
Junzhe Zou2df84502017-05-26 13:20:23 -0700784 __cam_isp_ctx_notify_eof_in_actived_state,
Jing Zhoud352ed12017-03-20 23:59:56 -0700785 __cam_isp_ctx_buf_done_in_bubble,
786 },
787 },
788 /* Bubble Applied */
789 {
790 .irq_ops = {
791 NULL,
Jing Zhoudedc4762017-06-19 17:45:36 +0530792 __cam_isp_ctx_sof_in_activated_state,
Jing Zhoud352ed12017-03-20 23:59:56 -0700793 __cam_isp_ctx_reg_upd_in_activated_state,
794 __cam_isp_ctx_epoch_in_bubble_applied,
795 NULL,
796 __cam_isp_ctx_buf_done_in_bubble_applied,
797 },
798 },
799 /* HALT */
800 {
801 },
802};
803
804static int __cam_isp_ctx_apply_req_in_activated_state(
805 struct cam_context *ctx, struct cam_req_mgr_apply_request *apply,
806 uint32_t next_state)
807{
808 int rc = 0;
809 struct cam_ctx_request *req;
Harsh Shah1b8eb232017-10-09 19:20:52 -0700810 struct cam_ctx_request *active_req;
Jing Zhoud352ed12017-03-20 23:59:56 -0700811 struct cam_isp_ctx_req *req_isp;
Harsh Shah1b8eb232017-10-09 19:20:52 -0700812 struct cam_isp_ctx_req *active_req_isp;
Jing Zhoud352ed12017-03-20 23:59:56 -0700813 struct cam_isp_context *ctx_isp;
814 struct cam_hw_config_args cfg;
815
816 if (list_empty(&ctx->pending_req_list)) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -0700817 CAM_ERR(CAM_ISP, "No available request for Apply id %lld",
818 apply->request_id);
Jing Zhoud352ed12017-03-20 23:59:56 -0700819 rc = -EFAULT;
820 goto end;
821 }
Jing Zhou9eabf472017-05-16 11:59:41 -0700822
823 /*
824 * When the pipeline has issue, the requests can be queued up in the
825 * pipeline. In this case, we should reject the additional request.
826 * The maximum number of request allowed to be outstanding is 2.
827 *
828 */
Jing Zhoudedc4762017-06-19 17:45:36 +0530829 ctx_isp = (struct cam_isp_context *) ctx->ctx_priv;
Jing Zhoud352ed12017-03-20 23:59:56 -0700830 req = list_first_entry(&ctx->pending_req_list, struct cam_ctx_request,
831 list);
832
833 /*
834 * Check whehter the request id is matching the tip, if not, this means
835 * we are in the middle of the error handling. Need to reject this apply
836 */
837 if (req->request_id != apply->request_id) {
Harsh Shahf7136392017-08-29 12:42:52 -0700838 CAM_ERR_RATE_LIMIT(CAM_ISP,
839 "Invalid Request Id asking %llu existing %llu",
840 apply->request_id, req->request_id);
Jing Zhoud352ed12017-03-20 23:59:56 -0700841 rc = -EFAULT;
842 goto end;
843 }
844
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -0700845 CAM_DBG(CAM_ISP, "Apply request %lld", req->request_id);
Jing Zhoud352ed12017-03-20 23:59:56 -0700846 req_isp = (struct cam_isp_ctx_req *) req->req_priv;
Jing Zhoud352ed12017-03-20 23:59:56 -0700847
Karthik Anantha Ramba3bd972017-09-25 15:35:26 -0700848 if (ctx_isp->active_req_cnt >= 2) {
849 CAM_ERR_RATE_LIMIT(CAM_ISP,
Harsh Shah1b8eb232017-10-09 19:20:52 -0700850 "Reject apply request (id %lld) due to congestion(cnt = %d)",
851 req->request_id,
Karthik Anantha Ramba3bd972017-09-25 15:35:26 -0700852 ctx_isp->active_req_cnt);
Harsh Shah1b8eb232017-10-09 19:20:52 -0700853 if (!list_empty(&ctx->active_req_list)) {
854 active_req = list_first_entry(&ctx->active_req_list,
855 struct cam_ctx_request, list);
856 active_req_isp =
857 (struct cam_isp_ctx_req *) active_req->req_priv;
858 __cam_isp_ctx_handle_buf_done_fail_log(active_req_isp);
859 } else {
860 CAM_ERR_RATE_LIMIT(CAM_ISP,
861 "WARNING: should not happen (cnt = %d) but active_list empty",
862 ctx_isp->active_req_cnt);
863 }
864 rc = -EFAULT;
865 goto end;
Karthik Anantha Ramba3bd972017-09-25 15:35:26 -0700866 }
Jing Zhoud352ed12017-03-20 23:59:56 -0700867 req_isp->bubble_report = apply->report_if_bubble;
868
869 cfg.ctxt_to_hw_map = ctx_isp->hw_ctx;
870 cfg.hw_update_entries = req_isp->cfg;
871 cfg.num_hw_update_entries = req_isp->num_cfg;
872
873 rc = ctx->hw_mgr_intf->hw_config(ctx->hw_mgr_intf->hw_mgr_priv, &cfg);
874 if (rc) {
Harsh Shahcb0072c2017-09-26 19:22:10 -0700875 CAM_ERR_RATE_LIMIT(CAM_ISP, "Can not apply the configuration");
Jing Zhoud352ed12017-03-20 23:59:56 -0700876 } else {
Jing Zhou93b3ec12017-06-15 17:43:39 -0700877 spin_lock_bh(&ctx->lock);
Jing Zhoud352ed12017-03-20 23:59:56 -0700878 ctx_isp->substate_activated = next_state;
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -0700879 CAM_DBG(CAM_ISP, "new state %d", next_state);
Jing Zhou93b3ec12017-06-15 17:43:39 -0700880 spin_unlock_bh(&ctx->lock);
Jing Zhoud352ed12017-03-20 23:59:56 -0700881 }
882end:
883 return rc;
884}
885
886static int __cam_isp_ctx_apply_req_in_sof(
887 struct cam_context *ctx, struct cam_req_mgr_apply_request *apply)
888{
889 int rc = 0;
890 struct cam_isp_context *ctx_isp =
891 (struct cam_isp_context *) ctx->ctx_priv;
892
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -0700893 CAM_DBG(CAM_ISP, "current substate %d",
Jing Zhoud352ed12017-03-20 23:59:56 -0700894 ctx_isp->substate_activated);
895 rc = __cam_isp_ctx_apply_req_in_activated_state(ctx, apply,
896 CAM_ISP_CTX_ACTIVATED_APPLIED);
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -0700897 CAM_DBG(CAM_ISP, "new substate %d", ctx_isp->substate_activated);
Jing Zhoud352ed12017-03-20 23:59:56 -0700898
899 return rc;
900}
901
902static int __cam_isp_ctx_apply_req_in_epoch(
903 struct cam_context *ctx, struct cam_req_mgr_apply_request *apply)
904{
905 int rc = 0;
906 struct cam_isp_context *ctx_isp =
907 (struct cam_isp_context *) ctx->ctx_priv;
908
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -0700909 CAM_DBG(CAM_ISP, "current substate %d",
Jing Zhoud352ed12017-03-20 23:59:56 -0700910 ctx_isp->substate_activated);
911 rc = __cam_isp_ctx_apply_req_in_activated_state(ctx, apply,
912 CAM_ISP_CTX_ACTIVATED_APPLIED);
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -0700913 CAM_DBG(CAM_ISP, "new substate %d", ctx_isp->substate_activated);
Jing Zhoud352ed12017-03-20 23:59:56 -0700914
915 return rc;
916}
917
918static int __cam_isp_ctx_apply_req_in_bubble(
919 struct cam_context *ctx, struct cam_req_mgr_apply_request *apply)
920{
921 int rc = 0;
922 struct cam_isp_context *ctx_isp =
923 (struct cam_isp_context *) ctx->ctx_priv;
924
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -0700925 CAM_DBG(CAM_ISP, "current substate %d",
Jing Zhoud352ed12017-03-20 23:59:56 -0700926 ctx_isp->substate_activated);
927 rc = __cam_isp_ctx_apply_req_in_activated_state(ctx, apply,
928 CAM_ISP_CTX_ACTIVATED_BUBBLE_APPLIED);
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -0700929 CAM_DBG(CAM_ISP, "new substate %d", ctx_isp->substate_activated);
Jing Zhoud352ed12017-03-20 23:59:56 -0700930
931 return rc;
932}
933
Jing Zhoub524a852017-05-16 15:47:30 +0530934static int __cam_isp_ctx_flush_req(struct cam_context *ctx,
935 struct list_head *req_list, struct cam_req_mgr_flush_request *flush_req)
936{
937 int i, rc;
938 uint32_t cancel_req_id_found = 0;
939 struct cam_ctx_request *req;
940 struct cam_ctx_request *req_temp;
941 struct cam_isp_ctx_req *req_isp;
942
943 spin_lock(&ctx->lock);
944 if (list_empty(req_list)) {
945 spin_unlock(&ctx->lock);
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -0700946 CAM_DBG(CAM_ISP, "request list is empty");
Jing Zhoub524a852017-05-16 15:47:30 +0530947 return 0;
948 }
949
950 list_for_each_entry_safe(req, req_temp, req_list, list) {
951 if ((flush_req->type == CAM_REQ_MGR_FLUSH_TYPE_CANCEL_REQ)
952 && (req->request_id != flush_req->req_id))
953 continue;
954
955 list_del_init(&req->list);
956 req_isp = (struct cam_isp_ctx_req *) req->req_priv;
957 for (i = 0; i < req_isp->num_fence_map_out; i++) {
958 if (req_isp->fence_map_out[i].sync_id != -1) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -0700959 CAM_DBG(CAM_ISP, "Flush req 0x%llx, fence %d",
960 req->request_id,
Jing Zhoub524a852017-05-16 15:47:30 +0530961 req_isp->fence_map_out[i].sync_id);
962 rc = cam_sync_signal(
963 req_isp->fence_map_out[i].sync_id,
964 CAM_SYNC_STATE_SIGNALED_ERROR);
965 if (rc)
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -0700966 CAM_ERR_RATE_LIMIT(CAM_ISP,
967 "signal fence failed\n");
Jing Zhoub524a852017-05-16 15:47:30 +0530968 req_isp->fence_map_out[i].sync_id = -1;
969 }
970 }
971 list_add_tail(&req->list, &ctx->free_req_list);
972
973 /* If flush request id found, exit the loop */
974 if (flush_req->type == CAM_REQ_MGR_FLUSH_TYPE_CANCEL_REQ) {
975 cancel_req_id_found = 1;
976 break;
977 }
978 }
979 spin_unlock(&ctx->lock);
980
981 if (flush_req->type == CAM_REQ_MGR_FLUSH_TYPE_CANCEL_REQ &&
982 !cancel_req_id_found)
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -0700983 CAM_DBG(CAM_ISP,
984 "Flush request id:%lld is not found in the list",
985 flush_req->req_id);
Jing Zhoub524a852017-05-16 15:47:30 +0530986
987 return 0;
988}
989
990static int __cam_isp_ctx_flush_req_in_top_state(
991 struct cam_context *ctx,
992 struct cam_req_mgr_flush_request *flush_req)
993{
994 int rc = 0;
995
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -0700996 CAM_DBG(CAM_ISP, "try to flush pending list");
Jing Zhoub524a852017-05-16 15:47:30 +0530997 rc = __cam_isp_ctx_flush_req(ctx, &ctx->pending_req_list, flush_req);
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -0700998 CAM_DBG(CAM_ISP, "Flush request in top state %d",
999 ctx->state);
Jing Zhoub524a852017-05-16 15:47:30 +05301000 return rc;
1001}
1002
1003static int __cam_isp_ctx_flush_req_in_ready(
1004 struct cam_context *ctx,
1005 struct cam_req_mgr_flush_request *flush_req)
1006{
1007 int rc = 0;
1008
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07001009 CAM_DBG(CAM_ISP, "try to flush pending list");
Jing Zhoub524a852017-05-16 15:47:30 +05301010 rc = __cam_isp_ctx_flush_req(ctx, &ctx->pending_req_list, flush_req);
1011
1012 /* if nothing is in pending req list, change state to acquire*/
1013 spin_lock(&ctx->lock);
1014 if (list_empty(&ctx->pending_req_list))
1015 ctx->state = CAM_CTX_ACQUIRED;
1016 spin_unlock(&ctx->lock);
1017
Gregory Bergschneider5164f3a2017-07-07 10:26:17 -06001018 trace_cam_context_state("ISP", ctx);
1019
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07001020 CAM_DBG(CAM_ISP, "Flush request in ready state. next state %d",
1021 ctx->state);
Jing Zhoub524a852017-05-16 15:47:30 +05301022 return rc;
1023}
1024
Jing Zhoud352ed12017-03-20 23:59:56 -07001025static struct cam_ctx_ops
1026 cam_isp_ctx_activated_state_machine[CAM_ISP_CTX_ACTIVATED_MAX] = {
1027 /* SOF */
1028 {
1029 .ioctl_ops = {},
1030 .crm_ops = {
1031 .apply_req = __cam_isp_ctx_apply_req_in_sof,
1032 },
1033 .irq_ops = NULL,
1034 },
1035 /* APPLIED */
1036 {
1037 .ioctl_ops = {},
1038 .crm_ops = {},
1039 .irq_ops = NULL,
1040 },
1041 /* EPOCH */
1042 {
1043 .ioctl_ops = {},
1044 .crm_ops = {
1045 .apply_req = __cam_isp_ctx_apply_req_in_epoch,
1046 },
1047 .irq_ops = NULL,
1048 },
1049 /* BUBBLE */
1050 {
1051 .ioctl_ops = {},
1052 .crm_ops = {
1053 .apply_req = __cam_isp_ctx_apply_req_in_bubble,
1054 },
1055 .irq_ops = NULL,
1056 },
1057 /* Bubble Applied */
1058 {
1059 .ioctl_ops = {},
1060 .crm_ops = {},
1061 .irq_ops = NULL,
1062 },
1063 /* HALT */
1064 {
1065 .ioctl_ops = {},
1066 .crm_ops = {},
1067 .irq_ops = NULL,
1068 },
1069};
1070
Ravikishore Pampanaad6bc902017-07-12 19:37:06 +05301071static int __cam_isp_ctx_rdi_only_sof_in_top_state(
1072 struct cam_isp_context *ctx_isp, void *evt_data)
1073{
1074 int rc = 0;
1075 struct cam_context *ctx = ctx_isp->base;
Junzhe Zou2df84502017-05-26 13:20:23 -07001076 struct cam_req_mgr_trigger_notify notify;
Ravikishore Pampanaad6bc902017-07-12 19:37:06 +05301077 struct cam_isp_hw_sof_event_data *sof_event_data = evt_data;
1078 uint64_t request_id = 0;
1079
1080 if (!evt_data) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07001081 CAM_ERR(CAM_ISP, "in valid sof event data");
Ravikishore Pampanaad6bc902017-07-12 19:37:06 +05301082 return -EINVAL;
1083 }
1084
1085 ctx_isp->frame_id++;
1086 ctx_isp->sof_timestamp_val = sof_event_data->timestamp;
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07001087 CAM_DBG(CAM_ISP, "frame id: %lld time stamp:0x%llx",
Ravikishore Pampanaad6bc902017-07-12 19:37:06 +05301088 ctx_isp->frame_id, ctx_isp->sof_timestamp_val);
1089
1090 /*
1091 * notify reqmgr with sof signal. Note, due to scheduling delay
1092 * we can run into situation that two active requests has already
1093 * be in the active queue while we try to do the notification.
1094 * In this case, we need to skip the current notification. This
1095 * helps the state machine to catch up the delay.
1096 */
Junzhe Zou2df84502017-05-26 13:20:23 -07001097 if (ctx->ctx_crm_intf && ctx->ctx_crm_intf->notify_trigger &&
Ravikishore Pampanaad6bc902017-07-12 19:37:06 +05301098 ctx_isp->active_req_cnt <= 2) {
1099 notify.link_hdl = ctx->link_hdl;
1100 notify.dev_hdl = ctx->dev_hdl;
1101 notify.frame_id = ctx_isp->frame_id;
Junzhe Zou2df84502017-05-26 13:20:23 -07001102 notify.trigger = CAM_TRIGGER_POINT_SOF;
Ravikishore Pampanaad6bc902017-07-12 19:37:06 +05301103
Junzhe Zou2df84502017-05-26 13:20:23 -07001104 ctx->ctx_crm_intf->notify_trigger(&notify);
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07001105 CAM_DBG(CAM_ISP, "Notify CRM SOF frame %lld",
Ravikishore Pampanaad6bc902017-07-12 19:37:06 +05301106 ctx_isp->frame_id);
1107
1108 /*
1109 * It is idle frame with out any applied request id, send
1110 * request id as zero
1111 */
1112 __cam_isp_ctx_send_sof_timestamp(ctx_isp, request_id,
1113 CAM_REQ_MGR_SOF_EVENT_SUCCESS);
1114 } else {
Harsh Shahcb0072c2017-09-26 19:22:10 -07001115 CAM_ERR_RATE_LIMIT(CAM_ISP, "Can not notify SOF to CRM");
Ravikishore Pampanaad6bc902017-07-12 19:37:06 +05301116 }
1117
1118 if (list_empty(&ctx->active_req_list))
1119 ctx_isp->substate_activated = CAM_ISP_CTX_ACTIVATED_SOF;
1120 else
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07001121 CAM_DBG(CAM_ISP, "Still need to wait for the buf done");
Ravikishore Pampanaad6bc902017-07-12 19:37:06 +05301122
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07001123 CAM_DBG(CAM_ISP, "next substate %d",
Ravikishore Pampanaad6bc902017-07-12 19:37:06 +05301124 ctx_isp->substate_activated);
1125 return rc;
1126}
1127
1128static int __cam_isp_ctx_rdi_only_sof_in_applied_state(
1129 struct cam_isp_context *ctx_isp, void *evt_data)
1130{
1131 struct cam_isp_hw_sof_event_data *sof_event_data = evt_data;
1132
1133 if (!evt_data) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07001134 CAM_ERR(CAM_ISP, "in valid sof event data");
Ravikishore Pampanaad6bc902017-07-12 19:37:06 +05301135 return -EINVAL;
1136 }
1137
1138 ctx_isp->frame_id++;
1139 ctx_isp->sof_timestamp_val = sof_event_data->timestamp;
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07001140 CAM_DBG(CAM_ISP, "frame id: %lld time stamp:0x%llx",
Ravikishore Pampanaad6bc902017-07-12 19:37:06 +05301141 ctx_isp->frame_id, ctx_isp->sof_timestamp_val);
1142
1143 ctx_isp->substate_activated = CAM_ISP_CTX_ACTIVATED_BUBBLE_APPLIED;
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07001144 CAM_DBG(CAM_ISP, "next substate %d", ctx_isp->substate_activated);
Ravikishore Pampanaad6bc902017-07-12 19:37:06 +05301145
1146 return 0;
1147}
1148
1149static int __cam_isp_ctx_rdi_only_sof_in_bubble_applied(
1150 struct cam_isp_context *ctx_isp, void *evt_data)
1151{
1152 struct cam_ctx_request *req;
1153 struct cam_isp_ctx_req *req_isp;
1154 struct cam_context *ctx = ctx_isp->base;
1155 struct cam_isp_hw_sof_event_data *sof_event_data = evt_data;
1156 uint64_t request_id = 0;
1157
1158 ctx_isp->frame_id++;
1159 ctx_isp->sof_timestamp_val = sof_event_data->timestamp;
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07001160 CAM_DBG(CAM_ISP, "frame id: %lld time stamp:0x%llx",
Ravikishore Pampanaad6bc902017-07-12 19:37:06 +05301161 ctx_isp->frame_id, ctx_isp->sof_timestamp_val);
1162
1163 if (list_empty(&ctx->pending_req_list)) {
1164 /*
1165 * If no pending req in epoch, this is an error case.
1166 * The recovery is to go back to sof state
1167 */
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07001168 CAM_ERR(CAM_ISP, "No pending request");
Ravikishore Pampanaad6bc902017-07-12 19:37:06 +05301169 ctx_isp->substate_activated = CAM_ISP_CTX_ACTIVATED_SOF;
1170
1171 /* Send SOF event as empty frame*/
1172 __cam_isp_ctx_send_sof_timestamp(ctx_isp, request_id,
1173 CAM_REQ_MGR_SOF_EVENT_SUCCESS);
1174
1175 goto end;
1176 }
1177
1178 req = list_first_entry(&ctx->pending_req_list, struct cam_ctx_request,
1179 list);
1180 req_isp = (struct cam_isp_ctx_req *)req->req_priv;
1181
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07001182 CAM_DBG(CAM_ISP, "Report Bubble flag %d", req_isp->bubble_report);
Ravikishore Pampanaad6bc902017-07-12 19:37:06 +05301183 if (req_isp->bubble_report && ctx->ctx_crm_intf &&
1184 ctx->ctx_crm_intf->notify_err) {
1185 struct cam_req_mgr_error_notify notify;
1186
1187 notify.link_hdl = ctx->link_hdl;
1188 notify.dev_hdl = ctx->dev_hdl;
1189 notify.req_id = req->request_id;
1190 notify.error = CRM_KMD_ERR_BUBBLE;
1191 ctx->ctx_crm_intf->notify_err(&notify);
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07001192 CAM_DBG(CAM_ISP, "Notify CRM about Bubble frame %lld",
Ravikishore Pampanaad6bc902017-07-12 19:37:06 +05301193 ctx_isp->frame_id);
1194 } else {
1195 /*
1196 * Since can not bubble report, always move the request to
1197 * active list.
1198 */
1199 list_del_init(&req->list);
1200 list_add_tail(&req->list, &ctx->active_req_list);
1201 ctx_isp->active_req_cnt++;
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07001202 CAM_DBG(CAM_ISP, "move request %lld to active list(cnt = %d)",
1203 req->request_id, ctx_isp->active_req_cnt);
Ravikishore Pampanaad6bc902017-07-12 19:37:06 +05301204 req_isp->bubble_report = 0;
1205 }
1206
1207 request_id = req->request_id;
1208 __cam_isp_ctx_send_sof_timestamp(ctx_isp, request_id,
1209 CAM_REQ_MGR_SOF_EVENT_ERROR);
1210
1211 /* change the state to bubble, as reg update has not come */
1212 ctx_isp->substate_activated = CAM_ISP_CTX_ACTIVATED_BUBBLE;
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07001213 CAM_DBG(CAM_ISP, "next substate %d", ctx_isp->substate_activated);
Ravikishore Pampanaad6bc902017-07-12 19:37:06 +05301214end:
1215 return 0;
1216}
1217
1218static int __cam_isp_ctx_rdi_only_sof_in_bubble_state(
1219 struct cam_isp_context *ctx_isp, void *evt_data)
1220{
1221 uint32_t i;
1222 struct cam_ctx_request *req;
1223 struct cam_context *ctx = ctx_isp->base;
Junzhe Zou2df84502017-05-26 13:20:23 -07001224 struct cam_req_mgr_trigger_notify notify;
Ravikishore Pampanaad6bc902017-07-12 19:37:06 +05301225 struct cam_isp_hw_sof_event_data *sof_event_data = evt_data;
1226 struct cam_isp_ctx_req *req_isp;
1227 uint64_t request_id = 0;
1228
1229 if (!evt_data) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07001230 CAM_ERR(CAM_ISP, "in valid sof event data");
Ravikishore Pampanaad6bc902017-07-12 19:37:06 +05301231 return -EINVAL;
1232 }
1233
1234 ctx_isp->frame_id++;
1235 ctx_isp->sof_timestamp_val = sof_event_data->timestamp;
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07001236 CAM_DBG(CAM_ISP, "frame id: %lld time stamp:0x%llx",
Ravikishore Pampanaad6bc902017-07-12 19:37:06 +05301237 ctx_isp->frame_id, ctx_isp->sof_timestamp_val);
1238 /*
1239 * Signal all active requests with error and move the all the active
1240 * requests to free list
1241 */
1242 while (!list_empty(&ctx->active_req_list)) {
1243 req = list_first_entry(&ctx->active_req_list,
1244 struct cam_ctx_request, list);
1245 list_del_init(&req->list);
1246 req_isp = (struct cam_isp_ctx_req *) req->req_priv;
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07001247 CAM_DBG(CAM_ISP, "signal fence in active list. fence num %d",
1248 req_isp->num_fence_map_out);
Ravikishore Pampanaad6bc902017-07-12 19:37:06 +05301249 for (i = 0; i < req_isp->num_fence_map_out; i++)
1250 if (req_isp->fence_map_out[i].sync_id != -1) {
1251 cam_sync_signal(
1252 req_isp->fence_map_out[i].sync_id,
1253 CAM_SYNC_STATE_SIGNALED_ERROR);
1254 }
1255 list_add_tail(&req->list, &ctx->free_req_list);
Harsh Shah1b8eb232017-10-09 19:20:52 -07001256 ctx_isp->active_req_cnt--;
Ravikishore Pampanaad6bc902017-07-12 19:37:06 +05301257 }
1258
1259 /* notify reqmgr with sof signal */
Junzhe Zou2df84502017-05-26 13:20:23 -07001260 if (ctx->ctx_crm_intf && ctx->ctx_crm_intf->notify_trigger) {
Ravikishore Pampanaad6bc902017-07-12 19:37:06 +05301261 notify.link_hdl = ctx->link_hdl;
1262 notify.dev_hdl = ctx->dev_hdl;
1263 notify.frame_id = ctx_isp->frame_id;
Junzhe Zou2df84502017-05-26 13:20:23 -07001264 notify.trigger = CAM_TRIGGER_POINT_SOF;
Ravikishore Pampanaad6bc902017-07-12 19:37:06 +05301265
Junzhe Zou2df84502017-05-26 13:20:23 -07001266 ctx->ctx_crm_intf->notify_trigger(&notify);
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07001267 CAM_DBG(CAM_ISP, "Notify CRM SOF frame %lld",
Ravikishore Pampanaad6bc902017-07-12 19:37:06 +05301268 ctx_isp->frame_id);
1269
1270 } else {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07001271 CAM_ERR(CAM_ISP, "Can not notify SOF to CRM");
Ravikishore Pampanaad6bc902017-07-12 19:37:06 +05301272 }
1273
1274 /*
1275 * It is idle frame with out any applied request id, send
1276 * request id as zero
1277 */
1278 __cam_isp_ctx_send_sof_timestamp(ctx_isp, request_id,
1279 CAM_REQ_MGR_SOF_EVENT_SUCCESS);
1280
1281 ctx_isp->substate_activated = CAM_ISP_CTX_ACTIVATED_SOF;
1282
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07001283 CAM_DBG(CAM_ISP, "next substate %d",
Ravikishore Pampanaad6bc902017-07-12 19:37:06 +05301284 ctx_isp->substate_activated);
1285
1286 return 0;
1287}
1288
1289static int __cam_isp_ctx_rdi_only_reg_upd_in_bubble_applied_state(
1290 struct cam_isp_context *ctx_isp, void *evt_data)
1291{
1292 struct cam_ctx_request *req;
1293 struct cam_context *ctx = ctx_isp->base;
1294 struct cam_isp_ctx_req *req_isp;
Junzhe Zou2df84502017-05-26 13:20:23 -07001295 struct cam_req_mgr_trigger_notify notify;
Ravikishore Pampanaad6bc902017-07-12 19:37:06 +05301296 uint64_t request_id = 0;
1297
1298 /* notify reqmgr with sof signal*/
Junzhe Zou2df84502017-05-26 13:20:23 -07001299 if (ctx->ctx_crm_intf && ctx->ctx_crm_intf->notify_trigger) {
Ravikishore Pampanaad6bc902017-07-12 19:37:06 +05301300 if (list_empty(&ctx->pending_req_list)) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07001301 CAM_ERR(CAM_ISP, "Reg upd ack with no pending request");
Ravikishore Pampanaad6bc902017-07-12 19:37:06 +05301302 goto error;
1303 }
1304 req = list_first_entry(&ctx->pending_req_list,
1305 struct cam_ctx_request, list);
1306 list_del_init(&req->list);
1307
1308 req_isp = (struct cam_isp_ctx_req *) req->req_priv;
1309 request_id = req->request_id;
1310 if (req_isp->num_fence_map_out != 0) {
1311 list_add_tail(&req->list, &ctx->active_req_list);
1312 ctx_isp->active_req_cnt++;
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07001313 CAM_DBG(CAM_ISP,
1314 "move request %lld to active list(cnt = %d)",
1315 req->request_id, ctx_isp->active_req_cnt);
Ravikishore Pampanaad6bc902017-07-12 19:37:06 +05301316 } else {
1317 /* no io config, so the request is completed. */
1318 list_add_tail(&req->list, &ctx->free_req_list);
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07001319 CAM_DBG(CAM_ISP,
1320 "move active req %lld to free list(cnt=%d)",
1321 req->request_id, ctx_isp->active_req_cnt);
Ravikishore Pampanaad6bc902017-07-12 19:37:06 +05301322 }
1323
1324 notify.link_hdl = ctx->link_hdl;
1325 notify.dev_hdl = ctx->dev_hdl;
1326 notify.frame_id = ctx_isp->frame_id;
Junzhe Zou2df84502017-05-26 13:20:23 -07001327 notify.trigger = CAM_TRIGGER_POINT_SOF;
Ravikishore Pampanaad6bc902017-07-12 19:37:06 +05301328
Junzhe Zou2df84502017-05-26 13:20:23 -07001329 ctx->ctx_crm_intf->notify_trigger(&notify);
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07001330 CAM_DBG(CAM_ISP, "Notify CRM SOF frame %lld",
Ravikishore Pampanaad6bc902017-07-12 19:37:06 +05301331 ctx_isp->frame_id);
1332 } else {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07001333 CAM_ERR(CAM_ISP, "Can not notify SOF to CRM");
Ravikishore Pampanaad6bc902017-07-12 19:37:06 +05301334 }
1335 __cam_isp_ctx_send_sof_timestamp(ctx_isp, request_id,
1336 CAM_REQ_MGR_SOF_EVENT_SUCCESS);
1337
1338 ctx_isp->substate_activated = CAM_ISP_CTX_ACTIVATED_EPOCH;
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07001339 CAM_DBG(CAM_ISP, "next substate %d", ctx_isp->substate_activated);
Ravikishore Pampanaad6bc902017-07-12 19:37:06 +05301340
1341 return 0;
1342error:
1343 /* Send SOF event as idle frame*/
1344 __cam_isp_ctx_send_sof_timestamp(ctx_isp, request_id,
1345 CAM_REQ_MGR_SOF_EVENT_SUCCESS);
1346
1347 /*
1348 * There is no request in the pending list, move the sub state machine
1349 * to SOF sub state
1350 */
1351 ctx_isp->substate_activated = CAM_ISP_CTX_ACTIVATED_SOF;
1352
1353 return 0;
1354}
1355
1356static struct cam_isp_ctx_irq_ops
1357 cam_isp_ctx_rdi_only_activated_state_machine_irq
1358 [CAM_ISP_CTX_ACTIVATED_MAX] = {
1359 /* SOF */
1360 {
1361 .irq_ops = {
1362 NULL,
1363 __cam_isp_ctx_rdi_only_sof_in_top_state,
1364 __cam_isp_ctx_reg_upd_in_sof,
1365 NULL,
1366 NULL,
1367 NULL,
1368 },
1369 },
1370 /* APPLIED */
1371 {
1372 .irq_ops = {
1373 __cam_isp_ctx_handle_error,
1374 __cam_isp_ctx_rdi_only_sof_in_applied_state,
1375 NULL,
1376 NULL,
1377 NULL,
1378 __cam_isp_ctx_buf_done_in_applied,
1379 },
1380 },
1381 /* EPOCH */
1382 {
1383 .irq_ops = {
1384 __cam_isp_ctx_handle_error,
1385 __cam_isp_ctx_rdi_only_sof_in_top_state,
1386 NULL,
1387 NULL,
1388 NULL,
1389 __cam_isp_ctx_buf_done_in_epoch,
1390 },
1391 },
1392 /* BUBBLE*/
1393 {
1394 .irq_ops = {
1395 __cam_isp_ctx_handle_error,
1396 __cam_isp_ctx_rdi_only_sof_in_bubble_state,
1397 NULL,
1398 NULL,
1399 NULL,
1400 __cam_isp_ctx_buf_done_in_bubble,
1401 },
1402 },
1403 /* BUBBLE APPLIED ie PRE_BUBBLE */
1404 {
1405 .irq_ops = {
1406 __cam_isp_ctx_handle_error,
1407 __cam_isp_ctx_rdi_only_sof_in_bubble_applied,
1408 __cam_isp_ctx_rdi_only_reg_upd_in_bubble_applied_state,
1409 NULL,
1410 NULL,
1411 __cam_isp_ctx_buf_done_in_bubble_applied,
1412 },
1413 },
1414
1415 /* HALT */
1416 {
1417 },
1418};
1419
1420static int __cam_isp_ctx_rdi_only_apply_req_top_state(
1421 struct cam_context *ctx, struct cam_req_mgr_apply_request *apply)
1422{
1423 int rc = 0;
1424 struct cam_isp_context *ctx_isp =
1425 (struct cam_isp_context *) ctx->ctx_priv;
1426
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07001427 CAM_DBG(CAM_ISP, "current substate %d",
Ravikishore Pampanaad6bc902017-07-12 19:37:06 +05301428 ctx_isp->substate_activated);
1429 rc = __cam_isp_ctx_apply_req_in_activated_state(ctx, apply,
1430 CAM_ISP_CTX_ACTIVATED_APPLIED);
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07001431 CAM_DBG(CAM_ISP, "new substate %d", ctx_isp->substate_activated);
Ravikishore Pampanaad6bc902017-07-12 19:37:06 +05301432
1433 return rc;
1434}
1435
1436static struct cam_ctx_ops
1437 cam_isp_ctx_rdi_only_activated_state_machine
1438 [CAM_ISP_CTX_ACTIVATED_MAX] = {
1439 /* SOF */
1440 {
1441 .ioctl_ops = {},
1442 .crm_ops = {
1443 .apply_req = __cam_isp_ctx_rdi_only_apply_req_top_state,
1444 },
1445 .irq_ops = NULL,
1446 },
1447 /* APPLIED */
1448 {
1449 .ioctl_ops = {},
1450 .crm_ops = {},
1451 .irq_ops = NULL,
1452 },
1453 /* EPOCH */
1454 {
1455 .ioctl_ops = {},
1456 .crm_ops = {
1457 .apply_req = __cam_isp_ctx_rdi_only_apply_req_top_state,
1458 },
1459 .irq_ops = NULL,
1460 },
1461 /* PRE BUBBLE */
1462 {
1463 .ioctl_ops = {},
1464 .crm_ops = {},
1465 .irq_ops = NULL,
1466 },
1467 /* BUBBLE */
1468 {
1469 .ioctl_ops = {},
1470 .crm_ops = {},
1471 .irq_ops = NULL,
1472 },
1473 /* HALT */
1474 {
1475 .ioctl_ops = {},
1476 .crm_ops = {},
1477 .irq_ops = NULL,
1478 },
1479};
1480
Jing Zhoud352ed12017-03-20 23:59:56 -07001481
1482/* top level state machine */
1483static int __cam_isp_ctx_release_dev_in_top_state(struct cam_context *ctx,
1484 struct cam_release_dev_cmd *cmd)
1485{
1486 int rc = 0;
Jing Zhoud352ed12017-03-20 23:59:56 -07001487 struct cam_hw_release_args rel_arg;
Jing Zhoud352ed12017-03-20 23:59:56 -07001488 struct cam_isp_context *ctx_isp =
1489 (struct cam_isp_context *) ctx->ctx_priv;
Jing Zhoub524a852017-05-16 15:47:30 +05301490 struct cam_req_mgr_flush_request flush_req;
Jing Zhoud352ed12017-03-20 23:59:56 -07001491
1492 if (ctx_isp->hw_ctx) {
1493 rel_arg.ctxt_to_hw_map = ctx_isp->hw_ctx;
1494 ctx->hw_mgr_intf->hw_release(ctx->hw_mgr_intf->hw_mgr_priv,
1495 &rel_arg);
1496 ctx_isp->hw_ctx = NULL;
1497 }
1498
Soundrapandian Jeyaprakash8d16e272017-10-12 11:05:37 -07001499 ctx->session_hdl = -1;
1500 ctx->dev_hdl = -1;
1501 ctx->link_hdl = -1;
Jing Zhoue71fd4a2017-05-15 19:44:34 -07001502 ctx->ctx_crm_intf = NULL;
Jing Zhoud352ed12017-03-20 23:59:56 -07001503 ctx_isp->frame_id = 0;
Jing Zhoudedc4762017-06-19 17:45:36 +05301504 ctx_isp->active_req_cnt = 0;
1505 ctx_isp->reported_req_id = 0;
Jing Zhoud352ed12017-03-20 23:59:56 -07001506
1507 /*
1508 * Ideally, we should never have any active request here.
1509 * But we still add some sanity check code here to help the debug
1510 */
1511 if (!list_empty(&ctx->active_req_list))
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07001512 CAM_ERR(CAM_ISP, "Active list is not empty");
Jing Zhoud352ed12017-03-20 23:59:56 -07001513
Jing Zhoub524a852017-05-16 15:47:30 +05301514 /* Flush all the pending request list */
1515 flush_req.type = CAM_REQ_MGR_FLUSH_TYPE_ALL;
1516 flush_req.link_hdl = ctx->link_hdl;
1517 flush_req.dev_hdl = ctx->dev_hdl;
1518
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07001519 CAM_DBG(CAM_ISP, "try to flush pending list");
Jing Zhoub524a852017-05-16 15:47:30 +05301520 rc = __cam_isp_ctx_flush_req(ctx, &ctx->pending_req_list, &flush_req);
1521
Jing Zhoud352ed12017-03-20 23:59:56 -07001522 ctx->state = CAM_CTX_AVAILABLE;
Gregory Bergschneider5164f3a2017-07-07 10:26:17 -06001523
1524 trace_cam_context_state("ISP", ctx);
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07001525 CAM_DBG(CAM_ISP, "next state %d", ctx->state);
Jing Zhoud352ed12017-03-20 23:59:56 -07001526 return rc;
1527}
1528
1529static int __cam_isp_ctx_config_dev_in_top_state(
1530 struct cam_context *ctx, struct cam_config_dev_cmd *cmd)
1531{
1532 int rc = 0;
1533 struct cam_ctx_request *req = NULL;
1534 struct cam_isp_ctx_req *req_isp;
1535 uint64_t packet_addr;
1536 struct cam_packet *packet;
1537 size_t len = 0;
1538 struct cam_hw_prepare_update_args cfg;
1539 struct cam_req_mgr_add_request add_req;
1540 struct cam_isp_context *ctx_isp =
1541 (struct cam_isp_context *) ctx->ctx_priv;
1542
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07001543 CAM_DBG(CAM_ISP, "get free request object......");
Jing Zhoud352ed12017-03-20 23:59:56 -07001544
1545 /* get free request */
Jing Zhou93b3ec12017-06-15 17:43:39 -07001546 spin_lock_bh(&ctx->lock);
Jing Zhoud352ed12017-03-20 23:59:56 -07001547 if (!list_empty(&ctx->free_req_list)) {
1548 req = list_first_entry(&ctx->free_req_list,
1549 struct cam_ctx_request, list);
1550 list_del_init(&req->list);
1551 }
Jing Zhou93b3ec12017-06-15 17:43:39 -07001552 spin_unlock_bh(&ctx->lock);
Jing Zhoud352ed12017-03-20 23:59:56 -07001553
1554 if (!req) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07001555 CAM_ERR(CAM_ISP, "No more request obj free");
Jing Zhoud352ed12017-03-20 23:59:56 -07001556 rc = -ENOMEM;
1557 goto end;
1558 }
1559
1560 req_isp = (struct cam_isp_ctx_req *) req->req_priv;
1561
1562 /* for config dev, only memory handle is supported */
1563 /* map packet from the memhandle */
1564 rc = cam_mem_get_cpu_buf((int32_t) cmd->packet_handle,
1565 (uint64_t *) &packet_addr, &len);
1566 if (rc != 0) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07001567 CAM_ERR(CAM_ISP, "Can not get packet address");
Jing Zhoud352ed12017-03-20 23:59:56 -07001568 rc = -EINVAL;
1569 goto free_req;
1570 }
1571
1572 packet = (struct cam_packet *) (packet_addr + cmd->offset);
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07001573 CAM_DBG(CAM_ISP, "pack_handle %llx", cmd->packet_handle);
1574 CAM_DBG(CAM_ISP, "packet address is 0x%llx", packet_addr);
1575 CAM_DBG(CAM_ISP, "packet with length %zu, offset 0x%llx",
Jing Zhoud352ed12017-03-20 23:59:56 -07001576 len, cmd->offset);
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07001577 CAM_DBG(CAM_ISP, "Packet request id %lld",
Jing Zhoud352ed12017-03-20 23:59:56 -07001578 packet->header.request_id);
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07001579 CAM_DBG(CAM_ISP, "Packet size 0x%x", packet->header.size);
1580 CAM_DBG(CAM_ISP, "packet op %d", packet->header.op_code);
Jing Zhoud352ed12017-03-20 23:59:56 -07001581
1582 /* preprocess the configuration */
1583 memset(&cfg, 0, sizeof(cfg));
1584 cfg.packet = packet;
1585 cfg.ctxt_to_hw_map = ctx_isp->hw_ctx;
1586 cfg.max_hw_update_entries = CAM_ISP_CTX_CFG_MAX;
1587 cfg.hw_update_entries = req_isp->cfg;
1588 cfg.max_out_map_entries = CAM_ISP_CTX_RES_MAX;
1589 cfg.max_in_map_entries = CAM_ISP_CTX_RES_MAX;
1590 cfg.out_map_entries = req_isp->fence_map_out;
1591 cfg.in_map_entries = req_isp->fence_map_in;
1592
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07001593 CAM_DBG(CAM_ISP, "try to prepare config packet......");
Jing Zhoud352ed12017-03-20 23:59:56 -07001594
1595 rc = ctx->hw_mgr_intf->hw_prepare_update(
1596 ctx->hw_mgr_intf->hw_mgr_priv, &cfg);
1597 if (rc != 0) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07001598 CAM_ERR(CAM_ISP, "Prepare config packet failed in HW layer");
Jing Zhoud352ed12017-03-20 23:59:56 -07001599 rc = -EFAULT;
1600 goto free_req;
1601 }
1602 req_isp->num_cfg = cfg.num_hw_update_entries;
1603 req_isp->num_fence_map_out = cfg.num_out_map_entries;
1604 req_isp->num_fence_map_in = cfg.num_in_map_entries;
1605 req_isp->num_acked = 0;
1606
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07001607 CAM_DBG(CAM_ISP, "num_entry: %d, num fence out: %d, num fence in: %d",
1608 req_isp->num_cfg, req_isp->num_fence_map_out,
Jing Zhoud352ed12017-03-20 23:59:56 -07001609 req_isp->num_fence_map_in);
1610
1611 req->request_id = packet->header.request_id;
1612 req->status = 1;
1613
1614 if (ctx->state == CAM_CTX_ACTIVATED && ctx->ctx_crm_intf->add_req) {
1615 add_req.link_hdl = ctx->link_hdl;
1616 add_req.dev_hdl = ctx->dev_hdl;
1617 add_req.req_id = req->request_id;
Sagar Gorea4d7dfd2017-09-13 19:56:24 -07001618 add_req.skip_before_applying = 0;
Jing Zhoud352ed12017-03-20 23:59:56 -07001619 rc = ctx->ctx_crm_intf->add_req(&add_req);
1620 if (rc) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07001621 CAM_ERR(CAM_ISP, "Error: Adding request id=%llu",
Jing Zhoud352ed12017-03-20 23:59:56 -07001622 req->request_id);
1623 goto free_req;
1624 }
1625 }
1626
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07001627 CAM_DBG(CAM_ISP, "Packet request id 0x%llx",
Jing Zhoud352ed12017-03-20 23:59:56 -07001628 packet->header.request_id);
1629
Jing Zhou77962c52017-09-18 19:13:34 -07001630 __cam_isp_ctx_enqueue_request_in_order(ctx, req);
Jing Zhoud352ed12017-03-20 23:59:56 -07001631
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07001632 CAM_DBG(CAM_ISP, "Preprocessing Config %lld successful",
Jing Zhoud352ed12017-03-20 23:59:56 -07001633 req->request_id);
1634
1635 return rc;
1636
1637free_req:
Jing Zhou93b3ec12017-06-15 17:43:39 -07001638 spin_lock_bh(&ctx->lock);
Jing Zhoud352ed12017-03-20 23:59:56 -07001639 list_add_tail(&req->list, &ctx->free_req_list);
Jing Zhou93b3ec12017-06-15 17:43:39 -07001640 spin_unlock_bh(&ctx->lock);
Jing Zhoud352ed12017-03-20 23:59:56 -07001641end:
1642 return rc;
1643}
1644
1645static int __cam_isp_ctx_acquire_dev_in_available(struct cam_context *ctx,
1646 struct cam_acquire_dev_cmd *cmd)
1647{
1648 int rc = 0;
1649 struct cam_hw_acquire_args param;
1650 struct cam_isp_resource *isp_res = NULL;
1651 struct cam_create_dev_hdl req_hdl_param;
1652 struct cam_hw_release_args release;
1653 struct cam_isp_context *ctx_isp =
1654 (struct cam_isp_context *) ctx->ctx_priv;
Ravikishore Pampanaad6bc902017-07-12 19:37:06 +05301655 struct cam_isp_hw_cmd_args hw_cmd_args;
Jing Zhoud352ed12017-03-20 23:59:56 -07001656
1657 if (!ctx->hw_mgr_intf) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07001658 CAM_ERR(CAM_ISP, "HW interface is not ready");
Jing Zhoud352ed12017-03-20 23:59:56 -07001659 rc = -EFAULT;
1660 goto end;
1661 }
1662
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07001663 CAM_DBG(CAM_ISP,
1664 "session_hdl 0x%x, num_resources %d, hdl type %d, res %lld",
1665 cmd->session_handle, cmd->num_resources,
Jing Zhoud352ed12017-03-20 23:59:56 -07001666 cmd->handle_type, cmd->resource_hdl);
1667
1668 if (cmd->num_resources > CAM_ISP_CTX_RES_MAX) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07001669 CAM_ERR(CAM_ISP, "Too much resources in the acquire");
Jing Zhoud352ed12017-03-20 23:59:56 -07001670 rc = -ENOMEM;
1671 goto end;
1672 }
1673
1674 /* for now we only support user pointer */
1675 if (cmd->handle_type != 1) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07001676 CAM_ERR(CAM_ISP, "Only user pointer is supported");
Jing Zhoud352ed12017-03-20 23:59:56 -07001677 rc = -EINVAL;
1678 goto end;
1679 }
1680
1681 isp_res = kzalloc(
1682 sizeof(*isp_res)*cmd->num_resources, GFP_KERNEL);
1683 if (!isp_res) {
1684 rc = -ENOMEM;
1685 goto end;
1686 }
1687
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07001688 CAM_DBG(CAM_ISP, "start copy %d resources from user",
1689 cmd->num_resources);
Jing Zhoud352ed12017-03-20 23:59:56 -07001690
1691 if (copy_from_user(isp_res, (void __user *)cmd->resource_hdl,
1692 sizeof(*isp_res)*cmd->num_resources)) {
1693 rc = -EFAULT;
1694 goto free_res;
1695 }
1696
1697 param.context_data = ctx;
1698 param.event_cb = ctx->irq_cb_intf;
1699 param.num_acq = cmd->num_resources;
1700 param.acquire_info = (uint64_t) isp_res;
1701
1702 /* call HW manager to reserve the resource */
1703 rc = ctx->hw_mgr_intf->hw_acquire(ctx->hw_mgr_intf->hw_mgr_priv,
1704 &param);
1705 if (rc != 0) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07001706 CAM_ERR(CAM_ISP, "Acquire device failed");
Jing Zhoud352ed12017-03-20 23:59:56 -07001707 goto free_res;
1708 }
1709
Ravikishore Pampanaad6bc902017-07-12 19:37:06 +05301710 /* Query the context has rdi only resource */
1711 hw_cmd_args.ctxt_to_hw_map = param.ctxt_to_hw_map;
1712 hw_cmd_args.cmd_type = CAM_ISP_HW_MGR_CMD_IS_RDI_ONLY_CONTEXT;
1713 rc = ctx->hw_mgr_intf->hw_cmd(ctx->hw_mgr_intf->hw_mgr_priv,
1714 &hw_cmd_args);
1715 if (rc) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07001716 CAM_ERR(CAM_ISP, "HW command failed");
Ravikishore Pampanaad6bc902017-07-12 19:37:06 +05301717 goto free_hw;
1718 }
1719
1720 if (hw_cmd_args.u.is_rdi_only_context) {
1721 /*
1722 * this context has rdi only resource assign rdi only
1723 * state machine
1724 */
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07001725 CAM_DBG(CAM_ISP, "RDI only session Context");
Ravikishore Pampanaad6bc902017-07-12 19:37:06 +05301726
1727 ctx_isp->substate_machine_irq =
1728 cam_isp_ctx_rdi_only_activated_state_machine_irq;
1729 ctx_isp->substate_machine =
1730 cam_isp_ctx_rdi_only_activated_state_machine;
1731 } else {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07001732 CAM_DBG(CAM_ISP, "Session has PIX or PIX and RDI resources");
Ravikishore Pampanaad6bc902017-07-12 19:37:06 +05301733 ctx_isp->substate_machine_irq =
1734 cam_isp_ctx_activated_state_machine_irq;
1735 ctx_isp->substate_machine =
1736 cam_isp_ctx_activated_state_machine;
1737 }
1738
Jing Zhoud352ed12017-03-20 23:59:56 -07001739 ctx_isp->hw_ctx = param.ctxt_to_hw_map;
1740
1741 req_hdl_param.session_hdl = cmd->session_handle;
1742 /* bridge is not ready for these flags. so false for now */
1743 req_hdl_param.v4l2_sub_dev_flag = 0;
1744 req_hdl_param.media_entity_flag = 0;
1745 req_hdl_param.ops = ctx->crm_ctx_intf;
1746 req_hdl_param.priv = ctx;
1747
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07001748 CAM_DBG(CAM_ISP, "get device handle form bridge");
Jing Zhoud352ed12017-03-20 23:59:56 -07001749 ctx->dev_hdl = cam_create_device_hdl(&req_hdl_param);
1750 if (ctx->dev_hdl <= 0) {
1751 rc = -EFAULT;
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07001752 CAM_ERR(CAM_ISP, "Can not create device handle");
Jing Zhoud352ed12017-03-20 23:59:56 -07001753 goto free_hw;
1754 }
1755 cmd->dev_handle = ctx->dev_hdl;
1756
1757 /* store session information */
1758 ctx->session_hdl = cmd->session_handle;
1759
1760 ctx->state = CAM_CTX_ACQUIRED;
1761
Gregory Bergschneider5164f3a2017-07-07 10:26:17 -06001762 trace_cam_context_state("ISP", ctx);
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07001763 CAM_DBG(CAM_ISP, "Acquire success.");
Jing Zhoud352ed12017-03-20 23:59:56 -07001764 kfree(isp_res);
1765 return rc;
1766
1767free_hw:
1768 release.ctxt_to_hw_map = ctx_isp->hw_ctx;
1769 ctx->hw_mgr_intf->hw_release(ctx->hw_mgr_intf->hw_mgr_priv, &release);
1770 ctx_isp->hw_ctx = NULL;
1771free_res:
1772 kfree(isp_res);
1773end:
1774 return rc;
1775}
1776
1777static int __cam_isp_ctx_config_dev_in_acquired(struct cam_context *ctx,
1778 struct cam_config_dev_cmd *cmd)
1779{
1780 int rc = 0;
1781
1782 rc = __cam_isp_ctx_config_dev_in_top_state(ctx, cmd);
1783
Karthik Anantha Ram34dc2652017-10-20 15:49:54 -07001784 if (!rc && (ctx->link_hdl >= 0)) {
Jing Zhoud352ed12017-03-20 23:59:56 -07001785 ctx->state = CAM_CTX_READY;
Gregory Bergschneider5164f3a2017-07-07 10:26:17 -06001786 trace_cam_context_state("ISP", ctx);
1787 }
Jing Zhoud352ed12017-03-20 23:59:56 -07001788
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07001789 CAM_DBG(CAM_ISP, "next state %d", ctx->state);
Jing Zhoud352ed12017-03-20 23:59:56 -07001790 return rc;
1791}
1792
1793static int __cam_isp_ctx_link_in_acquired(struct cam_context *ctx,
1794 struct cam_req_mgr_core_dev_link_setup *link)
1795{
1796 int rc = 0;
Junzhe Zou2df84502017-05-26 13:20:23 -07001797 struct cam_isp_context *ctx_isp =
1798 (struct cam_isp_context *) ctx->ctx_priv;
Jing Zhoud352ed12017-03-20 23:59:56 -07001799
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07001800 CAM_DBG(CAM_ISP, "Enter.........");
Jing Zhoud352ed12017-03-20 23:59:56 -07001801
1802 ctx->link_hdl = link->link_hdl;
1803 ctx->ctx_crm_intf = link->crm_cb;
Junzhe Zou2df84502017-05-26 13:20:23 -07001804 ctx_isp->subscribe_event = link->subscribe_event;
Jing Zhoud352ed12017-03-20 23:59:56 -07001805
1806 /* change state only if we had the init config */
Gregory Bergschneider5164f3a2017-07-07 10:26:17 -06001807 if (!list_empty(&ctx->pending_req_list)) {
Jing Zhoud352ed12017-03-20 23:59:56 -07001808 ctx->state = CAM_CTX_READY;
Gregory Bergschneider5164f3a2017-07-07 10:26:17 -06001809 trace_cam_context_state("ISP", ctx);
1810 }
Jing Zhoud352ed12017-03-20 23:59:56 -07001811
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07001812 CAM_DBG(CAM_ISP, "next state %d", ctx->state);
Jing Zhoud352ed12017-03-20 23:59:56 -07001813
1814 return rc;
1815}
1816
1817static int __cam_isp_ctx_unlink_in_acquired(struct cam_context *ctx,
1818 struct cam_req_mgr_core_dev_link_setup *unlink)
1819{
1820 int rc = 0;
1821
Karthik Anantha Ram34dc2652017-10-20 15:49:54 -07001822 ctx->link_hdl = -1;
Jing Zhoud352ed12017-03-20 23:59:56 -07001823 ctx->ctx_crm_intf = NULL;
1824
1825 return rc;
1826}
1827
1828static int __cam_isp_ctx_get_dev_info_in_acquired(struct cam_context *ctx,
1829 struct cam_req_mgr_device_info *dev_info)
1830{
1831 int rc = 0;
1832
1833 dev_info->dev_hdl = ctx->dev_hdl;
1834 strlcpy(dev_info->name, CAM_ISP_DEV_NAME, sizeof(dev_info->name));
1835 dev_info->dev_id = CAM_REQ_MGR_DEVICE_IFE;
1836 dev_info->p_delay = 1;
Junzhe Zou2df84502017-05-26 13:20:23 -07001837 dev_info->trigger = CAM_TRIGGER_POINT_SOF;
Jing Zhoud352ed12017-03-20 23:59:56 -07001838
1839 return rc;
1840}
1841
1842static int __cam_isp_ctx_start_dev_in_ready(struct cam_context *ctx,
1843 struct cam_start_stop_dev_cmd *cmd)
1844{
1845 int rc = 0;
1846 struct cam_hw_start_args arg;
1847 struct cam_ctx_request *req;
1848 struct cam_isp_ctx_req *req_isp;
1849 struct cam_isp_context *ctx_isp =
1850 (struct cam_isp_context *) ctx->ctx_priv;
1851
1852 if (cmd->session_handle != ctx->session_hdl ||
1853 cmd->dev_handle != ctx->dev_hdl) {
1854 rc = -EPERM;
1855 goto end;
1856 }
1857
1858 if (list_empty(&ctx->pending_req_list)) {
1859 /* should never happen */
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07001860 CAM_ERR(CAM_ISP, "Start device with empty configuration");
Jing Zhoud352ed12017-03-20 23:59:56 -07001861 rc = -EFAULT;
1862 goto end;
1863 } else {
1864 req = list_first_entry(&ctx->pending_req_list,
1865 struct cam_ctx_request, list);
1866 }
1867 req_isp = (struct cam_isp_ctx_req *) req->req_priv;
1868
1869 if (!ctx_isp->hw_ctx) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07001870 CAM_ERR(CAM_ISP, "Wrong hw context pointer.");
Jing Zhoud352ed12017-03-20 23:59:56 -07001871 rc = -EFAULT;
1872 goto end;
1873 }
1874 arg.ctxt_to_hw_map = ctx_isp->hw_ctx;
1875 arg.hw_update_entries = req_isp->cfg;
1876 arg.num_hw_update_entries = req_isp->num_cfg;
1877
1878 ctx_isp->frame_id = 0;
Jing Zhoudedc4762017-06-19 17:45:36 +05301879 ctx_isp->active_req_cnt = 0;
1880 ctx_isp->reported_req_id = 0;
Jing Zhoud352ed12017-03-20 23:59:56 -07001881 ctx_isp->substate_activated = CAM_ISP_CTX_ACTIVATED_SOF;
1882
1883 /*
1884 * Only place to change state before calling the hw due to
1885 * hardware tasklet has higher priority that can cause the
1886 * irq handling comes early
1887 */
1888 ctx->state = CAM_CTX_ACTIVATED;
Gregory Bergschneider5164f3a2017-07-07 10:26:17 -06001889 trace_cam_context_state("ISP", ctx);
Jing Zhoud352ed12017-03-20 23:59:56 -07001890 rc = ctx->hw_mgr_intf->hw_start(ctx->hw_mgr_intf->hw_mgr_priv, &arg);
1891 if (rc) {
1892 /* HW failure. user need to clean up the resource */
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07001893 CAM_ERR(CAM_ISP, "Start HW failed");
Jing Zhoud352ed12017-03-20 23:59:56 -07001894 ctx->state = CAM_CTX_READY;
Gregory Bergschneider5164f3a2017-07-07 10:26:17 -06001895 trace_cam_context_state("ISP", ctx);
Jing Zhoud352ed12017-03-20 23:59:56 -07001896 goto end;
1897 }
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07001898 CAM_DBG(CAM_ISP, "start device success");
Jing Zhoud352ed12017-03-20 23:59:56 -07001899end:
1900 return rc;
1901}
1902
1903static int __cam_isp_ctx_unlink_in_ready(struct cam_context *ctx,
1904 struct cam_req_mgr_core_dev_link_setup *unlink)
1905{
1906 int rc = 0;
1907
Karthik Anantha Ram34dc2652017-10-20 15:49:54 -07001908 ctx->link_hdl = -1;
Jing Zhoud352ed12017-03-20 23:59:56 -07001909 ctx->ctx_crm_intf = NULL;
1910 ctx->state = CAM_CTX_ACQUIRED;
Gregory Bergschneider5164f3a2017-07-07 10:26:17 -06001911 trace_cam_context_state("ISP", ctx);
Jing Zhoud352ed12017-03-20 23:59:56 -07001912
1913 return rc;
1914}
1915
1916static int __cam_isp_ctx_stop_dev_in_activated_unlock(
1917 struct cam_context *ctx)
1918{
1919 int rc = 0;
1920 uint32_t i;
1921 struct cam_hw_stop_args stop;
1922 struct cam_ctx_request *req;
1923 struct cam_isp_ctx_req *req_isp;
1924 struct cam_isp_context *ctx_isp =
1925 (struct cam_isp_context *) ctx->ctx_priv;
1926
1927 /* Mask off all the incoming hardware events */
Jing Zhou93b3ec12017-06-15 17:43:39 -07001928 spin_lock_bh(&ctx->lock);
Jing Zhoud352ed12017-03-20 23:59:56 -07001929 ctx_isp->substate_activated = CAM_ISP_CTX_ACTIVATED_HALT;
Jing Zhou93b3ec12017-06-15 17:43:39 -07001930 spin_unlock_bh(&ctx->lock);
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07001931 CAM_DBG(CAM_ISP, "next substate %d", ctx_isp->substate_activated);
Jing Zhoud352ed12017-03-20 23:59:56 -07001932
1933 /* stop hw first */
1934 if (ctx_isp->hw_ctx) {
1935 stop.ctxt_to_hw_map = ctx_isp->hw_ctx;
1936 ctx->hw_mgr_intf->hw_stop(ctx->hw_mgr_intf->hw_mgr_priv,
1937 &stop);
1938 }
1939
1940 while (!list_empty(&ctx->pending_req_list)) {
1941 req = list_first_entry(&ctx->pending_req_list,
1942 struct cam_ctx_request, list);
1943 list_del_init(&req->list);
1944 req_isp = (struct cam_isp_ctx_req *) req->req_priv;
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07001945 CAM_DBG(CAM_ISP, "signal fence in pending list. fence num %d",
1946 req_isp->num_fence_map_out);
Jing Zhoud352ed12017-03-20 23:59:56 -07001947 for (i = 0; i < req_isp->num_fence_map_out; i++)
1948 if (req_isp->fence_map_out[i].sync_id != -1) {
1949 cam_sync_signal(
1950 req_isp->fence_map_out[i].sync_id,
1951 CAM_SYNC_STATE_SIGNALED_ERROR);
1952 }
1953 list_add_tail(&req->list, &ctx->free_req_list);
1954 }
1955
1956 while (!list_empty(&ctx->active_req_list)) {
1957 req = list_first_entry(&ctx->active_req_list,
1958 struct cam_ctx_request, list);
1959 list_del_init(&req->list);
1960 req_isp = (struct cam_isp_ctx_req *) req->req_priv;
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07001961 CAM_DBG(CAM_ISP, "signal fence in active list. fence num %d",
1962 req_isp->num_fence_map_out);
Jing Zhoud352ed12017-03-20 23:59:56 -07001963 for (i = 0; i < req_isp->num_fence_map_out; i++)
1964 if (req_isp->fence_map_out[i].sync_id != -1) {
1965 cam_sync_signal(
1966 req_isp->fence_map_out[i].sync_id,
1967 CAM_SYNC_STATE_SIGNALED_ERROR);
1968 }
1969 list_add_tail(&req->list, &ctx->free_req_list);
1970 }
1971 ctx_isp->frame_id = 0;
Jing Zhoudedc4762017-06-19 17:45:36 +05301972 ctx_isp->active_req_cnt = 0;
1973 ctx_isp->reported_req_id = 0;
Jing Zhoud352ed12017-03-20 23:59:56 -07001974
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07001975 CAM_DBG(CAM_ISP, "next state %d", ctx->state);
Jing Zhoud352ed12017-03-20 23:59:56 -07001976 return rc;
1977}
1978
1979static int __cam_isp_ctx_stop_dev_in_activated(struct cam_context *ctx,
1980 struct cam_start_stop_dev_cmd *cmd)
1981{
1982 int rc = 0;
1983
1984 __cam_isp_ctx_stop_dev_in_activated_unlock(ctx);
1985 ctx->state = CAM_CTX_ACQUIRED;
Gregory Bergschneider5164f3a2017-07-07 10:26:17 -06001986 trace_cam_context_state("ISP", ctx);
Jing Zhoud352ed12017-03-20 23:59:56 -07001987 return rc;
1988}
1989
1990static int __cam_isp_ctx_release_dev_in_activated(struct cam_context *ctx,
1991 struct cam_release_dev_cmd *cmd)
1992{
1993 int rc = 0;
Jing Zhoud352ed12017-03-20 23:59:56 -07001994
Harsh Shah2d96c5e2017-09-29 11:58:45 -07001995 rc = __cam_isp_ctx_stop_dev_in_activated_unlock(ctx);
1996 if (rc)
1997 CAM_ERR(CAM_ISP, "Stop device failed rc=%d", rc);
Jing Zhoud352ed12017-03-20 23:59:56 -07001998
Harsh Shah2d96c5e2017-09-29 11:58:45 -07001999 rc = __cam_isp_ctx_release_dev_in_top_state(ctx, cmd);
2000 if (rc)
2001 CAM_ERR(CAM_ISP, "Release device failed rc=%d", rc);
Jing Zhoud352ed12017-03-20 23:59:56 -07002002
2003 return rc;
2004}
2005
2006static int __cam_isp_ctx_apply_req(struct cam_context *ctx,
2007 struct cam_req_mgr_apply_request *apply)
2008{
2009 int rc = 0;
2010 struct cam_isp_context *ctx_isp =
2011 (struct cam_isp_context *) ctx->ctx_priv;
2012
Junzhe Zou5fa08b12017-08-15 10:08:12 -07002013 trace_cam_apply_req("ISP", apply->request_id);
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07002014 CAM_DBG(CAM_ISP, "Enter: apply req in Substate %d request _id:%lld",
2015 ctx_isp->substate_activated, apply->request_id);
Jing Zhoud352ed12017-03-20 23:59:56 -07002016 if (ctx_isp->substate_machine[ctx_isp->substate_activated].
2017 crm_ops.apply_req) {
2018 rc = ctx_isp->substate_machine[ctx_isp->substate_activated].
2019 crm_ops.apply_req(ctx, apply);
2020 } else {
Harsh Shahcb0072c2017-09-26 19:22:10 -07002021 CAM_ERR_RATE_LIMIT(CAM_ISP,
2022 "No handle function in activated substate %d",
2023 ctx_isp->substate_activated);
Jing Zhoud352ed12017-03-20 23:59:56 -07002024 rc = -EFAULT;
2025 }
2026
2027 if (rc)
Harsh Shahcb0072c2017-09-26 19:22:10 -07002028 CAM_ERR_RATE_LIMIT(CAM_ISP,
2029 "Apply failed in active substate %d",
2030 ctx_isp->substate_activated);
Jing Zhoud352ed12017-03-20 23:59:56 -07002031 return rc;
2032}
2033
2034
2035
2036static int __cam_isp_ctx_handle_irq_in_activated(void *context,
2037 uint32_t evt_id, void *evt_data)
2038{
2039 int rc = 0;
2040 struct cam_context *ctx = (struct cam_context *)context;
2041 struct cam_isp_context *ctx_isp =
2042 (struct cam_isp_context *)ctx->ctx_priv;
2043
Jing Zhou93b3ec12017-06-15 17:43:39 -07002044 spin_lock_bh(&ctx->lock);
Gregory Bergschneider5164f3a2017-07-07 10:26:17 -06002045
2046 trace_cam_isp_activated_irq(ctx, ctx_isp->substate_activated, evt_id,
2047 __cam_isp_ctx_get_event_ts(evt_id, evt_data));
2048
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07002049 CAM_DBG(CAM_ISP, "Enter: State %d, Substate %d, evt id %d",
2050 ctx->state, ctx_isp->substate_activated, evt_id);
Jing Zhoud352ed12017-03-20 23:59:56 -07002051 if (ctx_isp->substate_machine_irq[ctx_isp->substate_activated].
2052 irq_ops[evt_id]) {
2053 rc = ctx_isp->substate_machine_irq[ctx_isp->substate_activated].
2054 irq_ops[evt_id](ctx_isp, evt_data);
2055 } else {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07002056 CAM_DBG(CAM_ISP, "No handle function for substate %d",
Jing Zhoud352ed12017-03-20 23:59:56 -07002057 ctx_isp->substate_activated);
2058 }
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07002059 CAM_DBG(CAM_ISP, "Exit: State %d Substate %d",
2060 ctx->state, ctx_isp->substate_activated);
Jing Zhou93b3ec12017-06-15 17:43:39 -07002061 spin_unlock_bh(&ctx->lock);
Jing Zhoud352ed12017-03-20 23:59:56 -07002062 return rc;
2063}
2064
2065/* top state machine */
2066static struct cam_ctx_ops
2067 cam_isp_ctx_top_state_machine[CAM_CTX_STATE_MAX] = {
2068 /* Uninit */
2069 {
2070 .ioctl_ops = {},
2071 .crm_ops = {},
2072 .irq_ops = NULL,
2073 },
2074 /* Available */
2075 {
2076 .ioctl_ops = {
2077 .acquire_dev = __cam_isp_ctx_acquire_dev_in_available,
2078 },
2079 .crm_ops = {},
2080 .irq_ops = NULL,
2081 },
2082 /* Acquired */
2083 {
2084 .ioctl_ops = {
2085 .release_dev = __cam_isp_ctx_release_dev_in_top_state,
2086 .config_dev = __cam_isp_ctx_config_dev_in_acquired,
2087 },
2088 .crm_ops = {
2089 .link = __cam_isp_ctx_link_in_acquired,
2090 .unlink = __cam_isp_ctx_unlink_in_acquired,
2091 .get_dev_info = __cam_isp_ctx_get_dev_info_in_acquired,
Jing Zhoub524a852017-05-16 15:47:30 +05302092 .flush_req = __cam_isp_ctx_flush_req_in_top_state,
Jing Zhoud352ed12017-03-20 23:59:56 -07002093 },
2094 .irq_ops = NULL,
2095 },
2096 /* Ready */
2097 {
2098 .ioctl_ops = {
2099 .start_dev = __cam_isp_ctx_start_dev_in_ready,
2100 .release_dev = __cam_isp_ctx_release_dev_in_top_state,
2101 .config_dev = __cam_isp_ctx_config_dev_in_top_state,
2102 },
2103 .crm_ops = {
2104 .unlink = __cam_isp_ctx_unlink_in_ready,
Jing Zhoub524a852017-05-16 15:47:30 +05302105 .flush_req = __cam_isp_ctx_flush_req_in_ready,
Jing Zhoud352ed12017-03-20 23:59:56 -07002106 },
2107 .irq_ops = NULL,
2108 },
2109 /* Activated */
2110 {
2111 .ioctl_ops = {
2112 .stop_dev = __cam_isp_ctx_stop_dev_in_activated,
2113 .release_dev = __cam_isp_ctx_release_dev_in_activated,
2114 .config_dev = __cam_isp_ctx_config_dev_in_top_state,
2115 },
2116 .crm_ops = {
2117 .apply_req = __cam_isp_ctx_apply_req,
Jing Zhoub524a852017-05-16 15:47:30 +05302118 .flush_req = __cam_isp_ctx_flush_req_in_top_state,
Jing Zhoud352ed12017-03-20 23:59:56 -07002119 },
2120 .irq_ops = __cam_isp_ctx_handle_irq_in_activated,
2121 },
2122};
2123
2124
2125int cam_isp_context_init(struct cam_isp_context *ctx,
2126 struct cam_context *ctx_base,
2127 struct cam_req_mgr_kmd_ops *crm_node_intf,
2128 struct cam_hw_mgr_intf *hw_intf)
2129
2130{
2131 int rc = -1;
2132 int i;
2133
2134 if (!ctx || !ctx_base) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07002135 CAM_ERR(CAM_ISP, "Invalid Context");
Jing Zhoud352ed12017-03-20 23:59:56 -07002136 goto err;
2137 }
2138
2139 /* ISP context setup */
2140 memset(ctx, 0, sizeof(*ctx));
2141
2142 ctx->base = ctx_base;
2143 ctx->frame_id = 0;
Jing Zhoudedc4762017-06-19 17:45:36 +05302144 ctx->active_req_cnt = 0;
2145 ctx->reported_req_id = 0;
Jing Zhoud352ed12017-03-20 23:59:56 -07002146 ctx->hw_ctx = NULL;
2147 ctx->substate_activated = CAM_ISP_CTX_ACTIVATED_SOF;
2148 ctx->substate_machine = cam_isp_ctx_activated_state_machine;
2149 ctx->substate_machine_irq = cam_isp_ctx_activated_state_machine_irq;
2150
2151 for (i = 0; i < CAM_CTX_REQ_MAX; i++) {
2152 ctx->req_base[i].req_priv = &ctx->req_isp[i];
2153 ctx->req_isp[i].base = &ctx->req_base[i];
2154 }
2155
2156 /* camera context setup */
2157 rc = cam_context_init(ctx_base, crm_node_intf, hw_intf, ctx->req_base,
2158 CAM_CTX_REQ_MAX);
2159 if (rc) {
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07002160 CAM_ERR(CAM_ISP, "Camera Context Base init failed");
Jing Zhoud352ed12017-03-20 23:59:56 -07002161 goto err;
2162 }
2163
2164 /* link camera context with isp context */
2165 ctx_base->state_machine = cam_isp_ctx_top_state_machine;
2166 ctx_base->ctx_priv = ctx;
2167
2168err:
2169 return rc;
2170}
2171
2172int cam_isp_context_deinit(struct cam_isp_context *ctx)
2173{
2174 int rc = 0;
2175
2176 if (ctx->base)
2177 cam_context_deinit(ctx->base);
2178
2179 if (ctx->substate_activated != CAM_ISP_CTX_ACTIVATED_SOF)
Jigarkumar Zala7c4fd372017-07-24 18:43:04 -07002180 CAM_ERR(CAM_ISP, "ISP context substate is invalid");
Jing Zhoud352ed12017-03-20 23:59:56 -07002181
2182 memset(ctx, 0, sizeof(*ctx));
2183 return rc;
2184}
2185