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