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