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