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