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