1 // SPDX-License-Identifier: GPL-2.0
2 /*
3 * Support for Clovertrail PNW Camera Imaging ISP subsystem.
4 *
5 * Copyright (c) 2013 Intel Corporation. All Rights Reserved.
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License version
9 * 2 as published by the Free Software Foundation.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 *
17 */
18
19 #include <media/videobuf-vmalloc.h>
20 #include <media/v4l2-dev.h>
21 #include <media/v4l2-event.h>
22
23 #include "mmu/isp_mmu.h"
24 #include "mmu/sh_mmu_mrfld.h"
25 #include "hmm/hmm_bo.h"
26 #include "hmm/hmm.h"
27
28 #include "atomisp_compat.h"
29 #include "atomisp_internal.h"
30 #include "atomisp_cmd.h"
31 #include "atomisp-regs.h"
32 #include "atomisp_fops.h"
33 #include "atomisp_ioctl.h"
34 #include "atomisp_acc.h"
35
36 #include "ia_css_debug.h"
37 #include "ia_css_isp_param.h"
38 #include "sh_css_hrt.h"
39 #include "ia_css_isys.h"
40
41 #include <linux/io.h>
42 #include <linux/pm_runtime.h>
43
44 /* Assume max number of ACC stages */
45 #define MAX_ACC_STAGES 20
46
47 /* Ideally, this should come from CSS headers */
48 #define NO_LINK -1
49
50 /*
51 * to serialize MMIO access , this is due to ISP2400 silicon issue Sighting
52 * #4684168, if concurrency access happened, system may hard hang.
53 */
54 static DEFINE_SPINLOCK(mmio_lock);
55
56 enum frame_info_type {
57 ATOMISP_CSS_VF_FRAME,
58 ATOMISP_CSS_SECOND_VF_FRAME,
59 ATOMISP_CSS_OUTPUT_FRAME,
60 ATOMISP_CSS_SECOND_OUTPUT_FRAME,
61 ATOMISP_CSS_RAW_FRAME,
62 };
63
64 struct bayer_ds_factor {
65 unsigned int numerator;
66 unsigned int denominator;
67 };
68
atomisp_css2_hw_store_8(hrt_address addr,uint8_t data)69 static void atomisp_css2_hw_store_8(hrt_address addr, uint8_t data)
70 {
71 struct atomisp_device *isp = dev_get_drvdata(atomisp_dev);
72 unsigned long flags;
73
74 spin_lock_irqsave(&mmio_lock, flags);
75 writeb(data, isp->base + (addr & 0x003FFFFF));
76 spin_unlock_irqrestore(&mmio_lock, flags);
77 }
78
atomisp_css2_hw_store_16(hrt_address addr,uint16_t data)79 static void atomisp_css2_hw_store_16(hrt_address addr, uint16_t data)
80 {
81 struct atomisp_device *isp = dev_get_drvdata(atomisp_dev);
82 unsigned long flags;
83
84 spin_lock_irqsave(&mmio_lock, flags);
85 writew(data, isp->base + (addr & 0x003FFFFF));
86 spin_unlock_irqrestore(&mmio_lock, flags);
87 }
88
atomisp_css2_hw_store_32(hrt_address addr,uint32_t data)89 void atomisp_css2_hw_store_32(hrt_address addr, uint32_t data)
90 {
91 struct atomisp_device *isp = dev_get_drvdata(atomisp_dev);
92 unsigned long flags;
93
94 spin_lock_irqsave(&mmio_lock, flags);
95 writel(data, isp->base + (addr & 0x003FFFFF));
96 spin_unlock_irqrestore(&mmio_lock, flags);
97 }
98
atomisp_css2_hw_load_8(hrt_address addr)99 static uint8_t atomisp_css2_hw_load_8(hrt_address addr)
100 {
101 struct atomisp_device *isp = dev_get_drvdata(atomisp_dev);
102 unsigned long flags;
103 u8 ret;
104
105 spin_lock_irqsave(&mmio_lock, flags);
106 ret = readb(isp->base + (addr & 0x003FFFFF));
107 spin_unlock_irqrestore(&mmio_lock, flags);
108 return ret;
109 }
110
atomisp_css2_hw_load_16(hrt_address addr)111 static uint16_t atomisp_css2_hw_load_16(hrt_address addr)
112 {
113 struct atomisp_device *isp = dev_get_drvdata(atomisp_dev);
114 unsigned long flags;
115 u16 ret;
116
117 spin_lock_irqsave(&mmio_lock, flags);
118 ret = readw(isp->base + (addr & 0x003FFFFF));
119 spin_unlock_irqrestore(&mmio_lock, flags);
120 return ret;
121 }
122
atomisp_css2_hw_load_32(hrt_address addr)123 static uint32_t atomisp_css2_hw_load_32(hrt_address addr)
124 {
125 struct atomisp_device *isp = dev_get_drvdata(atomisp_dev);
126 unsigned long flags;
127 u32 ret;
128
129 spin_lock_irqsave(&mmio_lock, flags);
130 ret = readl(isp->base + (addr & 0x003FFFFF));
131 spin_unlock_irqrestore(&mmio_lock, flags);
132 return ret;
133 }
134
atomisp_css2_hw_store(hrt_address addr,const void * from,uint32_t n)135 static void atomisp_css2_hw_store(hrt_address addr, const void *from, uint32_t n)
136 {
137 struct atomisp_device *isp = dev_get_drvdata(atomisp_dev);
138 unsigned long flags;
139 unsigned int i;
140
141 addr &= 0x003FFFFF;
142 spin_lock_irqsave(&mmio_lock, flags);
143 for (i = 0; i < n; i++, from++)
144 writeb(*(s8 *)from, isp->base + addr + i);
145
146 spin_unlock_irqrestore(&mmio_lock, flags);
147 }
148
atomisp_css2_hw_load(hrt_address addr,void * to,uint32_t n)149 static void atomisp_css2_hw_load(hrt_address addr, void *to, uint32_t n)
150 {
151 struct atomisp_device *isp = dev_get_drvdata(atomisp_dev);
152 unsigned long flags;
153 unsigned int i;
154
155 addr &= 0x003FFFFF;
156 spin_lock_irqsave(&mmio_lock, flags);
157 for (i = 0; i < n; i++, to++)
158 *(s8 *)to = readb(isp->base + addr + i);
159 spin_unlock_irqrestore(&mmio_lock, flags);
160 }
161
atomisp_css2_dbg_ftrace_print(const char * fmt,va_list args)162 static int __printf(1, 0) atomisp_css2_dbg_ftrace_print(const char *fmt,
163 va_list args)
164 {
165 ftrace_vprintk(fmt, args);
166 return 0;
167 }
168
atomisp_vprintk(const char * fmt,va_list args)169 static int __printf(1, 0) atomisp_vprintk(const char *fmt, va_list args)
170 {
171 vprintk(fmt, args);
172 return 0;
173 }
174
atomisp_load_uint32(hrt_address addr,uint32_t * data)175 void atomisp_load_uint32(hrt_address addr, uint32_t *data)
176 {
177 *data = atomisp_css2_hw_load_32(addr);
178 }
179
hmm_get_mmu_base_addr(struct device * dev,unsigned int * mmu_base_addr)180 static int hmm_get_mmu_base_addr(struct device *dev, unsigned int *mmu_base_addr)
181 {
182 if (!sh_mmu_mrfld.get_pd_base) {
183 dev_err(dev, "get mmu base address failed.\n");
184 return -EINVAL;
185 }
186
187 *mmu_base_addr = sh_mmu_mrfld.get_pd_base(&bo_device.mmu,
188 bo_device.mmu.base_address);
189 return 0;
190 }
191
__dump_pipe_config(struct atomisp_sub_device * asd,struct atomisp_stream_env * stream_env,unsigned int pipe_id)192 static void __dump_pipe_config(struct atomisp_sub_device *asd,
193 struct atomisp_stream_env *stream_env,
194 unsigned int pipe_id)
195 {
196 struct atomisp_device *isp = asd->isp;
197
198 if (stream_env->pipes[pipe_id]) {
199 struct ia_css_pipe_config *p_config;
200 struct ia_css_pipe_extra_config *pe_config;
201
202 p_config = &stream_env->pipe_configs[pipe_id];
203 pe_config = &stream_env->pipe_extra_configs[pipe_id];
204 dev_dbg(isp->dev, "dumping pipe[%d] config:\n", pipe_id);
205 dev_dbg(isp->dev,
206 "pipe_config.pipe_mode:%d.\n", p_config->mode);
207 dev_dbg(isp->dev,
208 "pipe_config.output_info[0] w=%d, h=%d.\n",
209 p_config->output_info[0].res.width,
210 p_config->output_info[0].res.height);
211 dev_dbg(isp->dev,
212 "pipe_config.vf_pp_in_res w=%d, h=%d.\n",
213 p_config->vf_pp_in_res.width,
214 p_config->vf_pp_in_res.height);
215 dev_dbg(isp->dev,
216 "pipe_config.capt_pp_in_res w=%d, h=%d.\n",
217 p_config->capt_pp_in_res.width,
218 p_config->capt_pp_in_res.height);
219 dev_dbg(isp->dev,
220 "pipe_config.output.padded w=%d.\n",
221 p_config->output_info[0].padded_width);
222 dev_dbg(isp->dev,
223 "pipe_config.vf_output_info[0] w=%d, h=%d.\n",
224 p_config->vf_output_info[0].res.width,
225 p_config->vf_output_info[0].res.height);
226 dev_dbg(isp->dev,
227 "pipe_config.bayer_ds_out_res w=%d, h=%d.\n",
228 p_config->bayer_ds_out_res.width,
229 p_config->bayer_ds_out_res.height);
230 dev_dbg(isp->dev,
231 "pipe_config.envelope w=%d, h=%d.\n",
232 p_config->dvs_envelope.width,
233 p_config->dvs_envelope.height);
234 dev_dbg(isp->dev,
235 "pipe_config.dvs_frame_delay=%d.\n",
236 p_config->dvs_frame_delay);
237 dev_dbg(isp->dev,
238 "pipe_config.isp_pipe_version:%d.\n",
239 p_config->isp_pipe_version);
240 dev_dbg(isp->dev,
241 "pipe_config.acc_extension=%p.\n",
242 p_config->acc_extension);
243 dev_dbg(isp->dev,
244 "pipe_config.acc_stages=%p.\n",
245 p_config->acc_stages);
246 dev_dbg(isp->dev,
247 "pipe_config.num_acc_stages=%d.\n",
248 p_config->num_acc_stages);
249 dev_dbg(isp->dev,
250 "pipe_config.acc_num_execs=%d.\n",
251 p_config->acc_num_execs);
252 dev_dbg(isp->dev,
253 "pipe_config.default_capture_config.capture_mode=%d.\n",
254 p_config->default_capture_config.mode);
255 dev_dbg(isp->dev,
256 "pipe_config.enable_dz=%d.\n",
257 p_config->enable_dz);
258 dev_dbg(isp->dev,
259 "pipe_config.default_capture_config.enable_xnr=%d.\n",
260 p_config->default_capture_config.enable_xnr);
261 dev_dbg(isp->dev,
262 "dumping pipe[%d] extra config:\n", pipe_id);
263 dev_dbg(isp->dev,
264 "pipe_extra_config.enable_raw_binning:%d.\n",
265 pe_config->enable_raw_binning);
266 dev_dbg(isp->dev,
267 "pipe_extra_config.enable_yuv_ds:%d.\n",
268 pe_config->enable_yuv_ds);
269 dev_dbg(isp->dev,
270 "pipe_extra_config.enable_high_speed:%d.\n",
271 pe_config->enable_high_speed);
272 dev_dbg(isp->dev,
273 "pipe_extra_config.enable_dvs_6axis:%d.\n",
274 pe_config->enable_dvs_6axis);
275 dev_dbg(isp->dev,
276 "pipe_extra_config.enable_reduced_pipe:%d.\n",
277 pe_config->enable_reduced_pipe);
278 dev_dbg(isp->dev,
279 "pipe_(extra_)config.enable_dz:%d.\n",
280 p_config->enable_dz);
281 dev_dbg(isp->dev,
282 "pipe_extra_config.disable_vf_pp:%d.\n",
283 pe_config->disable_vf_pp);
284 }
285 }
286
__dump_stream_config(struct atomisp_sub_device * asd,struct atomisp_stream_env * stream_env)287 static void __dump_stream_config(struct atomisp_sub_device *asd,
288 struct atomisp_stream_env *stream_env)
289 {
290 struct atomisp_device *isp = asd->isp;
291 struct ia_css_stream_config *s_config;
292 int j;
293 bool valid_stream = false;
294
295 for (j = 0; j < IA_CSS_PIPE_ID_NUM; j++) {
296 if (stream_env->pipes[j]) {
297 __dump_pipe_config(asd, stream_env, j);
298 valid_stream = true;
299 }
300 }
301 if (!valid_stream)
302 return;
303 s_config = &stream_env->stream_config;
304 dev_dbg(isp->dev, "stream_config.mode=%d.\n", s_config->mode);
305
306 if (s_config->mode == IA_CSS_INPUT_MODE_SENSOR ||
307 s_config->mode == IA_CSS_INPUT_MODE_BUFFERED_SENSOR) {
308 dev_dbg(isp->dev, "stream_config.source.port.port=%d.\n",
309 s_config->source.port.port);
310 dev_dbg(isp->dev, "stream_config.source.port.num_lanes=%d.\n",
311 s_config->source.port.num_lanes);
312 dev_dbg(isp->dev, "stream_config.source.port.timeout=%d.\n",
313 s_config->source.port.timeout);
314 dev_dbg(isp->dev, "stream_config.source.port.rxcount=0x%x.\n",
315 s_config->source.port.rxcount);
316 dev_dbg(isp->dev, "stream_config.source.port.compression.type=%d.\n",
317 s_config->source.port.compression.type);
318 dev_dbg(isp->dev,
319 "stream_config.source.port.compression.compressed_bits_per_pixel=%d.\n",
320 s_config->source.port.compression.
321 compressed_bits_per_pixel);
322 dev_dbg(isp->dev,
323 "stream_config.source.port.compression.uncompressed_bits_per_pixel=%d.\n",
324 s_config->source.port.compression.
325 uncompressed_bits_per_pixel);
326 } else if (s_config->mode == IA_CSS_INPUT_MODE_TPG) {
327 dev_dbg(isp->dev, "stream_config.source.tpg.id=%d.\n",
328 s_config->source.tpg.id);
329 dev_dbg(isp->dev, "stream_config.source.tpg.mode=%d.\n",
330 s_config->source.tpg.mode);
331 dev_dbg(isp->dev, "stream_config.source.tpg.x_mask=%d.\n",
332 s_config->source.tpg.x_mask);
333 dev_dbg(isp->dev, "stream_config.source.tpg.x_delta=%d.\n",
334 s_config->source.tpg.x_delta);
335 dev_dbg(isp->dev, "stream_config.source.tpg.y_mask=%d.\n",
336 s_config->source.tpg.y_mask);
337 dev_dbg(isp->dev, "stream_config.source.tpg.y_delta=%d.\n",
338 s_config->source.tpg.y_delta);
339 dev_dbg(isp->dev, "stream_config.source.tpg.xy_mask=%d.\n",
340 s_config->source.tpg.xy_mask);
341 } else if (s_config->mode == IA_CSS_INPUT_MODE_PRBS) {
342 dev_dbg(isp->dev, "stream_config.source.prbs.id=%d.\n",
343 s_config->source.prbs.id);
344 dev_dbg(isp->dev, "stream_config.source.prbs.h_blank=%d.\n",
345 s_config->source.prbs.h_blank);
346 dev_dbg(isp->dev, "stream_config.source.prbs.v_blank=%d.\n",
347 s_config->source.prbs.v_blank);
348 dev_dbg(isp->dev, "stream_config.source.prbs.seed=%d.\n",
349 s_config->source.prbs.seed);
350 dev_dbg(isp->dev, "stream_config.source.prbs.seed1=%d.\n",
351 s_config->source.prbs.seed1);
352 }
353
354 for (j = 0; j < IA_CSS_STREAM_MAX_ISYS_STREAM_PER_CH; j++) {
355 dev_dbg(isp->dev, "stream_configisys_config[%d].input_res w=%d, h=%d.\n",
356 j,
357 s_config->isys_config[j].input_res.width,
358 s_config->isys_config[j].input_res.height);
359
360 dev_dbg(isp->dev, "stream_configisys_config[%d].linked_isys_stream_id=%d\n",
361 j,
362 s_config->isys_config[j].linked_isys_stream_id);
363
364 dev_dbg(isp->dev, "stream_configisys_config[%d].format=%d\n",
365 j,
366 s_config->isys_config[j].format);
367
368 dev_dbg(isp->dev, "stream_configisys_config[%d].valid=%d.\n",
369 j,
370 s_config->isys_config[j].valid);
371 }
372
373 dev_dbg(isp->dev, "stream_config.input_config.input_res w=%d, h=%d.\n",
374 s_config->input_config.input_res.width,
375 s_config->input_config.input_res.height);
376
377 dev_dbg(isp->dev, "stream_config.input_config.effective_res w=%d, h=%d.\n",
378 s_config->input_config.effective_res.width,
379 s_config->input_config.effective_res.height);
380
381 dev_dbg(isp->dev, "stream_config.input_config.format=%d\n",
382 s_config->input_config.format);
383
384 dev_dbg(isp->dev, "stream_config.input_config.bayer_order=%d.\n",
385 s_config->input_config.bayer_order);
386
387 dev_dbg(isp->dev, "stream_config.pixels_per_clock=%d.\n",
388 s_config->pixels_per_clock);
389 dev_dbg(isp->dev, "stream_config.online=%d.\n", s_config->online);
390 dev_dbg(isp->dev, "stream_config.continuous=%d.\n",
391 s_config->continuous);
392 dev_dbg(isp->dev, "stream_config.disable_cont_viewfinder=%d.\n",
393 s_config->disable_cont_viewfinder);
394 dev_dbg(isp->dev, "stream_config.channel_id=%d.\n",
395 s_config->channel_id);
396 dev_dbg(isp->dev, "stream_config.init_num_cont_raw_buf=%d.\n",
397 s_config->init_num_cont_raw_buf);
398 dev_dbg(isp->dev, "stream_config.target_num_cont_raw_buf=%d.\n",
399 s_config->target_num_cont_raw_buf);
400 dev_dbg(isp->dev, "stream_config.left_padding=%d.\n",
401 s_config->left_padding);
402 dev_dbg(isp->dev, "stream_config.sensor_binning_factor=%d.\n",
403 s_config->sensor_binning_factor);
404 dev_dbg(isp->dev, "stream_config.pixels_per_clock=%d.\n",
405 s_config->pixels_per_clock);
406 dev_dbg(isp->dev, "stream_config.pack_raw_pixels=%d.\n",
407 s_config->pack_raw_pixels);
408 dev_dbg(isp->dev, "stream_config.flash_gpio_pin=%d.\n",
409 s_config->flash_gpio_pin);
410 dev_dbg(isp->dev, "stream_config.mipi_buffer_config.size_mem_words=%d.\n",
411 s_config->mipi_buffer_config.size_mem_words);
412 dev_dbg(isp->dev, "stream_config.mipi_buffer_config.contiguous=%d.\n",
413 s_config->mipi_buffer_config.contiguous);
414 dev_dbg(isp->dev, "stream_config.metadata_config.data_type=%d.\n",
415 s_config->metadata_config.data_type);
416 dev_dbg(isp->dev, "stream_config.metadata_config.resolution w=%d, h=%d.\n",
417 s_config->metadata_config.resolution.width,
418 s_config->metadata_config.resolution.height);
419 }
420
__destroy_stream(struct atomisp_sub_device * asd,struct atomisp_stream_env * stream_env,bool force)421 static int __destroy_stream(struct atomisp_sub_device *asd,
422 struct atomisp_stream_env *stream_env, bool force)
423 {
424 struct atomisp_device *isp = asd->isp;
425 int i;
426 unsigned long timeout;
427
428 if (!stream_env->stream)
429 return 0;
430
431 if (!force) {
432 for (i = 0; i < IA_CSS_PIPE_ID_NUM; i++)
433 if (stream_env->update_pipe[i])
434 break;
435
436 if (i == IA_CSS_PIPE_ID_NUM)
437 return 0;
438 }
439
440 if (stream_env->stream_state == CSS_STREAM_STARTED
441 && ia_css_stream_stop(stream_env->stream) != 0) {
442 dev_err(isp->dev, "stop stream failed.\n");
443 return -EINVAL;
444 }
445
446 if (stream_env->stream_state == CSS_STREAM_STARTED) {
447 timeout = jiffies + msecs_to_jiffies(40);
448 while (1) {
449 if (ia_css_stream_has_stopped(stream_env->stream))
450 break;
451
452 if (time_after(jiffies, timeout)) {
453 dev_warn(isp->dev, "stop stream timeout.\n");
454 break;
455 }
456
457 usleep_range(100, 200);
458 }
459 }
460
461 stream_env->stream_state = CSS_STREAM_STOPPED;
462
463 if (ia_css_stream_destroy(stream_env->stream)) {
464 dev_err(isp->dev, "destroy stream failed.\n");
465 return -EINVAL;
466 }
467 stream_env->stream_state = CSS_STREAM_UNINIT;
468 stream_env->stream = NULL;
469
470 return 0;
471 }
472
__destroy_streams(struct atomisp_sub_device * asd,bool force)473 static int __destroy_streams(struct atomisp_sub_device *asd, bool force)
474 {
475 int ret, i;
476
477 for (i = 0; i < ATOMISP_INPUT_STREAM_NUM; i++) {
478 ret = __destroy_stream(asd, &asd->stream_env[i], force);
479 if (ret)
480 return ret;
481 }
482 asd->stream_prepared = false;
483 return 0;
484 }
485
__create_stream(struct atomisp_sub_device * asd,struct atomisp_stream_env * stream_env)486 static int __create_stream(struct atomisp_sub_device *asd,
487 struct atomisp_stream_env *stream_env)
488 {
489 int pipe_index = 0, i;
490 struct ia_css_pipe *multi_pipes[IA_CSS_PIPE_ID_NUM];
491
492 for (i = 0; i < IA_CSS_PIPE_ID_NUM; i++) {
493 if (stream_env->pipes[i])
494 multi_pipes[pipe_index++] = stream_env->pipes[i];
495 }
496 if (pipe_index == 0)
497 return 0;
498
499 stream_env->stream_config.target_num_cont_raw_buf =
500 asd->continuous_raw_buffer_size->val;
501 stream_env->stream_config.channel_id = stream_env->ch_id;
502 stream_env->stream_config.ia_css_enable_raw_buffer_locking =
503 asd->enable_raw_buffer_lock->val;
504
505 __dump_stream_config(asd, stream_env);
506 if (ia_css_stream_create(&stream_env->stream_config,
507 pipe_index, multi_pipes, &stream_env->stream) != 0)
508 return -EINVAL;
509 if (ia_css_stream_get_info(stream_env->stream,
510 &stream_env->stream_info) != 0) {
511 ia_css_stream_destroy(stream_env->stream);
512 stream_env->stream = NULL;
513 return -EINVAL;
514 }
515
516 stream_env->stream_state = CSS_STREAM_CREATED;
517 return 0;
518 }
519
__create_streams(struct atomisp_sub_device * asd)520 static int __create_streams(struct atomisp_sub_device *asd)
521 {
522 int ret, i;
523
524 for (i = 0; i < ATOMISP_INPUT_STREAM_NUM; i++) {
525 ret = __create_stream(asd, &asd->stream_env[i]);
526 if (ret)
527 goto rollback;
528 }
529 asd->stream_prepared = true;
530 return 0;
531 rollback:
532 for (i--; i >= 0; i--)
533 __destroy_stream(asd, &asd->stream_env[i], true);
534 return ret;
535 }
536
__destroy_stream_pipes(struct atomisp_sub_device * asd,struct atomisp_stream_env * stream_env,bool force)537 static int __destroy_stream_pipes(struct atomisp_sub_device *asd,
538 struct atomisp_stream_env *stream_env,
539 bool force)
540 {
541 struct atomisp_device *isp = asd->isp;
542 int ret = 0;
543 int i;
544
545 for (i = 0; i < IA_CSS_PIPE_ID_NUM; i++) {
546 if (!stream_env->pipes[i] ||
547 !(force || stream_env->update_pipe[i]))
548 continue;
549 if (ia_css_pipe_destroy(stream_env->pipes[i])
550 != 0) {
551 dev_err(isp->dev,
552 "destroy pipe[%d]failed.cannot recover.\n", i);
553 ret = -EINVAL;
554 }
555 stream_env->pipes[i] = NULL;
556 stream_env->update_pipe[i] = false;
557 }
558 return ret;
559 }
560
__destroy_pipes(struct atomisp_sub_device * asd,bool force)561 static int __destroy_pipes(struct atomisp_sub_device *asd, bool force)
562 {
563 struct atomisp_device *isp = asd->isp;
564 int i;
565 int ret = 0;
566
567 for (i = 0; i < ATOMISP_INPUT_STREAM_NUM; i++) {
568 if (asd->stream_env[i].stream) {
569 dev_err(isp->dev,
570 "cannot destroy css pipes for stream[%d].\n",
571 i);
572 continue;
573 }
574
575 ret = __destroy_stream_pipes(asd, &asd->stream_env[i], force);
576 if (ret)
577 return ret;
578 }
579
580 return 0;
581 }
582
atomisp_destroy_pipes_stream_force(struct atomisp_sub_device * asd)583 void atomisp_destroy_pipes_stream_force(struct atomisp_sub_device *asd)
584 {
585 __destroy_streams(asd, true);
586 __destroy_pipes(asd, true);
587 }
588
__apply_additional_pipe_config(struct atomisp_sub_device * asd,struct atomisp_stream_env * stream_env,enum ia_css_pipe_id pipe_id)589 static void __apply_additional_pipe_config(
590 struct atomisp_sub_device *asd,
591 struct atomisp_stream_env *stream_env,
592 enum ia_css_pipe_id pipe_id)
593 {
594 struct atomisp_device *isp = asd->isp;
595
596 if (pipe_id < 0 || pipe_id >= IA_CSS_PIPE_ID_NUM) {
597 dev_err(isp->dev,
598 "wrong pipe_id for additional pipe config.\n");
599 return;
600 }
601
602 /* apply default pipe config */
603 stream_env->pipe_configs[pipe_id].isp_pipe_version = 2;
604 stream_env->pipe_configs[pipe_id].enable_dz =
605 asd->disable_dz->val ? false : true;
606 /* apply isp 2.2 specific config for baytrail*/
607 switch (pipe_id) {
608 case IA_CSS_PIPE_ID_CAPTURE:
609 /* enable capture pp/dz manually or digital zoom would
610 * fail*/
611 if (stream_env->pipe_configs[pipe_id].
612 default_capture_config.mode == IA_CSS_CAPTURE_MODE_RAW)
613 stream_env->pipe_configs[pipe_id].enable_dz = false;
614
615 if (IS_ISP2401) {
616 /* the isp default to use ISP2.2 and the camera hal will
617 * control whether use isp2.7 */
618 if (asd->select_isp_version->val == ATOMISP_CSS_ISP_PIPE_VERSION_2_7)
619 stream_env->pipe_configs[pipe_id].isp_pipe_version = SH_CSS_ISP_PIPE_VERSION_2_7;
620 else
621 stream_env->pipe_configs[pipe_id].isp_pipe_version = SH_CSS_ISP_PIPE_VERSION_2_2;
622 }
623 break;
624 case IA_CSS_PIPE_ID_VIDEO:
625 /* enable reduced pipe to have binary
626 * video_dz_2_min selected*/
627 stream_env->pipe_extra_configs[pipe_id]
628 .enable_reduced_pipe = true;
629 stream_env->pipe_configs[pipe_id]
630 .enable_dz = false;
631 if (ATOMISP_SOC_CAMERA(asd))
632 stream_env->pipe_configs[pipe_id].enable_dz = true;
633
634 if (asd->params.video_dis_en) {
635 stream_env->pipe_extra_configs[pipe_id]
636 .enable_dvs_6axis = true;
637 stream_env->pipe_configs[pipe_id]
638 .dvs_frame_delay =
639 ATOMISP_CSS2_NUM_DVS_FRAME_DELAY;
640 }
641 break;
642 case IA_CSS_PIPE_ID_PREVIEW:
643 break;
644 case IA_CSS_PIPE_ID_YUVPP:
645 case IA_CSS_PIPE_ID_COPY:
646 if (ATOMISP_SOC_CAMERA(asd))
647 stream_env->pipe_configs[pipe_id].enable_dz = true;
648 else
649 stream_env->pipe_configs[pipe_id].enable_dz = false;
650 break;
651 case IA_CSS_PIPE_ID_ACC:
652 stream_env->pipe_configs[pipe_id].mode = IA_CSS_PIPE_MODE_ACC;
653 stream_env->pipe_configs[pipe_id].enable_dz = false;
654 break;
655 default:
656 break;
657 }
658 }
659
is_pipe_valid_to_current_run_mode(struct atomisp_sub_device * asd,enum ia_css_pipe_id pipe_id)660 static bool is_pipe_valid_to_current_run_mode(struct atomisp_sub_device *asd,
661 enum ia_css_pipe_id pipe_id)
662 {
663 if (!asd)
664 return false;
665
666 if (pipe_id == IA_CSS_PIPE_ID_ACC || pipe_id == IA_CSS_PIPE_ID_YUVPP)
667 return true;
668
669 if (asd->vfpp) {
670 if (asd->vfpp->val == ATOMISP_VFPP_DISABLE_SCALER) {
671 if (pipe_id == IA_CSS_PIPE_ID_VIDEO)
672 return true;
673 else
674 return false;
675 } else if (asd->vfpp->val == ATOMISP_VFPP_DISABLE_LOWLAT) {
676 if (pipe_id == IA_CSS_PIPE_ID_CAPTURE)
677 return true;
678 else
679 return false;
680 }
681 }
682
683 if (!asd->run_mode)
684 return false;
685
686 if (asd->copy_mode && pipe_id == IA_CSS_PIPE_ID_COPY)
687 return true;
688
689 switch (asd->run_mode->val) {
690 case ATOMISP_RUN_MODE_STILL_CAPTURE:
691 if (pipe_id == IA_CSS_PIPE_ID_CAPTURE)
692 return true;
693
694 return false;
695 case ATOMISP_RUN_MODE_PREVIEW:
696 if (!asd->continuous_mode->val) {
697 if (pipe_id == IA_CSS_PIPE_ID_PREVIEW)
698 return true;
699
700 return false;
701 }
702 fallthrough;
703 case ATOMISP_RUN_MODE_CONTINUOUS_CAPTURE:
704 if (pipe_id == IA_CSS_PIPE_ID_CAPTURE ||
705 pipe_id == IA_CSS_PIPE_ID_PREVIEW)
706 return true;
707
708 return false;
709 case ATOMISP_RUN_MODE_VIDEO:
710 if (!asd->continuous_mode->val) {
711 if (pipe_id == IA_CSS_PIPE_ID_VIDEO ||
712 pipe_id == IA_CSS_PIPE_ID_YUVPP)
713 return true;
714 else
715 return false;
716 }
717 fallthrough;
718 case ATOMISP_RUN_MODE_SDV:
719 if (pipe_id == IA_CSS_PIPE_ID_CAPTURE ||
720 pipe_id == IA_CSS_PIPE_ID_VIDEO)
721 return true;
722
723 return false;
724 }
725
726 return false;
727 }
728
__create_pipe(struct atomisp_sub_device * asd,struct atomisp_stream_env * stream_env,enum ia_css_pipe_id pipe_id)729 static int __create_pipe(struct atomisp_sub_device *asd,
730 struct atomisp_stream_env *stream_env,
731 enum ia_css_pipe_id pipe_id)
732 {
733 struct atomisp_device *isp = asd->isp;
734 struct ia_css_pipe_extra_config extra_config;
735 int ret;
736
737 if (pipe_id >= IA_CSS_PIPE_ID_NUM)
738 return -EINVAL;
739
740 if (pipe_id != IA_CSS_PIPE_ID_ACC &&
741 !stream_env->pipe_configs[pipe_id].output_info[0].res.width)
742 return 0;
743
744 if (pipe_id == IA_CSS_PIPE_ID_ACC &&
745 !stream_env->pipe_configs[pipe_id].acc_extension)
746 return 0;
747
748 if (!is_pipe_valid_to_current_run_mode(asd, pipe_id))
749 return 0;
750
751 ia_css_pipe_extra_config_defaults(&extra_config);
752
753 __apply_additional_pipe_config(asd, stream_env, pipe_id);
754 if (!memcmp(&extra_config,
755 &stream_env->pipe_extra_configs[pipe_id],
756 sizeof(extra_config)))
757 ret = ia_css_pipe_create(
758 &stream_env->pipe_configs[pipe_id],
759 &stream_env->pipes[pipe_id]);
760 else
761 ret = ia_css_pipe_create_extra(
762 &stream_env->pipe_configs[pipe_id],
763 &stream_env->pipe_extra_configs[pipe_id],
764 &stream_env->pipes[pipe_id]);
765 if (ret)
766 dev_err(isp->dev, "create pipe[%d] error.\n", pipe_id);
767 return ret;
768 }
769
__create_pipes(struct atomisp_sub_device * asd)770 static int __create_pipes(struct atomisp_sub_device *asd)
771 {
772 int ret;
773 int i, j;
774
775 for (i = 0; i < ATOMISP_INPUT_STREAM_NUM; i++) {
776 for (j = 0; j < IA_CSS_PIPE_ID_NUM; j++) {
777 ret = __create_pipe(asd, &asd->stream_env[i], j);
778 if (ret)
779 break;
780 }
781 if (j < IA_CSS_PIPE_ID_NUM)
782 goto pipe_err;
783 }
784 return 0;
785 pipe_err:
786 for (; i >= 0; i--) {
787 for (j--; j >= 0; j--) {
788 if (asd->stream_env[i].pipes[j]) {
789 ia_css_pipe_destroy(asd->stream_env[i].pipes[j]);
790 asd->stream_env[i].pipes[j] = NULL;
791 }
792 }
793 j = IA_CSS_PIPE_ID_NUM;
794 }
795 return -EINVAL;
796 }
797
atomisp_create_pipes_stream(struct atomisp_sub_device * asd)798 void atomisp_create_pipes_stream(struct atomisp_sub_device *asd)
799 {
800 __create_pipes(asd);
801 __create_streams(asd);
802 }
803
atomisp_css_update_stream(struct atomisp_sub_device * asd)804 int atomisp_css_update_stream(struct atomisp_sub_device *asd)
805 {
806 int ret;
807 struct atomisp_device *isp = asd->isp;
808
809 if (__destroy_streams(asd, true))
810 dev_warn(isp->dev, "destroy stream failed.\n");
811
812 if (__destroy_pipes(asd, true))
813 dev_warn(isp->dev, "destroy pipe failed.\n");
814
815 ret = __create_pipes(asd);
816 if (ret) {
817 dev_err(isp->dev, "create pipe failed %d.\n", ret);
818 return -EIO;
819 }
820
821 ret = __create_streams(asd);
822 if (ret) {
823 dev_warn(isp->dev, "create stream failed %d.\n", ret);
824 __destroy_pipes(asd, true);
825 return -EIO;
826 }
827
828 return 0;
829 }
830
atomisp_css_init(struct atomisp_device * isp)831 int atomisp_css_init(struct atomisp_device *isp)
832 {
833 unsigned int mmu_base_addr;
834 int ret;
835 int err;
836
837 ret = hmm_get_mmu_base_addr(isp->dev, &mmu_base_addr);
838 if (ret)
839 return ret;
840
841 /* Init ISP */
842 err = ia_css_init(isp->dev, &isp->css_env.isp_css_env, NULL,
843 (uint32_t)mmu_base_addr, IA_CSS_IRQ_TYPE_PULSE);
844 if (err) {
845 dev_err(isp->dev, "css init failed --- bad firmware?\n");
846 return -EINVAL;
847 }
848 ia_css_enable_isys_event_queue(true);
849
850 isp->css_initialized = true;
851 dev_dbg(isp->dev, "sh_css_init success\n");
852
853 return 0;
854 }
855
__set_css_print_env(struct atomisp_device * isp,int opt)856 static inline int __set_css_print_env(struct atomisp_device *isp, int opt)
857 {
858 int ret = 0;
859
860 if (opt == 0)
861 isp->css_env.isp_css_env.print_env.debug_print = NULL;
862 else if (opt == 1)
863 isp->css_env.isp_css_env.print_env.debug_print =
864 atomisp_css2_dbg_ftrace_print;
865 else if (opt == 2)
866 isp->css_env.isp_css_env.print_env.debug_print = atomisp_vprintk;
867 else
868 ret = -EINVAL;
869
870 return ret;
871 }
872
atomisp_css_load_firmware(struct atomisp_device * isp)873 int atomisp_css_load_firmware(struct atomisp_device *isp)
874 {
875 int err;
876
877 /* set css env */
878 isp->css_env.isp_css_fw.data = (void *)isp->firmware->data;
879 isp->css_env.isp_css_fw.bytes = isp->firmware->size;
880
881 isp->css_env.isp_css_env.hw_access_env.store_8 =
882 atomisp_css2_hw_store_8;
883 isp->css_env.isp_css_env.hw_access_env.store_16 =
884 atomisp_css2_hw_store_16;
885 isp->css_env.isp_css_env.hw_access_env.store_32 =
886 atomisp_css2_hw_store_32;
887
888 isp->css_env.isp_css_env.hw_access_env.load_8 = atomisp_css2_hw_load_8;
889 isp->css_env.isp_css_env.hw_access_env.load_16 =
890 atomisp_css2_hw_load_16;
891 isp->css_env.isp_css_env.hw_access_env.load_32 =
892 atomisp_css2_hw_load_32;
893
894 isp->css_env.isp_css_env.hw_access_env.load = atomisp_css2_hw_load;
895 isp->css_env.isp_css_env.hw_access_env.store = atomisp_css2_hw_store;
896
897 __set_css_print_env(isp, dbg_func);
898
899 isp->css_env.isp_css_env.print_env.error_print = atomisp_vprintk;
900
901 /* load isp fw into ISP memory */
902 err = ia_css_load_firmware(isp->dev, &isp->css_env.isp_css_env,
903 &isp->css_env.isp_css_fw);
904 if (err) {
905 dev_err(isp->dev, "css load fw failed.\n");
906 return -EINVAL;
907 }
908
909 return 0;
910 }
911
atomisp_css_uninit(struct atomisp_device * isp)912 void atomisp_css_uninit(struct atomisp_device *isp)
913 {
914 struct atomisp_sub_device *asd;
915 unsigned int i;
916
917 for (i = 0; i < isp->num_of_streams; i++) {
918 asd = &isp->asd[i];
919 memset(&asd->params.config, 0, sizeof(asd->params.config));
920 asd->params.css_update_params_needed = false;
921 }
922
923 isp->css_initialized = false;
924 ia_css_uninit();
925 }
926
atomisp_css_suspend(struct atomisp_device * isp)927 void atomisp_css_suspend(struct atomisp_device *isp)
928 {
929 isp->css_initialized = false;
930 ia_css_uninit();
931 }
932
atomisp_css_resume(struct atomisp_device * isp)933 int atomisp_css_resume(struct atomisp_device *isp)
934 {
935 unsigned int mmu_base_addr;
936 int ret;
937
938 ret = hmm_get_mmu_base_addr(isp->dev, &mmu_base_addr);
939 if (ret) {
940 dev_err(isp->dev, "get base address error.\n");
941 return -EINVAL;
942 }
943
944 ret = ia_css_init(isp->dev, &isp->css_env.isp_css_env, NULL,
945 mmu_base_addr, IA_CSS_IRQ_TYPE_PULSE);
946 if (ret) {
947 dev_err(isp->dev, "re-init css failed.\n");
948 return -EINVAL;
949 }
950 ia_css_enable_isys_event_queue(true);
951
952 isp->css_initialized = true;
953 return 0;
954 }
955
atomisp_css_irq_translate(struct atomisp_device * isp,unsigned int * infos)956 int atomisp_css_irq_translate(struct atomisp_device *isp,
957 unsigned int *infos)
958 {
959 int err;
960
961 err = ia_css_irq_translate(infos);
962 if (err) {
963 dev_warn(isp->dev,
964 "%s:failed to translate irq (err = %d,infos = %d)\n",
965 __func__, err, *infos);
966 return -EINVAL;
967 }
968
969 return 0;
970 }
971
atomisp_css_rx_get_irq_info(enum mipi_port_id port,unsigned int * infos)972 void atomisp_css_rx_get_irq_info(enum mipi_port_id port,
973 unsigned int *infos)
974 {
975 #ifndef ISP2401_NEW_INPUT_SYSTEM
976 ia_css_isys_rx_get_irq_info(port, infos);
977 #else
978 *infos = 0;
979 #endif
980 }
981
atomisp_css_rx_clear_irq_info(enum mipi_port_id port,unsigned int infos)982 void atomisp_css_rx_clear_irq_info(enum mipi_port_id port,
983 unsigned int infos)
984 {
985 #ifndef ISP2401_NEW_INPUT_SYSTEM
986 ia_css_isys_rx_clear_irq_info(port, infos);
987 #endif
988 }
989
atomisp_css_irq_enable(struct atomisp_device * isp,enum ia_css_irq_info info,bool enable)990 int atomisp_css_irq_enable(struct atomisp_device *isp,
991 enum ia_css_irq_info info, bool enable)
992 {
993 dev_dbg(isp->dev, "%s: css irq info 0x%08x: %s (%d).\n",
994 __func__, info,
995 enable ? "enable" : "disable", enable);
996 if (ia_css_irq_enable(info, enable)) {
997 dev_warn(isp->dev, "%s:Invalid irq info: 0x%08x when %s.\n",
998 __func__, info,
999 enable ? "enabling" : "disabling");
1000 return -EINVAL;
1001 }
1002
1003 return 0;
1004 }
1005
atomisp_css_init_struct(struct atomisp_sub_device * asd)1006 void atomisp_css_init_struct(struct atomisp_sub_device *asd)
1007 {
1008 int i, j;
1009
1010 for (i = 0; i < ATOMISP_INPUT_STREAM_NUM; i++) {
1011 asd->stream_env[i].stream = NULL;
1012 for (j = 0; j < IA_CSS_PIPE_MODE_NUM; j++) {
1013 asd->stream_env[i].pipes[j] = NULL;
1014 asd->stream_env[i].update_pipe[j] = false;
1015 ia_css_pipe_config_defaults(
1016 &asd->stream_env[i].pipe_configs[j]);
1017 ia_css_pipe_extra_config_defaults(
1018 &asd->stream_env[i].pipe_extra_configs[j]);
1019 }
1020 ia_css_stream_config_defaults(&asd->stream_env[i].stream_config);
1021 }
1022 }
1023
atomisp_q_video_buffer_to_css(struct atomisp_sub_device * asd,struct videobuf_vmalloc_memory * vm_mem,enum atomisp_input_stream_id stream_id,enum ia_css_buffer_type css_buf_type,enum ia_css_pipe_id css_pipe_id)1024 int atomisp_q_video_buffer_to_css(struct atomisp_sub_device *asd,
1025 struct videobuf_vmalloc_memory *vm_mem,
1026 enum atomisp_input_stream_id stream_id,
1027 enum ia_css_buffer_type css_buf_type,
1028 enum ia_css_pipe_id css_pipe_id)
1029 {
1030 struct atomisp_stream_env *stream_env = &asd->stream_env[stream_id];
1031 struct ia_css_buffer css_buf = {0};
1032 int err;
1033
1034 css_buf.type = css_buf_type;
1035 css_buf.data.frame = vm_mem->vaddr;
1036
1037 err = ia_css_pipe_enqueue_buffer(
1038 stream_env->pipes[css_pipe_id], &css_buf);
1039 if (err)
1040 return -EINVAL;
1041
1042 return 0;
1043 }
1044
atomisp_q_metadata_buffer_to_css(struct atomisp_sub_device * asd,struct atomisp_metadata_buf * metadata_buf,enum atomisp_input_stream_id stream_id,enum ia_css_pipe_id css_pipe_id)1045 int atomisp_q_metadata_buffer_to_css(struct atomisp_sub_device *asd,
1046 struct atomisp_metadata_buf *metadata_buf,
1047 enum atomisp_input_stream_id stream_id,
1048 enum ia_css_pipe_id css_pipe_id)
1049 {
1050 struct atomisp_stream_env *stream_env = &asd->stream_env[stream_id];
1051 struct ia_css_buffer buffer = {0};
1052 struct atomisp_device *isp = asd->isp;
1053
1054 buffer.type = IA_CSS_BUFFER_TYPE_METADATA;
1055 buffer.data.metadata = metadata_buf->metadata;
1056 if (ia_css_pipe_enqueue_buffer(stream_env->pipes[css_pipe_id],
1057 &buffer)) {
1058 dev_err(isp->dev, "failed to q meta data buffer\n");
1059 return -EINVAL;
1060 }
1061
1062 return 0;
1063 }
1064
atomisp_q_s3a_buffer_to_css(struct atomisp_sub_device * asd,struct atomisp_s3a_buf * s3a_buf,enum atomisp_input_stream_id stream_id,enum ia_css_pipe_id css_pipe_id)1065 int atomisp_q_s3a_buffer_to_css(struct atomisp_sub_device *asd,
1066 struct atomisp_s3a_buf *s3a_buf,
1067 enum atomisp_input_stream_id stream_id,
1068 enum ia_css_pipe_id css_pipe_id)
1069 {
1070 struct atomisp_stream_env *stream_env = &asd->stream_env[stream_id];
1071 struct ia_css_buffer buffer = {0};
1072 struct atomisp_device *isp = asd->isp;
1073
1074 buffer.type = IA_CSS_BUFFER_TYPE_3A_STATISTICS;
1075 buffer.data.stats_3a = s3a_buf->s3a_data;
1076 if (ia_css_pipe_enqueue_buffer(
1077 stream_env->pipes[css_pipe_id],
1078 &buffer)) {
1079 dev_dbg(isp->dev, "failed to q s3a stat buffer\n");
1080 return -EINVAL;
1081 }
1082
1083 return 0;
1084 }
1085
atomisp_q_dis_buffer_to_css(struct atomisp_sub_device * asd,struct atomisp_dis_buf * dis_buf,enum atomisp_input_stream_id stream_id,enum ia_css_pipe_id css_pipe_id)1086 int atomisp_q_dis_buffer_to_css(struct atomisp_sub_device *asd,
1087 struct atomisp_dis_buf *dis_buf,
1088 enum atomisp_input_stream_id stream_id,
1089 enum ia_css_pipe_id css_pipe_id)
1090 {
1091 struct atomisp_stream_env *stream_env = &asd->stream_env[stream_id];
1092 struct ia_css_buffer buffer = {0};
1093 struct atomisp_device *isp = asd->isp;
1094
1095 buffer.type = IA_CSS_BUFFER_TYPE_DIS_STATISTICS;
1096 buffer.data.stats_dvs = dis_buf->dis_data;
1097 if (ia_css_pipe_enqueue_buffer(
1098 stream_env->pipes[css_pipe_id],
1099 &buffer)) {
1100 dev_dbg(isp->dev, "failed to q dvs stat buffer\n");
1101 return -EINVAL;
1102 }
1103
1104 return 0;
1105 }
1106
atomisp_css_start(struct atomisp_sub_device * asd,enum ia_css_pipe_id pipe_id,bool in_reset)1107 int atomisp_css_start(struct atomisp_sub_device *asd,
1108 enum ia_css_pipe_id pipe_id, bool in_reset)
1109 {
1110 struct atomisp_device *isp = asd->isp;
1111 bool sp_is_started = false;
1112 int ret = 0, i = 0;
1113
1114 if (in_reset) {
1115 if (__destroy_streams(asd, true))
1116 dev_warn(isp->dev, "destroy stream failed.\n");
1117
1118 if (__destroy_pipes(asd, true))
1119 dev_warn(isp->dev, "destroy pipe failed.\n");
1120
1121 if (__create_pipes(asd)) {
1122 dev_err(isp->dev, "create pipe error.\n");
1123 return -EINVAL;
1124 }
1125 if (__create_streams(asd)) {
1126 dev_err(isp->dev, "create stream error.\n");
1127 ret = -EINVAL;
1128 goto stream_err;
1129 }
1130 /* in_reset == true, extension firmwares are reloaded after the recovery */
1131 atomisp_acc_load_extensions(asd);
1132 }
1133
1134 /*
1135 * For dual steam case, it is possible that:
1136 * 1: for this stream, it is at the stage that:
1137 * - after set_fmt is called
1138 * - before stream on is called
1139 * 2: for the other stream, the stream off is called which css reset
1140 * has been done.
1141 *
1142 * Thus the stream created in set_fmt get destroyed and need to be
1143 * recreated in the next stream on.
1144 */
1145 if (asd->stream_prepared == false) {
1146 if (__create_pipes(asd)) {
1147 dev_err(isp->dev, "create pipe error.\n");
1148 return -EINVAL;
1149 }
1150 if (__create_streams(asd)) {
1151 dev_err(isp->dev, "create stream error.\n");
1152 ret = -EINVAL;
1153 goto stream_err;
1154 }
1155 }
1156 /*
1157 * SP can only be started one time
1158 * if atomisp_subdev_streaming_count() tell there already has some
1159 * subdev at streamming, then SP should already be started previously,
1160 * so need to skip start sp procedure
1161 */
1162 if (atomisp_streaming_count(isp)) {
1163 dev_dbg(isp->dev, "skip start sp\n");
1164 } else {
1165 if (!sh_css_hrt_system_is_idle())
1166 dev_err(isp->dev, "CSS HW not idle before starting SP\n");
1167 if (ia_css_start_sp()) {
1168 dev_err(isp->dev, "start sp error.\n");
1169 ret = -EINVAL;
1170 goto start_err;
1171 } else {
1172 sp_is_started = true;
1173 }
1174 }
1175
1176 for (i = 0; i < ATOMISP_INPUT_STREAM_NUM; i++) {
1177 if (asd->stream_env[i].stream) {
1178 if (ia_css_stream_start(asd->stream_env[i]
1179 .stream) != 0) {
1180 dev_err(isp->dev, "stream[%d] start error.\n", i);
1181 ret = -EINVAL;
1182 goto start_err;
1183 } else {
1184 asd->stream_env[i].stream_state = CSS_STREAM_STARTED;
1185 dev_dbg(isp->dev, "stream[%d] started.\n", i);
1186 }
1187 }
1188 }
1189
1190 return 0;
1191
1192 start_err:
1193 __destroy_streams(asd, true);
1194 stream_err:
1195 __destroy_pipes(asd, true);
1196
1197 /* css 2.0 API limitation: ia_css_stop_sp() could be only called after
1198 * destroy all pipes
1199 */
1200 /*
1201 * SP can not be stop if other streams are in use
1202 */
1203 if ((atomisp_streaming_count(isp) == 0) && sp_is_started)
1204 ia_css_stop_sp();
1205
1206 return ret;
1207 }
1208
atomisp_css_update_isp_params(struct atomisp_sub_device * asd)1209 void atomisp_css_update_isp_params(struct atomisp_sub_device *asd)
1210 {
1211 /*
1212 * FIXME!
1213 * for ISP2401 new input system, this api is under development.
1214 * Calling it would cause kernel panic.
1215 *
1216 * VIED BZ: 1458
1217 *
1218 * Check if it is Cherry Trail and also new input system
1219 */
1220 if (asd->copy_mode) {
1221 dev_warn(asd->isp->dev,
1222 "%s: ia_css_stream_set_isp_config() not supported in copy mode!.\n",
1223 __func__);
1224 return;
1225 }
1226
1227 ia_css_stream_set_isp_config(
1228 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream,
1229 &asd->params.config);
1230 memset(&asd->params.config, 0, sizeof(asd->params.config));
1231 }
1232
atomisp_css_update_isp_params_on_pipe(struct atomisp_sub_device * asd,struct ia_css_pipe * pipe)1233 void atomisp_css_update_isp_params_on_pipe(struct atomisp_sub_device *asd,
1234 struct ia_css_pipe *pipe)
1235 {
1236 int ret;
1237
1238 if (!pipe) {
1239 atomisp_css_update_isp_params(asd);
1240 return;
1241 }
1242
1243 dev_dbg(asd->isp->dev,
1244 "%s: apply parameter for ia_css_frame %p with isp_config_id %d on pipe %p.\n",
1245 __func__, asd->params.config.output_frame,
1246 asd->params.config.isp_config_id, pipe);
1247
1248 ret = ia_css_stream_set_isp_config_on_pipe(
1249 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream,
1250 &asd->params.config, pipe);
1251 if (ret)
1252 dev_warn(asd->isp->dev, "%s: ia_css_stream_set_isp_config_on_pipe failed %d\n",
1253 __func__, ret);
1254 memset(&asd->params.config, 0, sizeof(asd->params.config));
1255 }
1256
atomisp_css_queue_buffer(struct atomisp_sub_device * asd,enum atomisp_input_stream_id stream_id,enum ia_css_pipe_id pipe_id,enum ia_css_buffer_type buf_type,struct atomisp_css_buffer * isp_css_buffer)1257 int atomisp_css_queue_buffer(struct atomisp_sub_device *asd,
1258 enum atomisp_input_stream_id stream_id,
1259 enum ia_css_pipe_id pipe_id,
1260 enum ia_css_buffer_type buf_type,
1261 struct atomisp_css_buffer *isp_css_buffer)
1262 {
1263 if (ia_css_pipe_enqueue_buffer(
1264 asd->stream_env[stream_id].pipes[pipe_id],
1265 &isp_css_buffer->css_buffer)
1266 != 0)
1267 return -EINVAL;
1268
1269 return 0;
1270 }
1271
atomisp_css_dequeue_buffer(struct atomisp_sub_device * asd,enum atomisp_input_stream_id stream_id,enum ia_css_pipe_id pipe_id,enum ia_css_buffer_type buf_type,struct atomisp_css_buffer * isp_css_buffer)1272 int atomisp_css_dequeue_buffer(struct atomisp_sub_device *asd,
1273 enum atomisp_input_stream_id stream_id,
1274 enum ia_css_pipe_id pipe_id,
1275 enum ia_css_buffer_type buf_type,
1276 struct atomisp_css_buffer *isp_css_buffer)
1277 {
1278 struct atomisp_device *isp = asd->isp;
1279 int err;
1280
1281 err = ia_css_pipe_dequeue_buffer(
1282 asd->stream_env[stream_id].pipes[pipe_id],
1283 &isp_css_buffer->css_buffer);
1284 if (err) {
1285 dev_err(isp->dev,
1286 "ia_css_pipe_dequeue_buffer failed: 0x%x\n", err);
1287 return -EINVAL;
1288 }
1289
1290 return 0;
1291 }
1292
atomisp_css_allocate_stat_buffers(struct atomisp_sub_device * asd,u16 stream_id,struct atomisp_s3a_buf * s3a_buf,struct atomisp_dis_buf * dis_buf,struct atomisp_metadata_buf * md_buf)1293 int atomisp_css_allocate_stat_buffers(struct atomisp_sub_device *asd,
1294 u16 stream_id,
1295 struct atomisp_s3a_buf *s3a_buf,
1296 struct atomisp_dis_buf *dis_buf,
1297 struct atomisp_metadata_buf *md_buf)
1298 {
1299 struct atomisp_device *isp = asd->isp;
1300 struct ia_css_dvs_grid_info *dvs_grid_info =
1301 atomisp_css_get_dvs_grid_info(&asd->params.curr_grid_info);
1302
1303 if (s3a_buf && asd->params.curr_grid_info.s3a_grid.enable) {
1304 void *s3a_ptr;
1305
1306 s3a_buf->s3a_data = ia_css_isp_3a_statistics_allocate(
1307 &asd->params.curr_grid_info.s3a_grid);
1308 if (!s3a_buf->s3a_data) {
1309 dev_err(isp->dev, "3a buf allocation failed.\n");
1310 return -EINVAL;
1311 }
1312
1313 s3a_ptr = hmm_vmap(s3a_buf->s3a_data->data_ptr, true);
1314 s3a_buf->s3a_map = ia_css_isp_3a_statistics_map_allocate(
1315 s3a_buf->s3a_data, s3a_ptr);
1316 }
1317
1318 if (dis_buf && dvs_grid_info && dvs_grid_info->enable) {
1319 void *dvs_ptr;
1320
1321 dis_buf->dis_data = ia_css_isp_dvs2_statistics_allocate(
1322 dvs_grid_info);
1323 if (!dis_buf->dis_data) {
1324 dev_err(isp->dev, "dvs buf allocation failed.\n");
1325 if (s3a_buf)
1326 ia_css_isp_3a_statistics_free(s3a_buf->s3a_data);
1327 return -EINVAL;
1328 }
1329
1330 dvs_ptr = hmm_vmap(dis_buf->dis_data->data_ptr, true);
1331 dis_buf->dvs_map = ia_css_isp_dvs_statistics_map_allocate(
1332 dis_buf->dis_data, dvs_ptr);
1333 }
1334
1335 if (asd->stream_env[stream_id].stream_info.
1336 metadata_info.size && md_buf) {
1337 md_buf->metadata = ia_css_metadata_allocate(
1338 &asd->stream_env[stream_id].stream_info.metadata_info);
1339 if (!md_buf->metadata) {
1340 if (s3a_buf)
1341 ia_css_isp_3a_statistics_free(s3a_buf->s3a_data);
1342 if (dis_buf)
1343 ia_css_isp_dvs2_statistics_free(dis_buf->dis_data);
1344 dev_err(isp->dev, "metadata buf allocation failed.\n");
1345 return -EINVAL;
1346 }
1347 md_buf->md_vptr = hmm_vmap(md_buf->metadata->address, false);
1348 }
1349
1350 return 0;
1351 }
1352
atomisp_css_free_3a_buffer(struct atomisp_s3a_buf * s3a_buf)1353 void atomisp_css_free_3a_buffer(struct atomisp_s3a_buf *s3a_buf)
1354 {
1355 if (s3a_buf->s3a_data)
1356 hmm_vunmap(s3a_buf->s3a_data->data_ptr);
1357
1358 ia_css_isp_3a_statistics_map_free(s3a_buf->s3a_map);
1359 s3a_buf->s3a_map = NULL;
1360 ia_css_isp_3a_statistics_free(s3a_buf->s3a_data);
1361 }
1362
atomisp_css_free_dis_buffer(struct atomisp_dis_buf * dis_buf)1363 void atomisp_css_free_dis_buffer(struct atomisp_dis_buf *dis_buf)
1364 {
1365 if (dis_buf->dis_data)
1366 hmm_vunmap(dis_buf->dis_data->data_ptr);
1367
1368 ia_css_isp_dvs_statistics_map_free(dis_buf->dvs_map);
1369 dis_buf->dvs_map = NULL;
1370 ia_css_isp_dvs2_statistics_free(dis_buf->dis_data);
1371 }
1372
atomisp_css_free_metadata_buffer(struct atomisp_metadata_buf * metadata_buf)1373 void atomisp_css_free_metadata_buffer(struct atomisp_metadata_buf *metadata_buf)
1374 {
1375 if (metadata_buf->md_vptr) {
1376 hmm_vunmap(metadata_buf->metadata->address);
1377 metadata_buf->md_vptr = NULL;
1378 }
1379 ia_css_metadata_free(metadata_buf->metadata);
1380 }
1381
atomisp_css_free_stat_buffers(struct atomisp_sub_device * asd)1382 void atomisp_css_free_stat_buffers(struct atomisp_sub_device *asd)
1383 {
1384 struct atomisp_s3a_buf *s3a_buf, *_s3a_buf;
1385 struct atomisp_dis_buf *dis_buf, *_dis_buf;
1386 struct atomisp_metadata_buf *md_buf, *_md_buf;
1387 struct ia_css_dvs_grid_info *dvs_grid_info =
1388 atomisp_css_get_dvs_grid_info(&asd->params.curr_grid_info);
1389 unsigned int i;
1390
1391 /* 3A statistics use vmalloc, DIS use kmalloc */
1392 if (dvs_grid_info && dvs_grid_info->enable) {
1393 ia_css_dvs2_coefficients_free(asd->params.css_param.dvs2_coeff);
1394 ia_css_dvs2_statistics_free(asd->params.dvs_stat);
1395 asd->params.css_param.dvs2_coeff = NULL;
1396 asd->params.dvs_stat = NULL;
1397 asd->params.dvs_hor_proj_bytes = 0;
1398 asd->params.dvs_ver_proj_bytes = 0;
1399 asd->params.dvs_hor_coef_bytes = 0;
1400 asd->params.dvs_ver_coef_bytes = 0;
1401 asd->params.dis_proj_data_valid = false;
1402 list_for_each_entry_safe(dis_buf, _dis_buf,
1403 &asd->dis_stats, list) {
1404 atomisp_css_free_dis_buffer(dis_buf);
1405 list_del(&dis_buf->list);
1406 kfree(dis_buf);
1407 }
1408 list_for_each_entry_safe(dis_buf, _dis_buf,
1409 &asd->dis_stats_in_css, list) {
1410 atomisp_css_free_dis_buffer(dis_buf);
1411 list_del(&dis_buf->list);
1412 kfree(dis_buf);
1413 }
1414 }
1415 if (asd->params.curr_grid_info.s3a_grid.enable) {
1416 ia_css_3a_statistics_free(asd->params.s3a_user_stat);
1417 asd->params.s3a_user_stat = NULL;
1418 asd->params.s3a_output_bytes = 0;
1419 list_for_each_entry_safe(s3a_buf, _s3a_buf,
1420 &asd->s3a_stats, list) {
1421 atomisp_css_free_3a_buffer(s3a_buf);
1422 list_del(&s3a_buf->list);
1423 kfree(s3a_buf);
1424 }
1425 list_for_each_entry_safe(s3a_buf, _s3a_buf,
1426 &asd->s3a_stats_in_css, list) {
1427 atomisp_css_free_3a_buffer(s3a_buf);
1428 list_del(&s3a_buf->list);
1429 kfree(s3a_buf);
1430 }
1431 list_for_each_entry_safe(s3a_buf, _s3a_buf,
1432 &asd->s3a_stats_ready, list) {
1433 atomisp_css_free_3a_buffer(s3a_buf);
1434 list_del(&s3a_buf->list);
1435 kfree(s3a_buf);
1436 }
1437 }
1438
1439 if (asd->params.css_param.dvs_6axis) {
1440 ia_css_dvs2_6axis_config_free(asd->params.css_param.dvs_6axis);
1441 asd->params.css_param.dvs_6axis = NULL;
1442 }
1443
1444 for (i = 0; i < ATOMISP_METADATA_TYPE_NUM; i++) {
1445 list_for_each_entry_safe(md_buf, _md_buf,
1446 &asd->metadata[i], list) {
1447 atomisp_css_free_metadata_buffer(md_buf);
1448 list_del(&md_buf->list);
1449 kfree(md_buf);
1450 }
1451 list_for_each_entry_safe(md_buf, _md_buf,
1452 &asd->metadata_in_css[i], list) {
1453 atomisp_css_free_metadata_buffer(md_buf);
1454 list_del(&md_buf->list);
1455 kfree(md_buf);
1456 }
1457 list_for_each_entry_safe(md_buf, _md_buf,
1458 &asd->metadata_ready[i], list) {
1459 atomisp_css_free_metadata_buffer(md_buf);
1460 list_del(&md_buf->list);
1461 kfree(md_buf);
1462 }
1463 }
1464 asd->params.metadata_width_size = 0;
1465 atomisp_free_metadata_output_buf(asd);
1466 }
1467
atomisp_css_get_grid_info(struct atomisp_sub_device * asd,enum ia_css_pipe_id pipe_id,int source_pad)1468 int atomisp_css_get_grid_info(struct atomisp_sub_device *asd,
1469 enum ia_css_pipe_id pipe_id,
1470 int source_pad)
1471 {
1472 struct ia_css_pipe_info p_info;
1473 struct ia_css_grid_info old_info;
1474 struct atomisp_device *isp = asd->isp;
1475 int stream_index = atomisp_source_pad_to_stream_id(asd, source_pad);
1476 int md_width = asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].
1477 stream_config.metadata_config.resolution.width;
1478
1479 memset(&p_info, 0, sizeof(struct ia_css_pipe_info));
1480 memset(&old_info, 0, sizeof(struct ia_css_grid_info));
1481
1482 if (ia_css_pipe_get_info(
1483 asd->stream_env[stream_index].pipes[pipe_id],
1484 &p_info) != 0) {
1485 dev_err(isp->dev, "ia_css_pipe_get_info failed\n");
1486 return -EINVAL;
1487 }
1488
1489 memcpy(&old_info, &asd->params.curr_grid_info,
1490 sizeof(struct ia_css_grid_info));
1491 memcpy(&asd->params.curr_grid_info, &p_info.grid_info,
1492 sizeof(struct ia_css_grid_info));
1493 /*
1494 * Record which css pipe enables s3a_grid.
1495 * Currently would have one css pipe that need it
1496 */
1497 if (asd->params.curr_grid_info.s3a_grid.enable) {
1498 if (asd->params.s3a_enabled_pipe != IA_CSS_PIPE_ID_NUM)
1499 dev_dbg(isp->dev, "css pipe %d enabled s3a grid replaced by: %d.\n",
1500 asd->params.s3a_enabled_pipe, pipe_id);
1501 asd->params.s3a_enabled_pipe = pipe_id;
1502 }
1503
1504 /* If the grid info has not changed and the buffers for 3A and
1505 * DIS statistics buffers are allocated or buffer size would be zero
1506 * then no need to do anything. */
1507 if (((!memcmp(&old_info, &asd->params.curr_grid_info, sizeof(old_info))
1508 && asd->params.s3a_user_stat && asd->params.dvs_stat)
1509 || asd->params.curr_grid_info.s3a_grid.width == 0
1510 || asd->params.curr_grid_info.s3a_grid.height == 0)
1511 && asd->params.metadata_width_size == md_width) {
1512 dev_dbg(isp->dev,
1513 "grid info change escape. memcmp=%d, s3a_user_stat=%d,dvs_stat=%d, s3a.width=%d, s3a.height=%d, metadata width =%d\n",
1514 !memcmp(&old_info, &asd->params.curr_grid_info,
1515 sizeof(old_info)),
1516 !!asd->params.s3a_user_stat, !!asd->params.dvs_stat,
1517 asd->params.curr_grid_info.s3a_grid.width,
1518 asd->params.curr_grid_info.s3a_grid.height,
1519 asd->params.metadata_width_size);
1520 return -EINVAL;
1521 }
1522 asd->params.metadata_width_size = md_width;
1523
1524 return 0;
1525 }
1526
atomisp_alloc_3a_output_buf(struct atomisp_sub_device * asd)1527 int atomisp_alloc_3a_output_buf(struct atomisp_sub_device *asd)
1528 {
1529 if (!asd->params.curr_grid_info.s3a_grid.width ||
1530 !asd->params.curr_grid_info.s3a_grid.height)
1531 return 0;
1532
1533 asd->params.s3a_user_stat = ia_css_3a_statistics_allocate(
1534 &asd->params.curr_grid_info.s3a_grid);
1535 if (!asd->params.s3a_user_stat)
1536 return -ENOMEM;
1537 /* 3A statistics. These can be big, so we use vmalloc. */
1538 asd->params.s3a_output_bytes =
1539 asd->params.curr_grid_info.s3a_grid.width *
1540 asd->params.curr_grid_info.s3a_grid.height *
1541 sizeof(*asd->params.s3a_user_stat->data);
1542
1543 return 0;
1544 }
1545
atomisp_alloc_dis_coef_buf(struct atomisp_sub_device * asd)1546 int atomisp_alloc_dis_coef_buf(struct atomisp_sub_device *asd)
1547 {
1548 struct ia_css_dvs_grid_info *dvs_grid =
1549 atomisp_css_get_dvs_grid_info(&asd->params.curr_grid_info);
1550
1551 if (!dvs_grid)
1552 return 0;
1553
1554 if (!dvs_grid->enable) {
1555 dev_dbg(asd->isp->dev, "%s: dvs_grid not enabled.\n", __func__);
1556 return 0;
1557 }
1558
1559 /* DIS coefficients. */
1560 asd->params.css_param.dvs2_coeff = ia_css_dvs2_coefficients_allocate(
1561 dvs_grid);
1562 if (!asd->params.css_param.dvs2_coeff)
1563 return -ENOMEM;
1564
1565 asd->params.dvs_hor_coef_bytes = dvs_grid->num_hor_coefs *
1566 sizeof(*asd->params.css_param.dvs2_coeff->hor_coefs.odd_real);
1567
1568 asd->params.dvs_ver_coef_bytes = dvs_grid->num_ver_coefs *
1569 sizeof(*asd->params.css_param.dvs2_coeff->ver_coefs.odd_real);
1570
1571 /* DIS projections. */
1572 asd->params.dis_proj_data_valid = false;
1573 asd->params.dvs_stat = ia_css_dvs2_statistics_allocate(dvs_grid);
1574 if (!asd->params.dvs_stat)
1575 return -ENOMEM;
1576
1577 asd->params.dvs_hor_proj_bytes =
1578 dvs_grid->aligned_height * dvs_grid->aligned_width *
1579 sizeof(*asd->params.dvs_stat->hor_prod.odd_real);
1580
1581 asd->params.dvs_ver_proj_bytes =
1582 dvs_grid->aligned_height * dvs_grid->aligned_width *
1583 sizeof(*asd->params.dvs_stat->ver_prod.odd_real);
1584
1585 return 0;
1586 }
1587
atomisp_alloc_metadata_output_buf(struct atomisp_sub_device * asd)1588 int atomisp_alloc_metadata_output_buf(struct atomisp_sub_device *asd)
1589 {
1590 int i;
1591
1592 /* We allocate the cpu-side buffer used for communication with user
1593 * space */
1594 for (i = 0; i < ATOMISP_METADATA_TYPE_NUM; i++) {
1595 asd->params.metadata_user[i] = kvmalloc(
1596 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].
1597 stream_info.metadata_info.size, GFP_KERNEL);
1598 if (!asd->params.metadata_user[i]) {
1599 while (--i >= 0) {
1600 kvfree(asd->params.metadata_user[i]);
1601 asd->params.metadata_user[i] = NULL;
1602 }
1603 return -ENOMEM;
1604 }
1605 }
1606
1607 return 0;
1608 }
1609
atomisp_free_metadata_output_buf(struct atomisp_sub_device * asd)1610 void atomisp_free_metadata_output_buf(struct atomisp_sub_device *asd)
1611 {
1612 unsigned int i;
1613
1614 for (i = 0; i < ATOMISP_METADATA_TYPE_NUM; i++) {
1615 if (asd->params.metadata_user[i]) {
1616 kvfree(asd->params.metadata_user[i]);
1617 asd->params.metadata_user[i] = NULL;
1618 }
1619 }
1620 }
1621
atomisp_css_get_dis_statistics(struct atomisp_sub_device * asd,struct atomisp_css_buffer * isp_css_buffer,struct ia_css_isp_dvs_statistics_map * dvs_map)1622 void atomisp_css_get_dis_statistics(struct atomisp_sub_device *asd,
1623 struct atomisp_css_buffer *isp_css_buffer,
1624 struct ia_css_isp_dvs_statistics_map *dvs_map)
1625 {
1626 if (asd->params.dvs_stat) {
1627 if (dvs_map)
1628 ia_css_translate_dvs2_statistics(
1629 asd->params.dvs_stat, dvs_map);
1630 else
1631 ia_css_get_dvs2_statistics(asd->params.dvs_stat,
1632 isp_css_buffer->css_buffer.data.stats_dvs);
1633 }
1634 }
1635
atomisp_css_dequeue_event(struct atomisp_css_event * current_event)1636 int atomisp_css_dequeue_event(struct atomisp_css_event *current_event)
1637 {
1638 if (ia_css_dequeue_event(¤t_event->event))
1639 return -EINVAL;
1640
1641 return 0;
1642 }
1643
atomisp_css_temp_pipe_to_pipe_id(struct atomisp_sub_device * asd,struct atomisp_css_event * current_event)1644 void atomisp_css_temp_pipe_to_pipe_id(struct atomisp_sub_device *asd,
1645 struct atomisp_css_event *current_event)
1646 {
1647 /*
1648 * FIXME!
1649 * Pipe ID reported in CSS event is not correct for new system's
1650 * copy pipe.
1651 * VIED BZ: 1463
1652 */
1653 ia_css_temp_pipe_to_pipe_id(current_event->event.pipe,
1654 ¤t_event->pipe);
1655 if (asd && asd->copy_mode &&
1656 current_event->pipe == IA_CSS_PIPE_ID_CAPTURE)
1657 current_event->pipe = IA_CSS_PIPE_ID_COPY;
1658 }
1659
atomisp_css_isys_set_resolution(struct atomisp_sub_device * asd,enum atomisp_input_stream_id stream_id,struct v4l2_mbus_framefmt * ffmt,int isys_stream)1660 int atomisp_css_isys_set_resolution(struct atomisp_sub_device *asd,
1661 enum atomisp_input_stream_id stream_id,
1662 struct v4l2_mbus_framefmt *ffmt,
1663 int isys_stream)
1664 {
1665 struct ia_css_stream_config *s_config =
1666 &asd->stream_env[stream_id].stream_config;
1667
1668 if (isys_stream >= IA_CSS_STREAM_MAX_ISYS_STREAM_PER_CH)
1669 return -EINVAL;
1670
1671 s_config->isys_config[isys_stream].input_res.width = ffmt->width;
1672 s_config->isys_config[isys_stream].input_res.height = ffmt->height;
1673 return 0;
1674 }
1675
atomisp_css_input_set_resolution(struct atomisp_sub_device * asd,enum atomisp_input_stream_id stream_id,struct v4l2_mbus_framefmt * ffmt)1676 int atomisp_css_input_set_resolution(struct atomisp_sub_device *asd,
1677 enum atomisp_input_stream_id stream_id,
1678 struct v4l2_mbus_framefmt *ffmt)
1679 {
1680 struct ia_css_stream_config *s_config =
1681 &asd->stream_env[stream_id].stream_config;
1682
1683 s_config->input_config.input_res.width = ffmt->width;
1684 s_config->input_config.input_res.height = ffmt->height;
1685 return 0;
1686 }
1687
atomisp_css_input_set_binning_factor(struct atomisp_sub_device * asd,enum atomisp_input_stream_id stream_id,unsigned int bin_factor)1688 void atomisp_css_input_set_binning_factor(struct atomisp_sub_device *asd,
1689 enum atomisp_input_stream_id stream_id,
1690 unsigned int bin_factor)
1691 {
1692 asd->stream_env[stream_id]
1693 .stream_config.sensor_binning_factor = bin_factor;
1694 }
1695
atomisp_css_input_set_bayer_order(struct atomisp_sub_device * asd,enum atomisp_input_stream_id stream_id,enum ia_css_bayer_order bayer_order)1696 void atomisp_css_input_set_bayer_order(struct atomisp_sub_device *asd,
1697 enum atomisp_input_stream_id stream_id,
1698 enum ia_css_bayer_order bayer_order)
1699 {
1700 struct ia_css_stream_config *s_config =
1701 &asd->stream_env[stream_id].stream_config;
1702 s_config->input_config.bayer_order = bayer_order;
1703 }
1704
atomisp_css_isys_set_link(struct atomisp_sub_device * asd,enum atomisp_input_stream_id stream_id,int link,int isys_stream)1705 void atomisp_css_isys_set_link(struct atomisp_sub_device *asd,
1706 enum atomisp_input_stream_id stream_id,
1707 int link,
1708 int isys_stream)
1709 {
1710 struct ia_css_stream_config *s_config =
1711 &asd->stream_env[stream_id].stream_config;
1712
1713 s_config->isys_config[isys_stream].linked_isys_stream_id = link;
1714 }
1715
atomisp_css_isys_set_valid(struct atomisp_sub_device * asd,enum atomisp_input_stream_id stream_id,bool valid,int isys_stream)1716 void atomisp_css_isys_set_valid(struct atomisp_sub_device *asd,
1717 enum atomisp_input_stream_id stream_id,
1718 bool valid,
1719 int isys_stream)
1720 {
1721 struct ia_css_stream_config *s_config =
1722 &asd->stream_env[stream_id].stream_config;
1723
1724 s_config->isys_config[isys_stream].valid = valid;
1725 }
1726
atomisp_css_isys_set_format(struct atomisp_sub_device * asd,enum atomisp_input_stream_id stream_id,enum atomisp_input_format format,int isys_stream)1727 void atomisp_css_isys_set_format(struct atomisp_sub_device *asd,
1728 enum atomisp_input_stream_id stream_id,
1729 enum atomisp_input_format format,
1730 int isys_stream)
1731 {
1732 struct ia_css_stream_config *s_config =
1733 &asd->stream_env[stream_id].stream_config;
1734
1735 s_config->isys_config[isys_stream].format = format;
1736 }
1737
atomisp_css_input_set_format(struct atomisp_sub_device * asd,enum atomisp_input_stream_id stream_id,enum atomisp_input_format format)1738 void atomisp_css_input_set_format(struct atomisp_sub_device *asd,
1739 enum atomisp_input_stream_id stream_id,
1740 enum atomisp_input_format format)
1741 {
1742 struct ia_css_stream_config *s_config =
1743 &asd->stream_env[stream_id].stream_config;
1744
1745 s_config->input_config.format = format;
1746 }
1747
atomisp_css_set_default_isys_config(struct atomisp_sub_device * asd,enum atomisp_input_stream_id stream_id,struct v4l2_mbus_framefmt * ffmt)1748 int atomisp_css_set_default_isys_config(struct atomisp_sub_device *asd,
1749 enum atomisp_input_stream_id stream_id,
1750 struct v4l2_mbus_framefmt *ffmt)
1751 {
1752 int i;
1753 struct ia_css_stream_config *s_config =
1754 &asd->stream_env[stream_id].stream_config;
1755 /*
1756 * Set all isys configs to not valid.
1757 * Currently we support only one stream per channel
1758 */
1759 for (i = IA_CSS_STREAM_ISYS_STREAM_0;
1760 i < IA_CSS_STREAM_MAX_ISYS_STREAM_PER_CH; i++)
1761 s_config->isys_config[i].valid = false;
1762
1763 atomisp_css_isys_set_resolution(asd, stream_id, ffmt,
1764 IA_CSS_STREAM_DEFAULT_ISYS_STREAM_IDX);
1765 atomisp_css_isys_set_format(asd, stream_id,
1766 s_config->input_config.format,
1767 IA_CSS_STREAM_DEFAULT_ISYS_STREAM_IDX);
1768 atomisp_css_isys_set_link(asd, stream_id, NO_LINK,
1769 IA_CSS_STREAM_DEFAULT_ISYS_STREAM_IDX);
1770 atomisp_css_isys_set_valid(asd, stream_id, true,
1771 IA_CSS_STREAM_DEFAULT_ISYS_STREAM_IDX);
1772
1773 return 0;
1774 }
1775
atomisp_css_isys_two_stream_cfg(struct atomisp_sub_device * asd,enum atomisp_input_stream_id stream_id,enum atomisp_input_format input_format)1776 int atomisp_css_isys_two_stream_cfg(struct atomisp_sub_device *asd,
1777 enum atomisp_input_stream_id stream_id,
1778 enum atomisp_input_format input_format)
1779 {
1780 struct ia_css_stream_config *s_config =
1781 &asd->stream_env[stream_id].stream_config;
1782
1783 s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_1].input_res.width =
1784 s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_0].input_res.width;
1785
1786 s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_1].input_res.height =
1787 s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_0].input_res.height / 2;
1788
1789 s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_1].linked_isys_stream_id
1790 = IA_CSS_STREAM_ISYS_STREAM_0;
1791 s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_0].format =
1792 ATOMISP_INPUT_FORMAT_USER_DEF1;
1793 s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_1].format =
1794 ATOMISP_INPUT_FORMAT_USER_DEF2;
1795 s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_1].valid = true;
1796 return 0;
1797 }
1798
atomisp_css_isys_two_stream_cfg_update_stream1(struct atomisp_sub_device * asd,enum atomisp_input_stream_id stream_id,enum atomisp_input_format input_format,unsigned int width,unsigned int height)1799 void atomisp_css_isys_two_stream_cfg_update_stream1(
1800 struct atomisp_sub_device *asd,
1801 enum atomisp_input_stream_id stream_id,
1802 enum atomisp_input_format input_format,
1803 unsigned int width, unsigned int height)
1804 {
1805 struct ia_css_stream_config *s_config =
1806 &asd->stream_env[stream_id].stream_config;
1807
1808 s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_0].input_res.width =
1809 width;
1810 s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_0].input_res.height =
1811 height;
1812 s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_0].format =
1813 input_format;
1814 s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_0].valid = true;
1815 }
1816
atomisp_css_isys_two_stream_cfg_update_stream2(struct atomisp_sub_device * asd,enum atomisp_input_stream_id stream_id,enum atomisp_input_format input_format,unsigned int width,unsigned int height)1817 void atomisp_css_isys_two_stream_cfg_update_stream2(
1818 struct atomisp_sub_device *asd,
1819 enum atomisp_input_stream_id stream_id,
1820 enum atomisp_input_format input_format,
1821 unsigned int width, unsigned int height)
1822 {
1823 struct ia_css_stream_config *s_config =
1824 &asd->stream_env[stream_id].stream_config;
1825
1826 s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_1].input_res.width =
1827 width;
1828 s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_1].input_res.height =
1829 height;
1830 s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_1].linked_isys_stream_id
1831 = IA_CSS_STREAM_ISYS_STREAM_0;
1832 s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_1].format =
1833 input_format;
1834 s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_1].valid = true;
1835 }
1836
atomisp_css_input_set_effective_resolution(struct atomisp_sub_device * asd,enum atomisp_input_stream_id stream_id,unsigned int width,unsigned int height)1837 int atomisp_css_input_set_effective_resolution(
1838 struct atomisp_sub_device *asd,
1839 enum atomisp_input_stream_id stream_id,
1840 unsigned int width, unsigned int height)
1841 {
1842 struct ia_css_stream_config *s_config =
1843 &asd->stream_env[stream_id].stream_config;
1844 s_config->input_config.effective_res.width = width;
1845 s_config->input_config.effective_res.height = height;
1846 return 0;
1847 }
1848
atomisp_css_video_set_dis_envelope(struct atomisp_sub_device * asd,unsigned int dvs_w,unsigned int dvs_h)1849 void atomisp_css_video_set_dis_envelope(struct atomisp_sub_device *asd,
1850 unsigned int dvs_w, unsigned int dvs_h)
1851 {
1852 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]
1853 .pipe_configs[IA_CSS_PIPE_ID_VIDEO].dvs_envelope.width = dvs_w;
1854 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]
1855 .pipe_configs[IA_CSS_PIPE_ID_VIDEO].dvs_envelope.height = dvs_h;
1856 }
1857
atomisp_css_input_set_two_pixels_per_clock(struct atomisp_sub_device * asd,bool two_ppc)1858 void atomisp_css_input_set_two_pixels_per_clock(
1859 struct atomisp_sub_device *asd,
1860 bool two_ppc)
1861 {
1862 int i;
1863
1864 if (asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]
1865 .stream_config.pixels_per_clock == (two_ppc ? 2 : 1))
1866 return;
1867
1868 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]
1869 .stream_config.pixels_per_clock = (two_ppc ? 2 : 1);
1870 for (i = 0; i < IA_CSS_PIPE_ID_NUM; i++)
1871 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]
1872 .update_pipe[i] = true;
1873 }
1874
atomisp_css_enable_raw_binning(struct atomisp_sub_device * asd,bool enable)1875 void atomisp_css_enable_raw_binning(struct atomisp_sub_device *asd,
1876 bool enable)
1877 {
1878 struct atomisp_stream_env *stream_env =
1879 &asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL];
1880 unsigned int pipe;
1881
1882 if (asd->run_mode->val == ATOMISP_RUN_MODE_VIDEO)
1883 pipe = IA_CSS_PIPE_ID_VIDEO;
1884 else
1885 pipe = IA_CSS_PIPE_ID_PREVIEW;
1886
1887 stream_env->pipe_extra_configs[pipe].enable_raw_binning = enable;
1888 stream_env->update_pipe[pipe] = true;
1889 if (enable)
1890 stream_env->pipe_configs[pipe].output_info[0].padded_width =
1891 stream_env->stream_config.input_config.effective_res.width;
1892 }
1893
atomisp_css_enable_dz(struct atomisp_sub_device * asd,bool enable)1894 void atomisp_css_enable_dz(struct atomisp_sub_device *asd, bool enable)
1895 {
1896 int i;
1897
1898 for (i = 0; i < IA_CSS_PIPE_ID_NUM; i++)
1899 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]
1900 .pipe_configs[i].enable_dz = enable;
1901 }
1902
atomisp_css_capture_set_mode(struct atomisp_sub_device * asd,enum ia_css_capture_mode mode)1903 void atomisp_css_capture_set_mode(struct atomisp_sub_device *asd,
1904 enum ia_css_capture_mode mode)
1905 {
1906 struct atomisp_stream_env *stream_env =
1907 &asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL];
1908
1909 if (stream_env->pipe_configs[IA_CSS_PIPE_ID_CAPTURE]
1910 .default_capture_config.mode == mode)
1911 return;
1912
1913 stream_env->pipe_configs[IA_CSS_PIPE_ID_CAPTURE].
1914 default_capture_config.mode = mode;
1915 stream_env->update_pipe[IA_CSS_PIPE_ID_CAPTURE] = true;
1916 }
1917
atomisp_css_input_set_mode(struct atomisp_sub_device * asd,enum ia_css_input_mode mode)1918 void atomisp_css_input_set_mode(struct atomisp_sub_device *asd,
1919 enum ia_css_input_mode mode)
1920 {
1921 int i;
1922 struct atomisp_device *isp = asd->isp;
1923 unsigned int size_mem_words;
1924
1925 for (i = 0; i < ATOMISP_INPUT_STREAM_NUM; i++)
1926 asd->stream_env[i].stream_config.mode = mode;
1927
1928 if (isp->inputs[asd->input_curr].type == TEST_PATTERN) {
1929 struct ia_css_stream_config *s_config =
1930 &asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream_config;
1931 s_config->mode = IA_CSS_INPUT_MODE_TPG;
1932 s_config->source.tpg.mode = IA_CSS_TPG_MODE_CHECKERBOARD;
1933 s_config->source.tpg.x_mask = (1 << 4) - 1;
1934 s_config->source.tpg.x_delta = -2;
1935 s_config->source.tpg.y_mask = (1 << 4) - 1;
1936 s_config->source.tpg.y_delta = 3;
1937 s_config->source.tpg.xy_mask = (1 << 8) - 1;
1938 return;
1939 }
1940
1941 if (mode != IA_CSS_INPUT_MODE_BUFFERED_SENSOR)
1942 return;
1943
1944 for (i = 0; i < ATOMISP_INPUT_STREAM_NUM; i++) {
1945 /*
1946 * TODO: sensor needs to export the embedded_data_size_words
1947 * information to atomisp for each setting.
1948 * Here using a large safe value.
1949 */
1950 struct ia_css_stream_config *s_config =
1951 &asd->stream_env[i].stream_config;
1952
1953 if (s_config->input_config.input_res.width == 0)
1954 continue;
1955
1956 if (ia_css_mipi_frame_calculate_size(
1957 s_config->input_config.input_res.width,
1958 s_config->input_config.input_res.height,
1959 s_config->input_config.format,
1960 true,
1961 0x13000,
1962 &size_mem_words) != 0) {
1963 if (IS_MRFD)
1964 size_mem_words = CSS_MIPI_FRAME_BUFFER_SIZE_2;
1965 else
1966 size_mem_words = CSS_MIPI_FRAME_BUFFER_SIZE_1;
1967 dev_warn(asd->isp->dev,
1968 "ia_css_mipi_frame_calculate_size failed,applying pre-defined MIPI buffer size %u.\n",
1969 size_mem_words);
1970 }
1971 s_config->mipi_buffer_config.size_mem_words = size_mem_words;
1972 s_config->mipi_buffer_config.nof_mipi_buffers = 2;
1973 }
1974 }
1975
atomisp_css_capture_enable_online(struct atomisp_sub_device * asd,unsigned short stream_index,bool enable)1976 void atomisp_css_capture_enable_online(struct atomisp_sub_device *asd,
1977 unsigned short stream_index, bool enable)
1978 {
1979 struct atomisp_stream_env *stream_env =
1980 &asd->stream_env[stream_index];
1981
1982 if (stream_env->stream_config.online == !!enable)
1983 return;
1984
1985 stream_env->stream_config.online = !!enable;
1986 stream_env->update_pipe[IA_CSS_PIPE_ID_CAPTURE] = true;
1987 }
1988
atomisp_css_preview_enable_online(struct atomisp_sub_device * asd,unsigned short stream_index,bool enable)1989 void atomisp_css_preview_enable_online(struct atomisp_sub_device *asd,
1990 unsigned short stream_index, bool enable)
1991 {
1992 struct atomisp_stream_env *stream_env =
1993 &asd->stream_env[stream_index];
1994 int i;
1995
1996 if (stream_env->stream_config.online != !!enable) {
1997 stream_env->stream_config.online = !!enable;
1998 for (i = 0; i < IA_CSS_PIPE_ID_NUM; i++)
1999 stream_env->update_pipe[i] = true;
2000 }
2001 }
2002
atomisp_css_video_enable_online(struct atomisp_sub_device * asd,bool enable)2003 void atomisp_css_video_enable_online(struct atomisp_sub_device *asd,
2004 bool enable)
2005 {
2006 struct atomisp_stream_env *stream_env =
2007 &asd->stream_env[ATOMISP_INPUT_STREAM_VIDEO];
2008 int i;
2009
2010 if (stream_env->stream_config.online != enable) {
2011 stream_env->stream_config.online = enable;
2012 for (i = 0; i < IA_CSS_PIPE_ID_NUM; i++)
2013 stream_env->update_pipe[i] = true;
2014 }
2015 }
2016
atomisp_css_enable_continuous(struct atomisp_sub_device * asd,bool enable)2017 void atomisp_css_enable_continuous(struct atomisp_sub_device *asd,
2018 bool enable)
2019 {
2020 struct atomisp_stream_env *stream_env =
2021 &asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL];
2022 int i;
2023
2024 /*
2025 * To SOC camera, there is only one YUVPP pipe in any case
2026 * including ZSL/SDV/continuous viewfinder, so always set
2027 * stream_config.continuous to 0.
2028 */
2029 if (ATOMISP_USE_YUVPP(asd)) {
2030 stream_env->stream_config.continuous = 0;
2031 stream_env->stream_config.online = 1;
2032 return;
2033 }
2034
2035 if (stream_env->stream_config.continuous != !!enable) {
2036 stream_env->stream_config.continuous = !!enable;
2037 stream_env->stream_config.pack_raw_pixels = true;
2038 for (i = 0; i < IA_CSS_PIPE_ID_NUM; i++)
2039 stream_env->update_pipe[i] = true;
2040 }
2041 }
2042
atomisp_css_enable_cvf(struct atomisp_sub_device * asd,bool enable)2043 void atomisp_css_enable_cvf(struct atomisp_sub_device *asd,
2044 bool enable)
2045 {
2046 struct atomisp_stream_env *stream_env =
2047 &asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL];
2048 int i;
2049
2050 if (stream_env->stream_config.disable_cont_viewfinder != !enable) {
2051 stream_env->stream_config.disable_cont_viewfinder = !enable;
2052 for (i = 0; i < IA_CSS_PIPE_ID_NUM; i++)
2053 stream_env->update_pipe[i] = true;
2054 }
2055 }
2056
atomisp_css_input_configure_port(struct atomisp_sub_device * asd,enum mipi_port_id port,unsigned int num_lanes,unsigned int timeout,unsigned int mipi_freq,enum atomisp_input_format metadata_format,unsigned int metadata_width,unsigned int metadata_height)2057 int atomisp_css_input_configure_port(
2058 struct atomisp_sub_device *asd,
2059 enum mipi_port_id port,
2060 unsigned int num_lanes,
2061 unsigned int timeout,
2062 unsigned int mipi_freq,
2063 enum atomisp_input_format metadata_format,
2064 unsigned int metadata_width,
2065 unsigned int metadata_height)
2066 {
2067 int i;
2068 struct atomisp_stream_env *stream_env;
2069 /*
2070 * Calculate rx_count as follows:
2071 * Input: mipi_freq : CSI-2 bus frequency in Hz
2072 * UI = 1 / (2 * mipi_freq) : period of one bit on the bus
2073 * min = 85e-9 + 6 * UI : Limits for rx_count in seconds
2074 * max = 145e-9 + 10 * UI
2075 * rxcount0 = min / (4 / mipi_freq) : convert seconds to byte clocks
2076 * rxcount = rxcount0 - 2 : adjust for better results
2077 * The formula below is simplified version of the above with
2078 * 10-bit fixed points for improved accuracy.
2079 */
2080 const unsigned int rxcount =
2081 min(((mipi_freq / 46000) - 1280) >> 10, 0xffU) * 0x01010101U;
2082
2083 for (i = 0; i < ATOMISP_INPUT_STREAM_NUM; i++) {
2084 stream_env = &asd->stream_env[i];
2085 stream_env->stream_config.source.port.port = port;
2086 stream_env->stream_config.source.port.num_lanes = num_lanes;
2087 stream_env->stream_config.source.port.timeout = timeout;
2088 if (mipi_freq)
2089 stream_env->stream_config.source.port.rxcount = rxcount;
2090 stream_env->stream_config.
2091 metadata_config.data_type = metadata_format;
2092 stream_env->stream_config.
2093 metadata_config.resolution.width = metadata_width;
2094 stream_env->stream_config.
2095 metadata_config.resolution.height = metadata_height;
2096 }
2097
2098 return 0;
2099 }
2100
atomisp_css_stop(struct atomisp_sub_device * asd,enum ia_css_pipe_id pipe_id,bool in_reset)2101 int atomisp_css_stop(struct atomisp_sub_device *asd,
2102 enum ia_css_pipe_id pipe_id, bool in_reset)
2103 {
2104 struct atomisp_device *isp = asd->isp;
2105 struct atomisp_s3a_buf *s3a_buf;
2106 struct atomisp_dis_buf *dis_buf;
2107 struct atomisp_metadata_buf *md_buf;
2108 unsigned long irqflags;
2109 unsigned int i;
2110
2111 /* if is called in atomisp_reset(), force destroy stream */
2112 if (__destroy_streams(asd, true))
2113 dev_err(isp->dev, "destroy stream failed.\n");
2114
2115 /* if is called in atomisp_reset(), force destroy all pipes */
2116 if (__destroy_pipes(asd, true))
2117 dev_err(isp->dev, "destroy pipes failed.\n");
2118
2119 atomisp_init_raw_buffer_bitmap(asd);
2120
2121 /*
2122 * SP can not be stop if other streams are in use
2123 */
2124 if (atomisp_streaming_count(isp) == 0)
2125 ia_css_stop_sp();
2126
2127 if (!in_reset) {
2128 struct atomisp_stream_env *stream_env;
2129 int i, j;
2130
2131 for (i = 0; i < ATOMISP_INPUT_STREAM_NUM; i++) {
2132 stream_env = &asd->stream_env[i];
2133 for (j = 0; j < IA_CSS_PIPE_ID_NUM; j++) {
2134 ia_css_pipe_config_defaults(
2135 &stream_env->pipe_configs[j]);
2136 ia_css_pipe_extra_config_defaults(
2137 &stream_env->pipe_extra_configs[j]);
2138 }
2139 ia_css_stream_config_defaults(
2140 &stream_env->stream_config);
2141 }
2142 memset(&asd->params.config, 0, sizeof(asd->params.config));
2143 asd->params.css_update_params_needed = false;
2144 }
2145
2146 /* move stats buffers to free queue list */
2147 while (!list_empty(&asd->s3a_stats_in_css)) {
2148 s3a_buf = list_entry(asd->s3a_stats_in_css.next,
2149 struct atomisp_s3a_buf, list);
2150 list_del(&s3a_buf->list);
2151 list_add_tail(&s3a_buf->list, &asd->s3a_stats);
2152 }
2153 while (!list_empty(&asd->s3a_stats_ready)) {
2154 s3a_buf = list_entry(asd->s3a_stats_ready.next,
2155 struct atomisp_s3a_buf, list);
2156 list_del(&s3a_buf->list);
2157 list_add_tail(&s3a_buf->list, &asd->s3a_stats);
2158 }
2159
2160 spin_lock_irqsave(&asd->dis_stats_lock, irqflags);
2161 while (!list_empty(&asd->dis_stats_in_css)) {
2162 dis_buf = list_entry(asd->dis_stats_in_css.next,
2163 struct atomisp_dis_buf, list);
2164 list_del(&dis_buf->list);
2165 list_add_tail(&dis_buf->list, &asd->dis_stats);
2166 }
2167 asd->params.dis_proj_data_valid = false;
2168 spin_unlock_irqrestore(&asd->dis_stats_lock, irqflags);
2169
2170 for (i = 0; i < ATOMISP_METADATA_TYPE_NUM; i++) {
2171 while (!list_empty(&asd->metadata_in_css[i])) {
2172 md_buf = list_entry(asd->metadata_in_css[i].next,
2173 struct atomisp_metadata_buf, list);
2174 list_del(&md_buf->list);
2175 list_add_tail(&md_buf->list, &asd->metadata[i]);
2176 }
2177 while (!list_empty(&asd->metadata_ready[i])) {
2178 md_buf = list_entry(asd->metadata_ready[i].next,
2179 struct atomisp_metadata_buf, list);
2180 list_del(&md_buf->list);
2181 list_add_tail(&md_buf->list, &asd->metadata[i]);
2182 }
2183 }
2184
2185 atomisp_flush_params_queue(&asd->video_out_capture);
2186 atomisp_flush_params_queue(&asd->video_out_vf);
2187 atomisp_flush_params_queue(&asd->video_out_preview);
2188 atomisp_flush_params_queue(&asd->video_out_video_capture);
2189 atomisp_free_css_parameters(&asd->params.css_param);
2190 memset(&asd->params.css_param, 0, sizeof(asd->params.css_param));
2191 return 0;
2192 }
2193
atomisp_css_continuous_set_num_raw_frames(struct atomisp_sub_device * asd,int num_frames)2194 int atomisp_css_continuous_set_num_raw_frames(
2195 struct atomisp_sub_device *asd,
2196 int num_frames)
2197 {
2198 if (asd->enable_raw_buffer_lock->val) {
2199 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]
2200 .stream_config.init_num_cont_raw_buf =
2201 ATOMISP_CSS2_NUM_OFFLINE_INIT_CONTINUOUS_FRAMES_LOCK_EN;
2202 if (asd->run_mode->val == ATOMISP_RUN_MODE_VIDEO &&
2203 asd->params.video_dis_en)
2204 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]
2205 .stream_config.init_num_cont_raw_buf +=
2206 ATOMISP_CSS2_NUM_DVS_FRAME_DELAY;
2207 } else {
2208 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]
2209 .stream_config.init_num_cont_raw_buf =
2210 ATOMISP_CSS2_NUM_OFFLINE_INIT_CONTINUOUS_FRAMES;
2211 }
2212
2213 if (asd->params.video_dis_en)
2214 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]
2215 .stream_config.init_num_cont_raw_buf +=
2216 ATOMISP_CSS2_NUM_DVS_FRAME_DELAY;
2217
2218 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]
2219 .stream_config.target_num_cont_raw_buf = num_frames;
2220 return 0;
2221 }
2222
__pipe_id_to_pipe_mode(struct atomisp_sub_device * asd,enum ia_css_pipe_id pipe_id)2223 static enum ia_css_pipe_mode __pipe_id_to_pipe_mode(
2224 struct atomisp_sub_device *asd,
2225 enum ia_css_pipe_id pipe_id)
2226 {
2227 struct atomisp_device *isp = asd->isp;
2228 struct camera_mipi_info *mipi_info = atomisp_to_sensor_mipi_info(
2229 isp->inputs[asd->input_curr].camera);
2230
2231 switch (pipe_id) {
2232 case IA_CSS_PIPE_ID_COPY:
2233 /* Currently only YUVPP mode supports YUV420_Legacy format.
2234 * Revert this when other pipe modes can support
2235 * YUV420_Legacy format.
2236 */
2237 if (mipi_info && mipi_info->input_format ==
2238 ATOMISP_INPUT_FORMAT_YUV420_8_LEGACY)
2239 return IA_CSS_PIPE_MODE_YUVPP;
2240 return IA_CSS_PIPE_MODE_COPY;
2241 case IA_CSS_PIPE_ID_PREVIEW:
2242 return IA_CSS_PIPE_MODE_PREVIEW;
2243 case IA_CSS_PIPE_ID_CAPTURE:
2244 return IA_CSS_PIPE_MODE_CAPTURE;
2245 case IA_CSS_PIPE_ID_VIDEO:
2246 return IA_CSS_PIPE_MODE_VIDEO;
2247 case IA_CSS_PIPE_ID_ACC:
2248 return IA_CSS_PIPE_MODE_ACC;
2249 case IA_CSS_PIPE_ID_YUVPP:
2250 return IA_CSS_PIPE_MODE_YUVPP;
2251 default:
2252 WARN_ON(1);
2253 return IA_CSS_PIPE_MODE_PREVIEW;
2254 }
2255 }
2256
__configure_output(struct atomisp_sub_device * asd,unsigned int stream_index,unsigned int width,unsigned int height,unsigned int min_width,enum ia_css_frame_format format,enum ia_css_pipe_id pipe_id)2257 static void __configure_output(struct atomisp_sub_device *asd,
2258 unsigned int stream_index,
2259 unsigned int width, unsigned int height,
2260 unsigned int min_width,
2261 enum ia_css_frame_format format,
2262 enum ia_css_pipe_id pipe_id)
2263 {
2264 struct atomisp_device *isp = asd->isp;
2265 struct atomisp_stream_env *stream_env =
2266 &asd->stream_env[stream_index];
2267 struct ia_css_stream_config *s_config = &stream_env->stream_config;
2268
2269 stream_env->pipe_configs[pipe_id].mode =
2270 __pipe_id_to_pipe_mode(asd, pipe_id);
2271 stream_env->update_pipe[pipe_id] = true;
2272
2273 stream_env->pipe_configs[pipe_id].output_info[0].res.width = width;
2274 stream_env->pipe_configs[pipe_id].output_info[0].res.height = height;
2275 stream_env->pipe_configs[pipe_id].output_info[0].format = format;
2276 stream_env->pipe_configs[pipe_id].output_info[0].padded_width = min_width;
2277
2278 /* isp binary 2.2 specific setting*/
2279 if (width > s_config->input_config.effective_res.width ||
2280 height > s_config->input_config.effective_res.height) {
2281 s_config->input_config.effective_res.width = width;
2282 s_config->input_config.effective_res.height = height;
2283 }
2284
2285 dev_dbg(isp->dev, "configuring pipe[%d] output info w=%d.h=%d.f=%d.\n",
2286 pipe_id, width, height, format);
2287 }
2288
__configure_video_preview_output(struct atomisp_sub_device * asd,unsigned int stream_index,unsigned int width,unsigned int height,unsigned int min_width,enum ia_css_frame_format format,enum ia_css_pipe_id pipe_id)2289 static void __configure_video_preview_output(struct atomisp_sub_device *asd,
2290 unsigned int stream_index,
2291 unsigned int width, unsigned int height,
2292 unsigned int min_width,
2293 enum ia_css_frame_format format,
2294 enum ia_css_pipe_id pipe_id)
2295 {
2296 struct atomisp_device *isp = asd->isp;
2297 struct atomisp_stream_env *stream_env =
2298 &asd->stream_env[stream_index];
2299 struct ia_css_frame_info *css_output_info;
2300 struct ia_css_stream_config *stream_config = &stream_env->stream_config;
2301
2302 stream_env->pipe_configs[pipe_id].mode =
2303 __pipe_id_to_pipe_mode(asd, pipe_id);
2304 stream_env->update_pipe[pipe_id] = true;
2305
2306 /*
2307 * second_output will be as video main output in SDV mode
2308 * with SOC camera. output will be as video main output in
2309 * normal video mode.
2310 */
2311 if (asd->continuous_mode->val)
2312 css_output_info = &stream_env->pipe_configs[pipe_id].
2313 output_info[ATOMISP_CSS_OUTPUT_SECOND_INDEX];
2314 else
2315 css_output_info = &stream_env->pipe_configs[pipe_id].
2316 output_info[ATOMISP_CSS_OUTPUT_DEFAULT_INDEX];
2317
2318 css_output_info->res.width = width;
2319 css_output_info->res.height = height;
2320 css_output_info->format = format;
2321 css_output_info->padded_width = min_width;
2322
2323 /* isp binary 2.2 specific setting*/
2324 if (width > stream_config->input_config.effective_res.width ||
2325 height > stream_config->input_config.effective_res.height) {
2326 stream_config->input_config.effective_res.width = width;
2327 stream_config->input_config.effective_res.height = height;
2328 }
2329
2330 dev_dbg(isp->dev, "configuring pipe[%d] output info w=%d.h=%d.f=%d.\n",
2331 pipe_id, width, height, format);
2332 }
2333
2334 /*
2335 * For CSS2.1, capture pipe uses capture_pp_in_res to configure yuv
2336 * downscaling input resolution.
2337 */
__configure_capture_pp_input(struct atomisp_sub_device * asd,unsigned int width,unsigned int height,enum ia_css_pipe_id pipe_id)2338 static void __configure_capture_pp_input(struct atomisp_sub_device *asd,
2339 unsigned int width, unsigned int height,
2340 enum ia_css_pipe_id pipe_id)
2341 {
2342 struct atomisp_device *isp = asd->isp;
2343 struct atomisp_stream_env *stream_env =
2344 &asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL];
2345 struct ia_css_stream_config *stream_config = &stream_env->stream_config;
2346 struct ia_css_pipe_config *pipe_configs =
2347 &stream_env->pipe_configs[pipe_id];
2348 struct ia_css_pipe_extra_config *pipe_extra_configs =
2349 &stream_env->pipe_extra_configs[pipe_id];
2350 unsigned int hor_ds_factor = 0, ver_ds_factor = 0;
2351
2352 if (width == 0 && height == 0)
2353 return;
2354
2355 if (width * 9 / 10 < pipe_configs->output_info[0].res.width ||
2356 height * 9 / 10 < pipe_configs->output_info[0].res.height)
2357 return;
2358 /* here just copy the calculation in css */
2359 hor_ds_factor = CEIL_DIV(width >> 1,
2360 pipe_configs->output_info[0].res.width);
2361 ver_ds_factor = CEIL_DIV(height >> 1,
2362 pipe_configs->output_info[0].res.height);
2363
2364 if ((asd->isp->media_dev.hw_revision <
2365 (ATOMISP_HW_REVISION_ISP2401 << ATOMISP_HW_REVISION_SHIFT) ||
2366 IS_CHT) && hor_ds_factor != ver_ds_factor) {
2367 dev_warn(asd->isp->dev,
2368 "Cropping for capture due to FW limitation");
2369 return;
2370 }
2371
2372 pipe_configs->mode = __pipe_id_to_pipe_mode(asd, pipe_id);
2373 stream_env->update_pipe[pipe_id] = true;
2374
2375 pipe_extra_configs->enable_yuv_ds = true;
2376
2377 pipe_configs->capt_pp_in_res.width =
2378 stream_config->input_config.effective_res.width;
2379 pipe_configs->capt_pp_in_res.height =
2380 stream_config->input_config.effective_res.height;
2381
2382 dev_dbg(isp->dev, "configuring pipe[%d]capture pp input w=%d.h=%d.\n",
2383 pipe_id, width, height);
2384 }
2385
2386 /*
2387 * For CSS2.1, preview pipe could support bayer downscaling, yuv decimation and
2388 * yuv downscaling, which needs addtional configurations.
2389 */
__configure_preview_pp_input(struct atomisp_sub_device * asd,unsigned int width,unsigned int height,enum ia_css_pipe_id pipe_id)2390 static void __configure_preview_pp_input(struct atomisp_sub_device *asd,
2391 unsigned int width, unsigned int height,
2392 enum ia_css_pipe_id pipe_id)
2393 {
2394 struct atomisp_device *isp = asd->isp;
2395 int out_width, out_height, yuv_ds_in_width, yuv_ds_in_height;
2396 struct atomisp_stream_env *stream_env =
2397 &asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL];
2398 struct ia_css_stream_config *stream_config = &stream_env->stream_config;
2399 struct ia_css_pipe_config *pipe_configs =
2400 &stream_env->pipe_configs[pipe_id];
2401 struct ia_css_pipe_extra_config *pipe_extra_configs =
2402 &stream_env->pipe_extra_configs[pipe_id];
2403 struct ia_css_resolution *bayer_ds_out_res =
2404 &pipe_configs->bayer_ds_out_res;
2405 struct ia_css_resolution *vf_pp_in_res =
2406 &pipe_configs->vf_pp_in_res;
2407 struct ia_css_resolution *effective_res =
2408 &stream_config->input_config.effective_res;
2409
2410 static const struct bayer_ds_factor bds_fct[] = {{2, 1}, {3, 2}, {5, 4} };
2411 /*
2412 * BZ201033: YUV decimation factor of 4 causes couple of rightmost
2413 * columns to be shaded. Remove this factor to work around the CSS bug.
2414 * const unsigned int yuv_dec_fct[] = {4, 2};
2415 */
2416 static const unsigned int yuv_dec_fct[] = { 2 };
2417 unsigned int i;
2418
2419 if (width == 0 && height == 0)
2420 return;
2421
2422 pipe_configs->mode = __pipe_id_to_pipe_mode(asd, pipe_id);
2423 stream_env->update_pipe[pipe_id] = true;
2424
2425 out_width = pipe_configs->output_info[0].res.width;
2426 out_height = pipe_configs->output_info[0].res.height;
2427
2428 /*
2429 * The ISP could do bayer downscaling, yuv decimation and yuv
2430 * downscaling:
2431 * 1: Bayer Downscaling: between effective resolution and
2432 * bayer_ds_res_out;
2433 * 2: YUV Decimation: between bayer_ds_res_out and vf_pp_in_res;
2434 * 3: YUV Downscaling: between vf_pp_in_res and final vf output
2435 *
2436 * Rule for Bayer Downscaling: support factor 2, 1.5 and 1.25
2437 * Rule for YUV Decimation: support factor 2, 4
2438 * Rule for YUV Downscaling: arbitrary value below 2
2439 *
2440 * General rule of factor distribution among these stages:
2441 * 1: try to do Bayer downscaling first if not in online mode.
2442 * 2: try to do maximum of 2 for YUV downscaling
2443 * 3: the remainling for YUV decimation
2444 *
2445 * Note:
2446 * Do not configure bayer_ds_out_res if:
2447 * online == 1 or continuous == 0 or raw_binning = 0
2448 */
2449 if (stream_config->online || !stream_config->continuous ||
2450 !pipe_extra_configs->enable_raw_binning) {
2451 bayer_ds_out_res->width = 0;
2452 bayer_ds_out_res->height = 0;
2453 } else {
2454 bayer_ds_out_res->width = effective_res->width;
2455 bayer_ds_out_res->height = effective_res->height;
2456
2457 for (i = 0; i < ARRAY_SIZE(bds_fct); i++) {
2458 if (effective_res->width >= out_width *
2459 bds_fct[i].numerator / bds_fct[i].denominator &&
2460 effective_res->height >= out_height *
2461 bds_fct[i].numerator / bds_fct[i].denominator) {
2462 bayer_ds_out_res->width =
2463 effective_res->width *
2464 bds_fct[i].denominator /
2465 bds_fct[i].numerator;
2466 bayer_ds_out_res->height =
2467 effective_res->height *
2468 bds_fct[i].denominator /
2469 bds_fct[i].numerator;
2470 break;
2471 }
2472 }
2473 }
2474 /*
2475 * calculate YUV Decimation, YUV downscaling facor:
2476 * YUV Downscaling factor must not exceed 2.
2477 * YUV Decimation factor could be 2, 4.
2478 */
2479 /* first decide the yuv_ds input resolution */
2480 if (bayer_ds_out_res->width == 0) {
2481 yuv_ds_in_width = effective_res->width;
2482 yuv_ds_in_height = effective_res->height;
2483 } else {
2484 yuv_ds_in_width = bayer_ds_out_res->width;
2485 yuv_ds_in_height = bayer_ds_out_res->height;
2486 }
2487
2488 vf_pp_in_res->width = yuv_ds_in_width;
2489 vf_pp_in_res->height = yuv_ds_in_height;
2490
2491 /* find out the yuv decimation factor */
2492 for (i = 0; i < ARRAY_SIZE(yuv_dec_fct); i++) {
2493 if (yuv_ds_in_width >= out_width * yuv_dec_fct[i] &&
2494 yuv_ds_in_height >= out_height * yuv_dec_fct[i]) {
2495 vf_pp_in_res->width = yuv_ds_in_width / yuv_dec_fct[i];
2496 vf_pp_in_res->height = yuv_ds_in_height / yuv_dec_fct[i];
2497 break;
2498 }
2499 }
2500
2501 if (vf_pp_in_res->width == out_width &&
2502 vf_pp_in_res->height == out_height) {
2503 pipe_extra_configs->enable_yuv_ds = false;
2504 vf_pp_in_res->width = 0;
2505 vf_pp_in_res->height = 0;
2506 } else {
2507 pipe_extra_configs->enable_yuv_ds = true;
2508 }
2509
2510 dev_dbg(isp->dev, "configuring pipe[%d]preview pp input w=%d.h=%d.\n",
2511 pipe_id, width, height);
2512 }
2513
2514 /*
2515 * For CSS2.1, offline video pipe could support bayer decimation, and
2516 * yuv downscaling, which needs addtional configurations.
2517 */
__configure_video_pp_input(struct atomisp_sub_device * asd,unsigned int width,unsigned int height,enum ia_css_pipe_id pipe_id)2518 static void __configure_video_pp_input(struct atomisp_sub_device *asd,
2519 unsigned int width, unsigned int height,
2520 enum ia_css_pipe_id pipe_id)
2521 {
2522 struct atomisp_device *isp = asd->isp;
2523 int out_width, out_height;
2524 struct atomisp_stream_env *stream_env =
2525 &asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL];
2526 struct ia_css_stream_config *stream_config = &stream_env->stream_config;
2527 struct ia_css_pipe_config *pipe_configs =
2528 &stream_env->pipe_configs[pipe_id];
2529 struct ia_css_pipe_extra_config *pipe_extra_configs =
2530 &stream_env->pipe_extra_configs[pipe_id];
2531 struct ia_css_resolution *bayer_ds_out_res =
2532 &pipe_configs->bayer_ds_out_res;
2533 struct ia_css_resolution *effective_res =
2534 &stream_config->input_config.effective_res;
2535
2536 static const struct bayer_ds_factor bds_factors[] = {
2537 {8, 1}, {6, 1}, {4, 1}, {3, 1}, {2, 1}, {3, 2}
2538 };
2539 unsigned int i;
2540
2541 if (width == 0 && height == 0)
2542 return;
2543
2544 pipe_configs->mode = __pipe_id_to_pipe_mode(asd, pipe_id);
2545 stream_env->update_pipe[pipe_id] = true;
2546
2547 pipe_extra_configs->enable_yuv_ds = false;
2548
2549 /*
2550 * If DVS is enabled, video binary will take care the dvs envelope
2551 * and usually the bayer_ds_out_res should be larger than 120% of
2552 * destination resolution, the extra 20% will be cropped as DVS
2553 * envelope. But, if the bayer_ds_out_res is less than 120% of the
2554 * destination. The ISP can still work, but DVS quality is not good.
2555 */
2556 /* taking at least 10% as envelope */
2557 if (asd->params.video_dis_en) {
2558 out_width = pipe_configs->output_info[0].res.width * 110 / 100;
2559 out_height = pipe_configs->output_info[0].res.height * 110 / 100;
2560 } else {
2561 out_width = pipe_configs->output_info[0].res.width;
2562 out_height = pipe_configs->output_info[0].res.height;
2563 }
2564
2565 /*
2566 * calculate bayer decimate factor:
2567 * 1: only 1.5, 2, 4 and 8 get supported
2568 * 2: Do not configure bayer_ds_out_res if:
2569 * online == 1 or continuous == 0 or raw_binning = 0
2570 */
2571 if (stream_config->online || !stream_config->continuous) {
2572 bayer_ds_out_res->width = 0;
2573 bayer_ds_out_res->height = 0;
2574 goto done;
2575 }
2576
2577 pipe_extra_configs->enable_raw_binning = true;
2578 bayer_ds_out_res->width = effective_res->width;
2579 bayer_ds_out_res->height = effective_res->height;
2580
2581 for (i = 0; i < sizeof(bds_factors) / sizeof(struct bayer_ds_factor);
2582 i++) {
2583 if (effective_res->width >= out_width *
2584 bds_factors[i].numerator / bds_factors[i].denominator &&
2585 effective_res->height >= out_height *
2586 bds_factors[i].numerator / bds_factors[i].denominator) {
2587 bayer_ds_out_res->width = effective_res->width *
2588 bds_factors[i].denominator /
2589 bds_factors[i].numerator;
2590 bayer_ds_out_res->height = effective_res->height *
2591 bds_factors[i].denominator /
2592 bds_factors[i].numerator;
2593 break;
2594 }
2595 }
2596
2597 /*
2598 * DVS is cropped from BDS output, so we do not really need to set the
2599 * envelope to 20% of output resolution here. always set it to 12x12
2600 * per firmware requirement.
2601 */
2602 pipe_configs->dvs_envelope.width = 12;
2603 pipe_configs->dvs_envelope.height = 12;
2604
2605 done:
2606 if (pipe_id == IA_CSS_PIPE_ID_YUVPP)
2607 stream_config->left_padding = -1;
2608 else
2609 stream_config->left_padding = 12;
2610 dev_dbg(isp->dev, "configuring pipe[%d]video pp input w=%d.h=%d.\n",
2611 pipe_id, width, height);
2612 }
2613
__configure_vf_output(struct atomisp_sub_device * asd,unsigned int width,unsigned int height,unsigned int min_width,enum ia_css_frame_format format,enum ia_css_pipe_id pipe_id)2614 static void __configure_vf_output(struct atomisp_sub_device *asd,
2615 unsigned int width, unsigned int height,
2616 unsigned int min_width,
2617 enum ia_css_frame_format format,
2618 enum ia_css_pipe_id pipe_id)
2619 {
2620 struct atomisp_device *isp = asd->isp;
2621 struct atomisp_stream_env *stream_env =
2622 &asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL];
2623 stream_env->pipe_configs[pipe_id].mode =
2624 __pipe_id_to_pipe_mode(asd, pipe_id);
2625 stream_env->update_pipe[pipe_id] = true;
2626
2627 stream_env->pipe_configs[pipe_id].vf_output_info[0].res.width = width;
2628 stream_env->pipe_configs[pipe_id].vf_output_info[0].res.height = height;
2629 stream_env->pipe_configs[pipe_id].vf_output_info[0].format = format;
2630 stream_env->pipe_configs[pipe_id].vf_output_info[0].padded_width =
2631 min_width;
2632 dev_dbg(isp->dev,
2633 "configuring pipe[%d] vf output info w=%d.h=%d.f=%d.\n",
2634 pipe_id, width, height, format);
2635 }
2636
__configure_video_vf_output(struct atomisp_sub_device * asd,unsigned int width,unsigned int height,unsigned int min_width,enum ia_css_frame_format format,enum ia_css_pipe_id pipe_id)2637 static void __configure_video_vf_output(struct atomisp_sub_device *asd,
2638 unsigned int width, unsigned int height,
2639 unsigned int min_width,
2640 enum ia_css_frame_format format,
2641 enum ia_css_pipe_id pipe_id)
2642 {
2643 struct atomisp_device *isp = asd->isp;
2644 struct atomisp_stream_env *stream_env =
2645 &asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL];
2646 struct ia_css_frame_info *css_output_info;
2647
2648 stream_env->pipe_configs[pipe_id].mode =
2649 __pipe_id_to_pipe_mode(asd, pipe_id);
2650 stream_env->update_pipe[pipe_id] = true;
2651
2652 /*
2653 * second_vf_output will be as video viewfinder in SDV mode
2654 * with SOC camera. vf_output will be as video viewfinder in
2655 * normal video mode.
2656 */
2657 if (asd->continuous_mode->val)
2658 css_output_info = &stream_env->pipe_configs[pipe_id].
2659 vf_output_info[ATOMISP_CSS_OUTPUT_SECOND_INDEX];
2660 else
2661 css_output_info = &stream_env->pipe_configs[pipe_id].
2662 vf_output_info[ATOMISP_CSS_OUTPUT_DEFAULT_INDEX];
2663
2664 css_output_info->res.width = width;
2665 css_output_info->res.height = height;
2666 css_output_info->format = format;
2667 css_output_info->padded_width = min_width;
2668 dev_dbg(isp->dev,
2669 "configuring pipe[%d] vf output info w=%d.h=%d.f=%d.\n",
2670 pipe_id, width, height, format);
2671 }
2672
__get_frame_info(struct atomisp_sub_device * asd,unsigned int stream_index,struct ia_css_frame_info * info,enum frame_info_type type,enum ia_css_pipe_id pipe_id)2673 static int __get_frame_info(struct atomisp_sub_device *asd,
2674 unsigned int stream_index,
2675 struct ia_css_frame_info *info,
2676 enum frame_info_type type,
2677 enum ia_css_pipe_id pipe_id)
2678 {
2679 struct atomisp_device *isp = asd->isp;
2680 int ret;
2681 struct ia_css_pipe_info p_info;
2682
2683 /* FIXME! No need to destroy/recreate all streams */
2684 if (__destroy_streams(asd, true))
2685 dev_warn(isp->dev, "destroy stream failed.\n");
2686
2687 if (__destroy_pipes(asd, true))
2688 dev_warn(isp->dev, "destroy pipe failed.\n");
2689
2690 if (__create_pipes(asd))
2691 return -EINVAL;
2692
2693 if (__create_streams(asd))
2694 goto stream_err;
2695
2696 ret = ia_css_pipe_get_info(
2697 asd->stream_env[stream_index]
2698 .pipes[pipe_id], &p_info);
2699 if (!ret) {
2700 switch (type) {
2701 case ATOMISP_CSS_VF_FRAME:
2702 *info = p_info.vf_output_info[0];
2703 dev_dbg(isp->dev, "getting vf frame info.\n");
2704 break;
2705 case ATOMISP_CSS_SECOND_VF_FRAME:
2706 *info = p_info.vf_output_info[1];
2707 dev_dbg(isp->dev, "getting second vf frame info.\n");
2708 break;
2709 case ATOMISP_CSS_OUTPUT_FRAME:
2710 *info = p_info.output_info[0];
2711 dev_dbg(isp->dev, "getting main frame info.\n");
2712 break;
2713 case ATOMISP_CSS_SECOND_OUTPUT_FRAME:
2714 *info = p_info.output_info[1];
2715 dev_dbg(isp->dev, "getting second main frame info.\n");
2716 break;
2717 case ATOMISP_CSS_RAW_FRAME:
2718 *info = p_info.raw_output_info;
2719 dev_dbg(isp->dev, "getting raw frame info.\n");
2720 }
2721 dev_dbg(isp->dev, "get frame info: w=%d, h=%d, num_invalid_frames %d.\n",
2722 info->res.width, info->res.height, p_info.num_invalid_frames);
2723 return 0;
2724 }
2725
2726 stream_err:
2727 __destroy_pipes(asd, true);
2728 return -EINVAL;
2729 }
2730
atomisp_get_pipe_index(struct atomisp_sub_device * asd,uint16_t source_pad)2731 static unsigned int atomisp_get_pipe_index(struct atomisp_sub_device *asd,
2732 uint16_t source_pad)
2733 {
2734 struct atomisp_device *isp = asd->isp;
2735 /*
2736 * to SOC camera, use yuvpp pipe.
2737 */
2738 if (ATOMISP_USE_YUVPP(asd))
2739 return IA_CSS_PIPE_ID_YUVPP;
2740
2741 switch (source_pad) {
2742 case ATOMISP_SUBDEV_PAD_SOURCE_VIDEO:
2743 if (asd->yuvpp_mode)
2744 return IA_CSS_PIPE_ID_YUVPP;
2745 if (asd->copy_mode)
2746 return IA_CSS_PIPE_ID_COPY;
2747 if (asd->run_mode->val == ATOMISP_RUN_MODE_VIDEO
2748 || asd->vfpp->val == ATOMISP_VFPP_DISABLE_SCALER)
2749 return IA_CSS_PIPE_ID_VIDEO;
2750
2751 return IA_CSS_PIPE_ID_CAPTURE;
2752 case ATOMISP_SUBDEV_PAD_SOURCE_CAPTURE:
2753 if (asd->copy_mode)
2754 return IA_CSS_PIPE_ID_COPY;
2755
2756 return IA_CSS_PIPE_ID_CAPTURE;
2757 case ATOMISP_SUBDEV_PAD_SOURCE_VF:
2758 if (!atomisp_is_mbuscode_raw(asd->fmt[asd->capture_pad].fmt.code)) {
2759 return IA_CSS_PIPE_ID_CAPTURE;
2760 }
2761 fallthrough;
2762 case ATOMISP_SUBDEV_PAD_SOURCE_PREVIEW:
2763 if (asd->yuvpp_mode)
2764 return IA_CSS_PIPE_ID_YUVPP;
2765 if (asd->copy_mode)
2766 return IA_CSS_PIPE_ID_COPY;
2767 if (asd->run_mode->val == ATOMISP_RUN_MODE_VIDEO)
2768 return IA_CSS_PIPE_ID_VIDEO;
2769
2770 return IA_CSS_PIPE_ID_PREVIEW;
2771 }
2772 dev_warn(isp->dev,
2773 "invalid source pad:%d, return default preview pipe index.\n",
2774 source_pad);
2775 return IA_CSS_PIPE_ID_PREVIEW;
2776 }
2777
atomisp_get_css_frame_info(struct atomisp_sub_device * asd,u16 source_pad,struct ia_css_frame_info * frame_info)2778 int atomisp_get_css_frame_info(struct atomisp_sub_device *asd,
2779 u16 source_pad,
2780 struct ia_css_frame_info *frame_info)
2781 {
2782 struct ia_css_pipe_info info;
2783 int pipe_index = atomisp_get_pipe_index(asd, source_pad);
2784 int stream_index;
2785 struct atomisp_device *isp = asd->isp;
2786
2787 if (ATOMISP_SOC_CAMERA(asd))
2788 stream_index = atomisp_source_pad_to_stream_id(asd, source_pad);
2789 else {
2790 stream_index = (pipe_index == IA_CSS_PIPE_ID_YUVPP) ?
2791 ATOMISP_INPUT_STREAM_VIDEO :
2792 atomisp_source_pad_to_stream_id(asd, source_pad);
2793 }
2794
2795 if (0 != ia_css_pipe_get_info(asd->stream_env[stream_index]
2796 .pipes[pipe_index], &info)) {
2797 dev_err(isp->dev, "ia_css_pipe_get_info FAILED");
2798 return -EINVAL;
2799 }
2800
2801 switch (source_pad) {
2802 case ATOMISP_SUBDEV_PAD_SOURCE_CAPTURE:
2803 *frame_info = info.output_info[0];
2804 break;
2805 case ATOMISP_SUBDEV_PAD_SOURCE_VIDEO:
2806 if (ATOMISP_USE_YUVPP(asd) && asd->continuous_mode->val)
2807 *frame_info = info.
2808 output_info[ATOMISP_CSS_OUTPUT_SECOND_INDEX];
2809 else
2810 *frame_info = info.
2811 output_info[ATOMISP_CSS_OUTPUT_DEFAULT_INDEX];
2812 break;
2813 case ATOMISP_SUBDEV_PAD_SOURCE_VF:
2814 if (stream_index == ATOMISP_INPUT_STREAM_POSTVIEW)
2815 *frame_info = info.output_info[0];
2816 else
2817 *frame_info = info.vf_output_info[0];
2818 break;
2819 case ATOMISP_SUBDEV_PAD_SOURCE_PREVIEW:
2820 if (asd->run_mode->val == ATOMISP_RUN_MODE_VIDEO &&
2821 (pipe_index == IA_CSS_PIPE_ID_VIDEO ||
2822 pipe_index == IA_CSS_PIPE_ID_YUVPP))
2823 if (ATOMISP_USE_YUVPP(asd) && asd->continuous_mode->val)
2824 *frame_info = info.
2825 vf_output_info[ATOMISP_CSS_OUTPUT_SECOND_INDEX];
2826 else
2827 *frame_info = info.
2828 vf_output_info[ATOMISP_CSS_OUTPUT_DEFAULT_INDEX];
2829 else if (ATOMISP_USE_YUVPP(asd) && asd->continuous_mode->val)
2830 *frame_info =
2831 info.output_info[ATOMISP_CSS_OUTPUT_SECOND_INDEX];
2832 else
2833 *frame_info =
2834 info.output_info[ATOMISP_CSS_OUTPUT_DEFAULT_INDEX];
2835
2836 break;
2837 default:
2838 frame_info = NULL;
2839 break;
2840 }
2841 return frame_info ? 0 : -EINVAL;
2842 }
2843
atomisp_css_copy_configure_output(struct atomisp_sub_device * asd,unsigned int stream_index,unsigned int width,unsigned int height,unsigned int padded_width,enum ia_css_frame_format format)2844 int atomisp_css_copy_configure_output(struct atomisp_sub_device *asd,
2845 unsigned int stream_index,
2846 unsigned int width, unsigned int height,
2847 unsigned int padded_width,
2848 enum ia_css_frame_format format)
2849 {
2850 asd->stream_env[stream_index].pipe_configs[IA_CSS_PIPE_ID_COPY].
2851 default_capture_config.mode =
2852 IA_CSS_CAPTURE_MODE_RAW;
2853
2854 __configure_output(asd, stream_index, width, height, padded_width,
2855 format, IA_CSS_PIPE_ID_COPY);
2856 return 0;
2857 }
2858
atomisp_css_yuvpp_configure_output(struct atomisp_sub_device * asd,unsigned int stream_index,unsigned int width,unsigned int height,unsigned int padded_width,enum ia_css_frame_format format)2859 int atomisp_css_yuvpp_configure_output(struct atomisp_sub_device *asd,
2860 unsigned int stream_index,
2861 unsigned int width, unsigned int height,
2862 unsigned int padded_width,
2863 enum ia_css_frame_format format)
2864 {
2865 asd->stream_env[stream_index].pipe_configs[IA_CSS_PIPE_ID_YUVPP].
2866 default_capture_config.mode =
2867 IA_CSS_CAPTURE_MODE_RAW;
2868
2869 __configure_output(asd, stream_index, width, height, padded_width,
2870 format, IA_CSS_PIPE_ID_YUVPP);
2871 return 0;
2872 }
2873
atomisp_css_yuvpp_configure_viewfinder(struct atomisp_sub_device * asd,unsigned int stream_index,unsigned int width,unsigned int height,unsigned int min_width,enum ia_css_frame_format format)2874 int atomisp_css_yuvpp_configure_viewfinder(
2875 struct atomisp_sub_device *asd,
2876 unsigned int stream_index,
2877 unsigned int width, unsigned int height,
2878 unsigned int min_width,
2879 enum ia_css_frame_format format)
2880 {
2881 struct atomisp_stream_env *stream_env =
2882 &asd->stream_env[stream_index];
2883 enum ia_css_pipe_id pipe_id = IA_CSS_PIPE_ID_YUVPP;
2884
2885 stream_env->pipe_configs[pipe_id].mode =
2886 __pipe_id_to_pipe_mode(asd, pipe_id);
2887 stream_env->update_pipe[pipe_id] = true;
2888
2889 stream_env->pipe_configs[pipe_id].vf_output_info[0].res.width = width;
2890 stream_env->pipe_configs[pipe_id].vf_output_info[0].res.height = height;
2891 stream_env->pipe_configs[pipe_id].vf_output_info[0].format = format;
2892 stream_env->pipe_configs[pipe_id].vf_output_info[0].padded_width =
2893 min_width;
2894 return 0;
2895 }
2896
atomisp_css_yuvpp_get_output_frame_info(struct atomisp_sub_device * asd,unsigned int stream_index,struct ia_css_frame_info * info)2897 int atomisp_css_yuvpp_get_output_frame_info(
2898 struct atomisp_sub_device *asd,
2899 unsigned int stream_index,
2900 struct ia_css_frame_info *info)
2901 {
2902 return __get_frame_info(asd, stream_index, info,
2903 ATOMISP_CSS_OUTPUT_FRAME, IA_CSS_PIPE_ID_YUVPP);
2904 }
2905
atomisp_css_yuvpp_get_viewfinder_frame_info(struct atomisp_sub_device * asd,unsigned int stream_index,struct ia_css_frame_info * info)2906 int atomisp_css_yuvpp_get_viewfinder_frame_info(
2907 struct atomisp_sub_device *asd,
2908 unsigned int stream_index,
2909 struct ia_css_frame_info *info)
2910 {
2911 return __get_frame_info(asd, stream_index, info,
2912 ATOMISP_CSS_VF_FRAME, IA_CSS_PIPE_ID_YUVPP);
2913 }
2914
atomisp_css_preview_configure_output(struct atomisp_sub_device * asd,unsigned int width,unsigned int height,unsigned int min_width,enum ia_css_frame_format format)2915 int atomisp_css_preview_configure_output(struct atomisp_sub_device *asd,
2916 unsigned int width, unsigned int height,
2917 unsigned int min_width,
2918 enum ia_css_frame_format format)
2919 {
2920 /*
2921 * to SOC camera, use yuvpp pipe.
2922 */
2923 if (ATOMISP_USE_YUVPP(asd))
2924 __configure_video_preview_output(asd, ATOMISP_INPUT_STREAM_GENERAL, width,
2925 height,
2926 min_width, format, IA_CSS_PIPE_ID_YUVPP);
2927 else
2928 __configure_output(asd, ATOMISP_INPUT_STREAM_GENERAL, width, height,
2929 min_width, format, IA_CSS_PIPE_ID_PREVIEW);
2930 return 0;
2931 }
2932
atomisp_css_capture_configure_output(struct atomisp_sub_device * asd,unsigned int width,unsigned int height,unsigned int min_width,enum ia_css_frame_format format)2933 int atomisp_css_capture_configure_output(struct atomisp_sub_device *asd,
2934 unsigned int width, unsigned int height,
2935 unsigned int min_width,
2936 enum ia_css_frame_format format)
2937 {
2938 enum ia_css_pipe_id pipe_id;
2939
2940 /*
2941 * to SOC camera, use yuvpp pipe.
2942 */
2943 if (ATOMISP_USE_YUVPP(asd))
2944 pipe_id = IA_CSS_PIPE_ID_YUVPP;
2945 else
2946 pipe_id = IA_CSS_PIPE_ID_CAPTURE;
2947
2948 __configure_output(asd, ATOMISP_INPUT_STREAM_GENERAL, width, height,
2949 min_width, format, pipe_id);
2950 return 0;
2951 }
2952
atomisp_css_video_configure_output(struct atomisp_sub_device * asd,unsigned int width,unsigned int height,unsigned int min_width,enum ia_css_frame_format format)2953 int atomisp_css_video_configure_output(struct atomisp_sub_device *asd,
2954 unsigned int width, unsigned int height,
2955 unsigned int min_width,
2956 enum ia_css_frame_format format)
2957 {
2958 /*
2959 * to SOC camera, use yuvpp pipe.
2960 */
2961 if (ATOMISP_USE_YUVPP(asd))
2962 __configure_video_preview_output(asd, ATOMISP_INPUT_STREAM_GENERAL, width,
2963 height,
2964 min_width, format, IA_CSS_PIPE_ID_YUVPP);
2965 else
2966 __configure_output(asd, ATOMISP_INPUT_STREAM_GENERAL, width, height,
2967 min_width, format, IA_CSS_PIPE_ID_VIDEO);
2968 return 0;
2969 }
2970
atomisp_css_video_configure_viewfinder(struct atomisp_sub_device * asd,unsigned int width,unsigned int height,unsigned int min_width,enum ia_css_frame_format format)2971 int atomisp_css_video_configure_viewfinder(
2972 struct atomisp_sub_device *asd,
2973 unsigned int width, unsigned int height,
2974 unsigned int min_width,
2975 enum ia_css_frame_format format)
2976 {
2977 /*
2978 * to SOC camera, video will use yuvpp pipe.
2979 */
2980 if (ATOMISP_USE_YUVPP(asd))
2981 __configure_video_vf_output(asd, width, height, min_width, format,
2982 IA_CSS_PIPE_ID_YUVPP);
2983 else
2984 __configure_vf_output(asd, width, height, min_width, format,
2985 IA_CSS_PIPE_ID_VIDEO);
2986 return 0;
2987 }
2988
atomisp_css_capture_configure_viewfinder(struct atomisp_sub_device * asd,unsigned int width,unsigned int height,unsigned int min_width,enum ia_css_frame_format format)2989 int atomisp_css_capture_configure_viewfinder(
2990 struct atomisp_sub_device *asd,
2991 unsigned int width, unsigned int height,
2992 unsigned int min_width,
2993 enum ia_css_frame_format format)
2994 {
2995 enum ia_css_pipe_id pipe_id;
2996
2997 /*
2998 * to SOC camera, video will use yuvpp pipe.
2999 */
3000 if (ATOMISP_USE_YUVPP(asd))
3001 pipe_id = IA_CSS_PIPE_ID_YUVPP;
3002 else
3003 pipe_id = IA_CSS_PIPE_ID_CAPTURE;
3004
3005 __configure_vf_output(asd, width, height, min_width, format,
3006 pipe_id);
3007 return 0;
3008 }
3009
atomisp_css_video_get_viewfinder_frame_info(struct atomisp_sub_device * asd,struct ia_css_frame_info * info)3010 int atomisp_css_video_get_viewfinder_frame_info(
3011 struct atomisp_sub_device *asd,
3012 struct ia_css_frame_info *info)
3013 {
3014 enum ia_css_pipe_id pipe_id;
3015 enum frame_info_type frame_type = ATOMISP_CSS_VF_FRAME;
3016
3017 if (ATOMISP_USE_YUVPP(asd)) {
3018 pipe_id = IA_CSS_PIPE_ID_YUVPP;
3019 if (asd->continuous_mode->val)
3020 frame_type = ATOMISP_CSS_SECOND_VF_FRAME;
3021 } else {
3022 pipe_id = IA_CSS_PIPE_ID_VIDEO;
3023 }
3024
3025 return __get_frame_info(asd, ATOMISP_INPUT_STREAM_GENERAL, info,
3026 frame_type, pipe_id);
3027 }
3028
atomisp_css_capture_get_viewfinder_frame_info(struct atomisp_sub_device * asd,struct ia_css_frame_info * info)3029 int atomisp_css_capture_get_viewfinder_frame_info(
3030 struct atomisp_sub_device *asd,
3031 struct ia_css_frame_info *info)
3032 {
3033 enum ia_css_pipe_id pipe_id;
3034
3035 if (ATOMISP_USE_YUVPP(asd))
3036 pipe_id = IA_CSS_PIPE_ID_YUVPP;
3037 else
3038 pipe_id = IA_CSS_PIPE_ID_CAPTURE;
3039
3040 return __get_frame_info(asd, ATOMISP_INPUT_STREAM_GENERAL, info,
3041 ATOMISP_CSS_VF_FRAME, pipe_id);
3042 }
3043
atomisp_css_capture_get_output_raw_frame_info(struct atomisp_sub_device * asd,struct ia_css_frame_info * info)3044 int atomisp_css_capture_get_output_raw_frame_info(
3045 struct atomisp_sub_device *asd,
3046 struct ia_css_frame_info *info)
3047 {
3048 if (ATOMISP_USE_YUVPP(asd))
3049 return 0;
3050
3051 return __get_frame_info(asd, ATOMISP_INPUT_STREAM_GENERAL, info,
3052 ATOMISP_CSS_RAW_FRAME, IA_CSS_PIPE_ID_CAPTURE);
3053 }
3054
atomisp_css_copy_get_output_frame_info(struct atomisp_sub_device * asd,unsigned int stream_index,struct ia_css_frame_info * info)3055 int atomisp_css_copy_get_output_frame_info(
3056 struct atomisp_sub_device *asd,
3057 unsigned int stream_index,
3058 struct ia_css_frame_info *info)
3059 {
3060 return __get_frame_info(asd, stream_index, info,
3061 ATOMISP_CSS_OUTPUT_FRAME, IA_CSS_PIPE_ID_COPY);
3062 }
3063
atomisp_css_preview_get_output_frame_info(struct atomisp_sub_device * asd,struct ia_css_frame_info * info)3064 int atomisp_css_preview_get_output_frame_info(
3065 struct atomisp_sub_device *asd,
3066 struct ia_css_frame_info *info)
3067 {
3068 enum ia_css_pipe_id pipe_id;
3069 enum frame_info_type frame_type = ATOMISP_CSS_OUTPUT_FRAME;
3070
3071 if (ATOMISP_USE_YUVPP(asd)) {
3072 pipe_id = IA_CSS_PIPE_ID_YUVPP;
3073 if (asd->continuous_mode->val)
3074 frame_type = ATOMISP_CSS_SECOND_OUTPUT_FRAME;
3075 } else {
3076 pipe_id = IA_CSS_PIPE_ID_PREVIEW;
3077 }
3078
3079 return __get_frame_info(asd, ATOMISP_INPUT_STREAM_GENERAL, info,
3080 frame_type, pipe_id);
3081 }
3082
atomisp_css_capture_get_output_frame_info(struct atomisp_sub_device * asd,struct ia_css_frame_info * info)3083 int atomisp_css_capture_get_output_frame_info(
3084 struct atomisp_sub_device *asd,
3085 struct ia_css_frame_info *info)
3086 {
3087 enum ia_css_pipe_id pipe_id;
3088
3089 if (ATOMISP_USE_YUVPP(asd))
3090 pipe_id = IA_CSS_PIPE_ID_YUVPP;
3091 else
3092 pipe_id = IA_CSS_PIPE_ID_CAPTURE;
3093
3094 return __get_frame_info(asd, ATOMISP_INPUT_STREAM_GENERAL, info,
3095 ATOMISP_CSS_OUTPUT_FRAME, pipe_id);
3096 }
3097
atomisp_css_video_get_output_frame_info(struct atomisp_sub_device * asd,struct ia_css_frame_info * info)3098 int atomisp_css_video_get_output_frame_info(
3099 struct atomisp_sub_device *asd,
3100 struct ia_css_frame_info *info)
3101 {
3102 enum ia_css_pipe_id pipe_id;
3103 enum frame_info_type frame_type = ATOMISP_CSS_OUTPUT_FRAME;
3104
3105 if (ATOMISP_USE_YUVPP(asd)) {
3106 pipe_id = IA_CSS_PIPE_ID_YUVPP;
3107 if (asd->continuous_mode->val)
3108 frame_type = ATOMISP_CSS_SECOND_OUTPUT_FRAME;
3109 } else {
3110 pipe_id = IA_CSS_PIPE_ID_VIDEO;
3111 }
3112
3113 return __get_frame_info(asd, ATOMISP_INPUT_STREAM_GENERAL, info,
3114 frame_type, pipe_id);
3115 }
3116
atomisp_css_preview_configure_pp_input(struct atomisp_sub_device * asd,unsigned int width,unsigned int height)3117 int atomisp_css_preview_configure_pp_input(
3118 struct atomisp_sub_device *asd,
3119 unsigned int width, unsigned int height)
3120 {
3121 struct atomisp_stream_env *stream_env =
3122 &asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL];
3123 __configure_preview_pp_input(asd, width, height,
3124 ATOMISP_USE_YUVPP(asd) ?
3125 IA_CSS_PIPE_ID_YUVPP : IA_CSS_PIPE_ID_PREVIEW);
3126
3127 if (width > stream_env->pipe_configs[IA_CSS_PIPE_ID_CAPTURE].
3128 capt_pp_in_res.width)
3129 __configure_capture_pp_input(asd, width, height,
3130 ATOMISP_USE_YUVPP(asd) ?
3131 IA_CSS_PIPE_ID_YUVPP : IA_CSS_PIPE_ID_CAPTURE);
3132 return 0;
3133 }
3134
atomisp_css_capture_configure_pp_input(struct atomisp_sub_device * asd,unsigned int width,unsigned int height)3135 int atomisp_css_capture_configure_pp_input(
3136 struct atomisp_sub_device *asd,
3137 unsigned int width, unsigned int height)
3138 {
3139 __configure_capture_pp_input(asd, width, height,
3140 ATOMISP_USE_YUVPP(asd) ?
3141 IA_CSS_PIPE_ID_YUVPP : IA_CSS_PIPE_ID_CAPTURE);
3142 return 0;
3143 }
3144
atomisp_css_video_configure_pp_input(struct atomisp_sub_device * asd,unsigned int width,unsigned int height)3145 int atomisp_css_video_configure_pp_input(
3146 struct atomisp_sub_device *asd,
3147 unsigned int width, unsigned int height)
3148 {
3149 struct atomisp_stream_env *stream_env =
3150 &asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL];
3151
3152 __configure_video_pp_input(asd, width, height,
3153 ATOMISP_USE_YUVPP(asd) ?
3154 IA_CSS_PIPE_ID_YUVPP : IA_CSS_PIPE_ID_VIDEO);
3155
3156 if (width > stream_env->pipe_configs[IA_CSS_PIPE_ID_CAPTURE].
3157 capt_pp_in_res.width)
3158 __configure_capture_pp_input(asd, width, height,
3159 ATOMISP_USE_YUVPP(asd) ?
3160 IA_CSS_PIPE_ID_YUVPP : IA_CSS_PIPE_ID_CAPTURE);
3161 return 0;
3162 }
3163
atomisp_css_offline_capture_configure(struct atomisp_sub_device * asd,int num_captures,unsigned int skip,int offset)3164 int atomisp_css_offline_capture_configure(struct atomisp_sub_device *asd,
3165 int num_captures, unsigned int skip, int offset)
3166 {
3167 int ret;
3168
3169 dev_dbg(asd->isp->dev, "%s num_capture:%d skip:%d offset:%d\n",
3170 __func__, num_captures, skip, offset);
3171
3172 ret = ia_css_stream_capture(
3173 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream,
3174 num_captures, skip, offset);
3175 if (ret)
3176 return -EINVAL;
3177
3178 return 0;
3179 }
3180
atomisp_css_exp_id_capture(struct atomisp_sub_device * asd,int exp_id)3181 int atomisp_css_exp_id_capture(struct atomisp_sub_device *asd, int exp_id)
3182 {
3183 int ret;
3184
3185 ret = ia_css_stream_capture_frame(
3186 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream,
3187 exp_id);
3188 if (ret == -ENOBUFS) {
3189 /* capture cmd queue is full */
3190 return -EBUSY;
3191 } else if (ret) {
3192 return -EIO;
3193 }
3194
3195 return 0;
3196 }
3197
atomisp_css_exp_id_unlock(struct atomisp_sub_device * asd,int exp_id)3198 int atomisp_css_exp_id_unlock(struct atomisp_sub_device *asd, int exp_id)
3199 {
3200 int ret;
3201
3202 ret = ia_css_unlock_raw_frame(
3203 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream,
3204 exp_id);
3205 if (ret == -ENOBUFS)
3206 return -EAGAIN;
3207 else if (ret)
3208 return -EIO;
3209
3210 return 0;
3211 }
3212
atomisp_css_capture_enable_xnr(struct atomisp_sub_device * asd,bool enable)3213 int atomisp_css_capture_enable_xnr(struct atomisp_sub_device *asd,
3214 bool enable)
3215 {
3216 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]
3217 .pipe_configs[IA_CSS_PIPE_ID_CAPTURE]
3218 .default_capture_config.enable_xnr = enable;
3219 asd->params.capture_config.enable_xnr = enable;
3220 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]
3221 .update_pipe[IA_CSS_PIPE_ID_CAPTURE] = true;
3222
3223 return 0;
3224 }
3225
atomisp_css_set_ctc_table(struct atomisp_sub_device * asd,struct ia_css_ctc_table * ctc_table)3226 void atomisp_css_set_ctc_table(struct atomisp_sub_device *asd,
3227 struct ia_css_ctc_table *ctc_table)
3228 {
3229 int i;
3230 u16 *vamem_ptr = ctc_table->data.vamem_1;
3231 int data_size = IA_CSS_VAMEM_1_CTC_TABLE_SIZE;
3232 bool valid = false;
3233
3234 /* workaround: if ctc_table is all 0, do not apply it */
3235 if (ctc_table->vamem_type == IA_CSS_VAMEM_TYPE_2) {
3236 vamem_ptr = ctc_table->data.vamem_2;
3237 data_size = IA_CSS_VAMEM_2_CTC_TABLE_SIZE;
3238 }
3239
3240 for (i = 0; i < data_size; i++) {
3241 if (*(vamem_ptr + i)) {
3242 valid = true;
3243 break;
3244 }
3245 }
3246
3247 if (valid)
3248 asd->params.config.ctc_table = ctc_table;
3249 else
3250 dev_warn(asd->isp->dev, "Bypass the invalid ctc_table.\n");
3251 }
3252
atomisp_css_set_anr_thres(struct atomisp_sub_device * asd,struct ia_css_anr_thres * anr_thres)3253 void atomisp_css_set_anr_thres(struct atomisp_sub_device *asd,
3254 struct ia_css_anr_thres *anr_thres)
3255 {
3256 asd->params.config.anr_thres = anr_thres;
3257 }
3258
atomisp_css_set_dvs_6axis(struct atomisp_sub_device * asd,struct ia_css_dvs_6axis_config * dvs_6axis)3259 void atomisp_css_set_dvs_6axis(struct atomisp_sub_device *asd,
3260 struct ia_css_dvs_6axis_config *dvs_6axis)
3261 {
3262 asd->params.config.dvs_6axis_config = dvs_6axis;
3263 }
3264
atomisp_css_video_set_dis_vector(struct atomisp_sub_device * asd,struct atomisp_dis_vector * vector)3265 void atomisp_css_video_set_dis_vector(struct atomisp_sub_device *asd,
3266 struct atomisp_dis_vector *vector)
3267 {
3268 if (!asd->params.config.motion_vector)
3269 asd->params.config.motion_vector = &asd->params.css_param.motion_vector;
3270
3271 memset(asd->params.config.motion_vector,
3272 0, sizeof(struct ia_css_vector));
3273 asd->params.css_param.motion_vector.x = vector->x;
3274 asd->params.css_param.motion_vector.y = vector->y;
3275 }
3276
atomisp_compare_dvs_grid(struct atomisp_sub_device * asd,struct atomisp_dvs_grid_info * atomgrid)3277 static int atomisp_compare_dvs_grid(struct atomisp_sub_device *asd,
3278 struct atomisp_dvs_grid_info *atomgrid)
3279 {
3280 struct ia_css_dvs_grid_info *cur =
3281 atomisp_css_get_dvs_grid_info(&asd->params.curr_grid_info);
3282
3283 if (!cur) {
3284 dev_err(asd->isp->dev, "dvs grid not available!\n");
3285 return -EINVAL;
3286 }
3287
3288 if (sizeof(*cur) != sizeof(*atomgrid)) {
3289 dev_err(asd->isp->dev, "dvs grid mis-match!\n");
3290 return -EINVAL;
3291 }
3292
3293 if (!cur->enable) {
3294 dev_err(asd->isp->dev, "dvs not enabled!\n");
3295 return -EINVAL;
3296 }
3297
3298 return memcmp(atomgrid, cur, sizeof(*cur));
3299 }
3300
atomisp_css_set_dvs2_coefs(struct atomisp_sub_device * asd,struct ia_css_dvs2_coefficients * coefs)3301 void atomisp_css_set_dvs2_coefs(struct atomisp_sub_device *asd,
3302 struct ia_css_dvs2_coefficients *coefs)
3303 {
3304 asd->params.config.dvs2_coefs = coefs;
3305 }
3306
atomisp_css_set_dis_coefs(struct atomisp_sub_device * asd,struct atomisp_dis_coefficients * coefs)3307 int atomisp_css_set_dis_coefs(struct atomisp_sub_device *asd,
3308 struct atomisp_dis_coefficients *coefs)
3309 {
3310 if (atomisp_compare_dvs_grid(asd, &coefs->grid_info) != 0)
3311 /* If the grid info in the argument differs from the current
3312 grid info, we tell the caller to reset the grid size and
3313 try again. */
3314 return -EAGAIN;
3315
3316 if (!coefs->hor_coefs.odd_real ||
3317 !coefs->hor_coefs.odd_imag ||
3318 !coefs->hor_coefs.even_real ||
3319 !coefs->hor_coefs.even_imag ||
3320 !coefs->ver_coefs.odd_real ||
3321 !coefs->ver_coefs.odd_imag ||
3322 !coefs->ver_coefs.even_real ||
3323 !coefs->ver_coefs.even_imag ||
3324 !asd->params.css_param.dvs2_coeff->hor_coefs.odd_real ||
3325 !asd->params.css_param.dvs2_coeff->hor_coefs.odd_imag ||
3326 !asd->params.css_param.dvs2_coeff->hor_coefs.even_real ||
3327 !asd->params.css_param.dvs2_coeff->hor_coefs.even_imag ||
3328 !asd->params.css_param.dvs2_coeff->ver_coefs.odd_real ||
3329 !asd->params.css_param.dvs2_coeff->ver_coefs.odd_imag ||
3330 !asd->params.css_param.dvs2_coeff->ver_coefs.even_real ||
3331 !asd->params.css_param.dvs2_coeff->ver_coefs.even_imag)
3332 return -EINVAL;
3333
3334 if (copy_from_user(asd->params.css_param.dvs2_coeff->hor_coefs.odd_real,
3335 coefs->hor_coefs.odd_real, asd->params.dvs_hor_coef_bytes))
3336 return -EFAULT;
3337 if (copy_from_user(asd->params.css_param.dvs2_coeff->hor_coefs.odd_imag,
3338 coefs->hor_coefs.odd_imag, asd->params.dvs_hor_coef_bytes))
3339 return -EFAULT;
3340 if (copy_from_user(asd->params.css_param.dvs2_coeff->hor_coefs.even_real,
3341 coefs->hor_coefs.even_real, asd->params.dvs_hor_coef_bytes))
3342 return -EFAULT;
3343 if (copy_from_user(asd->params.css_param.dvs2_coeff->hor_coefs.even_imag,
3344 coefs->hor_coefs.even_imag, asd->params.dvs_hor_coef_bytes))
3345 return -EFAULT;
3346
3347 if (copy_from_user(asd->params.css_param.dvs2_coeff->ver_coefs.odd_real,
3348 coefs->ver_coefs.odd_real, asd->params.dvs_ver_coef_bytes))
3349 return -EFAULT;
3350 if (copy_from_user(asd->params.css_param.dvs2_coeff->ver_coefs.odd_imag,
3351 coefs->ver_coefs.odd_imag, asd->params.dvs_ver_coef_bytes))
3352 return -EFAULT;
3353 if (copy_from_user(asd->params.css_param.dvs2_coeff->ver_coefs.even_real,
3354 coefs->ver_coefs.even_real, asd->params.dvs_ver_coef_bytes))
3355 return -EFAULT;
3356 if (copy_from_user(asd->params.css_param.dvs2_coeff->ver_coefs.even_imag,
3357 coefs->ver_coefs.even_imag, asd->params.dvs_ver_coef_bytes))
3358 return -EFAULT;
3359
3360 asd->params.css_param.update_flag.dvs2_coefs =
3361 (struct atomisp_dis_coefficients *)
3362 asd->params.css_param.dvs2_coeff;
3363 /* FIXME! */
3364 /* asd->params.dis_proj_data_valid = false; */
3365 asd->params.css_update_params_needed = true;
3366
3367 return 0;
3368 }
3369
atomisp_css_set_zoom_factor(struct atomisp_sub_device * asd,unsigned int zoom)3370 void atomisp_css_set_zoom_factor(struct atomisp_sub_device *asd,
3371 unsigned int zoom)
3372 {
3373 struct atomisp_device *isp = asd->isp;
3374
3375 if (zoom == asd->params.css_param.dz_config.dx &&
3376 zoom == asd->params.css_param.dz_config.dy) {
3377 dev_dbg(isp->dev, "same zoom scale. skipped.\n");
3378 return;
3379 }
3380
3381 memset(&asd->params.css_param.dz_config, 0,
3382 sizeof(struct ia_css_dz_config));
3383 asd->params.css_param.dz_config.dx = zoom;
3384 asd->params.css_param.dz_config.dy = zoom;
3385
3386 asd->params.css_param.update_flag.dz_config =
3387 (struct atomisp_dz_config *)&asd->params.css_param.dz_config;
3388 asd->params.css_update_params_needed = true;
3389 }
3390
atomisp_css_set_formats_config(struct atomisp_sub_device * asd,struct ia_css_formats_config * formats_config)3391 void atomisp_css_set_formats_config(struct atomisp_sub_device *asd,
3392 struct ia_css_formats_config *formats_config)
3393 {
3394 asd->params.config.formats_config = formats_config;
3395 }
3396
atomisp_css_get_wb_config(struct atomisp_sub_device * asd,struct atomisp_wb_config * config)3397 int atomisp_css_get_wb_config(struct atomisp_sub_device *asd,
3398 struct atomisp_wb_config *config)
3399 {
3400 struct ia_css_wb_config wb_config;
3401 struct ia_css_isp_config isp_config;
3402 struct atomisp_device *isp = asd->isp;
3403
3404 if (!asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream) {
3405 dev_err(isp->dev, "%s called after streamoff, skipping.\n",
3406 __func__);
3407 return -EINVAL;
3408 }
3409 memset(&wb_config, 0, sizeof(struct ia_css_wb_config));
3410 memset(&isp_config, 0, sizeof(struct ia_css_isp_config));
3411 isp_config.wb_config = &wb_config;
3412 ia_css_stream_get_isp_config(
3413 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream,
3414 &isp_config);
3415 memcpy(config, &wb_config, sizeof(*config));
3416
3417 return 0;
3418 }
3419
atomisp_css_get_ob_config(struct atomisp_sub_device * asd,struct atomisp_ob_config * config)3420 int atomisp_css_get_ob_config(struct atomisp_sub_device *asd,
3421 struct atomisp_ob_config *config)
3422 {
3423 struct ia_css_ob_config ob_config;
3424 struct ia_css_isp_config isp_config;
3425 struct atomisp_device *isp = asd->isp;
3426
3427 if (!asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream) {
3428 dev_err(isp->dev, "%s called after streamoff, skipping.\n",
3429 __func__);
3430 return -EINVAL;
3431 }
3432 memset(&ob_config, 0, sizeof(struct ia_css_ob_config));
3433 memset(&isp_config, 0, sizeof(struct ia_css_isp_config));
3434 isp_config.ob_config = &ob_config;
3435 ia_css_stream_get_isp_config(
3436 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream,
3437 &isp_config);
3438 memcpy(config, &ob_config, sizeof(*config));
3439
3440 return 0;
3441 }
3442
atomisp_css_get_dp_config(struct atomisp_sub_device * asd,struct atomisp_dp_config * config)3443 int atomisp_css_get_dp_config(struct atomisp_sub_device *asd,
3444 struct atomisp_dp_config *config)
3445 {
3446 struct ia_css_dp_config dp_config;
3447 struct ia_css_isp_config isp_config;
3448 struct atomisp_device *isp = asd->isp;
3449
3450 if (!asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream) {
3451 dev_err(isp->dev, "%s called after streamoff, skipping.\n",
3452 __func__);
3453 return -EINVAL;
3454 }
3455 memset(&dp_config, 0, sizeof(struct ia_css_dp_config));
3456 memset(&isp_config, 0, sizeof(struct ia_css_isp_config));
3457 isp_config.dp_config = &dp_config;
3458 ia_css_stream_get_isp_config(
3459 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream,
3460 &isp_config);
3461 memcpy(config, &dp_config, sizeof(*config));
3462
3463 return 0;
3464 }
3465
atomisp_css_get_de_config(struct atomisp_sub_device * asd,struct atomisp_de_config * config)3466 int atomisp_css_get_de_config(struct atomisp_sub_device *asd,
3467 struct atomisp_de_config *config)
3468 {
3469 struct ia_css_de_config de_config;
3470 struct ia_css_isp_config isp_config;
3471 struct atomisp_device *isp = asd->isp;
3472
3473 if (!asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream) {
3474 dev_err(isp->dev, "%s called after streamoff, skipping.\n",
3475 __func__);
3476 return -EINVAL;
3477 }
3478 memset(&de_config, 0, sizeof(struct ia_css_de_config));
3479 memset(&isp_config, 0, sizeof(struct ia_css_isp_config));
3480 isp_config.de_config = &de_config;
3481 ia_css_stream_get_isp_config(
3482 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream,
3483 &isp_config);
3484 memcpy(config, &de_config, sizeof(*config));
3485
3486 return 0;
3487 }
3488
atomisp_css_get_nr_config(struct atomisp_sub_device * asd,struct atomisp_nr_config * config)3489 int atomisp_css_get_nr_config(struct atomisp_sub_device *asd,
3490 struct atomisp_nr_config *config)
3491 {
3492 struct ia_css_nr_config nr_config;
3493 struct ia_css_isp_config isp_config;
3494 struct atomisp_device *isp = asd->isp;
3495
3496 if (!asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream) {
3497 dev_err(isp->dev, "%s called after streamoff, skipping.\n",
3498 __func__);
3499 return -EINVAL;
3500 }
3501 memset(&nr_config, 0, sizeof(struct ia_css_nr_config));
3502 memset(&isp_config, 0, sizeof(struct ia_css_isp_config));
3503
3504 isp_config.nr_config = &nr_config;
3505 ia_css_stream_get_isp_config(
3506 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream,
3507 &isp_config);
3508 memcpy(config, &nr_config, sizeof(*config));
3509
3510 return 0;
3511 }
3512
atomisp_css_get_ee_config(struct atomisp_sub_device * asd,struct atomisp_ee_config * config)3513 int atomisp_css_get_ee_config(struct atomisp_sub_device *asd,
3514 struct atomisp_ee_config *config)
3515 {
3516 struct ia_css_ee_config ee_config;
3517 struct ia_css_isp_config isp_config;
3518 struct atomisp_device *isp = asd->isp;
3519
3520 if (!asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream) {
3521 dev_err(isp->dev, "%s called after streamoff, skipping.\n",
3522 __func__);
3523 return -EINVAL;
3524 }
3525 memset(&ee_config, 0, sizeof(struct ia_css_ee_config));
3526 memset(&isp_config, 0, sizeof(struct ia_css_isp_config));
3527 isp_config.ee_config = &ee_config;
3528 ia_css_stream_get_isp_config(
3529 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream,
3530 &isp_config);
3531 memcpy(config, &ee_config, sizeof(*config));
3532
3533 return 0;
3534 }
3535
atomisp_css_get_tnr_config(struct atomisp_sub_device * asd,struct atomisp_tnr_config * config)3536 int atomisp_css_get_tnr_config(struct atomisp_sub_device *asd,
3537 struct atomisp_tnr_config *config)
3538 {
3539 struct ia_css_tnr_config tnr_config;
3540 struct ia_css_isp_config isp_config;
3541 struct atomisp_device *isp = asd->isp;
3542
3543 if (!asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream) {
3544 dev_err(isp->dev, "%s called after streamoff, skipping.\n",
3545 __func__);
3546 return -EINVAL;
3547 }
3548 memset(&tnr_config, 0, sizeof(struct ia_css_tnr_config));
3549 memset(&isp_config, 0, sizeof(struct ia_css_isp_config));
3550 isp_config.tnr_config = &tnr_config;
3551 ia_css_stream_get_isp_config(
3552 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream,
3553 &isp_config);
3554 memcpy(config, &tnr_config, sizeof(*config));
3555
3556 return 0;
3557 }
3558
atomisp_css_get_ctc_table(struct atomisp_sub_device * asd,struct atomisp_ctc_table * config)3559 int atomisp_css_get_ctc_table(struct atomisp_sub_device *asd,
3560 struct atomisp_ctc_table *config)
3561 {
3562 struct ia_css_ctc_table *tab;
3563 struct ia_css_isp_config isp_config;
3564 struct atomisp_device *isp = asd->isp;
3565
3566 if (!asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream) {
3567 dev_err(isp->dev, "%s called after streamoff, skipping.\n",
3568 __func__);
3569 return -EINVAL;
3570 }
3571
3572 tab = vzalloc(sizeof(struct ia_css_ctc_table));
3573 if (!tab)
3574 return -ENOMEM;
3575
3576 memset(&isp_config, 0, sizeof(struct ia_css_isp_config));
3577 isp_config.ctc_table = tab;
3578 ia_css_stream_get_isp_config(
3579 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream,
3580 &isp_config);
3581 memcpy(config, tab, sizeof(*tab));
3582 vfree(tab);
3583
3584 return 0;
3585 }
3586
atomisp_css_get_gamma_table(struct atomisp_sub_device * asd,struct atomisp_gamma_table * config)3587 int atomisp_css_get_gamma_table(struct atomisp_sub_device *asd,
3588 struct atomisp_gamma_table *config)
3589 {
3590 struct ia_css_gamma_table *tab;
3591 struct ia_css_isp_config isp_config;
3592 struct atomisp_device *isp = asd->isp;
3593
3594 if (!asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream) {
3595 dev_err(isp->dev, "%s called after streamoff, skipping.\n",
3596 __func__);
3597 return -EINVAL;
3598 }
3599
3600 tab = vzalloc(sizeof(struct ia_css_gamma_table));
3601 if (!tab)
3602 return -ENOMEM;
3603
3604 memset(&isp_config, 0, sizeof(struct ia_css_isp_config));
3605 isp_config.gamma_table = tab;
3606 ia_css_stream_get_isp_config(
3607 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream,
3608 &isp_config);
3609 memcpy(config, tab, sizeof(*tab));
3610 vfree(tab);
3611
3612 return 0;
3613 }
3614
atomisp_css_get_gc_config(struct atomisp_sub_device * asd,struct atomisp_gc_config * config)3615 int atomisp_css_get_gc_config(struct atomisp_sub_device *asd,
3616 struct atomisp_gc_config *config)
3617 {
3618 struct ia_css_gc_config gc_config;
3619 struct ia_css_isp_config isp_config;
3620 struct atomisp_device *isp = asd->isp;
3621
3622 if (!asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream) {
3623 dev_err(isp->dev, "%s called after streamoff, skipping.\n",
3624 __func__);
3625 return -EINVAL;
3626 }
3627 memset(&gc_config, 0, sizeof(struct ia_css_gc_config));
3628 memset(&isp_config, 0, sizeof(struct ia_css_isp_config));
3629 isp_config.gc_config = &gc_config;
3630 ia_css_stream_get_isp_config(
3631 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream,
3632 &isp_config);
3633 /* Get gamma correction params from current setup */
3634 memcpy(config, &gc_config, sizeof(*config));
3635
3636 return 0;
3637 }
3638
atomisp_css_get_3a_config(struct atomisp_sub_device * asd,struct atomisp_3a_config * config)3639 int atomisp_css_get_3a_config(struct atomisp_sub_device *asd,
3640 struct atomisp_3a_config *config)
3641 {
3642 struct ia_css_3a_config s3a_config;
3643 struct ia_css_isp_config isp_config;
3644 struct atomisp_device *isp = asd->isp;
3645
3646 if (!asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream) {
3647 dev_err(isp->dev, "%s called after streamoff, skipping.\n",
3648 __func__);
3649 return -EINVAL;
3650 }
3651 memset(&s3a_config, 0, sizeof(struct ia_css_3a_config));
3652 memset(&isp_config, 0, sizeof(struct ia_css_isp_config));
3653 isp_config.s3a_config = &s3a_config;
3654 ia_css_stream_get_isp_config(
3655 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream,
3656 &isp_config);
3657 /* Get white balance from current setup */
3658 memcpy(config, &s3a_config, sizeof(*config));
3659
3660 return 0;
3661 }
3662
atomisp_css_get_formats_config(struct atomisp_sub_device * asd,struct atomisp_formats_config * config)3663 int atomisp_css_get_formats_config(struct atomisp_sub_device *asd,
3664 struct atomisp_formats_config *config)
3665 {
3666 struct ia_css_formats_config formats_config;
3667 struct ia_css_isp_config isp_config;
3668 struct atomisp_device *isp = asd->isp;
3669
3670 if (!asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream) {
3671 dev_err(isp->dev, "%s called after streamoff, skipping.\n",
3672 __func__);
3673 return -EINVAL;
3674 }
3675 memset(&formats_config, 0, sizeof(formats_config));
3676 memset(&isp_config, 0, sizeof(isp_config));
3677 isp_config.formats_config = &formats_config;
3678 ia_css_stream_get_isp_config(
3679 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream,
3680 &isp_config);
3681 /* Get narrow gamma from current setup */
3682 memcpy(config, &formats_config, sizeof(*config));
3683
3684 return 0;
3685 }
3686
atomisp_css_get_zoom_factor(struct atomisp_sub_device * asd,unsigned int * zoom)3687 int atomisp_css_get_zoom_factor(struct atomisp_sub_device *asd,
3688 unsigned int *zoom)
3689 {
3690 struct ia_css_dz_config dz_config; /** Digital Zoom */
3691 struct ia_css_isp_config isp_config;
3692 struct atomisp_device *isp = asd->isp;
3693
3694 if (!asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream) {
3695 dev_err(isp->dev, "%s called after streamoff, skipping.\n",
3696 __func__);
3697 return -EINVAL;
3698 }
3699 memset(&dz_config, 0, sizeof(struct ia_css_dz_config));
3700 memset(&isp_config, 0, sizeof(struct ia_css_isp_config));
3701 isp_config.dz_config = &dz_config;
3702 ia_css_stream_get_isp_config(
3703 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream,
3704 &isp_config);
3705 *zoom = dz_config.dx;
3706
3707 return 0;
3708 }
3709
3710 /*
3711 * Function to set/get image stablization statistics
3712 */
atomisp_css_get_dis_stat(struct atomisp_sub_device * asd,struct atomisp_dis_statistics * stats)3713 int atomisp_css_get_dis_stat(struct atomisp_sub_device *asd,
3714 struct atomisp_dis_statistics *stats)
3715 {
3716 struct atomisp_device *isp = asd->isp;
3717 struct atomisp_dis_buf *dis_buf;
3718 unsigned long flags;
3719
3720 if (!asd->params.dvs_stat->hor_prod.odd_real ||
3721 !asd->params.dvs_stat->hor_prod.odd_imag ||
3722 !asd->params.dvs_stat->hor_prod.even_real ||
3723 !asd->params.dvs_stat->hor_prod.even_imag ||
3724 !asd->params.dvs_stat->ver_prod.odd_real ||
3725 !asd->params.dvs_stat->ver_prod.odd_imag ||
3726 !asd->params.dvs_stat->ver_prod.even_real ||
3727 !asd->params.dvs_stat->ver_prod.even_imag)
3728 return -EINVAL;
3729
3730 /* isp needs to be streaming to get DIS statistics */
3731 spin_lock_irqsave(&isp->lock, flags);
3732 if (asd->streaming != ATOMISP_DEVICE_STREAMING_ENABLED) {
3733 spin_unlock_irqrestore(&isp->lock, flags);
3734 return -EINVAL;
3735 }
3736 spin_unlock_irqrestore(&isp->lock, flags);
3737
3738 if (atomisp_compare_dvs_grid(asd, &stats->dvs2_stat.grid_info) != 0)
3739 /* If the grid info in the argument differs from the current
3740 grid info, we tell the caller to reset the grid size and
3741 try again. */
3742 return -EAGAIN;
3743
3744 spin_lock_irqsave(&asd->dis_stats_lock, flags);
3745 if (!asd->params.dis_proj_data_valid || list_empty(&asd->dis_stats)) {
3746 spin_unlock_irqrestore(&asd->dis_stats_lock, flags);
3747 dev_err(isp->dev, "dis statistics is not valid.\n");
3748 return -EAGAIN;
3749 }
3750
3751 dis_buf = list_entry(asd->dis_stats.next,
3752 struct atomisp_dis_buf, list);
3753 list_del_init(&dis_buf->list);
3754 spin_unlock_irqrestore(&asd->dis_stats_lock, flags);
3755
3756 if (dis_buf->dvs_map)
3757 ia_css_translate_dvs2_statistics(
3758 asd->params.dvs_stat, dis_buf->dvs_map);
3759 else
3760 ia_css_get_dvs2_statistics(asd->params.dvs_stat,
3761 dis_buf->dis_data);
3762 stats->exp_id = dis_buf->dis_data->exp_id;
3763
3764 spin_lock_irqsave(&asd->dis_stats_lock, flags);
3765 list_add_tail(&dis_buf->list, &asd->dis_stats);
3766 spin_unlock_irqrestore(&asd->dis_stats_lock, flags);
3767
3768 if (copy_to_user(stats->dvs2_stat.ver_prod.odd_real,
3769 asd->params.dvs_stat->ver_prod.odd_real,
3770 asd->params.dvs_ver_proj_bytes))
3771 return -EFAULT;
3772 if (copy_to_user(stats->dvs2_stat.ver_prod.odd_imag,
3773 asd->params.dvs_stat->ver_prod.odd_imag,
3774 asd->params.dvs_ver_proj_bytes))
3775 return -EFAULT;
3776 if (copy_to_user(stats->dvs2_stat.ver_prod.even_real,
3777 asd->params.dvs_stat->ver_prod.even_real,
3778 asd->params.dvs_ver_proj_bytes))
3779 return -EFAULT;
3780 if (copy_to_user(stats->dvs2_stat.ver_prod.even_imag,
3781 asd->params.dvs_stat->ver_prod.even_imag,
3782 asd->params.dvs_ver_proj_bytes))
3783 return -EFAULT;
3784 if (copy_to_user(stats->dvs2_stat.hor_prod.odd_real,
3785 asd->params.dvs_stat->hor_prod.odd_real,
3786 asd->params.dvs_hor_proj_bytes))
3787 return -EFAULT;
3788 if (copy_to_user(stats->dvs2_stat.hor_prod.odd_imag,
3789 asd->params.dvs_stat->hor_prod.odd_imag,
3790 asd->params.dvs_hor_proj_bytes))
3791 return -EFAULT;
3792 if (copy_to_user(stats->dvs2_stat.hor_prod.even_real,
3793 asd->params.dvs_stat->hor_prod.even_real,
3794 asd->params.dvs_hor_proj_bytes))
3795 return -EFAULT;
3796 if (copy_to_user(stats->dvs2_stat.hor_prod.even_imag,
3797 asd->params.dvs_stat->hor_prod.even_imag,
3798 asd->params.dvs_hor_proj_bytes))
3799 return -EFAULT;
3800
3801 return 0;
3802 }
3803
atomisp_css_shading_table_alloc(unsigned int width,unsigned int height)3804 struct ia_css_shading_table *atomisp_css_shading_table_alloc(
3805 unsigned int width, unsigned int height)
3806 {
3807 return ia_css_shading_table_alloc(width, height);
3808 }
3809
atomisp_css_set_shading_table(struct atomisp_sub_device * asd,struct ia_css_shading_table * table)3810 void atomisp_css_set_shading_table(struct atomisp_sub_device *asd,
3811 struct ia_css_shading_table *table)
3812 {
3813 asd->params.config.shading_table = table;
3814 }
3815
atomisp_css_shading_table_free(struct ia_css_shading_table * table)3816 void atomisp_css_shading_table_free(struct ia_css_shading_table *table)
3817 {
3818 ia_css_shading_table_free(table);
3819 }
3820
atomisp_css_morph_table_allocate(unsigned int width,unsigned int height)3821 struct ia_css_morph_table *atomisp_css_morph_table_allocate(
3822 unsigned int width, unsigned int height)
3823 {
3824 return ia_css_morph_table_allocate(width, height);
3825 }
3826
atomisp_css_set_morph_table(struct atomisp_sub_device * asd,struct ia_css_morph_table * table)3827 void atomisp_css_set_morph_table(struct atomisp_sub_device *asd,
3828 struct ia_css_morph_table *table)
3829 {
3830 asd->params.config.morph_table = table;
3831 }
3832
atomisp_css_get_morph_table(struct atomisp_sub_device * asd,struct ia_css_morph_table * table)3833 void atomisp_css_get_morph_table(struct atomisp_sub_device *asd,
3834 struct ia_css_morph_table *table)
3835 {
3836 struct ia_css_isp_config isp_config;
3837 struct atomisp_device *isp = asd->isp;
3838
3839 if (!asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream) {
3840 dev_err(isp->dev,
3841 "%s called after streamoff, skipping.\n", __func__);
3842 return;
3843 }
3844 memset(table, 0, sizeof(struct ia_css_morph_table));
3845 memset(&isp_config, 0, sizeof(struct ia_css_isp_config));
3846 isp_config.morph_table = table;
3847 ia_css_stream_get_isp_config(
3848 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream,
3849 &isp_config);
3850 }
3851
atomisp_css_morph_table_free(struct ia_css_morph_table * table)3852 void atomisp_css_morph_table_free(struct ia_css_morph_table *table)
3853 {
3854 ia_css_morph_table_free(table);
3855 }
3856
atomisp_css_set_cont_prev_start_time(struct atomisp_device * isp,unsigned int overlap)3857 void atomisp_css_set_cont_prev_start_time(struct atomisp_device *isp,
3858 unsigned int overlap)
3859 {
3860 /* CSS 2.0 doesn't support this API. */
3861 dev_dbg(isp->dev, "set cont prev start time is not supported.\n");
3862 return;
3863 }
3864
atomisp_css_acc_done(struct atomisp_sub_device * asd)3865 void atomisp_css_acc_done(struct atomisp_sub_device *asd)
3866 {
3867 complete(&asd->acc.acc_done);
3868 }
3869
atomisp_css_wait_acc_finish(struct atomisp_sub_device * asd)3870 int atomisp_css_wait_acc_finish(struct atomisp_sub_device *asd)
3871 {
3872 int ret = 0;
3873 struct atomisp_device *isp = asd->isp;
3874
3875 /* Unlock the isp mutex taken in IOCTL handler before sleeping! */
3876 rt_mutex_unlock(&isp->mutex);
3877 if (wait_for_completion_interruptible_timeout(&asd->acc.acc_done,
3878 ATOMISP_ISP_TIMEOUT_DURATION) == 0) {
3879 dev_err(isp->dev, "<%s: completion timeout\n", __func__);
3880 ia_css_debug_dump_sp_sw_debug_info();
3881 ia_css_debug_dump_debug_info(__func__);
3882 ret = -EIO;
3883 }
3884 rt_mutex_lock(&isp->mutex);
3885
3886 return ret;
3887 }
3888
3889 /* Set the ACC binary arguments */
atomisp_css_set_acc_parameters(struct atomisp_acc_fw * acc_fw)3890 int atomisp_css_set_acc_parameters(struct atomisp_acc_fw *acc_fw)
3891 {
3892 unsigned int mem;
3893
3894 for (mem = 0; mem < ATOMISP_ACC_NR_MEMORY; mem++) {
3895 if (acc_fw->args[mem].length == 0)
3896 continue;
3897
3898 ia_css_isp_param_set_css_mem_init(&acc_fw->fw->mem_initializers,
3899 IA_CSS_PARAM_CLASS_PARAM, mem,
3900 acc_fw->args[mem].css_ptr,
3901 acc_fw->args[mem].length);
3902 }
3903
3904 return 0;
3905 }
3906
3907 /* Load acc binary extension */
atomisp_css_load_acc_extension(struct atomisp_sub_device * asd,struct ia_css_fw_info * fw,enum ia_css_pipe_id pipe_id,unsigned int type)3908 int atomisp_css_load_acc_extension(struct atomisp_sub_device *asd,
3909 struct ia_css_fw_info *fw,
3910 enum ia_css_pipe_id pipe_id,
3911 unsigned int type)
3912 {
3913 struct ia_css_fw_info **hd;
3914
3915 fw->next = NULL;
3916 hd = &(asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]
3917 .pipe_configs[pipe_id].acc_extension);
3918 while (*hd)
3919 hd = &(*hd)->next;
3920 *hd = fw;
3921
3922 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]
3923 .update_pipe[pipe_id] = true;
3924 return 0;
3925 }
3926
3927 /* Unload acc binary extension */
atomisp_css_unload_acc_extension(struct atomisp_sub_device * asd,struct ia_css_fw_info * fw,enum ia_css_pipe_id pipe_id)3928 void atomisp_css_unload_acc_extension(struct atomisp_sub_device *asd,
3929 struct ia_css_fw_info *fw,
3930 enum ia_css_pipe_id pipe_id)
3931 {
3932 struct ia_css_fw_info **hd;
3933
3934 hd = &(asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]
3935 .pipe_configs[pipe_id].acc_extension);
3936 while (*hd && *hd != fw)
3937 hd = &(*hd)->next;
3938 if (!*hd) {
3939 dev_err(asd->isp->dev, "did not find acc fw for removal\n");
3940 return;
3941 }
3942 *hd = fw->next;
3943 fw->next = NULL;
3944
3945 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]
3946 .update_pipe[pipe_id] = true;
3947 }
3948
atomisp_css_create_acc_pipe(struct atomisp_sub_device * asd)3949 int atomisp_css_create_acc_pipe(struct atomisp_sub_device *asd)
3950 {
3951 struct atomisp_device *isp = asd->isp;
3952 struct ia_css_pipe_config *pipe_config;
3953 struct atomisp_stream_env *stream_env =
3954 &asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL];
3955
3956 if (stream_env->acc_stream) {
3957 if (stream_env->acc_stream_state == CSS_STREAM_STARTED) {
3958 if (ia_css_stream_stop(stream_env->acc_stream)
3959 != 0) {
3960 dev_err(isp->dev, "stop acc_stream failed.\n");
3961 return -EBUSY;
3962 }
3963 }
3964
3965 if (ia_css_stream_destroy(stream_env->acc_stream)
3966 != 0) {
3967 dev_err(isp->dev, "destroy acc_stream failed.\n");
3968 return -EBUSY;
3969 }
3970 stream_env->acc_stream = NULL;
3971 }
3972
3973 pipe_config = &stream_env->pipe_configs[IA_CSS_PIPE_ID_ACC];
3974 ia_css_pipe_config_defaults(pipe_config);
3975 asd->acc.acc_stages = kzalloc(MAX_ACC_STAGES *
3976 sizeof(void *), GFP_KERNEL);
3977 if (!asd->acc.acc_stages)
3978 return -ENOMEM;
3979 pipe_config->acc_stages = asd->acc.acc_stages;
3980 pipe_config->mode = IA_CSS_PIPE_MODE_ACC;
3981 pipe_config->num_acc_stages = 0;
3982
3983 /*
3984 * We delay the ACC pipeline creation to atomisp_css_start_acc_pipe,
3985 * because pipe configuration will soon be changed by
3986 * atomisp_css_load_acc_binary()
3987 */
3988 return 0;
3989 }
3990
atomisp_css_start_acc_pipe(struct atomisp_sub_device * asd)3991 int atomisp_css_start_acc_pipe(struct atomisp_sub_device *asd)
3992 {
3993 struct atomisp_device *isp = asd->isp;
3994 struct atomisp_stream_env *stream_env =
3995 &asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL];
3996 struct ia_css_pipe_config *pipe_config =
3997 &stream_env->pipe_configs[IA_CSS_PIPE_ID_ACC];
3998
3999 if (ia_css_pipe_create(pipe_config,
4000 &stream_env->pipes[IA_CSS_PIPE_ID_ACC]) != 0) {
4001 dev_err(isp->dev, "%s: ia_css_pipe_create failed\n",
4002 __func__);
4003 return -EBADE;
4004 }
4005
4006 memset(&stream_env->acc_stream_config, 0,
4007 sizeof(struct ia_css_stream_config));
4008 if (ia_css_stream_create(&stream_env->acc_stream_config, 1,
4009 &stream_env->pipes[IA_CSS_PIPE_ID_ACC],
4010 &stream_env->acc_stream) != 0) {
4011 dev_err(isp->dev, "%s: create acc_stream error.\n", __func__);
4012 return -EINVAL;
4013 }
4014 stream_env->acc_stream_state = CSS_STREAM_CREATED;
4015
4016 init_completion(&asd->acc.acc_done);
4017 asd->acc.pipeline = stream_env->pipes[IA_CSS_PIPE_ID_ACC];
4018
4019 atomisp_freq_scaling(isp, ATOMISP_DFS_MODE_MAX, false);
4020
4021 if (ia_css_start_sp()) {
4022 dev_err(isp->dev, "start sp error.\n");
4023 return -EIO;
4024 }
4025
4026 if (ia_css_stream_start(stream_env->acc_stream)
4027 != 0) {
4028 dev_err(isp->dev, "acc_stream start error.\n");
4029 return -EIO;
4030 }
4031
4032 stream_env->acc_stream_state = CSS_STREAM_STARTED;
4033 return 0;
4034 }
4035
atomisp_css_stop_acc_pipe(struct atomisp_sub_device * asd)4036 int atomisp_css_stop_acc_pipe(struct atomisp_sub_device *asd)
4037 {
4038 struct atomisp_stream_env *stream_env =
4039 &asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL];
4040 if (stream_env->acc_stream_state == CSS_STREAM_STARTED) {
4041 ia_css_stream_stop(stream_env->acc_stream);
4042 stream_env->acc_stream_state = CSS_STREAM_STOPPED;
4043 }
4044 return 0;
4045 }
4046
atomisp_css_destroy_acc_pipe(struct atomisp_sub_device * asd)4047 void atomisp_css_destroy_acc_pipe(struct atomisp_sub_device *asd)
4048 {
4049 struct atomisp_stream_env *stream_env =
4050 &asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL];
4051 if (stream_env->acc_stream) {
4052 if (ia_css_stream_destroy(stream_env->acc_stream)
4053 != 0)
4054 dev_warn(asd->isp->dev,
4055 "destroy acc_stream failed.\n");
4056 stream_env->acc_stream = NULL;
4057 }
4058
4059 if (stream_env->pipes[IA_CSS_PIPE_ID_ACC]) {
4060 if (ia_css_pipe_destroy(stream_env->pipes[IA_CSS_PIPE_ID_ACC])
4061 != 0)
4062 dev_warn(asd->isp->dev,
4063 "destroy ACC pipe failed.\n");
4064 stream_env->pipes[IA_CSS_PIPE_ID_ACC] = NULL;
4065 stream_env->update_pipe[IA_CSS_PIPE_ID_ACC] = false;
4066 ia_css_pipe_config_defaults(
4067 &stream_env->pipe_configs[IA_CSS_PIPE_ID_ACC]);
4068 ia_css_pipe_extra_config_defaults(
4069 &stream_env->pipe_extra_configs[IA_CSS_PIPE_ID_ACC]);
4070 }
4071 asd->acc.pipeline = NULL;
4072
4073 /* css 2.0 API limitation: ia_css_stop_sp() could be only called after
4074 * destroy all pipes
4075 */
4076 ia_css_stop_sp();
4077
4078 kfree(asd->acc.acc_stages);
4079 asd->acc.acc_stages = NULL;
4080
4081 atomisp_freq_scaling(asd->isp, ATOMISP_DFS_MODE_LOW, false);
4082 }
4083
atomisp_css_load_acc_binary(struct atomisp_sub_device * asd,struct ia_css_fw_info * fw,unsigned int index)4084 int atomisp_css_load_acc_binary(struct atomisp_sub_device *asd,
4085 struct ia_css_fw_info *fw,
4086 unsigned int index)
4087 {
4088 struct ia_css_pipe_config *pipe_config =
4089 &asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]
4090 .pipe_configs[IA_CSS_PIPE_ID_ACC];
4091
4092 if (index >= MAX_ACC_STAGES) {
4093 dev_dbg(asd->isp->dev, "%s: index(%d) out of range\n",
4094 __func__, index);
4095 return -ENOMEM;
4096 }
4097
4098 pipe_config->acc_stages[index] = fw;
4099 pipe_config->num_acc_stages = index + 1;
4100 pipe_config->acc_num_execs = 1;
4101
4102 return 0;
4103 }
4104
__get_atomisp_subdev(struct ia_css_pipe * css_pipe,struct atomisp_device * isp,enum atomisp_input_stream_id * stream_id)4105 static struct atomisp_sub_device *__get_atomisp_subdev(
4106 struct ia_css_pipe *css_pipe,
4107 struct atomisp_device *isp,
4108 enum atomisp_input_stream_id *stream_id)
4109 {
4110 int i, j, k;
4111 struct atomisp_sub_device *asd;
4112 struct atomisp_stream_env *stream_env;
4113
4114 for (i = 0; i < isp->num_of_streams; i++) {
4115 asd = &isp->asd[i];
4116 if (asd->streaming == ATOMISP_DEVICE_STREAMING_DISABLED &&
4117 !asd->acc.pipeline)
4118 continue;
4119 for (j = 0; j < ATOMISP_INPUT_STREAM_NUM; j++) {
4120 stream_env = &asd->stream_env[j];
4121 for (k = 0; k < IA_CSS_PIPE_ID_NUM; k++) {
4122 if (stream_env->pipes[k] &&
4123 stream_env->pipes[k] == css_pipe) {
4124 *stream_id = j;
4125 return asd;
4126 }
4127 }
4128 }
4129 }
4130
4131 return NULL;
4132 }
4133
atomisp_css_isr_thread(struct atomisp_device * isp,bool * frame_done_found,bool * css_pipe_done)4134 int atomisp_css_isr_thread(struct atomisp_device *isp,
4135 bool *frame_done_found,
4136 bool *css_pipe_done)
4137 {
4138 enum atomisp_input_stream_id stream_id = 0;
4139 struct atomisp_css_event current_event;
4140 struct atomisp_sub_device *asd;
4141 bool reset_wdt_timer[MAX_STREAM_NUM] = {false};
4142 int i;
4143
4144 while (!atomisp_css_dequeue_event(¤t_event)) {
4145 if (current_event.event.type ==
4146 IA_CSS_EVENT_TYPE_FW_ASSERT) {
4147 /*
4148 * Received FW assertion signal,
4149 * trigger WDT to recover
4150 */
4151 dev_err(isp->dev,
4152 "%s: ISP reports FW_ASSERT event! fw_assert_module_id %d fw_assert_line_no %d\n",
4153 __func__,
4154 current_event.event.fw_assert_module_id,
4155 current_event.event.fw_assert_line_no);
4156 for (i = 0; i < isp->num_of_streams; i++)
4157 atomisp_wdt_stop(&isp->asd[i], 0);
4158
4159 if (!IS_ISP2401)
4160 atomisp_wdt(&isp->asd[0].wdt);
4161 else
4162 queue_work(isp->wdt_work_queue, &isp->wdt_work);
4163
4164 return -EINVAL;
4165 } else if (current_event.event.type == IA_CSS_EVENT_TYPE_FW_WARNING) {
4166 dev_warn(isp->dev, "%s: ISP reports warning, code is %d, exp_id %d\n",
4167 __func__, current_event.event.fw_warning,
4168 current_event.event.exp_id);
4169 continue;
4170 }
4171
4172 asd = __get_atomisp_subdev(current_event.event.pipe,
4173 isp, &stream_id);
4174 if (!asd) {
4175 if (current_event.event.type == IA_CSS_EVENT_TYPE_TIMER)
4176 dev_dbg(isp->dev,
4177 "event: Timer event.");
4178 else
4179 dev_warn(isp->dev, "%s:no subdev.event:%d",
4180 __func__,
4181 current_event.event.type);
4182 continue;
4183 }
4184
4185 atomisp_css_temp_pipe_to_pipe_id(asd, ¤t_event);
4186 switch (current_event.event.type) {
4187 case IA_CSS_EVENT_TYPE_OUTPUT_FRAME_DONE:
4188 dev_dbg(isp->dev, "event: Output frame done");
4189 frame_done_found[asd->index] = true;
4190 atomisp_buf_done(asd, 0, IA_CSS_BUFFER_TYPE_OUTPUT_FRAME,
4191 current_event.pipe, true, stream_id);
4192
4193 if (!IS_ISP2401)
4194 reset_wdt_timer[asd->index] = true; /* ISP running */
4195
4196 break;
4197 case IA_CSS_EVENT_TYPE_SECOND_OUTPUT_FRAME_DONE:
4198 dev_dbg(isp->dev, "event: Second output frame done");
4199 frame_done_found[asd->index] = true;
4200 atomisp_buf_done(asd, 0, IA_CSS_BUFFER_TYPE_SEC_OUTPUT_FRAME,
4201 current_event.pipe, true, stream_id);
4202
4203 if (!IS_ISP2401)
4204 reset_wdt_timer[asd->index] = true; /* ISP running */
4205
4206 break;
4207 case IA_CSS_EVENT_TYPE_3A_STATISTICS_DONE:
4208 dev_dbg(isp->dev, "event: 3A stats frame done");
4209 atomisp_buf_done(asd, 0,
4210 IA_CSS_BUFFER_TYPE_3A_STATISTICS,
4211 current_event.pipe,
4212 false, stream_id);
4213 break;
4214 case IA_CSS_EVENT_TYPE_METADATA_DONE:
4215 dev_dbg(isp->dev, "event: metadata frame done");
4216 atomisp_buf_done(asd, 0,
4217 IA_CSS_BUFFER_TYPE_METADATA,
4218 current_event.pipe,
4219 false, stream_id);
4220 break;
4221 case IA_CSS_EVENT_TYPE_VF_OUTPUT_FRAME_DONE:
4222 dev_dbg(isp->dev, "event: VF output frame done");
4223 atomisp_buf_done(asd, 0,
4224 IA_CSS_BUFFER_TYPE_VF_OUTPUT_FRAME,
4225 current_event.pipe, true, stream_id);
4226
4227 if (!IS_ISP2401)
4228 reset_wdt_timer[asd->index] = true; /* ISP running */
4229
4230 break;
4231 case IA_CSS_EVENT_TYPE_SECOND_VF_OUTPUT_FRAME_DONE:
4232 dev_dbg(isp->dev, "event: second VF output frame done");
4233 atomisp_buf_done(asd, 0,
4234 IA_CSS_BUFFER_TYPE_SEC_VF_OUTPUT_FRAME,
4235 current_event.pipe, true, stream_id);
4236 if (!IS_ISP2401)
4237 reset_wdt_timer[asd->index] = true; /* ISP running */
4238
4239 break;
4240 case IA_CSS_EVENT_TYPE_DIS_STATISTICS_DONE:
4241 dev_dbg(isp->dev, "event: dis stats frame done");
4242 atomisp_buf_done(asd, 0,
4243 IA_CSS_BUFFER_TYPE_DIS_STATISTICS,
4244 current_event.pipe,
4245 false, stream_id);
4246 break;
4247 case IA_CSS_EVENT_TYPE_PIPELINE_DONE:
4248 dev_dbg(isp->dev, "event: pipeline done");
4249 css_pipe_done[asd->index] = true;
4250 break;
4251 case IA_CSS_EVENT_TYPE_ACC_STAGE_COMPLETE:
4252 dev_dbg(isp->dev, "event: acc stage done");
4253 atomisp_acc_done(asd, current_event.event.fw_handle);
4254 break;
4255 default:
4256 dev_dbg(isp->dev, "unhandled css stored event: 0x%x\n",
4257 current_event.event.type);
4258 break;
4259 }
4260 }
4261
4262 if (IS_ISP2401)
4263 return 0;
4264
4265 /* ISP2400: If there are no buffers queued then delete wdt timer. */
4266 for (i = 0; i < isp->num_of_streams; i++) {
4267 asd = &isp->asd[i];
4268 if (!asd)
4269 continue;
4270 if (asd->streaming != ATOMISP_DEVICE_STREAMING_ENABLED)
4271 continue;
4272 if (!atomisp_buffers_queued(asd))
4273 atomisp_wdt_stop(asd, false);
4274 else if (reset_wdt_timer[i])
4275 /* SOF irq should not reset wdt timer. */
4276 atomisp_wdt_refresh(asd,
4277 ATOMISP_WDT_KEEP_CURRENT_DELAY);
4278 }
4279
4280 return 0;
4281 }
4282
atomisp_css_valid_sof(struct atomisp_device * isp)4283 bool atomisp_css_valid_sof(struct atomisp_device *isp)
4284 {
4285 unsigned int i, j;
4286
4287 /* Loop for each css stream */
4288 for (i = 0; i < isp->num_of_streams; i++) {
4289 struct atomisp_sub_device *asd = &isp->asd[i];
4290 /* Loop for each css vc stream */
4291 for (j = 0; j < ATOMISP_INPUT_STREAM_NUM; j++) {
4292 if (!asd->stream_env[j].stream)
4293 continue;
4294
4295 dev_dbg(isp->dev,
4296 "stream #%d: mode: %d\n", j,
4297 asd->stream_env[j].stream_config.mode);
4298 if (asd->stream_env[j].stream_config.mode ==
4299 IA_CSS_INPUT_MODE_BUFFERED_SENSOR)
4300 return false;
4301 }
4302 }
4303
4304 return true;
4305 }
4306
atomisp_css_debug_dump_isp_binary(void)4307 int atomisp_css_debug_dump_isp_binary(void)
4308 {
4309 ia_css_debug_dump_isp_binary();
4310 return 0;
4311 }
4312
atomisp_css_dump_sp_raw_copy_linecount(bool reduced)4313 int atomisp_css_dump_sp_raw_copy_linecount(bool reduced)
4314 {
4315 sh_css_dump_sp_raw_copy_linecount(reduced);
4316 return 0;
4317 }
4318
4319 static const char * const fw_type_name[] = {
4320 [ia_css_sp_firmware] = "SP",
4321 [ia_css_isp_firmware] = "ISP",
4322 [ia_css_bootloader_firmware] = "BootLoader",
4323 [ia_css_acc_firmware] = "accel",
4324 };
4325
4326 static const char * const fw_acc_type_name[] = {
4327 [IA_CSS_ACC_NONE] = "Normal",
4328 [IA_CSS_ACC_OUTPUT] = "Accel stage on output",
4329 [IA_CSS_ACC_VIEWFINDER] = "Accel stage on viewfinder",
4330 [IA_CSS_ACC_STANDALONE] = "Stand-alone acceleration",
4331 };
4332
atomisp_css_dump_blob_infor(struct atomisp_device * isp)4333 int atomisp_css_dump_blob_infor(struct atomisp_device *isp)
4334 {
4335 struct ia_css_blob_descr *bd = sh_css_blob_info;
4336 unsigned int i, nm = sh_css_num_binaries;
4337
4338 if (nm == 0)
4339 return -EPERM;
4340 if (!bd)
4341 return -EPERM;
4342
4343 /*
4344 * The sh_css_load_firmware function discard the initial
4345 * "SPS" binaries
4346 */
4347 for (i = 0; i < sh_css_num_binaries - NUM_OF_SPS; i++) {
4348 switch (bd[i].header.type) {
4349 case ia_css_isp_firmware:
4350 dev_dbg(isp->dev, "Num%2d type %s (%s), binary id is %2d, name is %s\n",
4351 i + NUM_OF_SPS,
4352 fw_type_name[bd[i].header.type],
4353 fw_acc_type_name[bd[i].header.info.isp.type],
4354 bd[i].header.info.isp.sp.id,
4355 bd[i].name);
4356 break;
4357 default:
4358 dev_dbg(isp->dev, "Num%2d type %s, name is %s\n",
4359 i + NUM_OF_SPS, fw_type_name[bd[i].header.type],
4360 bd[i].name);
4361 }
4362 }
4363
4364 return 0;
4365 }
4366
atomisp_css_set_isp_config_id(struct atomisp_sub_device * asd,uint32_t isp_config_id)4367 void atomisp_css_set_isp_config_id(struct atomisp_sub_device *asd,
4368 uint32_t isp_config_id)
4369 {
4370 asd->params.config.isp_config_id = isp_config_id;
4371 }
4372
atomisp_css_set_isp_config_applied_frame(struct atomisp_sub_device * asd,struct ia_css_frame * output_frame)4373 void atomisp_css_set_isp_config_applied_frame(struct atomisp_sub_device *asd,
4374 struct ia_css_frame *output_frame)
4375 {
4376 asd->params.config.output_frame = output_frame;
4377 }
4378
atomisp_get_css_dbgfunc(void)4379 int atomisp_get_css_dbgfunc(void)
4380 {
4381 return dbg_func;
4382 }
4383
atomisp_set_css_dbgfunc(struct atomisp_device * isp,int opt)4384 int atomisp_set_css_dbgfunc(struct atomisp_device *isp, int opt)
4385 {
4386 int ret;
4387
4388 ret = __set_css_print_env(isp, opt);
4389 if (ret == 0)
4390 dbg_func = opt;
4391
4392 return ret;
4393 }
4394
atomisp_en_dz_capt_pipe(struct atomisp_sub_device * asd,bool enable)4395 void atomisp_en_dz_capt_pipe(struct atomisp_sub_device *asd, bool enable)
4396 {
4397 ia_css_en_dz_capt_pipe(
4398 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream,
4399 enable);
4400 }
4401
atomisp_css_get_dvs_grid_info(struct ia_css_grid_info * grid_info)4402 struct ia_css_dvs_grid_info *atomisp_css_get_dvs_grid_info(
4403 struct ia_css_grid_info *grid_info)
4404 {
4405 if (!grid_info)
4406 return NULL;
4407
4408 #ifdef IA_CSS_DVS_STAT_GRID_INFO_SUPPORTED
4409 return &grid_info->dvs_grid.dvs_grid_info;
4410 #else
4411 return &grid_info->dvs_grid;
4412 #endif
4413 }
4414