media: atomisp: Turn asd->streaming state tracker into a bool
[platform/kernel/linux-starfive.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
35 #include "ia_css_debug.h"
36 #include "ia_css_isp_param.h"
37 #include "sh_css_hrt.h"
38 #include "ia_css_isys.h"
39
40 #include <linux/io.h>
41 #include <linux/pm_runtime.h>
42
43 /* Assume max number of ACC stages */
44 #define MAX_ACC_STAGES  20
45
46 /* Ideally, this should come from CSS headers */
47 #define NO_LINK -1
48
49 /*
50  * to serialize MMIO access , this is due to ISP2400 silicon issue Sighting
51  * #4684168, if concurrency access happened, system may hard hang.
52  */
53 static DEFINE_SPINLOCK(mmio_lock);
54
55 enum frame_info_type {
56         ATOMISP_CSS_VF_FRAME,
57         ATOMISP_CSS_SECOND_VF_FRAME,
58         ATOMISP_CSS_OUTPUT_FRAME,
59         ATOMISP_CSS_SECOND_OUTPUT_FRAME,
60         ATOMISP_CSS_RAW_FRAME,
61 };
62
63 struct bayer_ds_factor {
64         unsigned int numerator;
65         unsigned int denominator;
66 };
67
68 static void atomisp_css2_hw_store_8(hrt_address addr, uint8_t data)
69 {
70         struct atomisp_device *isp = dev_get_drvdata(atomisp_dev);
71         unsigned long flags;
72
73         spin_lock_irqsave(&mmio_lock, flags);
74         writeb(data, isp->base + (addr & 0x003FFFFF));
75         spin_unlock_irqrestore(&mmio_lock, flags);
76 }
77
78 static void atomisp_css2_hw_store_16(hrt_address addr, uint16_t data)
79 {
80         struct atomisp_device *isp = dev_get_drvdata(atomisp_dev);
81         unsigned long flags;
82
83         spin_lock_irqsave(&mmio_lock, flags);
84         writew(data, isp->base + (addr & 0x003FFFFF));
85         spin_unlock_irqrestore(&mmio_lock, flags);
86 }
87
88 void atomisp_css2_hw_store_32(hrt_address addr, uint32_t data)
89 {
90         struct atomisp_device *isp = dev_get_drvdata(atomisp_dev);
91         unsigned long flags;
92
93         spin_lock_irqsave(&mmio_lock, flags);
94         writel(data, isp->base + (addr & 0x003FFFFF));
95         spin_unlock_irqrestore(&mmio_lock, flags);
96 }
97
98 static uint8_t atomisp_css2_hw_load_8(hrt_address addr)
99 {
100         struct atomisp_device *isp = dev_get_drvdata(atomisp_dev);
101         unsigned long flags;
102         u8 ret;
103
104         spin_lock_irqsave(&mmio_lock, flags);
105         ret = readb(isp->base + (addr & 0x003FFFFF));
106         spin_unlock_irqrestore(&mmio_lock, flags);
107         return ret;
108 }
109
110 static uint16_t atomisp_css2_hw_load_16(hrt_address addr)
111 {
112         struct atomisp_device *isp = dev_get_drvdata(atomisp_dev);
113         unsigned long flags;
114         u16 ret;
115
116         spin_lock_irqsave(&mmio_lock, flags);
117         ret = readw(isp->base + (addr & 0x003FFFFF));
118         spin_unlock_irqrestore(&mmio_lock, flags);
119         return ret;
120 }
121
122 static uint32_t atomisp_css2_hw_load_32(hrt_address addr)
123 {
124         struct atomisp_device *isp = dev_get_drvdata(atomisp_dev);
125         unsigned long flags;
126         u32 ret;
127
128         spin_lock_irqsave(&mmio_lock, flags);
129         ret = readl(isp->base + (addr & 0x003FFFFF));
130         spin_unlock_irqrestore(&mmio_lock, flags);
131         return ret;
132 }
133
134 static void atomisp_css2_hw_store(hrt_address addr, const void *from, uint32_t n)
135 {
136         struct atomisp_device *isp = dev_get_drvdata(atomisp_dev);
137         unsigned long flags;
138         unsigned int i;
139
140         addr &= 0x003FFFFF;
141         spin_lock_irqsave(&mmio_lock, flags);
142         for (i = 0; i < n; i++, from++)
143                 writeb(*(s8 *)from, isp->base + addr + i);
144
145         spin_unlock_irqrestore(&mmio_lock, flags);
146 }
147
148 static void atomisp_css2_hw_load(hrt_address addr, void *to, uint32_t n)
149 {
150         struct atomisp_device *isp = dev_get_drvdata(atomisp_dev);
151         unsigned long flags;
152         unsigned int i;
153
154         addr &= 0x003FFFFF;
155         spin_lock_irqsave(&mmio_lock, flags);
156         for (i = 0; i < n; i++, to++)
157                 *(s8 *)to = readb(isp->base + addr + i);
158         spin_unlock_irqrestore(&mmio_lock, flags);
159 }
160
161 static int  __printf(1, 0) atomisp_vprintk(const char *fmt, va_list args)
162 {
163         vprintk(fmt, args);
164         return 0;
165 }
166
167 void atomisp_load_uint32(hrt_address addr, uint32_t *data)
168 {
169         *data = atomisp_css2_hw_load_32(addr);
170 }
171
172 static int hmm_get_mmu_base_addr(struct device *dev, unsigned int *mmu_base_addr)
173 {
174         if (!sh_mmu_mrfld.get_pd_base) {
175                 dev_err(dev, "get mmu base address failed.\n");
176                 return -EINVAL;
177         }
178
179         *mmu_base_addr = sh_mmu_mrfld.get_pd_base(&bo_device.mmu,
180                          bo_device.mmu.base_address);
181         return 0;
182 }
183
184 static void __dump_pipe_config(struct atomisp_sub_device *asd,
185                                struct atomisp_stream_env *stream_env,
186                                unsigned int pipe_id)
187 {
188         struct atomisp_device *isp = asd->isp;
189
190         if (stream_env->pipes[pipe_id]) {
191                 struct ia_css_pipe_config *p_config;
192                 struct ia_css_pipe_extra_config *pe_config;
193
194                 p_config = &stream_env->pipe_configs[pipe_id];
195                 pe_config = &stream_env->pipe_extra_configs[pipe_id];
196                 dev_dbg(isp->dev, "dumping pipe[%d] config:\n", pipe_id);
197                 dev_dbg(isp->dev,
198                         "pipe_config.pipe_mode:%d.\n", p_config->mode);
199                 dev_dbg(isp->dev,
200                         "pipe_config.output_info[0] w=%d, h=%d.\n",
201                         p_config->output_info[0].res.width,
202                         p_config->output_info[0].res.height);
203                 dev_dbg(isp->dev,
204                         "pipe_config.vf_pp_in_res w=%d, h=%d.\n",
205                         p_config->vf_pp_in_res.width,
206                         p_config->vf_pp_in_res.height);
207                 dev_dbg(isp->dev,
208                         "pipe_config.capt_pp_in_res w=%d, h=%d.\n",
209                         p_config->capt_pp_in_res.width,
210                         p_config->capt_pp_in_res.height);
211                 dev_dbg(isp->dev,
212                         "pipe_config.output.padded w=%d.\n",
213                         p_config->output_info[0].padded_width);
214                 dev_dbg(isp->dev,
215                         "pipe_config.vf_output_info[0] w=%d, h=%d.\n",
216                         p_config->vf_output_info[0].res.width,
217                         p_config->vf_output_info[0].res.height);
218                 dev_dbg(isp->dev,
219                         "pipe_config.bayer_ds_out_res w=%d, h=%d.\n",
220                         p_config->bayer_ds_out_res.width,
221                         p_config->bayer_ds_out_res.height);
222                 dev_dbg(isp->dev,
223                         "pipe_config.envelope w=%d, h=%d.\n",
224                         p_config->dvs_envelope.width,
225                         p_config->dvs_envelope.height);
226                 dev_dbg(isp->dev,
227                         "pipe_config.dvs_frame_delay=%d.\n",
228                         p_config->dvs_frame_delay);
229                 dev_dbg(isp->dev,
230                         "pipe_config.isp_pipe_version:%d.\n",
231                         p_config->isp_pipe_version);
232                 dev_dbg(isp->dev,
233                         "pipe_config.default_capture_config.capture_mode=%d.\n",
234                         p_config->default_capture_config.mode);
235                 dev_dbg(isp->dev,
236                         "pipe_config.enable_dz=%d.\n",
237                         p_config->enable_dz);
238                 dev_dbg(isp->dev,
239                         "pipe_config.default_capture_config.enable_xnr=%d.\n",
240                         p_config->default_capture_config.enable_xnr);
241                 dev_dbg(isp->dev,
242                         "dumping pipe[%d] extra config:\n", pipe_id);
243                 dev_dbg(isp->dev,
244                         "pipe_extra_config.enable_raw_binning:%d.\n",
245                         pe_config->enable_raw_binning);
246                 dev_dbg(isp->dev,
247                         "pipe_extra_config.enable_yuv_ds:%d.\n",
248                         pe_config->enable_yuv_ds);
249                 dev_dbg(isp->dev,
250                         "pipe_extra_config.enable_high_speed:%d.\n",
251                         pe_config->enable_high_speed);
252                 dev_dbg(isp->dev,
253                         "pipe_extra_config.enable_dvs_6axis:%d.\n",
254                         pe_config->enable_dvs_6axis);
255                 dev_dbg(isp->dev,
256                         "pipe_extra_config.enable_reduced_pipe:%d.\n",
257                         pe_config->enable_reduced_pipe);
258                 dev_dbg(isp->dev,
259                         "pipe_(extra_)config.enable_dz:%d.\n",
260                         p_config->enable_dz);
261                 dev_dbg(isp->dev,
262                         "pipe_extra_config.disable_vf_pp:%d.\n",
263                         pe_config->disable_vf_pp);
264         }
265 }
266
267 static void __dump_stream_config(struct atomisp_sub_device *asd,
268                                  struct atomisp_stream_env *stream_env)
269 {
270         struct atomisp_device *isp = asd->isp;
271         struct ia_css_stream_config *s_config;
272         int j;
273         bool valid_stream = false;
274
275         for (j = 0; j < IA_CSS_PIPE_ID_NUM; j++) {
276                 if (stream_env->pipes[j]) {
277                         __dump_pipe_config(asd, stream_env, j);
278                         valid_stream = true;
279                 }
280         }
281         if (!valid_stream)
282                 return;
283         s_config = &stream_env->stream_config;
284         dev_dbg(isp->dev, "stream_config.mode=%d.\n", s_config->mode);
285
286         if (s_config->mode == IA_CSS_INPUT_MODE_SENSOR ||
287             s_config->mode == IA_CSS_INPUT_MODE_BUFFERED_SENSOR) {
288                 dev_dbg(isp->dev, "stream_config.source.port.port=%d.\n",
289                         s_config->source.port.port);
290                 dev_dbg(isp->dev, "stream_config.source.port.num_lanes=%d.\n",
291                         s_config->source.port.num_lanes);
292                 dev_dbg(isp->dev, "stream_config.source.port.timeout=%d.\n",
293                         s_config->source.port.timeout);
294                 dev_dbg(isp->dev, "stream_config.source.port.rxcount=0x%x.\n",
295                         s_config->source.port.rxcount);
296                 dev_dbg(isp->dev, "stream_config.source.port.compression.type=%d.\n",
297                         s_config->source.port.compression.type);
298                 dev_dbg(isp->dev,
299                         "stream_config.source.port.compression.compressed_bits_per_pixel=%d.\n",
300                         s_config->source.port.compression.
301                         compressed_bits_per_pixel);
302                 dev_dbg(isp->dev,
303                         "stream_config.source.port.compression.uncompressed_bits_per_pixel=%d.\n",
304                         s_config->source.port.compression.
305                         uncompressed_bits_per_pixel);
306         } else if (s_config->mode == IA_CSS_INPUT_MODE_TPG) {
307                 dev_dbg(isp->dev, "stream_config.source.tpg.id=%d.\n",
308                         s_config->source.tpg.id);
309                 dev_dbg(isp->dev, "stream_config.source.tpg.mode=%d.\n",
310                         s_config->source.tpg.mode);
311                 dev_dbg(isp->dev, "stream_config.source.tpg.x_mask=%d.\n",
312                         s_config->source.tpg.x_mask);
313                 dev_dbg(isp->dev, "stream_config.source.tpg.x_delta=%d.\n",
314                         s_config->source.tpg.x_delta);
315                 dev_dbg(isp->dev, "stream_config.source.tpg.y_mask=%d.\n",
316                         s_config->source.tpg.y_mask);
317                 dev_dbg(isp->dev, "stream_config.source.tpg.y_delta=%d.\n",
318                         s_config->source.tpg.y_delta);
319                 dev_dbg(isp->dev, "stream_config.source.tpg.xy_mask=%d.\n",
320                         s_config->source.tpg.xy_mask);
321         } else if (s_config->mode == IA_CSS_INPUT_MODE_PRBS) {
322                 dev_dbg(isp->dev, "stream_config.source.prbs.id=%d.\n",
323                         s_config->source.prbs.id);
324                 dev_dbg(isp->dev, "stream_config.source.prbs.h_blank=%d.\n",
325                         s_config->source.prbs.h_blank);
326                 dev_dbg(isp->dev, "stream_config.source.prbs.v_blank=%d.\n",
327                         s_config->source.prbs.v_blank);
328                 dev_dbg(isp->dev, "stream_config.source.prbs.seed=%d.\n",
329                         s_config->source.prbs.seed);
330                 dev_dbg(isp->dev, "stream_config.source.prbs.seed1=%d.\n",
331                         s_config->source.prbs.seed1);
332         }
333
334         for (j = 0; j < IA_CSS_STREAM_MAX_ISYS_STREAM_PER_CH; j++) {
335                 dev_dbg(isp->dev, "stream_configisys_config[%d].input_res w=%d, h=%d.\n",
336                         j,
337                         s_config->isys_config[j].input_res.width,
338                         s_config->isys_config[j].input_res.height);
339
340                 dev_dbg(isp->dev, "stream_configisys_config[%d].linked_isys_stream_id=%d\n",
341                         j,
342                         s_config->isys_config[j].linked_isys_stream_id);
343
344                 dev_dbg(isp->dev, "stream_configisys_config[%d].format=%d\n",
345                         j,
346                         s_config->isys_config[j].format);
347
348                 dev_dbg(isp->dev, "stream_configisys_config[%d].valid=%d.\n",
349                         j,
350                         s_config->isys_config[j].valid);
351         }
352
353         dev_dbg(isp->dev, "stream_config.input_config.input_res w=%d, h=%d.\n",
354                 s_config->input_config.input_res.width,
355                 s_config->input_config.input_res.height);
356
357         dev_dbg(isp->dev, "stream_config.input_config.effective_res w=%d, h=%d.\n",
358                 s_config->input_config.effective_res.width,
359                 s_config->input_config.effective_res.height);
360
361         dev_dbg(isp->dev, "stream_config.input_config.format=%d\n",
362                 s_config->input_config.format);
363
364         dev_dbg(isp->dev, "stream_config.input_config.bayer_order=%d.\n",
365                 s_config->input_config.bayer_order);
366
367         dev_dbg(isp->dev, "stream_config.pixels_per_clock=%d.\n",
368                 s_config->pixels_per_clock);
369         dev_dbg(isp->dev, "stream_config.online=%d.\n", s_config->online);
370         dev_dbg(isp->dev, "stream_config.continuous=%d.\n",
371                 s_config->continuous);
372         dev_dbg(isp->dev, "stream_config.disable_cont_viewfinder=%d.\n",
373                 s_config->disable_cont_viewfinder);
374         dev_dbg(isp->dev, "stream_config.channel_id=%d.\n",
375                 s_config->channel_id);
376         dev_dbg(isp->dev, "stream_config.init_num_cont_raw_buf=%d.\n",
377                 s_config->init_num_cont_raw_buf);
378         dev_dbg(isp->dev, "stream_config.target_num_cont_raw_buf=%d.\n",
379                 s_config->target_num_cont_raw_buf);
380         dev_dbg(isp->dev, "stream_config.left_padding=%d.\n",
381                 s_config->left_padding);
382         dev_dbg(isp->dev, "stream_config.sensor_binning_factor=%d.\n",
383                 s_config->sensor_binning_factor);
384         dev_dbg(isp->dev, "stream_config.pixels_per_clock=%d.\n",
385                 s_config->pixels_per_clock);
386         dev_dbg(isp->dev, "stream_config.pack_raw_pixels=%d.\n",
387                 s_config->pack_raw_pixels);
388         dev_dbg(isp->dev, "stream_config.flash_gpio_pin=%d.\n",
389                 s_config->flash_gpio_pin);
390         dev_dbg(isp->dev, "stream_config.mipi_buffer_config.size_mem_words=%d.\n",
391                 s_config->mipi_buffer_config.size_mem_words);
392         dev_dbg(isp->dev, "stream_config.mipi_buffer_config.contiguous=%d.\n",
393                 s_config->mipi_buffer_config.contiguous);
394         dev_dbg(isp->dev, "stream_config.metadata_config.data_type=%d.\n",
395                 s_config->metadata_config.data_type);
396         dev_dbg(isp->dev, "stream_config.metadata_config.resolution w=%d, h=%d.\n",
397                 s_config->metadata_config.resolution.width,
398                 s_config->metadata_config.resolution.height);
399 }
400
401 static int __destroy_stream(struct atomisp_sub_device *asd,
402                             struct atomisp_stream_env *stream_env)
403 {
404         struct atomisp_device *isp = asd->isp;
405         unsigned long timeout;
406
407         if (!stream_env->stream)
408                 return 0;
409
410         if (stream_env->stream_state == CSS_STREAM_STARTED
411             && ia_css_stream_stop(stream_env->stream) != 0) {
412                 dev_err(isp->dev, "stop stream failed.\n");
413                 return -EINVAL;
414         }
415
416         if (stream_env->stream_state == CSS_STREAM_STARTED) {
417                 timeout = jiffies + msecs_to_jiffies(40);
418                 while (1) {
419                         if (ia_css_stream_has_stopped(stream_env->stream))
420                                 break;
421
422                         if (time_after(jiffies, timeout)) {
423                                 dev_warn(isp->dev, "stop stream timeout.\n");
424                                 break;
425                         }
426
427                         usleep_range(100, 200);
428                 }
429         }
430
431         stream_env->stream_state = CSS_STREAM_STOPPED;
432
433         if (ia_css_stream_destroy(stream_env->stream)) {
434                 dev_err(isp->dev, "destroy stream failed.\n");
435                 return -EINVAL;
436         }
437         stream_env->stream_state = CSS_STREAM_UNINIT;
438         stream_env->stream = NULL;
439
440         return 0;
441 }
442
443 static int __destroy_streams(struct atomisp_sub_device *asd)
444 {
445         int ret, i;
446
447         for (i = 0; i < ATOMISP_INPUT_STREAM_NUM; i++) {
448                 ret = __destroy_stream(asd, &asd->stream_env[i]);
449                 if (ret)
450                         return ret;
451         }
452         asd->stream_prepared = false;
453         return 0;
454 }
455
456 static int __create_stream(struct atomisp_sub_device *asd,
457                            struct atomisp_stream_env *stream_env)
458 {
459         int pipe_index = 0, i;
460         struct ia_css_pipe *multi_pipes[IA_CSS_PIPE_ID_NUM];
461
462         for (i = 0; i < IA_CSS_PIPE_ID_NUM; i++) {
463                 if (stream_env->pipes[i])
464                         multi_pipes[pipe_index++] = stream_env->pipes[i];
465         }
466         if (pipe_index == 0)
467                 return 0;
468
469         stream_env->stream_config.target_num_cont_raw_buf =
470             asd->continuous_raw_buffer_size->val;
471         stream_env->stream_config.channel_id = stream_env->ch_id;
472         stream_env->stream_config.ia_css_enable_raw_buffer_locking =
473             asd->enable_raw_buffer_lock->val;
474
475         __dump_stream_config(asd, stream_env);
476         if (ia_css_stream_create(&stream_env->stream_config,
477                                  pipe_index, multi_pipes, &stream_env->stream) != 0)
478                 return -EINVAL;
479         if (ia_css_stream_get_info(stream_env->stream,
480                                    &stream_env->stream_info) != 0) {
481                 ia_css_stream_destroy(stream_env->stream);
482                 stream_env->stream = NULL;
483                 return -EINVAL;
484         }
485
486         stream_env->stream_state = CSS_STREAM_CREATED;
487         return 0;
488 }
489
490 static int __create_streams(struct atomisp_sub_device *asd)
491 {
492         int ret, i;
493
494         for (i = 0; i < ATOMISP_INPUT_STREAM_NUM; i++) {
495                 ret = __create_stream(asd, &asd->stream_env[i]);
496                 if (ret)
497                         goto rollback;
498         }
499         asd->stream_prepared = true;
500         return 0;
501 rollback:
502         for (i--; i >= 0; i--)
503                 __destroy_stream(asd, &asd->stream_env[i]);
504         return ret;
505 }
506
507 static int __destroy_stream_pipes(struct atomisp_sub_device *asd,
508                                   struct atomisp_stream_env *stream_env)
509 {
510         struct atomisp_device *isp = asd->isp;
511         int ret = 0;
512         int i;
513
514         for (i = 0; i < IA_CSS_PIPE_ID_NUM; i++) {
515                 if (!stream_env->pipes[i])
516                         continue;
517                 if (ia_css_pipe_destroy(stream_env->pipes[i])
518                     != 0) {
519                         dev_err(isp->dev,
520                                 "destroy pipe[%d]failed.cannot recover.\n", i);
521                         ret = -EINVAL;
522                 }
523                 stream_env->pipes[i] = NULL;
524                 stream_env->update_pipe[i] = false;
525         }
526         return ret;
527 }
528
529 static int __destroy_pipes(struct atomisp_sub_device *asd)
530 {
531         struct atomisp_device *isp = asd->isp;
532         int i;
533         int ret = 0;
534
535         for (i = 0; i < ATOMISP_INPUT_STREAM_NUM; i++) {
536                 if (asd->stream_env[i].stream) {
537                         dev_err(isp->dev,
538                                 "cannot destroy css pipes for stream[%d].\n",
539                                 i);
540                         continue;
541                 }
542
543                 ret = __destroy_stream_pipes(asd, &asd->stream_env[i]);
544                 if (ret)
545                         return ret;
546         }
547
548         return 0;
549 }
550
551 void atomisp_destroy_pipes_stream_force(struct atomisp_sub_device *asd)
552 {
553         if (__destroy_streams(asd))
554                 dev_warn(asd->isp->dev, "destroy stream failed.\n");
555
556         if (__destroy_pipes(asd))
557                 dev_warn(asd->isp->dev, "destroy pipe failed.\n");
558 }
559
560 static void __apply_additional_pipe_config(
561     struct atomisp_sub_device *asd,
562     struct atomisp_stream_env *stream_env,
563     enum ia_css_pipe_id pipe_id)
564 {
565         struct atomisp_device *isp = asd->isp;
566
567         if (pipe_id < 0 || pipe_id >= IA_CSS_PIPE_ID_NUM) {
568                 dev_err(isp->dev,
569                         "wrong pipe_id for additional pipe config.\n");
570                 return;
571         }
572
573         /* apply default pipe config */
574         stream_env->pipe_configs[pipe_id].isp_pipe_version = 2;
575         stream_env->pipe_configs[pipe_id].enable_dz =
576             asd->disable_dz->val ? false : true;
577         /* apply isp 2.2 specific config for baytrail*/
578         switch (pipe_id) {
579         case IA_CSS_PIPE_ID_CAPTURE:
580                 /* enable capture pp/dz manually or digital zoom would
581                  * fail*/
582                 if (stream_env->pipe_configs[pipe_id].
583                     default_capture_config.mode == IA_CSS_CAPTURE_MODE_RAW)
584                         stream_env->pipe_configs[pipe_id].enable_dz = false;
585                 break;
586         case IA_CSS_PIPE_ID_VIDEO:
587                 /* enable reduced pipe to have binary
588                  * video_dz_2_min selected*/
589                 stream_env->pipe_extra_configs[pipe_id]
590                 .enable_reduced_pipe = true;
591                 stream_env->pipe_configs[pipe_id]
592                 .enable_dz = false;
593
594                 if (asd->params.video_dis_en) {
595                         stream_env->pipe_extra_configs[pipe_id]
596                         .enable_dvs_6axis = true;
597                         stream_env->pipe_configs[pipe_id]
598                         .dvs_frame_delay =
599                             ATOMISP_CSS2_NUM_DVS_FRAME_DELAY;
600                 }
601                 break;
602         case IA_CSS_PIPE_ID_PREVIEW:
603                 break;
604         case IA_CSS_PIPE_ID_YUVPP:
605         case IA_CSS_PIPE_ID_COPY:
606                 stream_env->pipe_configs[pipe_id].enable_dz = false;
607                 break;
608         default:
609                 break;
610         }
611 }
612
613 static bool is_pipe_valid_to_current_run_mode(struct atomisp_sub_device *asd,
614         enum ia_css_pipe_id pipe_id)
615 {
616         if (!asd)
617                 return false;
618
619         if (pipe_id == IA_CSS_PIPE_ID_YUVPP)
620                 return true;
621
622         if (asd->vfpp) {
623                 if (asd->vfpp->val == ATOMISP_VFPP_DISABLE_SCALER) {
624                         if (pipe_id == IA_CSS_PIPE_ID_VIDEO)
625                                 return true;
626                         else
627                                 return false;
628                 } else if (asd->vfpp->val == ATOMISP_VFPP_DISABLE_LOWLAT) {
629                         if (pipe_id == IA_CSS_PIPE_ID_CAPTURE)
630                                 return true;
631                         else
632                                 return false;
633                 }
634         }
635
636         if (!asd->run_mode)
637                 return false;
638
639         if (asd->copy_mode && pipe_id == IA_CSS_PIPE_ID_COPY)
640                 return true;
641
642         switch (asd->run_mode->val) {
643         case ATOMISP_RUN_MODE_STILL_CAPTURE:
644                 if (pipe_id == IA_CSS_PIPE_ID_CAPTURE)
645                         return true;
646
647                 return false;
648         case ATOMISP_RUN_MODE_PREVIEW:
649                 if (pipe_id == IA_CSS_PIPE_ID_PREVIEW)
650                         return true;
651
652                 return false;
653         case ATOMISP_RUN_MODE_VIDEO:
654                 if (pipe_id == IA_CSS_PIPE_ID_VIDEO || pipe_id == IA_CSS_PIPE_ID_YUVPP)
655                         return true;
656
657                 return false;
658         }
659
660         return false;
661 }
662
663 static int __create_pipe(struct atomisp_sub_device *asd,
664                          struct atomisp_stream_env *stream_env,
665                          enum ia_css_pipe_id pipe_id)
666 {
667         struct atomisp_device *isp = asd->isp;
668         struct ia_css_pipe_extra_config extra_config;
669         int ret;
670
671         if (pipe_id >= IA_CSS_PIPE_ID_NUM)
672                 return -EINVAL;
673
674         if (!stream_env->pipe_configs[pipe_id].output_info[0].res.width)
675                 return 0;
676
677         if (!is_pipe_valid_to_current_run_mode(asd, pipe_id))
678                 return 0;
679
680         ia_css_pipe_extra_config_defaults(&extra_config);
681
682         __apply_additional_pipe_config(asd, stream_env, pipe_id);
683         if (!memcmp(&extra_config,
684                     &stream_env->pipe_extra_configs[pipe_id],
685                     sizeof(extra_config)))
686                 ret = ia_css_pipe_create(
687                           &stream_env->pipe_configs[pipe_id],
688                           &stream_env->pipes[pipe_id]);
689         else
690                 ret = ia_css_pipe_create_extra(
691                           &stream_env->pipe_configs[pipe_id],
692                           &stream_env->pipe_extra_configs[pipe_id],
693                           &stream_env->pipes[pipe_id]);
694         if (ret)
695                 dev_err(isp->dev, "create pipe[%d] error.\n", pipe_id);
696         return ret;
697 }
698
699 static int __create_pipes(struct atomisp_sub_device *asd)
700 {
701         int ret;
702         int i, j;
703
704         for (i = 0; i < ATOMISP_INPUT_STREAM_NUM; i++) {
705                 for (j = 0; j < IA_CSS_PIPE_ID_NUM; j++) {
706                         ret = __create_pipe(asd, &asd->stream_env[i], j);
707                         if (ret)
708                                 break;
709                 }
710                 if (j < IA_CSS_PIPE_ID_NUM)
711                         goto pipe_err;
712         }
713         return 0;
714 pipe_err:
715         for (; i >= 0; i--) {
716                 for (j--; j >= 0; j--) {
717                         if (asd->stream_env[i].pipes[j]) {
718                                 ia_css_pipe_destroy(asd->stream_env[i].pipes[j]);
719                                 asd->stream_env[i].pipes[j] = NULL;
720                         }
721                 }
722                 j = IA_CSS_PIPE_ID_NUM;
723         }
724         return -EINVAL;
725 }
726
727 int atomisp_create_pipes_stream(struct atomisp_sub_device *asd)
728 {
729         int ret;
730
731         ret = __create_pipes(asd);
732         if (ret) {
733                 dev_err(asd->isp->dev, "create pipe failed %d.\n", ret);
734                 return ret;
735         }
736
737         ret = __create_streams(asd);
738         if (ret) {
739                 dev_warn(asd->isp->dev, "create stream failed %d.\n", ret);
740                 __destroy_pipes(asd);
741                 return ret;
742         }
743
744         return 0;
745 }
746
747 int atomisp_css_update_stream(struct atomisp_sub_device *asd)
748 {
749         atomisp_destroy_pipes_stream_force(asd);
750         return atomisp_create_pipes_stream(asd);
751 }
752
753 int atomisp_css_init(struct atomisp_device *isp)
754 {
755         unsigned int mmu_base_addr;
756         int ret;
757         int err;
758
759         ret = hmm_get_mmu_base_addr(isp->dev, &mmu_base_addr);
760         if (ret)
761                 return ret;
762
763         /* Init ISP */
764         err = ia_css_init(isp->dev, &isp->css_env.isp_css_env, NULL,
765                           (uint32_t)mmu_base_addr, IA_CSS_IRQ_TYPE_PULSE);
766         if (err) {
767                 dev_err(isp->dev, "css init failed --- bad firmware?\n");
768                 return -EINVAL;
769         }
770         ia_css_enable_isys_event_queue(true);
771
772         isp->css_initialized = true;
773         dev_dbg(isp->dev, "sh_css_init success\n");
774
775         return 0;
776 }
777
778 static inline int __set_css_print_env(struct atomisp_device *isp, int opt)
779 {
780         int ret = 0;
781
782         if (opt == 0)
783                 isp->css_env.isp_css_env.print_env.debug_print = NULL;
784         else if (opt == 1)
785                 isp->css_env.isp_css_env.print_env.debug_print = atomisp_vprintk;
786         else
787                 ret = -EINVAL;
788
789         return ret;
790 }
791
792 int atomisp_css_load_firmware(struct atomisp_device *isp)
793 {
794         int err;
795
796         /* set css env */
797         isp->css_env.isp_css_fw.data = (void *)isp->firmware->data;
798         isp->css_env.isp_css_fw.bytes = isp->firmware->size;
799
800         isp->css_env.isp_css_env.hw_access_env.store_8 =
801             atomisp_css2_hw_store_8;
802         isp->css_env.isp_css_env.hw_access_env.store_16 =
803             atomisp_css2_hw_store_16;
804         isp->css_env.isp_css_env.hw_access_env.store_32 =
805             atomisp_css2_hw_store_32;
806
807         isp->css_env.isp_css_env.hw_access_env.load_8 = atomisp_css2_hw_load_8;
808         isp->css_env.isp_css_env.hw_access_env.load_16 =
809             atomisp_css2_hw_load_16;
810         isp->css_env.isp_css_env.hw_access_env.load_32 =
811             atomisp_css2_hw_load_32;
812
813         isp->css_env.isp_css_env.hw_access_env.load = atomisp_css2_hw_load;
814         isp->css_env.isp_css_env.hw_access_env.store = atomisp_css2_hw_store;
815
816         __set_css_print_env(isp, dbg_func);
817
818         isp->css_env.isp_css_env.print_env.error_print = atomisp_vprintk;
819
820         /* load isp fw into ISP memory */
821         err = ia_css_load_firmware(isp->dev, &isp->css_env.isp_css_env,
822                                    &isp->css_env.isp_css_fw);
823         if (err) {
824                 dev_err(isp->dev, "css load fw failed.\n");
825                 return -EINVAL;
826         }
827
828         return 0;
829 }
830
831 void atomisp_css_uninit(struct atomisp_device *isp)
832 {
833         isp->css_initialized = false;
834         ia_css_uninit();
835 }
836
837 int atomisp_css_irq_translate(struct atomisp_device *isp,
838                               unsigned int *infos)
839 {
840         int err;
841
842         err = ia_css_irq_translate(infos);
843         if (err) {
844                 dev_warn(isp->dev,
845                          "%s:failed to translate irq (err = %d,infos = %d)\n",
846                          __func__, err, *infos);
847                 return -EINVAL;
848         }
849
850         return 0;
851 }
852
853 void atomisp_css_rx_get_irq_info(enum mipi_port_id port,
854                                  unsigned int *infos)
855 {
856 #ifndef ISP2401
857         ia_css_isys_rx_get_irq_info(port, infos);
858 #else
859         *infos = 0;
860 #endif
861 }
862
863 void atomisp_css_rx_clear_irq_info(enum mipi_port_id port,
864                                    unsigned int infos)
865 {
866 #ifndef ISP2401
867         ia_css_isys_rx_clear_irq_info(port, infos);
868 #endif
869 }
870
871 int atomisp_css_irq_enable(struct atomisp_device *isp,
872                            enum ia_css_irq_info info, bool enable)
873 {
874         dev_dbg(isp->dev, "%s: css irq info 0x%08x: %s (%d).\n",
875                 __func__, info,
876                 enable ? "enable" : "disable", enable);
877         if (ia_css_irq_enable(info, enable)) {
878                 dev_warn(isp->dev, "%s:Invalid irq info: 0x%08x when %s.\n",
879                          __func__, info,
880                          enable ? "enabling" : "disabling");
881                 return -EINVAL;
882         }
883
884         return 0;
885 }
886
887 void atomisp_css_init_struct(struct atomisp_sub_device *asd)
888 {
889         int i, j;
890
891         for (i = 0; i < ATOMISP_INPUT_STREAM_NUM; i++) {
892                 asd->stream_env[i].stream = NULL;
893                 for (j = 0; j < IA_CSS_PIPE_MODE_NUM; j++) {
894                         asd->stream_env[i].pipes[j] = NULL;
895                         asd->stream_env[i].update_pipe[j] = false;
896                         ia_css_pipe_config_defaults(
897                             &asd->stream_env[i].pipe_configs[j]);
898                         ia_css_pipe_extra_config_defaults(
899                             &asd->stream_env[i].pipe_extra_configs[j]);
900                 }
901                 ia_css_stream_config_defaults(&asd->stream_env[i].stream_config);
902         }
903 }
904
905 int atomisp_q_video_buffer_to_css(struct atomisp_sub_device *asd,
906                                   struct ia_css_frame *frame,
907                                   enum atomisp_input_stream_id stream_id,
908                                   enum ia_css_buffer_type css_buf_type,
909                                   enum ia_css_pipe_id css_pipe_id)
910 {
911         struct atomisp_stream_env *stream_env = &asd->stream_env[stream_id];
912         struct ia_css_buffer css_buf = {0};
913         int err;
914
915         css_buf.type = css_buf_type;
916         css_buf.data.frame = frame;
917
918         err = ia_css_pipe_enqueue_buffer(
919                   stream_env->pipes[css_pipe_id], &css_buf);
920         if (err)
921                 return -EINVAL;
922
923         return 0;
924 }
925
926 int atomisp_q_metadata_buffer_to_css(struct atomisp_sub_device *asd,
927                                      struct atomisp_metadata_buf *metadata_buf,
928                                      enum atomisp_input_stream_id stream_id,
929                                      enum ia_css_pipe_id css_pipe_id)
930 {
931         struct atomisp_stream_env *stream_env = &asd->stream_env[stream_id];
932         struct ia_css_buffer buffer = {0};
933         struct atomisp_device *isp = asd->isp;
934
935         buffer.type = IA_CSS_BUFFER_TYPE_METADATA;
936         buffer.data.metadata = metadata_buf->metadata;
937         if (ia_css_pipe_enqueue_buffer(stream_env->pipes[css_pipe_id],
938                                        &buffer)) {
939                 dev_err(isp->dev, "failed to q meta data buffer\n");
940                 return -EINVAL;
941         }
942
943         return 0;
944 }
945
946 int atomisp_q_s3a_buffer_to_css(struct atomisp_sub_device *asd,
947                                 struct atomisp_s3a_buf *s3a_buf,
948                                 enum atomisp_input_stream_id stream_id,
949                                 enum ia_css_pipe_id css_pipe_id)
950 {
951         struct atomisp_stream_env *stream_env = &asd->stream_env[stream_id];
952         struct ia_css_buffer buffer = {0};
953         struct atomisp_device *isp = asd->isp;
954
955         buffer.type = IA_CSS_BUFFER_TYPE_3A_STATISTICS;
956         buffer.data.stats_3a = s3a_buf->s3a_data;
957         if (ia_css_pipe_enqueue_buffer(
958                 stream_env->pipes[css_pipe_id],
959                 &buffer)) {
960                 dev_dbg(isp->dev, "failed to q s3a stat buffer\n");
961                 return -EINVAL;
962         }
963
964         return 0;
965 }
966
967 int atomisp_q_dis_buffer_to_css(struct atomisp_sub_device *asd,
968                                 struct atomisp_dis_buf *dis_buf,
969                                 enum atomisp_input_stream_id stream_id,
970                                 enum ia_css_pipe_id css_pipe_id)
971 {
972         struct atomisp_stream_env *stream_env = &asd->stream_env[stream_id];
973         struct ia_css_buffer buffer = {0};
974         struct atomisp_device *isp = asd->isp;
975
976         buffer.type = IA_CSS_BUFFER_TYPE_DIS_STATISTICS;
977         buffer.data.stats_dvs = dis_buf->dis_data;
978         if (ia_css_pipe_enqueue_buffer(
979                 stream_env->pipes[css_pipe_id],
980                 &buffer)) {
981                 dev_dbg(isp->dev, "failed to q dvs stat buffer\n");
982                 return -EINVAL;
983         }
984
985         return 0;
986 }
987
988 int atomisp_css_start(struct atomisp_sub_device *asd,
989                       enum ia_css_pipe_id pipe_id, bool in_reset)
990 {
991         struct atomisp_device *isp = asd->isp;
992         bool sp_is_started = false;
993         int ret = 0, i = 0;
994
995         if (in_reset) {
996                 ret = atomisp_css_update_stream(asd);
997                 if (ret)
998                         return ret;
999
1000                 /* Invalidate caches. FIXME: should flush only necessary buffers */
1001                 wbinvd();
1002         }
1003
1004         if (!sh_css_hrt_system_is_idle())
1005                 dev_err(isp->dev, "CSS HW not idle before starting SP\n");
1006
1007         if (ia_css_start_sp()) {
1008                 dev_err(isp->dev, "start sp error.\n");
1009                 ret = -EINVAL;
1010                 goto start_err;
1011         }
1012
1013         sp_is_started = true;
1014
1015         for (i = 0; i < ATOMISP_INPUT_STREAM_NUM; i++) {
1016                 if (asd->stream_env[i].stream) {
1017                         if (ia_css_stream_start(asd->stream_env[i]
1018                                                 .stream) != 0) {
1019                                 dev_err(isp->dev, "stream[%d] start error.\n", i);
1020                                 ret = -EINVAL;
1021                                 goto start_err;
1022                         } else {
1023                                 asd->stream_env[i].stream_state = CSS_STREAM_STARTED;
1024                                 dev_dbg(isp->dev, "stream[%d] started.\n", i);
1025                         }
1026                 }
1027         }
1028
1029         return 0;
1030
1031 start_err:
1032         /*
1033          * CSS 2.0 API limitation: ia_css_stop_sp() can only be called after
1034          * destroying all pipes.
1035          */
1036         if (sp_is_started) {
1037                 atomisp_destroy_pipes_stream_force(asd);
1038                 ia_css_stop_sp();
1039                 atomisp_create_pipes_stream(asd);
1040         }
1041
1042         return ret;
1043 }
1044
1045 void atomisp_css_update_isp_params(struct atomisp_sub_device *asd)
1046 {
1047         /*
1048          * FIXME!
1049          * for ISP2401 new input system, this api is under development.
1050          * Calling it would cause kernel panic.
1051          *
1052          * VIED BZ: 1458
1053          *
1054          * Check if it is Cherry Trail and also new input system
1055          */
1056         if (asd->copy_mode) {
1057                 dev_warn(asd->isp->dev,
1058                          "%s: ia_css_stream_set_isp_config() not supported in copy mode!.\n",
1059                          __func__);
1060                 return;
1061         }
1062
1063         ia_css_stream_set_isp_config(
1064             asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream,
1065             &asd->params.config);
1066         memset(&asd->params.config, 0, sizeof(asd->params.config));
1067 }
1068
1069 void atomisp_css_update_isp_params_on_pipe(struct atomisp_sub_device *asd,
1070         struct ia_css_pipe *pipe)
1071 {
1072         int ret;
1073
1074         if (!pipe) {
1075                 atomisp_css_update_isp_params(asd);
1076                 return;
1077         }
1078
1079         dev_dbg(asd->isp->dev,
1080                 "%s: apply parameter for ia_css_frame %p with isp_config_id %d on pipe %p.\n",
1081                 __func__, asd->params.config.output_frame,
1082                 asd->params.config.isp_config_id, pipe);
1083
1084         ret = ia_css_stream_set_isp_config_on_pipe(
1085                   asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream,
1086                   &asd->params.config, pipe);
1087         if (ret)
1088                 dev_warn(asd->isp->dev, "%s: ia_css_stream_set_isp_config_on_pipe failed %d\n",
1089                          __func__, ret);
1090         memset(&asd->params.config, 0, sizeof(asd->params.config));
1091 }
1092
1093 int atomisp_css_queue_buffer(struct atomisp_sub_device *asd,
1094                              enum atomisp_input_stream_id stream_id,
1095                              enum ia_css_pipe_id pipe_id,
1096                              enum ia_css_buffer_type buf_type,
1097                              struct atomisp_css_buffer *isp_css_buffer)
1098 {
1099         if (ia_css_pipe_enqueue_buffer(
1100                 asd->stream_env[stream_id].pipes[pipe_id],
1101                 &isp_css_buffer->css_buffer)
1102             != 0)
1103                 return -EINVAL;
1104
1105         return 0;
1106 }
1107
1108 int atomisp_css_dequeue_buffer(struct atomisp_sub_device *asd,
1109                                enum atomisp_input_stream_id stream_id,
1110                                enum ia_css_pipe_id pipe_id,
1111                                enum ia_css_buffer_type buf_type,
1112                                struct atomisp_css_buffer *isp_css_buffer)
1113 {
1114         struct atomisp_device *isp = asd->isp;
1115         int err;
1116
1117         err = ia_css_pipe_dequeue_buffer(
1118                   asd->stream_env[stream_id].pipes[pipe_id],
1119                   &isp_css_buffer->css_buffer);
1120         if (err) {
1121                 dev_err(isp->dev,
1122                         "ia_css_pipe_dequeue_buffer failed: 0x%x\n", err);
1123                 return -EINVAL;
1124         }
1125
1126         return 0;
1127 }
1128
1129 int atomisp_css_allocate_stat_buffers(struct atomisp_sub_device   *asd,
1130                                       u16 stream_id,
1131                                       struct atomisp_s3a_buf      *s3a_buf,
1132                                       struct atomisp_dis_buf      *dis_buf,
1133                                       struct atomisp_metadata_buf *md_buf)
1134 {
1135         struct atomisp_device *isp = asd->isp;
1136         struct ia_css_dvs_grid_info *dvs_grid_info =
1137             atomisp_css_get_dvs_grid_info(&asd->params.curr_grid_info);
1138
1139         if (s3a_buf && asd->params.curr_grid_info.s3a_grid.enable) {
1140                 void *s3a_ptr;
1141
1142                 s3a_buf->s3a_data = ia_css_isp_3a_statistics_allocate(
1143                                         &asd->params.curr_grid_info.s3a_grid);
1144                 if (!s3a_buf->s3a_data) {
1145                         dev_err(isp->dev, "3a buf allocation failed.\n");
1146                         return -EINVAL;
1147                 }
1148
1149                 s3a_ptr = hmm_vmap(s3a_buf->s3a_data->data_ptr, true);
1150                 s3a_buf->s3a_map = ia_css_isp_3a_statistics_map_allocate(
1151                                        s3a_buf->s3a_data, s3a_ptr);
1152         }
1153
1154         if (dis_buf && dvs_grid_info && dvs_grid_info->enable) {
1155                 void *dvs_ptr;
1156
1157                 dis_buf->dis_data = ia_css_isp_dvs2_statistics_allocate(
1158                                         dvs_grid_info);
1159                 if (!dis_buf->dis_data) {
1160                         dev_err(isp->dev, "dvs buf allocation failed.\n");
1161                         if (s3a_buf)
1162                                 ia_css_isp_3a_statistics_free(s3a_buf->s3a_data);
1163                         return -EINVAL;
1164                 }
1165
1166                 dvs_ptr = hmm_vmap(dis_buf->dis_data->data_ptr, true);
1167                 dis_buf->dvs_map = ia_css_isp_dvs_statistics_map_allocate(
1168                                        dis_buf->dis_data, dvs_ptr);
1169         }
1170
1171         if (asd->stream_env[stream_id].stream_info.
1172             metadata_info.size && md_buf) {
1173                 md_buf->metadata = ia_css_metadata_allocate(
1174                                        &asd->stream_env[stream_id].stream_info.metadata_info);
1175                 if (!md_buf->metadata) {
1176                         if (s3a_buf)
1177                                 ia_css_isp_3a_statistics_free(s3a_buf->s3a_data);
1178                         if (dis_buf)
1179                                 ia_css_isp_dvs2_statistics_free(dis_buf->dis_data);
1180                         dev_err(isp->dev, "metadata buf allocation failed.\n");
1181                         return -EINVAL;
1182                 }
1183                 md_buf->md_vptr = hmm_vmap(md_buf->metadata->address, false);
1184         }
1185
1186         return 0;
1187 }
1188
1189 void atomisp_css_free_3a_buffer(struct atomisp_s3a_buf *s3a_buf)
1190 {
1191         if (s3a_buf->s3a_data)
1192                 hmm_vunmap(s3a_buf->s3a_data->data_ptr);
1193
1194         ia_css_isp_3a_statistics_map_free(s3a_buf->s3a_map);
1195         s3a_buf->s3a_map = NULL;
1196         ia_css_isp_3a_statistics_free(s3a_buf->s3a_data);
1197 }
1198
1199 void atomisp_css_free_dis_buffer(struct atomisp_dis_buf *dis_buf)
1200 {
1201         if (dis_buf->dis_data)
1202                 hmm_vunmap(dis_buf->dis_data->data_ptr);
1203
1204         ia_css_isp_dvs_statistics_map_free(dis_buf->dvs_map);
1205         dis_buf->dvs_map = NULL;
1206         ia_css_isp_dvs2_statistics_free(dis_buf->dis_data);
1207 }
1208
1209 void atomisp_css_free_metadata_buffer(struct atomisp_metadata_buf *metadata_buf)
1210 {
1211         if (metadata_buf->md_vptr) {
1212                 hmm_vunmap(metadata_buf->metadata->address);
1213                 metadata_buf->md_vptr = NULL;
1214         }
1215         ia_css_metadata_free(metadata_buf->metadata);
1216 }
1217
1218 void atomisp_css_free_stat_buffers(struct atomisp_sub_device *asd)
1219 {
1220         struct atomisp_s3a_buf *s3a_buf, *_s3a_buf;
1221         struct atomisp_dis_buf *dis_buf, *_dis_buf;
1222         struct atomisp_metadata_buf *md_buf, *_md_buf;
1223         struct ia_css_dvs_grid_info *dvs_grid_info =
1224             atomisp_css_get_dvs_grid_info(&asd->params.curr_grid_info);
1225         unsigned int i;
1226
1227         /* 3A statistics use vmalloc, DIS use kmalloc */
1228         if (dvs_grid_info && dvs_grid_info->enable) {
1229                 ia_css_dvs2_coefficients_free(asd->params.css_param.dvs2_coeff);
1230                 ia_css_dvs2_statistics_free(asd->params.dvs_stat);
1231                 asd->params.css_param.dvs2_coeff = NULL;
1232                 asd->params.dvs_stat = NULL;
1233                 asd->params.dvs_hor_proj_bytes = 0;
1234                 asd->params.dvs_ver_proj_bytes = 0;
1235                 asd->params.dvs_hor_coef_bytes = 0;
1236                 asd->params.dvs_ver_coef_bytes = 0;
1237                 asd->params.dis_proj_data_valid = false;
1238                 list_for_each_entry_safe(dis_buf, _dis_buf,
1239                                          &asd->dis_stats, list) {
1240                         atomisp_css_free_dis_buffer(dis_buf);
1241                         list_del(&dis_buf->list);
1242                         kfree(dis_buf);
1243                 }
1244                 list_for_each_entry_safe(dis_buf, _dis_buf,
1245                                          &asd->dis_stats_in_css, list) {
1246                         atomisp_css_free_dis_buffer(dis_buf);
1247                         list_del(&dis_buf->list);
1248                         kfree(dis_buf);
1249                 }
1250         }
1251         if (asd->params.curr_grid_info.s3a_grid.enable) {
1252                 ia_css_3a_statistics_free(asd->params.s3a_user_stat);
1253                 asd->params.s3a_user_stat = NULL;
1254                 asd->params.s3a_output_bytes = 0;
1255                 list_for_each_entry_safe(s3a_buf, _s3a_buf,
1256                                          &asd->s3a_stats, list) {
1257                         atomisp_css_free_3a_buffer(s3a_buf);
1258                         list_del(&s3a_buf->list);
1259                         kfree(s3a_buf);
1260                 }
1261                 list_for_each_entry_safe(s3a_buf, _s3a_buf,
1262                                          &asd->s3a_stats_in_css, list) {
1263                         atomisp_css_free_3a_buffer(s3a_buf);
1264                         list_del(&s3a_buf->list);
1265                         kfree(s3a_buf);
1266                 }
1267                 list_for_each_entry_safe(s3a_buf, _s3a_buf,
1268                                          &asd->s3a_stats_ready, list) {
1269                         atomisp_css_free_3a_buffer(s3a_buf);
1270                         list_del(&s3a_buf->list);
1271                         kfree(s3a_buf);
1272                 }
1273         }
1274
1275         if (asd->params.css_param.dvs_6axis) {
1276                 ia_css_dvs2_6axis_config_free(asd->params.css_param.dvs_6axis);
1277                 asd->params.css_param.dvs_6axis = NULL;
1278         }
1279
1280         for (i = 0; i < ATOMISP_METADATA_TYPE_NUM; i++) {
1281                 list_for_each_entry_safe(md_buf, _md_buf,
1282                                          &asd->metadata[i], list) {
1283                         atomisp_css_free_metadata_buffer(md_buf);
1284                         list_del(&md_buf->list);
1285                         kfree(md_buf);
1286                 }
1287                 list_for_each_entry_safe(md_buf, _md_buf,
1288                                          &asd->metadata_in_css[i], list) {
1289                         atomisp_css_free_metadata_buffer(md_buf);
1290                         list_del(&md_buf->list);
1291                         kfree(md_buf);
1292                 }
1293                 list_for_each_entry_safe(md_buf, _md_buf,
1294                                          &asd->metadata_ready[i], list) {
1295                         atomisp_css_free_metadata_buffer(md_buf);
1296                         list_del(&md_buf->list);
1297                         kfree(md_buf);
1298                 }
1299         }
1300         asd->params.metadata_width_size = 0;
1301         atomisp_free_metadata_output_buf(asd);
1302 }
1303
1304 int atomisp_css_get_grid_info(struct atomisp_sub_device *asd,
1305                               enum ia_css_pipe_id pipe_id)
1306 {
1307         struct ia_css_pipe_info p_info;
1308         struct ia_css_grid_info old_info;
1309         struct atomisp_device *isp = asd->isp;
1310         int md_width = asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].
1311                        stream_config.metadata_config.resolution.width;
1312
1313         memset(&p_info, 0, sizeof(struct ia_css_pipe_info));
1314         memset(&old_info, 0, sizeof(struct ia_css_grid_info));
1315
1316         if (ia_css_pipe_get_info(
1317                 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].pipes[pipe_id],
1318                 &p_info) != 0) {
1319                 dev_err(isp->dev, "ia_css_pipe_get_info failed\n");
1320                 return -EINVAL;
1321         }
1322
1323         memcpy(&old_info, &asd->params.curr_grid_info,
1324                sizeof(struct ia_css_grid_info));
1325         memcpy(&asd->params.curr_grid_info, &p_info.grid_info,
1326                sizeof(struct ia_css_grid_info));
1327         /*
1328          * Record which css pipe enables s3a_grid.
1329          * Currently would have one css pipe that need it
1330          */
1331         if (asd->params.curr_grid_info.s3a_grid.enable) {
1332                 if (asd->params.s3a_enabled_pipe != IA_CSS_PIPE_ID_NUM)
1333                         dev_dbg(isp->dev, "css pipe %d enabled s3a grid replaced by: %d.\n",
1334                                 asd->params.s3a_enabled_pipe, pipe_id);
1335                 asd->params.s3a_enabled_pipe = pipe_id;
1336         }
1337
1338         /* If the grid info has not changed and the buffers for 3A and
1339          * DIS statistics buffers are allocated or buffer size would be zero
1340          * then no need to do anything. */
1341         if (((!memcmp(&old_info, &asd->params.curr_grid_info, sizeof(old_info))
1342               && asd->params.s3a_user_stat && asd->params.dvs_stat)
1343              || asd->params.curr_grid_info.s3a_grid.width == 0
1344              || asd->params.curr_grid_info.s3a_grid.height == 0)
1345             && asd->params.metadata_width_size == md_width) {
1346                 dev_dbg(isp->dev,
1347                         "grid info change escape. memcmp=%d, s3a_user_stat=%d,dvs_stat=%d, s3a.width=%d, s3a.height=%d, metadata width =%d\n",
1348                         !memcmp(&old_info, &asd->params.curr_grid_info,
1349                                 sizeof(old_info)),
1350                         !!asd->params.s3a_user_stat, !!asd->params.dvs_stat,
1351                         asd->params.curr_grid_info.s3a_grid.width,
1352                         asd->params.curr_grid_info.s3a_grid.height,
1353                         asd->params.metadata_width_size);
1354                 return -EINVAL;
1355         }
1356         asd->params.metadata_width_size = md_width;
1357
1358         return 0;
1359 }
1360
1361 int atomisp_alloc_3a_output_buf(struct atomisp_sub_device *asd)
1362 {
1363         if (!asd->params.curr_grid_info.s3a_grid.width ||
1364             !asd->params.curr_grid_info.s3a_grid.height)
1365                 return 0;
1366
1367         asd->params.s3a_user_stat = ia_css_3a_statistics_allocate(
1368                                         &asd->params.curr_grid_info.s3a_grid);
1369         if (!asd->params.s3a_user_stat)
1370                 return -ENOMEM;
1371         /* 3A statistics. These can be big, so we use vmalloc. */
1372         asd->params.s3a_output_bytes =
1373             asd->params.curr_grid_info.s3a_grid.width *
1374             asd->params.curr_grid_info.s3a_grid.height *
1375             sizeof(*asd->params.s3a_user_stat->data);
1376
1377         return 0;
1378 }
1379
1380 int atomisp_alloc_dis_coef_buf(struct atomisp_sub_device *asd)
1381 {
1382         struct ia_css_dvs_grid_info *dvs_grid =
1383             atomisp_css_get_dvs_grid_info(&asd->params.curr_grid_info);
1384
1385         if (!dvs_grid)
1386                 return 0;
1387
1388         if (!dvs_grid->enable) {
1389                 dev_dbg(asd->isp->dev, "%s: dvs_grid not enabled.\n", __func__);
1390                 return 0;
1391         }
1392
1393         /* DIS coefficients. */
1394         asd->params.css_param.dvs2_coeff = ia_css_dvs2_coefficients_allocate(
1395                                                dvs_grid);
1396         if (!asd->params.css_param.dvs2_coeff)
1397                 return -ENOMEM;
1398
1399         asd->params.dvs_hor_coef_bytes = dvs_grid->num_hor_coefs *
1400                                          sizeof(*asd->params.css_param.dvs2_coeff->hor_coefs.odd_real);
1401
1402         asd->params.dvs_ver_coef_bytes = dvs_grid->num_ver_coefs *
1403                                          sizeof(*asd->params.css_param.dvs2_coeff->ver_coefs.odd_real);
1404
1405         /* DIS projections. */
1406         asd->params.dis_proj_data_valid = false;
1407         asd->params.dvs_stat = ia_css_dvs2_statistics_allocate(dvs_grid);
1408         if (!asd->params.dvs_stat)
1409                 return -ENOMEM;
1410
1411         asd->params.dvs_hor_proj_bytes =
1412             dvs_grid->aligned_height * dvs_grid->aligned_width *
1413             sizeof(*asd->params.dvs_stat->hor_prod.odd_real);
1414
1415         asd->params.dvs_ver_proj_bytes =
1416             dvs_grid->aligned_height * dvs_grid->aligned_width *
1417             sizeof(*asd->params.dvs_stat->ver_prod.odd_real);
1418
1419         return 0;
1420 }
1421
1422 int atomisp_alloc_metadata_output_buf(struct atomisp_sub_device *asd)
1423 {
1424         int i;
1425
1426         /* We allocate the cpu-side buffer used for communication with user
1427          * space */
1428         for (i = 0; i < ATOMISP_METADATA_TYPE_NUM; i++) {
1429                 asd->params.metadata_user[i] = kvmalloc(
1430                                                    asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].
1431                                                    stream_info.metadata_info.size, GFP_KERNEL);
1432                 if (!asd->params.metadata_user[i]) {
1433                         while (--i >= 0) {
1434                                 kvfree(asd->params.metadata_user[i]);
1435                                 asd->params.metadata_user[i] = NULL;
1436                         }
1437                         return -ENOMEM;
1438                 }
1439         }
1440
1441         return 0;
1442 }
1443
1444 void atomisp_free_metadata_output_buf(struct atomisp_sub_device *asd)
1445 {
1446         unsigned int i;
1447
1448         for (i = 0; i < ATOMISP_METADATA_TYPE_NUM; i++) {
1449                 if (asd->params.metadata_user[i]) {
1450                         kvfree(asd->params.metadata_user[i]);
1451                         asd->params.metadata_user[i] = NULL;
1452                 }
1453         }
1454 }
1455
1456 void atomisp_css_temp_pipe_to_pipe_id(struct atomisp_sub_device *asd,
1457                                       struct atomisp_css_event *current_event)
1458 {
1459         /*
1460          * FIXME!
1461          * Pipe ID reported in CSS event is not correct for new system's
1462          * copy pipe.
1463          * VIED BZ: 1463
1464          */
1465         ia_css_temp_pipe_to_pipe_id(current_event->event.pipe,
1466                                     &current_event->pipe);
1467         if (asd && asd->copy_mode &&
1468             current_event->pipe == IA_CSS_PIPE_ID_CAPTURE)
1469                 current_event->pipe = IA_CSS_PIPE_ID_COPY;
1470 }
1471
1472 int atomisp_css_isys_set_resolution(struct atomisp_sub_device *asd,
1473                                     enum atomisp_input_stream_id stream_id,
1474                                     struct v4l2_mbus_framefmt *ffmt,
1475                                     int isys_stream)
1476 {
1477         struct ia_css_stream_config *s_config =
1478                     &asd->stream_env[stream_id].stream_config;
1479
1480         if (isys_stream >= IA_CSS_STREAM_MAX_ISYS_STREAM_PER_CH)
1481                 return -EINVAL;
1482
1483         s_config->isys_config[isys_stream].input_res.width = ffmt->width;
1484         s_config->isys_config[isys_stream].input_res.height = ffmt->height;
1485         return 0;
1486 }
1487
1488 int atomisp_css_input_set_resolution(struct atomisp_sub_device *asd,
1489                                      enum atomisp_input_stream_id stream_id,
1490                                      struct v4l2_mbus_framefmt *ffmt)
1491 {
1492         struct ia_css_stream_config *s_config =
1493                     &asd->stream_env[stream_id].stream_config;
1494
1495         s_config->input_config.input_res.width = ffmt->width;
1496         s_config->input_config.input_res.height = ffmt->height;
1497         return 0;
1498 }
1499
1500 void atomisp_css_input_set_binning_factor(struct atomisp_sub_device *asd,
1501         enum atomisp_input_stream_id stream_id,
1502         unsigned int bin_factor)
1503 {
1504         asd->stream_env[stream_id]
1505         .stream_config.sensor_binning_factor = bin_factor;
1506 }
1507
1508 void atomisp_css_input_set_bayer_order(struct atomisp_sub_device *asd,
1509                                        enum atomisp_input_stream_id stream_id,
1510                                        enum ia_css_bayer_order bayer_order)
1511 {
1512         struct ia_css_stream_config *s_config =
1513                     &asd->stream_env[stream_id].stream_config;
1514         s_config->input_config.bayer_order = bayer_order;
1515 }
1516
1517 void atomisp_css_isys_set_link(struct atomisp_sub_device *asd,
1518                                enum atomisp_input_stream_id stream_id,
1519                                int link,
1520                                int isys_stream)
1521 {
1522         struct ia_css_stream_config *s_config =
1523                     &asd->stream_env[stream_id].stream_config;
1524
1525         s_config->isys_config[isys_stream].linked_isys_stream_id = link;
1526 }
1527
1528 void atomisp_css_isys_set_valid(struct atomisp_sub_device *asd,
1529                                 enum atomisp_input_stream_id stream_id,
1530                                 bool valid,
1531                                 int isys_stream)
1532 {
1533         struct ia_css_stream_config *s_config =
1534                     &asd->stream_env[stream_id].stream_config;
1535
1536         s_config->isys_config[isys_stream].valid = valid;
1537 }
1538
1539 void atomisp_css_isys_set_format(struct atomisp_sub_device *asd,
1540                                  enum atomisp_input_stream_id stream_id,
1541                                  enum atomisp_input_format format,
1542                                  int isys_stream)
1543 {
1544         struct ia_css_stream_config *s_config =
1545                     &asd->stream_env[stream_id].stream_config;
1546
1547         s_config->isys_config[isys_stream].format = format;
1548 }
1549
1550 void atomisp_css_input_set_format(struct atomisp_sub_device *asd,
1551                                   enum atomisp_input_stream_id stream_id,
1552                                   enum atomisp_input_format format)
1553 {
1554         struct ia_css_stream_config *s_config =
1555                     &asd->stream_env[stream_id].stream_config;
1556
1557         s_config->input_config.format = format;
1558 }
1559
1560 int atomisp_css_set_default_isys_config(struct atomisp_sub_device *asd,
1561                                         enum atomisp_input_stream_id stream_id,
1562                                         struct v4l2_mbus_framefmt *ffmt)
1563 {
1564         int i;
1565         struct ia_css_stream_config *s_config =
1566                     &asd->stream_env[stream_id].stream_config;
1567         /*
1568          * Set all isys configs to not valid.
1569          * Currently we support only one stream per channel
1570          */
1571         for (i = IA_CSS_STREAM_ISYS_STREAM_0;
1572              i < IA_CSS_STREAM_MAX_ISYS_STREAM_PER_CH; i++)
1573                 s_config->isys_config[i].valid = false;
1574
1575         atomisp_css_isys_set_resolution(asd, stream_id, ffmt,
1576                                         IA_CSS_STREAM_DEFAULT_ISYS_STREAM_IDX);
1577         atomisp_css_isys_set_format(asd, stream_id,
1578                                     s_config->input_config.format,
1579                                     IA_CSS_STREAM_DEFAULT_ISYS_STREAM_IDX);
1580         atomisp_css_isys_set_link(asd, stream_id, NO_LINK,
1581                                   IA_CSS_STREAM_DEFAULT_ISYS_STREAM_IDX);
1582         atomisp_css_isys_set_valid(asd, stream_id, true,
1583                                    IA_CSS_STREAM_DEFAULT_ISYS_STREAM_IDX);
1584
1585         return 0;
1586 }
1587
1588 void atomisp_css_isys_two_stream_cfg_update_stream1(
1589     struct atomisp_sub_device *asd,
1590     enum atomisp_input_stream_id stream_id,
1591     enum atomisp_input_format input_format,
1592     unsigned int width, unsigned int height)
1593 {
1594         struct ia_css_stream_config *s_config =
1595                     &asd->stream_env[stream_id].stream_config;
1596
1597         s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_0].input_res.width =
1598             width;
1599         s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_0].input_res.height =
1600             height;
1601         s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_0].format =
1602             input_format;
1603         s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_0].valid = true;
1604 }
1605
1606 void atomisp_css_isys_two_stream_cfg_update_stream2(
1607     struct atomisp_sub_device *asd,
1608     enum atomisp_input_stream_id stream_id,
1609     enum atomisp_input_format input_format,
1610     unsigned int width, unsigned int height)
1611 {
1612         struct ia_css_stream_config *s_config =
1613                     &asd->stream_env[stream_id].stream_config;
1614
1615         s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_1].input_res.width =
1616             width;
1617         s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_1].input_res.height =
1618             height;
1619         s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_1].linked_isys_stream_id
1620             = IA_CSS_STREAM_ISYS_STREAM_0;
1621         s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_1].format =
1622             input_format;
1623         s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_1].valid = true;
1624 }
1625
1626 int atomisp_css_input_set_effective_resolution(
1627     struct atomisp_sub_device *asd,
1628     enum atomisp_input_stream_id stream_id,
1629     unsigned int width, unsigned int height)
1630 {
1631         struct ia_css_stream_config *s_config =
1632                     &asd->stream_env[stream_id].stream_config;
1633         s_config->input_config.effective_res.width = width;
1634         s_config->input_config.effective_res.height = height;
1635         return 0;
1636 }
1637
1638 void atomisp_css_video_set_dis_envelope(struct atomisp_sub_device *asd,
1639                                         unsigned int dvs_w, unsigned int dvs_h)
1640 {
1641         asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]
1642         .pipe_configs[IA_CSS_PIPE_ID_VIDEO].dvs_envelope.width = dvs_w;
1643         asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]
1644         .pipe_configs[IA_CSS_PIPE_ID_VIDEO].dvs_envelope.height = dvs_h;
1645 }
1646
1647 void atomisp_css_input_set_two_pixels_per_clock(
1648     struct atomisp_sub_device *asd,
1649     bool two_ppc)
1650 {
1651         int i;
1652
1653         if (asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]
1654             .stream_config.pixels_per_clock == (two_ppc ? 2 : 1))
1655                 return;
1656
1657         asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]
1658         .stream_config.pixels_per_clock = (two_ppc ? 2 : 1);
1659         for (i = 0; i < IA_CSS_PIPE_ID_NUM; i++)
1660                 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]
1661                 .update_pipe[i] = true;
1662 }
1663
1664 void atomisp_css_enable_dz(struct atomisp_sub_device *asd, bool enable)
1665 {
1666         int i;
1667
1668         for (i = 0; i < IA_CSS_PIPE_ID_NUM; i++)
1669                 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]
1670                 .pipe_configs[i].enable_dz = enable;
1671 }
1672
1673 void atomisp_css_capture_set_mode(struct atomisp_sub_device *asd,
1674                                   enum ia_css_capture_mode mode)
1675 {
1676         struct atomisp_stream_env *stream_env =
1677                     &asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL];
1678
1679         if (stream_env->pipe_configs[IA_CSS_PIPE_ID_CAPTURE]
1680             .default_capture_config.mode == mode)
1681                 return;
1682
1683         stream_env->pipe_configs[IA_CSS_PIPE_ID_CAPTURE].
1684         default_capture_config.mode = mode;
1685         stream_env->update_pipe[IA_CSS_PIPE_ID_CAPTURE] = true;
1686 }
1687
1688 void atomisp_css_input_set_mode(struct atomisp_sub_device *asd,
1689                                 enum ia_css_input_mode mode)
1690 {
1691         int i;
1692         struct atomisp_device *isp = asd->isp;
1693         unsigned int size_mem_words;
1694
1695         for (i = 0; i < ATOMISP_INPUT_STREAM_NUM; i++)
1696                 asd->stream_env[i].stream_config.mode = mode;
1697
1698         if (isp->inputs[asd->input_curr].type == TEST_PATTERN) {
1699                 struct ia_css_stream_config *s_config =
1700                             &asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream_config;
1701                 s_config->mode = IA_CSS_INPUT_MODE_TPG;
1702                 s_config->source.tpg.mode = IA_CSS_TPG_MODE_CHECKERBOARD;
1703                 s_config->source.tpg.x_mask = (1 << 4) - 1;
1704                 s_config->source.tpg.x_delta = -2;
1705                 s_config->source.tpg.y_mask = (1 << 4) - 1;
1706                 s_config->source.tpg.y_delta = 3;
1707                 s_config->source.tpg.xy_mask = (1 << 8) - 1;
1708                 return;
1709         }
1710
1711         if (mode != IA_CSS_INPUT_MODE_BUFFERED_SENSOR)
1712                 return;
1713
1714         for (i = 0; i < ATOMISP_INPUT_STREAM_NUM; i++) {
1715                 /*
1716                  * TODO: sensor needs to export the embedded_data_size_words
1717                  * information to atomisp for each setting.
1718                  * Here using a large safe value.
1719                  */
1720                 struct ia_css_stream_config *s_config =
1721                             &asd->stream_env[i].stream_config;
1722
1723                 if (s_config->input_config.input_res.width == 0)
1724                         continue;
1725
1726                 if (ia_css_mipi_frame_calculate_size(
1727                         s_config->input_config.input_res.width,
1728                         s_config->input_config.input_res.height,
1729                         s_config->input_config.format,
1730                         true,
1731                         0x13000,
1732                         &size_mem_words) != 0) {
1733                         if (IS_MRFD)
1734                                 size_mem_words = CSS_MIPI_FRAME_BUFFER_SIZE_2;
1735                         else
1736                                 size_mem_words = CSS_MIPI_FRAME_BUFFER_SIZE_1;
1737                         dev_warn(asd->isp->dev,
1738                                  "ia_css_mipi_frame_calculate_size failed,applying pre-defined MIPI buffer size %u.\n",
1739                                  size_mem_words);
1740                 }
1741                 s_config->mipi_buffer_config.size_mem_words = size_mem_words;
1742                 s_config->mipi_buffer_config.nof_mipi_buffers = 2;
1743         }
1744 }
1745
1746 void atomisp_css_capture_enable_online(struct atomisp_sub_device *asd,
1747                                        unsigned short stream_index, bool enable)
1748 {
1749         struct atomisp_stream_env *stream_env =
1750                     &asd->stream_env[stream_index];
1751
1752         if (stream_env->stream_config.online == !!enable)
1753                 return;
1754
1755         stream_env->stream_config.online = !!enable;
1756         stream_env->update_pipe[IA_CSS_PIPE_ID_CAPTURE] = true;
1757 }
1758
1759 void atomisp_css_preview_enable_online(struct atomisp_sub_device *asd,
1760                                        unsigned short stream_index, bool enable)
1761 {
1762         struct atomisp_stream_env *stream_env =
1763                     &asd->stream_env[stream_index];
1764         int i;
1765
1766         if (stream_env->stream_config.online != !!enable) {
1767                 stream_env->stream_config.online = !!enable;
1768                 for (i = 0; i < IA_CSS_PIPE_ID_NUM; i++)
1769                         stream_env->update_pipe[i] = true;
1770         }
1771 }
1772
1773 int atomisp_css_input_configure_port(
1774     struct atomisp_sub_device *asd,
1775     enum mipi_port_id port,
1776     unsigned int num_lanes,
1777     unsigned int timeout,
1778     unsigned int mipi_freq,
1779     enum atomisp_input_format metadata_format,
1780     unsigned int metadata_width,
1781     unsigned int metadata_height)
1782 {
1783         int i;
1784         struct atomisp_stream_env *stream_env;
1785         /*
1786          * Calculate rx_count as follows:
1787          * Input: mipi_freq                 : CSI-2 bus frequency in Hz
1788          * UI = 1 / (2 * mipi_freq)         : period of one bit on the bus
1789          * min = 85e-9 + 6 * UI             : Limits for rx_count in seconds
1790          * max = 145e-9 + 10 * UI
1791          * rxcount0 = min / (4 / mipi_freq) : convert seconds to byte clocks
1792          * rxcount = rxcount0 - 2           : adjust for better results
1793          * The formula below is simplified version of the above with
1794          * 10-bit fixed points for improved accuracy.
1795          */
1796         const unsigned int rxcount =
1797             min(((mipi_freq / 46000) - 1280) >> 10, 0xffU) * 0x01010101U;
1798
1799         for (i = 0; i < ATOMISP_INPUT_STREAM_NUM; i++) {
1800                 stream_env = &asd->stream_env[i];
1801                 stream_env->stream_config.source.port.port = port;
1802                 stream_env->stream_config.source.port.num_lanes = num_lanes;
1803                 stream_env->stream_config.source.port.timeout = timeout;
1804                 if (mipi_freq)
1805                         stream_env->stream_config.source.port.rxcount = rxcount;
1806                 stream_env->stream_config.
1807                 metadata_config.data_type = metadata_format;
1808                 stream_env->stream_config.
1809                 metadata_config.resolution.width = metadata_width;
1810                 stream_env->stream_config.
1811                 metadata_config.resolution.height = metadata_height;
1812         }
1813
1814         return 0;
1815 }
1816
1817 void atomisp_css_stop(struct atomisp_sub_device *asd,
1818                       enum ia_css_pipe_id pipe_id, bool in_reset)
1819 {
1820         unsigned long irqflags;
1821         unsigned int i;
1822
1823         /*
1824          * CSS 2.0 API limitation: ia_css_stop_sp() can only be called after
1825          * destroying all pipes.
1826          */
1827         atomisp_destroy_pipes_stream_force(asd);
1828
1829         atomisp_init_raw_buffer_bitmap(asd);
1830
1831         ia_css_stop_sp();
1832
1833         if (!in_reset) {
1834                 struct atomisp_stream_env *stream_env;
1835                 int i, j;
1836
1837                 for (i = 0; i < ATOMISP_INPUT_STREAM_NUM; i++) {
1838                         stream_env = &asd->stream_env[i];
1839                         for (j = 0; j < IA_CSS_PIPE_ID_NUM; j++) {
1840                                 ia_css_pipe_config_defaults(
1841                                     &stream_env->pipe_configs[j]);
1842                                 ia_css_pipe_extra_config_defaults(
1843                                     &stream_env->pipe_extra_configs[j]);
1844                         }
1845                         ia_css_stream_config_defaults(
1846                             &stream_env->stream_config);
1847                 }
1848                 memset(&asd->params.config, 0, sizeof(asd->params.config));
1849                 asd->params.css_update_params_needed = false;
1850         }
1851
1852         /* move stats buffers to free queue list */
1853         list_splice_init(&asd->s3a_stats_in_css, &asd->s3a_stats);
1854         list_splice_init(&asd->s3a_stats_ready, &asd->s3a_stats);
1855
1856         spin_lock_irqsave(&asd->dis_stats_lock, irqflags);
1857         list_splice_init(&asd->dis_stats_in_css, &asd->dis_stats);
1858         asd->params.dis_proj_data_valid = false;
1859         spin_unlock_irqrestore(&asd->dis_stats_lock, irqflags);
1860
1861         for (i = 0; i < ATOMISP_METADATA_TYPE_NUM; i++) {
1862                 list_splice_init(&asd->metadata_in_css[i], &asd->metadata[i]);
1863                 list_splice_init(&asd->metadata_ready[i], &asd->metadata[i]);
1864         }
1865
1866         atomisp_flush_params_queue(&asd->video_out);
1867         atomisp_free_css_parameters(&asd->params.css_param);
1868         memset(&asd->params.css_param, 0, sizeof(asd->params.css_param));
1869 }
1870
1871 void atomisp_css_continuous_set_num_raw_frames(
1872      struct atomisp_sub_device *asd,
1873      int num_frames)
1874 {
1875         if (asd->enable_raw_buffer_lock->val) {
1876                 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]
1877                 .stream_config.init_num_cont_raw_buf =
1878                     ATOMISP_CSS2_NUM_OFFLINE_INIT_CONTINUOUS_FRAMES_LOCK_EN;
1879                 if (asd->run_mode->val == ATOMISP_RUN_MODE_VIDEO &&
1880                     asd->params.video_dis_en)
1881                         asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]
1882                         .stream_config.init_num_cont_raw_buf +=
1883                             ATOMISP_CSS2_NUM_DVS_FRAME_DELAY;
1884         } else {
1885                 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]
1886                 .stream_config.init_num_cont_raw_buf =
1887                     ATOMISP_CSS2_NUM_OFFLINE_INIT_CONTINUOUS_FRAMES;
1888         }
1889
1890         if (asd->params.video_dis_en)
1891                 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]
1892                 .stream_config.init_num_cont_raw_buf +=
1893                     ATOMISP_CSS2_NUM_DVS_FRAME_DELAY;
1894
1895         asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]
1896         .stream_config.target_num_cont_raw_buf = num_frames;
1897 }
1898
1899 static enum ia_css_pipe_mode __pipe_id_to_pipe_mode(
1900     struct atomisp_sub_device *asd,
1901     enum ia_css_pipe_id pipe_id)
1902 {
1903         struct atomisp_device *isp = asd->isp;
1904         struct camera_mipi_info *mipi_info = atomisp_to_sensor_mipi_info(
1905                 isp->inputs[asd->input_curr].camera);
1906
1907         switch (pipe_id) {
1908         case IA_CSS_PIPE_ID_COPY:
1909                 /* Currently only YUVPP mode supports YUV420_Legacy format.
1910                  * Revert this when other pipe modes can support
1911                  * YUV420_Legacy format.
1912                  */
1913                 if (mipi_info && mipi_info->input_format ==
1914                     ATOMISP_INPUT_FORMAT_YUV420_8_LEGACY)
1915                         return IA_CSS_PIPE_MODE_YUVPP;
1916                 return IA_CSS_PIPE_MODE_COPY;
1917         case IA_CSS_PIPE_ID_PREVIEW:
1918                 return IA_CSS_PIPE_MODE_PREVIEW;
1919         case IA_CSS_PIPE_ID_CAPTURE:
1920                 return IA_CSS_PIPE_MODE_CAPTURE;
1921         case IA_CSS_PIPE_ID_VIDEO:
1922                 return IA_CSS_PIPE_MODE_VIDEO;
1923         case IA_CSS_PIPE_ID_YUVPP:
1924                 return IA_CSS_PIPE_MODE_YUVPP;
1925         default:
1926                 WARN_ON(1);
1927                 return IA_CSS_PIPE_MODE_PREVIEW;
1928         }
1929 }
1930
1931 static void __configure_output(struct atomisp_sub_device *asd,
1932                                unsigned int stream_index,
1933                                unsigned int width, unsigned int height,
1934                                unsigned int min_width,
1935                                enum ia_css_frame_format format,
1936                                enum ia_css_pipe_id pipe_id)
1937 {
1938         struct atomisp_device *isp = asd->isp;
1939         struct atomisp_stream_env *stream_env =
1940                     &asd->stream_env[stream_index];
1941         struct ia_css_stream_config *s_config = &stream_env->stream_config;
1942
1943         stream_env->pipe_configs[pipe_id].mode =
1944             __pipe_id_to_pipe_mode(asd, pipe_id);
1945         stream_env->update_pipe[pipe_id] = true;
1946
1947         stream_env->pipe_configs[pipe_id].output_info[0].res.width = width;
1948         stream_env->pipe_configs[pipe_id].output_info[0].res.height = height;
1949         stream_env->pipe_configs[pipe_id].output_info[0].format = format;
1950         stream_env->pipe_configs[pipe_id].output_info[0].padded_width = min_width;
1951
1952         /* isp binary 2.2 specific setting*/
1953         if (width > s_config->input_config.effective_res.width ||
1954             height > s_config->input_config.effective_res.height) {
1955                 s_config->input_config.effective_res.width = width;
1956                 s_config->input_config.effective_res.height = height;
1957         }
1958
1959         dev_dbg(isp->dev, "configuring pipe[%d] output info w=%d.h=%d.f=%d.\n",
1960                 pipe_id, width, height, format);
1961 }
1962
1963 /*
1964  * For CSS2.1, capture pipe uses capture_pp_in_res to configure yuv
1965  * downscaling input resolution.
1966  */
1967 static void __configure_capture_pp_input(struct atomisp_sub_device *asd,
1968         unsigned int width, unsigned int height,
1969         enum ia_css_pipe_id pipe_id)
1970 {
1971         struct atomisp_device *isp = asd->isp;
1972         struct atomisp_stream_env *stream_env =
1973                     &asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL];
1974         struct ia_css_stream_config *stream_config = &stream_env->stream_config;
1975         struct ia_css_pipe_config *pipe_configs =
1976                     &stream_env->pipe_configs[pipe_id];
1977         struct ia_css_pipe_extra_config *pipe_extra_configs =
1978                     &stream_env->pipe_extra_configs[pipe_id];
1979         unsigned int hor_ds_factor = 0, ver_ds_factor = 0;
1980
1981         if (width == 0 && height == 0)
1982                 return;
1983
1984         if (width * 9 / 10 < pipe_configs->output_info[0].res.width ||
1985             height * 9 / 10 < pipe_configs->output_info[0].res.height)
1986                 return;
1987         /* here just copy the calculation in css */
1988         hor_ds_factor = CEIL_DIV(width >> 1,
1989                                  pipe_configs->output_info[0].res.width);
1990         ver_ds_factor = CEIL_DIV(height >> 1,
1991                                  pipe_configs->output_info[0].res.height);
1992
1993         if ((asd->isp->media_dev.hw_revision <
1994              (ATOMISP_HW_REVISION_ISP2401 << ATOMISP_HW_REVISION_SHIFT) ||
1995              IS_CHT) && hor_ds_factor != ver_ds_factor) {
1996                 dev_warn(asd->isp->dev,
1997                          "Cropping for capture due to FW limitation");
1998                 return;
1999         }
2000
2001         pipe_configs->mode = __pipe_id_to_pipe_mode(asd, pipe_id);
2002         stream_env->update_pipe[pipe_id] = true;
2003
2004         pipe_extra_configs->enable_yuv_ds = true;
2005
2006         pipe_configs->capt_pp_in_res.width =
2007             stream_config->input_config.effective_res.width;
2008         pipe_configs->capt_pp_in_res.height =
2009             stream_config->input_config.effective_res.height;
2010
2011         dev_dbg(isp->dev, "configuring pipe[%d]capture pp input w=%d.h=%d.\n",
2012                 pipe_id, width, height);
2013 }
2014
2015 /*
2016  * For CSS2.1, preview pipe could support bayer downscaling, yuv decimation and
2017  * yuv downscaling, which needs addtional configurations.
2018  */
2019 static void __configure_preview_pp_input(struct atomisp_sub_device *asd,
2020         unsigned int width, unsigned int height,
2021         enum ia_css_pipe_id pipe_id)
2022 {
2023         struct atomisp_device *isp = asd->isp;
2024         int out_width, out_height, yuv_ds_in_width, yuv_ds_in_height;
2025         struct atomisp_stream_env *stream_env =
2026                     &asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL];
2027         struct ia_css_stream_config *stream_config = &stream_env->stream_config;
2028         struct ia_css_pipe_config *pipe_configs =
2029                     &stream_env->pipe_configs[pipe_id];
2030         struct ia_css_pipe_extra_config *pipe_extra_configs =
2031                     &stream_env->pipe_extra_configs[pipe_id];
2032         struct ia_css_resolution *bayer_ds_out_res =
2033                     &pipe_configs->bayer_ds_out_res;
2034         struct ia_css_resolution *vf_pp_in_res =
2035                     &pipe_configs->vf_pp_in_res;
2036         struct ia_css_resolution  *effective_res =
2037                     &stream_config->input_config.effective_res;
2038
2039         static const struct bayer_ds_factor bds_fct[] = {{2, 1}, {3, 2}, {5, 4} };
2040         /*
2041          * BZ201033: YUV decimation factor of 4 causes couple of rightmost
2042          * columns to be shaded. Remove this factor to work around the CSS bug.
2043          * const unsigned int yuv_dec_fct[] = {4, 2};
2044          */
2045         static const unsigned int yuv_dec_fct[] = { 2 };
2046         unsigned int i;
2047
2048         if (width == 0 && height == 0)
2049                 return;
2050
2051         pipe_configs->mode = __pipe_id_to_pipe_mode(asd, pipe_id);
2052         stream_env->update_pipe[pipe_id] = true;
2053
2054         out_width = pipe_configs->output_info[0].res.width;
2055         out_height = pipe_configs->output_info[0].res.height;
2056
2057         /*
2058          * The ISP could do bayer downscaling, yuv decimation and yuv
2059          * downscaling:
2060          * 1: Bayer Downscaling: between effective resolution and
2061          * bayer_ds_res_out;
2062          * 2: YUV Decimation: between bayer_ds_res_out and vf_pp_in_res;
2063          * 3: YUV Downscaling: between vf_pp_in_res and final vf output
2064          *
2065          * Rule for Bayer Downscaling: support factor 2, 1.5 and 1.25
2066          * Rule for YUV Decimation: support factor 2, 4
2067          * Rule for YUV Downscaling: arbitrary value below 2
2068          *
2069          * General rule of factor distribution among these stages:
2070          * 1: try to do Bayer downscaling first if not in online mode.
2071          * 2: try to do maximum of 2 for YUV downscaling
2072          * 3: the remainling for YUV decimation
2073          *
2074          * Note:
2075          * Do not configure bayer_ds_out_res if:
2076          * online == 1 or continuous == 0 or raw_binning = 0
2077          */
2078         if (stream_config->online || !stream_config->continuous ||
2079             !pipe_extra_configs->enable_raw_binning) {
2080                 bayer_ds_out_res->width = 0;
2081                 bayer_ds_out_res->height = 0;
2082         } else {
2083                 bayer_ds_out_res->width = effective_res->width;
2084                 bayer_ds_out_res->height = effective_res->height;
2085
2086                 for (i = 0; i < ARRAY_SIZE(bds_fct); i++) {
2087                         if (effective_res->width >= out_width *
2088                             bds_fct[i].numerator / bds_fct[i].denominator &&
2089                             effective_res->height >= out_height *
2090                             bds_fct[i].numerator / bds_fct[i].denominator) {
2091                                 bayer_ds_out_res->width =
2092                                     effective_res->width *
2093                                     bds_fct[i].denominator /
2094                                     bds_fct[i].numerator;
2095                                 bayer_ds_out_res->height =
2096                                     effective_res->height *
2097                                     bds_fct[i].denominator /
2098                                     bds_fct[i].numerator;
2099                                 break;
2100                         }
2101                 }
2102         }
2103         /*
2104          * calculate YUV Decimation, YUV downscaling facor:
2105          * YUV Downscaling factor must not exceed 2.
2106          * YUV Decimation factor could be 2, 4.
2107          */
2108         /* first decide the yuv_ds input resolution */
2109         if (bayer_ds_out_res->width == 0) {
2110                 yuv_ds_in_width = effective_res->width;
2111                 yuv_ds_in_height = effective_res->height;
2112         } else {
2113                 yuv_ds_in_width = bayer_ds_out_res->width;
2114                 yuv_ds_in_height = bayer_ds_out_res->height;
2115         }
2116
2117         vf_pp_in_res->width = yuv_ds_in_width;
2118         vf_pp_in_res->height = yuv_ds_in_height;
2119
2120         /* find out the yuv decimation factor */
2121         for (i = 0; i < ARRAY_SIZE(yuv_dec_fct); i++) {
2122                 if (yuv_ds_in_width >= out_width * yuv_dec_fct[i] &&
2123                     yuv_ds_in_height >= out_height * yuv_dec_fct[i]) {
2124                         vf_pp_in_res->width = yuv_ds_in_width / yuv_dec_fct[i];
2125                         vf_pp_in_res->height = yuv_ds_in_height / yuv_dec_fct[i];
2126                         break;
2127                 }
2128         }
2129
2130         if (vf_pp_in_res->width == out_width &&
2131             vf_pp_in_res->height == out_height) {
2132                 pipe_extra_configs->enable_yuv_ds = false;
2133                 vf_pp_in_res->width = 0;
2134                 vf_pp_in_res->height = 0;
2135         } else {
2136                 pipe_extra_configs->enable_yuv_ds = true;
2137         }
2138
2139         dev_dbg(isp->dev, "configuring pipe[%d]preview pp input w=%d.h=%d.\n",
2140                 pipe_id, width, height);
2141 }
2142
2143 /*
2144  * For CSS2.1, offline video pipe could support bayer decimation, and
2145  * yuv downscaling, which needs addtional configurations.
2146  */
2147 static void __configure_video_pp_input(struct atomisp_sub_device *asd,
2148                                        unsigned int width, unsigned int height,
2149                                        enum ia_css_pipe_id pipe_id)
2150 {
2151         struct atomisp_device *isp = asd->isp;
2152         int out_width, out_height;
2153         struct atomisp_stream_env *stream_env =
2154                     &asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL];
2155         struct ia_css_stream_config *stream_config = &stream_env->stream_config;
2156         struct ia_css_pipe_config *pipe_configs =
2157                     &stream_env->pipe_configs[pipe_id];
2158         struct ia_css_pipe_extra_config *pipe_extra_configs =
2159                     &stream_env->pipe_extra_configs[pipe_id];
2160         struct ia_css_resolution *bayer_ds_out_res =
2161                     &pipe_configs->bayer_ds_out_res;
2162         struct ia_css_resolution  *effective_res =
2163                     &stream_config->input_config.effective_res;
2164
2165         static const struct bayer_ds_factor bds_factors[] = {
2166                 {8, 1}, {6, 1}, {4, 1}, {3, 1}, {2, 1}, {3, 2}
2167         };
2168         unsigned int i;
2169
2170         if (width == 0 && height == 0)
2171                 return;
2172
2173         pipe_configs->mode = __pipe_id_to_pipe_mode(asd, pipe_id);
2174         stream_env->update_pipe[pipe_id] = true;
2175
2176         pipe_extra_configs->enable_yuv_ds = false;
2177
2178         /*
2179          * If DVS is enabled,  video binary will take care the dvs envelope
2180          * and usually the bayer_ds_out_res should be larger than 120% of
2181          * destination resolution, the extra 20% will be cropped as DVS
2182          * envelope. But,  if the bayer_ds_out_res is less than 120% of the
2183          * destination. The ISP can still work,  but DVS quality is not good.
2184          */
2185         /* taking at least 10% as envelope */
2186         if (asd->params.video_dis_en) {
2187                 out_width = pipe_configs->output_info[0].res.width * 110 / 100;
2188                 out_height = pipe_configs->output_info[0].res.height * 110 / 100;
2189         } else {
2190                 out_width = pipe_configs->output_info[0].res.width;
2191                 out_height = pipe_configs->output_info[0].res.height;
2192         }
2193
2194         /*
2195          * calculate bayer decimate factor:
2196          * 1: only 1.5, 2, 4 and 8 get supported
2197          * 2: Do not configure bayer_ds_out_res if:
2198          *    online == 1 or continuous == 0 or raw_binning = 0
2199          */
2200         if (stream_config->online || !stream_config->continuous) {
2201                 bayer_ds_out_res->width = 0;
2202                 bayer_ds_out_res->height = 0;
2203                 goto done;
2204         }
2205
2206         pipe_extra_configs->enable_raw_binning = true;
2207         bayer_ds_out_res->width = effective_res->width;
2208         bayer_ds_out_res->height = effective_res->height;
2209
2210         for (i = 0; i < sizeof(bds_factors) / sizeof(struct bayer_ds_factor);
2211              i++) {
2212                 if (effective_res->width >= out_width *
2213                     bds_factors[i].numerator / bds_factors[i].denominator &&
2214                     effective_res->height >= out_height *
2215                     bds_factors[i].numerator / bds_factors[i].denominator) {
2216                         bayer_ds_out_res->width = effective_res->width *
2217                                                   bds_factors[i].denominator /
2218                                                   bds_factors[i].numerator;
2219                         bayer_ds_out_res->height = effective_res->height *
2220                                                    bds_factors[i].denominator /
2221                                                    bds_factors[i].numerator;
2222                         break;
2223                 }
2224         }
2225
2226         /*
2227          * DVS is cropped from BDS output, so we do not really need to set the
2228          * envelope to 20% of output resolution here. always set it to 12x12
2229          * per firmware requirement.
2230          */
2231         pipe_configs->dvs_envelope.width = 12;
2232         pipe_configs->dvs_envelope.height = 12;
2233
2234 done:
2235         if (pipe_id == IA_CSS_PIPE_ID_YUVPP)
2236                 stream_config->left_padding = -1;
2237         else
2238                 stream_config->left_padding = 12;
2239         dev_dbg(isp->dev, "configuring pipe[%d]video pp input w=%d.h=%d.\n",
2240                 pipe_id, width, height);
2241 }
2242
2243 static void __configure_vf_output(struct atomisp_sub_device *asd,
2244                                   unsigned int width, unsigned int height,
2245                                   unsigned int min_width,
2246                                   enum ia_css_frame_format format,
2247                                   enum ia_css_pipe_id pipe_id)
2248 {
2249         struct atomisp_device *isp = asd->isp;
2250         struct atomisp_stream_env *stream_env =
2251                     &asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL];
2252         stream_env->pipe_configs[pipe_id].mode =
2253             __pipe_id_to_pipe_mode(asd, pipe_id);
2254         stream_env->update_pipe[pipe_id] = true;
2255
2256         stream_env->pipe_configs[pipe_id].vf_output_info[0].res.width = width;
2257         stream_env->pipe_configs[pipe_id].vf_output_info[0].res.height = height;
2258         stream_env->pipe_configs[pipe_id].vf_output_info[0].format = format;
2259         stream_env->pipe_configs[pipe_id].vf_output_info[0].padded_width =
2260             min_width;
2261         dev_dbg(isp->dev,
2262                 "configuring pipe[%d] vf output info w=%d.h=%d.f=%d.\n",
2263                 pipe_id, width, height, format);
2264 }
2265
2266 static int __get_frame_info(struct atomisp_sub_device *asd,
2267                             unsigned int stream_index,
2268                             struct ia_css_frame_info *info,
2269                             enum frame_info_type type,
2270                             enum ia_css_pipe_id pipe_id)
2271 {
2272         struct atomisp_device *isp = asd->isp;
2273         int ret;
2274         struct ia_css_pipe_info p_info;
2275
2276         /* FIXME! No need to destroy/recreate all streams */
2277         ret = atomisp_css_update_stream(asd);
2278         if (ret)
2279                 return ret;
2280
2281         ret = ia_css_pipe_get_info(asd->stream_env[stream_index].pipes[pipe_id],
2282                                    &p_info);
2283         if (ret) {
2284                 dev_err(isp->dev, "can't get info from pipe\n");
2285                 goto get_info_err;
2286         }
2287
2288         switch (type) {
2289         case ATOMISP_CSS_VF_FRAME:
2290                 *info = p_info.vf_output_info[0];
2291                 dev_dbg(isp->dev, "getting vf frame info.\n");
2292                 break;
2293         case ATOMISP_CSS_SECOND_VF_FRAME:
2294                 *info = p_info.vf_output_info[1];
2295                 dev_dbg(isp->dev, "getting second vf frame info.\n");
2296                 break;
2297         case ATOMISP_CSS_OUTPUT_FRAME:
2298                 *info = p_info.output_info[0];
2299                 dev_dbg(isp->dev, "getting main frame info.\n");
2300                 break;
2301         case ATOMISP_CSS_SECOND_OUTPUT_FRAME:
2302                 *info = p_info.output_info[1];
2303                 dev_dbg(isp->dev, "getting second main frame info.\n");
2304                 break;
2305         default:
2306         case ATOMISP_CSS_RAW_FRAME:
2307                 *info = p_info.raw_output_info;
2308                 dev_dbg(isp->dev, "getting raw frame info.\n");
2309                 break;
2310         }
2311         dev_dbg(isp->dev, "get frame info: w=%d, h=%d, num_invalid_frames %d.\n",
2312                 info->res.width, info->res.height, p_info.num_invalid_frames);
2313
2314         return 0;
2315
2316 get_info_err:
2317         atomisp_destroy_pipes_stream_force(asd);
2318         return -EINVAL;
2319 }
2320
2321 static unsigned int atomisp_get_pipe_index(struct atomisp_sub_device *asd)
2322 {
2323         if (asd->copy_mode)
2324                 return IA_CSS_PIPE_ID_COPY;
2325
2326         switch (asd->run_mode->val) {
2327         case ATOMISP_RUN_MODE_VIDEO:
2328                 return IA_CSS_PIPE_ID_VIDEO;
2329         case ATOMISP_RUN_MODE_STILL_CAPTURE:
2330                 return IA_CSS_PIPE_ID_CAPTURE;
2331         case ATOMISP_RUN_MODE_PREVIEW:
2332                 return IA_CSS_PIPE_ID_PREVIEW;
2333         }
2334
2335         dev_warn(asd->isp->dev, "cannot determine pipe-index return default preview pipe\n");
2336         return IA_CSS_PIPE_ID_PREVIEW;
2337 }
2338
2339 int atomisp_get_css_frame_info(struct atomisp_sub_device *asd,
2340                                struct ia_css_frame_info *frame_info)
2341 {
2342         struct ia_css_pipe_info info;
2343         int pipe_index = atomisp_get_pipe_index(asd);
2344         int stream_index;
2345         struct atomisp_device *isp = asd->isp;
2346
2347         stream_index = (pipe_index == IA_CSS_PIPE_ID_YUVPP) ?
2348                                ATOMISP_INPUT_STREAM_VIDEO :
2349                                ATOMISP_INPUT_STREAM_GENERAL;
2350
2351         if (0 != ia_css_pipe_get_info(asd->stream_env[stream_index]
2352                 .pipes[pipe_index], &info)) {
2353                 dev_dbg(isp->dev, "ia_css_pipe_get_info FAILED");
2354                 return -EINVAL;
2355         }
2356
2357         *frame_info = info.output_info[0];
2358         return 0;
2359 }
2360
2361 int atomisp_css_copy_configure_output(struct atomisp_sub_device *asd,
2362                                       unsigned int stream_index,
2363                                       unsigned int width, unsigned int height,
2364                                       unsigned int padded_width,
2365                                       enum ia_css_frame_format format)
2366 {
2367         asd->stream_env[stream_index].pipe_configs[IA_CSS_PIPE_ID_COPY].
2368         default_capture_config.mode =
2369             IA_CSS_CAPTURE_MODE_RAW;
2370
2371         __configure_output(asd, stream_index, width, height, padded_width,
2372                            format, IA_CSS_PIPE_ID_COPY);
2373         return 0;
2374 }
2375
2376 int atomisp_css_preview_configure_output(struct atomisp_sub_device *asd,
2377         unsigned int width, unsigned int height,
2378         unsigned int min_width,
2379         enum ia_css_frame_format format)
2380 {
2381         __configure_output(asd, ATOMISP_INPUT_STREAM_GENERAL, width, height,
2382                            min_width, format, IA_CSS_PIPE_ID_PREVIEW);
2383         return 0;
2384 }
2385
2386 int atomisp_css_capture_configure_output(struct atomisp_sub_device *asd,
2387         unsigned int width, unsigned int height,
2388         unsigned int min_width,
2389         enum ia_css_frame_format format)
2390 {
2391         __configure_output(asd, ATOMISP_INPUT_STREAM_GENERAL, width, height,
2392                            min_width, format, IA_CSS_PIPE_ID_CAPTURE);
2393         return 0;
2394 }
2395
2396 int atomisp_css_video_configure_output(struct atomisp_sub_device *asd,
2397                                        unsigned int width, unsigned int height,
2398                                        unsigned int min_width,
2399                                        enum ia_css_frame_format format)
2400 {
2401         __configure_output(asd, ATOMISP_INPUT_STREAM_GENERAL, width, height,
2402                            min_width, format, IA_CSS_PIPE_ID_VIDEO);
2403         return 0;
2404 }
2405
2406 int atomisp_css_video_configure_viewfinder(
2407     struct atomisp_sub_device *asd,
2408     unsigned int width, unsigned int height,
2409     unsigned int min_width,
2410     enum ia_css_frame_format format)
2411 {
2412         __configure_vf_output(asd, width, height, min_width, format,
2413                               IA_CSS_PIPE_ID_VIDEO);
2414         return 0;
2415 }
2416
2417 int atomisp_css_capture_configure_viewfinder(
2418     struct atomisp_sub_device *asd,
2419     unsigned int width, unsigned int height,
2420     unsigned int min_width,
2421     enum ia_css_frame_format format)
2422 {
2423         __configure_vf_output(asd, width, height, min_width, format, IA_CSS_PIPE_ID_CAPTURE);
2424         return 0;
2425 }
2426
2427 int atomisp_css_video_get_viewfinder_frame_info(
2428     struct atomisp_sub_device *asd,
2429     struct ia_css_frame_info *info)
2430 {
2431         return __get_frame_info(asd, ATOMISP_INPUT_STREAM_GENERAL, info,
2432                                 ATOMISP_CSS_VF_FRAME, IA_CSS_PIPE_ID_VIDEO);
2433 }
2434
2435 int atomisp_css_capture_get_viewfinder_frame_info(
2436     struct atomisp_sub_device *asd,
2437     struct ia_css_frame_info *info)
2438 {
2439         return __get_frame_info(asd, ATOMISP_INPUT_STREAM_GENERAL, info,
2440                                 ATOMISP_CSS_VF_FRAME, IA_CSS_PIPE_ID_CAPTURE);
2441 }
2442
2443 int atomisp_css_copy_get_output_frame_info(
2444     struct atomisp_sub_device *asd,
2445     unsigned int stream_index,
2446     struct ia_css_frame_info *info)
2447 {
2448         return __get_frame_info(asd, stream_index, info,
2449                                 ATOMISP_CSS_OUTPUT_FRAME, IA_CSS_PIPE_ID_COPY);
2450 }
2451
2452 int atomisp_css_preview_get_output_frame_info(
2453     struct atomisp_sub_device *asd,
2454     struct ia_css_frame_info *info)
2455 {
2456         return __get_frame_info(asd, ATOMISP_INPUT_STREAM_GENERAL, info,
2457                                 ATOMISP_CSS_OUTPUT_FRAME, IA_CSS_PIPE_ID_PREVIEW);
2458 }
2459
2460 int atomisp_css_capture_get_output_frame_info(
2461     struct atomisp_sub_device *asd,
2462     struct ia_css_frame_info *info)
2463 {
2464         return __get_frame_info(asd, ATOMISP_INPUT_STREAM_GENERAL, info,
2465                                 ATOMISP_CSS_OUTPUT_FRAME, IA_CSS_PIPE_ID_CAPTURE);
2466 }
2467
2468 int atomisp_css_video_get_output_frame_info(
2469     struct atomisp_sub_device *asd,
2470     struct ia_css_frame_info *info)
2471 {
2472         return __get_frame_info(asd, ATOMISP_INPUT_STREAM_GENERAL, info,
2473                                 ATOMISP_CSS_OUTPUT_FRAME, IA_CSS_PIPE_ID_VIDEO);
2474 }
2475
2476 int atomisp_css_preview_configure_pp_input(
2477     struct atomisp_sub_device *asd,
2478     unsigned int width, unsigned int height)
2479 {
2480         struct atomisp_stream_env *stream_env =
2481                     &asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL];
2482         __configure_preview_pp_input(asd, width, height, IA_CSS_PIPE_ID_PREVIEW);
2483
2484         if (width > stream_env->pipe_configs[IA_CSS_PIPE_ID_CAPTURE].
2485             capt_pp_in_res.width)
2486                 __configure_capture_pp_input(asd, width, height, IA_CSS_PIPE_ID_CAPTURE);
2487
2488         return 0;
2489 }
2490
2491 int atomisp_css_capture_configure_pp_input(
2492     struct atomisp_sub_device *asd,
2493     unsigned int width, unsigned int height)
2494 {
2495         __configure_capture_pp_input(asd, width, height, IA_CSS_PIPE_ID_CAPTURE);
2496         return 0;
2497 }
2498
2499 int atomisp_css_video_configure_pp_input(
2500     struct atomisp_sub_device *asd,
2501     unsigned int width, unsigned int height)
2502 {
2503         struct atomisp_stream_env *stream_env =
2504                     &asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL];
2505
2506         __configure_video_pp_input(asd, width, height, IA_CSS_PIPE_ID_VIDEO);
2507
2508         if (width > stream_env->pipe_configs[IA_CSS_PIPE_ID_CAPTURE].
2509             capt_pp_in_res.width)
2510                 __configure_capture_pp_input(asd, width, height, IA_CSS_PIPE_ID_CAPTURE);
2511
2512         return 0;
2513 }
2514
2515 int atomisp_css_offline_capture_configure(struct atomisp_sub_device *asd,
2516         int num_captures, unsigned int skip, int offset)
2517 {
2518         int ret;
2519
2520         dev_dbg(asd->isp->dev, "%s num_capture:%d skip:%d offset:%d\n",
2521                 __func__, num_captures, skip, offset);
2522
2523         ret = ia_css_stream_capture(
2524                   asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream,
2525                   num_captures, skip, offset);
2526         if (ret)
2527                 return -EINVAL;
2528
2529         return 0;
2530 }
2531
2532 int atomisp_css_exp_id_capture(struct atomisp_sub_device *asd, int exp_id)
2533 {
2534         int ret;
2535
2536         ret = ia_css_stream_capture_frame(
2537                   asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream,
2538                   exp_id);
2539         if (ret == -ENOBUFS) {
2540                 /* capture cmd queue is full */
2541                 return -EBUSY;
2542         } else if (ret) {
2543                 return -EIO;
2544         }
2545
2546         return 0;
2547 }
2548
2549 int atomisp_css_exp_id_unlock(struct atomisp_sub_device *asd, int exp_id)
2550 {
2551         int ret;
2552
2553         ret = ia_css_unlock_raw_frame(
2554                   asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream,
2555                   exp_id);
2556         if (ret == -ENOBUFS)
2557                 return -EAGAIN;
2558         else if (ret)
2559                 return -EIO;
2560
2561         return 0;
2562 }
2563
2564 int atomisp_css_capture_enable_xnr(struct atomisp_sub_device *asd,
2565                                    bool enable)
2566 {
2567         asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]
2568         .pipe_configs[IA_CSS_PIPE_ID_CAPTURE]
2569         .default_capture_config.enable_xnr = enable;
2570         asd->params.capture_config.enable_xnr = enable;
2571         asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]
2572         .update_pipe[IA_CSS_PIPE_ID_CAPTURE] = true;
2573
2574         return 0;
2575 }
2576
2577 void atomisp_css_set_ctc_table(struct atomisp_sub_device *asd,
2578                                struct ia_css_ctc_table *ctc_table)
2579 {
2580         int i;
2581         u16 *vamem_ptr = ctc_table->data.vamem_1;
2582         int data_size = IA_CSS_VAMEM_1_CTC_TABLE_SIZE;
2583         bool valid = false;
2584
2585         /* workaround: if ctc_table is all 0, do not apply it */
2586         if (ctc_table->vamem_type == IA_CSS_VAMEM_TYPE_2) {
2587                 vamem_ptr = ctc_table->data.vamem_2;
2588                 data_size = IA_CSS_VAMEM_2_CTC_TABLE_SIZE;
2589         }
2590
2591         for (i = 0; i < data_size; i++) {
2592                 if (*(vamem_ptr + i)) {
2593                         valid = true;
2594                         break;
2595                 }
2596         }
2597
2598         if (valid)
2599                 asd->params.config.ctc_table = ctc_table;
2600         else
2601                 dev_warn(asd->isp->dev, "Bypass the invalid ctc_table.\n");
2602 }
2603
2604 void atomisp_css_set_anr_thres(struct atomisp_sub_device *asd,
2605                                struct ia_css_anr_thres *anr_thres)
2606 {
2607         asd->params.config.anr_thres = anr_thres;
2608 }
2609
2610 void atomisp_css_set_dvs_6axis(struct atomisp_sub_device *asd,
2611                                struct ia_css_dvs_6axis_config *dvs_6axis)
2612 {
2613         asd->params.config.dvs_6axis_config = dvs_6axis;
2614 }
2615
2616 void atomisp_css_video_set_dis_vector(struct atomisp_sub_device *asd,
2617                                       struct atomisp_dis_vector *vector)
2618 {
2619         if (!asd->params.config.motion_vector)
2620                 asd->params.config.motion_vector = &asd->params.css_param.motion_vector;
2621
2622         memset(asd->params.config.motion_vector,
2623                0, sizeof(struct ia_css_vector));
2624         asd->params.css_param.motion_vector.x = vector->x;
2625         asd->params.css_param.motion_vector.y = vector->y;
2626 }
2627
2628 static int atomisp_compare_dvs_grid(struct atomisp_sub_device *asd,
2629                                     struct atomisp_dvs_grid_info *atomgrid)
2630 {
2631         struct ia_css_dvs_grid_info *cur =
2632             atomisp_css_get_dvs_grid_info(&asd->params.curr_grid_info);
2633
2634         if (!cur) {
2635                 dev_err(asd->isp->dev, "dvs grid not available!\n");
2636                 return -EINVAL;
2637         }
2638
2639         if (sizeof(*cur) != sizeof(*atomgrid)) {
2640                 dev_err(asd->isp->dev, "dvs grid mismatch!\n");
2641                 return -EINVAL;
2642         }
2643
2644         if (!cur->enable) {
2645                 dev_err(asd->isp->dev, "dvs not enabled!\n");
2646                 return -EINVAL;
2647         }
2648
2649         return memcmp(atomgrid, cur, sizeof(*cur));
2650 }
2651
2652 void  atomisp_css_set_dvs2_coefs(struct atomisp_sub_device *asd,
2653                                  struct ia_css_dvs2_coefficients *coefs)
2654 {
2655         asd->params.config.dvs2_coefs = coefs;
2656 }
2657
2658 int atomisp_css_set_dis_coefs(struct atomisp_sub_device *asd,
2659                               struct atomisp_dis_coefficients *coefs)
2660 {
2661         if (atomisp_compare_dvs_grid(asd, &coefs->grid_info) != 0)
2662                 /* If the grid info in the argument differs from the current
2663                    grid info, we tell the caller to reset the grid size and
2664                    try again. */
2665                 return -EAGAIN;
2666
2667         if (!coefs->hor_coefs.odd_real ||
2668             !coefs->hor_coefs.odd_imag ||
2669             !coefs->hor_coefs.even_real ||
2670             !coefs->hor_coefs.even_imag ||
2671             !coefs->ver_coefs.odd_real ||
2672             !coefs->ver_coefs.odd_imag ||
2673             !coefs->ver_coefs.even_real ||
2674             !coefs->ver_coefs.even_imag ||
2675             !asd->params.css_param.dvs2_coeff->hor_coefs.odd_real ||
2676             !asd->params.css_param.dvs2_coeff->hor_coefs.odd_imag ||
2677             !asd->params.css_param.dvs2_coeff->hor_coefs.even_real ||
2678             !asd->params.css_param.dvs2_coeff->hor_coefs.even_imag ||
2679             !asd->params.css_param.dvs2_coeff->ver_coefs.odd_real ||
2680             !asd->params.css_param.dvs2_coeff->ver_coefs.odd_imag ||
2681             !asd->params.css_param.dvs2_coeff->ver_coefs.even_real ||
2682             !asd->params.css_param.dvs2_coeff->ver_coefs.even_imag)
2683                 return -EINVAL;
2684
2685         if (copy_from_user(asd->params.css_param.dvs2_coeff->hor_coefs.odd_real,
2686                            coefs->hor_coefs.odd_real, asd->params.dvs_hor_coef_bytes))
2687                 return -EFAULT;
2688         if (copy_from_user(asd->params.css_param.dvs2_coeff->hor_coefs.odd_imag,
2689                            coefs->hor_coefs.odd_imag, asd->params.dvs_hor_coef_bytes))
2690                 return -EFAULT;
2691         if (copy_from_user(asd->params.css_param.dvs2_coeff->hor_coefs.even_real,
2692                            coefs->hor_coefs.even_real, asd->params.dvs_hor_coef_bytes))
2693                 return -EFAULT;
2694         if (copy_from_user(asd->params.css_param.dvs2_coeff->hor_coefs.even_imag,
2695                            coefs->hor_coefs.even_imag, asd->params.dvs_hor_coef_bytes))
2696                 return -EFAULT;
2697
2698         if (copy_from_user(asd->params.css_param.dvs2_coeff->ver_coefs.odd_real,
2699                            coefs->ver_coefs.odd_real, asd->params.dvs_ver_coef_bytes))
2700                 return -EFAULT;
2701         if (copy_from_user(asd->params.css_param.dvs2_coeff->ver_coefs.odd_imag,
2702                            coefs->ver_coefs.odd_imag, asd->params.dvs_ver_coef_bytes))
2703                 return -EFAULT;
2704         if (copy_from_user(asd->params.css_param.dvs2_coeff->ver_coefs.even_real,
2705                            coefs->ver_coefs.even_real, asd->params.dvs_ver_coef_bytes))
2706                 return -EFAULT;
2707         if (copy_from_user(asd->params.css_param.dvs2_coeff->ver_coefs.even_imag,
2708                            coefs->ver_coefs.even_imag, asd->params.dvs_ver_coef_bytes))
2709                 return -EFAULT;
2710
2711         asd->params.css_param.update_flag.dvs2_coefs =
2712                 (struct atomisp_dis_coefficients *)
2713                 asd->params.css_param.dvs2_coeff;
2714         /* FIXME! */
2715         /*      asd->params.dis_proj_data_valid = false; */
2716         asd->params.css_update_params_needed = true;
2717
2718         return 0;
2719 }
2720
2721 void atomisp_css_set_zoom_factor(struct atomisp_sub_device *asd,
2722                                  unsigned int zoom)
2723 {
2724         struct atomisp_device *isp = asd->isp;
2725
2726         if (zoom == asd->params.css_param.dz_config.dx &&
2727             zoom == asd->params.css_param.dz_config.dy) {
2728                 dev_dbg(isp->dev, "same zoom scale. skipped.\n");
2729                 return;
2730         }
2731
2732         memset(&asd->params.css_param.dz_config, 0,
2733                sizeof(struct ia_css_dz_config));
2734         asd->params.css_param.dz_config.dx = zoom;
2735         asd->params.css_param.dz_config.dy = zoom;
2736
2737         asd->params.css_param.update_flag.dz_config =
2738             (struct atomisp_dz_config *)&asd->params.css_param.dz_config;
2739         asd->params.css_update_params_needed = true;
2740 }
2741
2742 void atomisp_css_set_formats_config(struct atomisp_sub_device *asd,
2743                                     struct ia_css_formats_config *formats_config)
2744 {
2745         asd->params.config.formats_config = formats_config;
2746 }
2747
2748 int atomisp_css_get_wb_config(struct atomisp_sub_device *asd,
2749                               struct atomisp_wb_config *config)
2750 {
2751         struct ia_css_wb_config wb_config;
2752         struct ia_css_isp_config isp_config;
2753         struct atomisp_device *isp = asd->isp;
2754
2755         if (!asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream) {
2756                 dev_err(isp->dev, "%s called after streamoff, skipping.\n",
2757                         __func__);
2758                 return -EINVAL;
2759         }
2760         memset(&wb_config, 0, sizeof(struct ia_css_wb_config));
2761         memset(&isp_config, 0, sizeof(struct ia_css_isp_config));
2762         isp_config.wb_config = &wb_config;
2763         ia_css_stream_get_isp_config(
2764             asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream,
2765             &isp_config);
2766         memcpy(config, &wb_config, sizeof(*config));
2767
2768         return 0;
2769 }
2770
2771 int atomisp_css_get_ob_config(struct atomisp_sub_device *asd,
2772                               struct atomisp_ob_config *config)
2773 {
2774         struct ia_css_ob_config ob_config;
2775         struct ia_css_isp_config isp_config;
2776         struct atomisp_device *isp = asd->isp;
2777
2778         if (!asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream) {
2779                 dev_err(isp->dev, "%s called after streamoff, skipping.\n",
2780                         __func__);
2781                 return -EINVAL;
2782         }
2783         memset(&ob_config, 0, sizeof(struct ia_css_ob_config));
2784         memset(&isp_config, 0, sizeof(struct ia_css_isp_config));
2785         isp_config.ob_config = &ob_config;
2786         ia_css_stream_get_isp_config(
2787             asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream,
2788             &isp_config);
2789         memcpy(config, &ob_config, sizeof(*config));
2790
2791         return 0;
2792 }
2793
2794 int atomisp_css_get_dp_config(struct atomisp_sub_device *asd,
2795                               struct atomisp_dp_config *config)
2796 {
2797         struct ia_css_dp_config dp_config;
2798         struct ia_css_isp_config isp_config;
2799         struct atomisp_device *isp = asd->isp;
2800
2801         if (!asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream) {
2802                 dev_err(isp->dev, "%s called after streamoff, skipping.\n",
2803                         __func__);
2804                 return -EINVAL;
2805         }
2806         memset(&dp_config, 0, sizeof(struct ia_css_dp_config));
2807         memset(&isp_config, 0, sizeof(struct ia_css_isp_config));
2808         isp_config.dp_config = &dp_config;
2809         ia_css_stream_get_isp_config(
2810             asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream,
2811             &isp_config);
2812         memcpy(config, &dp_config, sizeof(*config));
2813
2814         return 0;
2815 }
2816
2817 int atomisp_css_get_de_config(struct atomisp_sub_device *asd,
2818                               struct atomisp_de_config *config)
2819 {
2820         struct ia_css_de_config de_config;
2821         struct ia_css_isp_config isp_config;
2822         struct atomisp_device *isp = asd->isp;
2823
2824         if (!asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream) {
2825                 dev_err(isp->dev, "%s called after streamoff, skipping.\n",
2826                         __func__);
2827                 return -EINVAL;
2828         }
2829         memset(&de_config, 0, sizeof(struct ia_css_de_config));
2830         memset(&isp_config, 0, sizeof(struct ia_css_isp_config));
2831         isp_config.de_config = &de_config;
2832         ia_css_stream_get_isp_config(
2833             asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream,
2834             &isp_config);
2835         memcpy(config, &de_config, sizeof(*config));
2836
2837         return 0;
2838 }
2839
2840 int atomisp_css_get_nr_config(struct atomisp_sub_device *asd,
2841                               struct atomisp_nr_config *config)
2842 {
2843         struct ia_css_nr_config nr_config;
2844         struct ia_css_isp_config isp_config;
2845         struct atomisp_device *isp = asd->isp;
2846
2847         if (!asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream) {
2848                 dev_err(isp->dev, "%s called after streamoff, skipping.\n",
2849                         __func__);
2850                 return -EINVAL;
2851         }
2852         memset(&nr_config, 0, sizeof(struct ia_css_nr_config));
2853         memset(&isp_config, 0, sizeof(struct ia_css_isp_config));
2854
2855         isp_config.nr_config = &nr_config;
2856         ia_css_stream_get_isp_config(
2857             asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream,
2858             &isp_config);
2859         memcpy(config, &nr_config, sizeof(*config));
2860
2861         return 0;
2862 }
2863
2864 int atomisp_css_get_ee_config(struct atomisp_sub_device *asd,
2865                               struct atomisp_ee_config *config)
2866 {
2867         struct ia_css_ee_config ee_config;
2868         struct ia_css_isp_config isp_config;
2869         struct atomisp_device *isp = asd->isp;
2870
2871         if (!asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream) {
2872                 dev_err(isp->dev, "%s called after streamoff, skipping.\n",
2873                         __func__);
2874                 return -EINVAL;
2875         }
2876         memset(&ee_config, 0, sizeof(struct ia_css_ee_config));
2877         memset(&isp_config, 0, sizeof(struct ia_css_isp_config));
2878         isp_config.ee_config = &ee_config;
2879         ia_css_stream_get_isp_config(
2880             asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream,
2881             &isp_config);
2882         memcpy(config, &ee_config, sizeof(*config));
2883
2884         return 0;
2885 }
2886
2887 int atomisp_css_get_tnr_config(struct atomisp_sub_device *asd,
2888                                struct atomisp_tnr_config *config)
2889 {
2890         struct ia_css_tnr_config tnr_config;
2891         struct ia_css_isp_config isp_config;
2892         struct atomisp_device *isp = asd->isp;
2893
2894         if (!asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream) {
2895                 dev_err(isp->dev, "%s called after streamoff, skipping.\n",
2896                         __func__);
2897                 return -EINVAL;
2898         }
2899         memset(&tnr_config, 0, sizeof(struct ia_css_tnr_config));
2900         memset(&isp_config, 0, sizeof(struct ia_css_isp_config));
2901         isp_config.tnr_config = &tnr_config;
2902         ia_css_stream_get_isp_config(
2903             asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream,
2904             &isp_config);
2905         memcpy(config, &tnr_config, sizeof(*config));
2906
2907         return 0;
2908 }
2909
2910 int atomisp_css_get_ctc_table(struct atomisp_sub_device *asd,
2911                               struct atomisp_ctc_table *config)
2912 {
2913         struct ia_css_ctc_table *tab;
2914         struct ia_css_isp_config isp_config;
2915         struct atomisp_device *isp = asd->isp;
2916
2917         if (!asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream) {
2918                 dev_err(isp->dev, "%s called after streamoff, skipping.\n",
2919                         __func__);
2920                 return -EINVAL;
2921         }
2922
2923         tab = vzalloc(sizeof(struct ia_css_ctc_table));
2924         if (!tab)
2925                 return -ENOMEM;
2926
2927         memset(&isp_config, 0, sizeof(struct ia_css_isp_config));
2928         isp_config.ctc_table = tab;
2929         ia_css_stream_get_isp_config(
2930             asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream,
2931             &isp_config);
2932         memcpy(config, tab, sizeof(*tab));
2933         vfree(tab);
2934
2935         return 0;
2936 }
2937
2938 int atomisp_css_get_gamma_table(struct atomisp_sub_device *asd,
2939                                 struct atomisp_gamma_table *config)
2940 {
2941         struct ia_css_gamma_table *tab;
2942         struct ia_css_isp_config isp_config;
2943         struct atomisp_device *isp = asd->isp;
2944
2945         if (!asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream) {
2946                 dev_err(isp->dev, "%s called after streamoff, skipping.\n",
2947                         __func__);
2948                 return -EINVAL;
2949         }
2950
2951         tab = vzalloc(sizeof(struct ia_css_gamma_table));
2952         if (!tab)
2953                 return -ENOMEM;
2954
2955         memset(&isp_config, 0, sizeof(struct ia_css_isp_config));
2956         isp_config.gamma_table = tab;
2957         ia_css_stream_get_isp_config(
2958             asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream,
2959             &isp_config);
2960         memcpy(config, tab, sizeof(*tab));
2961         vfree(tab);
2962
2963         return 0;
2964 }
2965
2966 int atomisp_css_get_gc_config(struct atomisp_sub_device *asd,
2967                               struct atomisp_gc_config *config)
2968 {
2969         struct ia_css_gc_config gc_config;
2970         struct ia_css_isp_config isp_config;
2971         struct atomisp_device *isp = asd->isp;
2972
2973         if (!asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream) {
2974                 dev_err(isp->dev, "%s called after streamoff, skipping.\n",
2975                         __func__);
2976                 return -EINVAL;
2977         }
2978         memset(&gc_config, 0, sizeof(struct ia_css_gc_config));
2979         memset(&isp_config, 0, sizeof(struct ia_css_isp_config));
2980         isp_config.gc_config = &gc_config;
2981         ia_css_stream_get_isp_config(
2982             asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream,
2983             &isp_config);
2984         /* Get gamma correction params from current setup */
2985         memcpy(config, &gc_config, sizeof(*config));
2986
2987         return 0;
2988 }
2989
2990 int atomisp_css_get_3a_config(struct atomisp_sub_device *asd,
2991                               struct atomisp_3a_config *config)
2992 {
2993         struct ia_css_3a_config s3a_config;
2994         struct ia_css_isp_config isp_config;
2995         struct atomisp_device *isp = asd->isp;
2996
2997         if (!asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream) {
2998                 dev_err(isp->dev, "%s called after streamoff, skipping.\n",
2999                         __func__);
3000                 return -EINVAL;
3001         }
3002         memset(&s3a_config, 0, sizeof(struct ia_css_3a_config));
3003         memset(&isp_config, 0, sizeof(struct ia_css_isp_config));
3004         isp_config.s3a_config = &s3a_config;
3005         ia_css_stream_get_isp_config(
3006             asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream,
3007             &isp_config);
3008         /* Get white balance from current setup */
3009         memcpy(config, &s3a_config, sizeof(*config));
3010
3011         return 0;
3012 }
3013
3014 int atomisp_css_get_formats_config(struct atomisp_sub_device *asd,
3015                                    struct atomisp_formats_config *config)
3016 {
3017         struct ia_css_formats_config formats_config;
3018         struct ia_css_isp_config isp_config;
3019         struct atomisp_device *isp = asd->isp;
3020
3021         if (!asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream) {
3022                 dev_err(isp->dev, "%s called after streamoff, skipping.\n",
3023                         __func__);
3024                 return -EINVAL;
3025         }
3026         memset(&formats_config, 0, sizeof(formats_config));
3027         memset(&isp_config, 0, sizeof(isp_config));
3028         isp_config.formats_config = &formats_config;
3029         ia_css_stream_get_isp_config(
3030             asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream,
3031             &isp_config);
3032         /* Get narrow gamma from current setup */
3033         memcpy(config, &formats_config, sizeof(*config));
3034
3035         return 0;
3036 }
3037
3038 int atomisp_css_get_zoom_factor(struct atomisp_sub_device *asd,
3039                                 unsigned int *zoom)
3040 {
3041         struct ia_css_dz_config dz_config;  /** Digital Zoom */
3042         struct ia_css_isp_config isp_config;
3043         struct atomisp_device *isp = asd->isp;
3044
3045         if (!asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream) {
3046                 dev_err(isp->dev, "%s called after streamoff, skipping.\n",
3047                         __func__);
3048                 return -EINVAL;
3049         }
3050         memset(&dz_config, 0, sizeof(struct ia_css_dz_config));
3051         memset(&isp_config, 0, sizeof(struct ia_css_isp_config));
3052         isp_config.dz_config = &dz_config;
3053         ia_css_stream_get_isp_config(
3054             asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream,
3055             &isp_config);
3056         *zoom = dz_config.dx;
3057
3058         return 0;
3059 }
3060
3061 /*
3062  * Function to set/get image stablization statistics
3063  */
3064 int atomisp_css_get_dis_stat(struct atomisp_sub_device *asd,
3065                              struct atomisp_dis_statistics *stats)
3066 {
3067         struct atomisp_device *isp = asd->isp;
3068         struct atomisp_dis_buf *dis_buf;
3069         unsigned long flags;
3070
3071         lockdep_assert_held(&isp->mutex);
3072
3073         if (!asd->params.dvs_stat->hor_prod.odd_real ||
3074             !asd->params.dvs_stat->hor_prod.odd_imag ||
3075             !asd->params.dvs_stat->hor_prod.even_real ||
3076             !asd->params.dvs_stat->hor_prod.even_imag ||
3077             !asd->params.dvs_stat->ver_prod.odd_real ||
3078             !asd->params.dvs_stat->ver_prod.odd_imag ||
3079             !asd->params.dvs_stat->ver_prod.even_real ||
3080             !asd->params.dvs_stat->ver_prod.even_imag)
3081                 return -EINVAL;
3082
3083         /* isp needs to be streaming to get DIS statistics */
3084         if (!asd->streaming)
3085                 return -EINVAL;
3086
3087         if (atomisp_compare_dvs_grid(asd, &stats->dvs2_stat.grid_info) != 0)
3088                 /* If the grid info in the argument differs from the current
3089                    grid info, we tell the caller to reset the grid size and
3090                    try again. */
3091                 return -EAGAIN;
3092
3093         spin_lock_irqsave(&asd->dis_stats_lock, flags);
3094         if (!asd->params.dis_proj_data_valid || list_empty(&asd->dis_stats)) {
3095                 spin_unlock_irqrestore(&asd->dis_stats_lock, flags);
3096                 dev_err(isp->dev, "dis statistics is not valid.\n");
3097                 return -EAGAIN;
3098         }
3099
3100         dis_buf = list_entry(asd->dis_stats.next,
3101                              struct atomisp_dis_buf, list);
3102         list_del_init(&dis_buf->list);
3103         spin_unlock_irqrestore(&asd->dis_stats_lock, flags);
3104
3105         if (dis_buf->dvs_map)
3106                 ia_css_translate_dvs2_statistics(
3107                     asd->params.dvs_stat, dis_buf->dvs_map);
3108         else
3109                 ia_css_get_dvs2_statistics(asd->params.dvs_stat,
3110                                            dis_buf->dis_data);
3111         stats->exp_id = dis_buf->dis_data->exp_id;
3112
3113         spin_lock_irqsave(&asd->dis_stats_lock, flags);
3114         list_add_tail(&dis_buf->list, &asd->dis_stats);
3115         spin_unlock_irqrestore(&asd->dis_stats_lock, flags);
3116
3117         if (copy_to_user(stats->dvs2_stat.ver_prod.odd_real,
3118                          asd->params.dvs_stat->ver_prod.odd_real,
3119                          asd->params.dvs_ver_proj_bytes))
3120                 return -EFAULT;
3121         if (copy_to_user(stats->dvs2_stat.ver_prod.odd_imag,
3122                          asd->params.dvs_stat->ver_prod.odd_imag,
3123                          asd->params.dvs_ver_proj_bytes))
3124                 return -EFAULT;
3125         if (copy_to_user(stats->dvs2_stat.ver_prod.even_real,
3126                          asd->params.dvs_stat->ver_prod.even_real,
3127                          asd->params.dvs_ver_proj_bytes))
3128                 return -EFAULT;
3129         if (copy_to_user(stats->dvs2_stat.ver_prod.even_imag,
3130                          asd->params.dvs_stat->ver_prod.even_imag,
3131                          asd->params.dvs_ver_proj_bytes))
3132                 return -EFAULT;
3133         if (copy_to_user(stats->dvs2_stat.hor_prod.odd_real,
3134                          asd->params.dvs_stat->hor_prod.odd_real,
3135                          asd->params.dvs_hor_proj_bytes))
3136                 return -EFAULT;
3137         if (copy_to_user(stats->dvs2_stat.hor_prod.odd_imag,
3138                          asd->params.dvs_stat->hor_prod.odd_imag,
3139                          asd->params.dvs_hor_proj_bytes))
3140                 return -EFAULT;
3141         if (copy_to_user(stats->dvs2_stat.hor_prod.even_real,
3142                          asd->params.dvs_stat->hor_prod.even_real,
3143                          asd->params.dvs_hor_proj_bytes))
3144                 return -EFAULT;
3145         if (copy_to_user(stats->dvs2_stat.hor_prod.even_imag,
3146                          asd->params.dvs_stat->hor_prod.even_imag,
3147                          asd->params.dvs_hor_proj_bytes))
3148                 return -EFAULT;
3149
3150         return 0;
3151 }
3152
3153 struct ia_css_shading_table *atomisp_css_shading_table_alloc(
3154     unsigned int width, unsigned int height)
3155 {
3156         return ia_css_shading_table_alloc(width, height);
3157 }
3158
3159 void atomisp_css_set_shading_table(struct atomisp_sub_device *asd,
3160                                    struct ia_css_shading_table *table)
3161 {
3162         asd->params.config.shading_table = table;
3163 }
3164
3165 void atomisp_css_shading_table_free(struct ia_css_shading_table *table)
3166 {
3167         ia_css_shading_table_free(table);
3168 }
3169
3170 struct ia_css_morph_table *atomisp_css_morph_table_allocate(
3171     unsigned int width, unsigned int height)
3172 {
3173         return ia_css_morph_table_allocate(width, height);
3174 }
3175
3176 void atomisp_css_set_morph_table(struct atomisp_sub_device *asd,
3177                                  struct ia_css_morph_table *table)
3178 {
3179         asd->params.config.morph_table = table;
3180 }
3181
3182 void atomisp_css_get_morph_table(struct atomisp_sub_device *asd,
3183                                  struct ia_css_morph_table *table)
3184 {
3185         struct ia_css_isp_config isp_config;
3186         struct atomisp_device *isp = asd->isp;
3187
3188         if (!asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream) {
3189                 dev_err(isp->dev,
3190                         "%s called after streamoff, skipping.\n", __func__);
3191                 return;
3192         }
3193         memset(table, 0, sizeof(struct ia_css_morph_table));
3194         memset(&isp_config, 0, sizeof(struct ia_css_isp_config));
3195         isp_config.morph_table = table;
3196         ia_css_stream_get_isp_config(
3197             asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream,
3198             &isp_config);
3199 }
3200
3201 void atomisp_css_morph_table_free(struct ia_css_morph_table *table)
3202 {
3203         ia_css_morph_table_free(table);
3204 }
3205
3206 static bool atomisp_css_isr_get_stream_id(struct ia_css_pipe *css_pipe,
3207                                           struct atomisp_device *isp,
3208                                           enum atomisp_input_stream_id *stream_id)
3209 {
3210         struct atomisp_stream_env *stream_env;
3211         int i, j;
3212
3213         if (!isp->asd.streaming)
3214                 return false;
3215
3216         for (i = 0; i < ATOMISP_INPUT_STREAM_NUM; i++) {
3217                 stream_env = &isp->asd.stream_env[i];
3218                 for (j = 0; j < IA_CSS_PIPE_ID_NUM; j++) {
3219                         if (stream_env->pipes[j] && stream_env->pipes[j] == css_pipe) {
3220                                 *stream_id = i;
3221                                 return true;
3222                         }
3223                 }
3224         }
3225
3226         return false;
3227 }
3228
3229 int atomisp_css_isr_thread(struct atomisp_device *isp)
3230 {
3231         enum atomisp_input_stream_id stream_id = 0;
3232         struct atomisp_css_event current_event;
3233
3234         lockdep_assert_held(&isp->mutex);
3235
3236         while (!ia_css_dequeue_psys_event(&current_event.event)) {
3237                 if (current_event.event.type ==
3238                     IA_CSS_EVENT_TYPE_FW_ASSERT) {
3239                         /*
3240                          * Received FW assertion signal,
3241                          * trigger WDT to recover
3242                          */
3243                         dev_err(isp->dev,
3244                                 "%s: ISP reports FW_ASSERT event! fw_assert_module_id %d fw_assert_line_no %d\n",
3245                                 __func__,
3246                                 current_event.event.fw_assert_module_id,
3247                                 current_event.event.fw_assert_line_no);
3248
3249                         queue_work(system_long_wq, &isp->assert_recovery_work);
3250                         return -EINVAL;
3251                 } else if (current_event.event.type == IA_CSS_EVENT_TYPE_FW_WARNING) {
3252                         dev_warn(isp->dev, "%s: ISP reports warning, code is %d, exp_id %d\n",
3253                                  __func__, current_event.event.fw_warning,
3254                                  current_event.event.exp_id);
3255                         continue;
3256                 }
3257
3258                 if (!atomisp_css_isr_get_stream_id(current_event.event.pipe, isp, &stream_id)) {
3259                         if (current_event.event.type == IA_CSS_EVENT_TYPE_TIMER)
3260                                 dev_dbg(isp->dev,
3261                                         "event: Timer event.");
3262                         else
3263                                 dev_warn(isp->dev, "%s:no subdev.event:%d",
3264                                          __func__,
3265                                          current_event.event.type);
3266                         continue;
3267                 }
3268
3269                 atomisp_css_temp_pipe_to_pipe_id(&isp->asd, &current_event);
3270                 switch (current_event.event.type) {
3271                 case IA_CSS_EVENT_TYPE_OUTPUT_FRAME_DONE:
3272                         dev_dbg(isp->dev, "event: Output frame done");
3273                         atomisp_buf_done(&isp->asd, 0, IA_CSS_BUFFER_TYPE_OUTPUT_FRAME,
3274                                          current_event.pipe, true, stream_id);
3275                         break;
3276                 case IA_CSS_EVENT_TYPE_SECOND_OUTPUT_FRAME_DONE:
3277                         dev_dbg(isp->dev, "event: Second output frame done");
3278                         atomisp_buf_done(&isp->asd, 0, IA_CSS_BUFFER_TYPE_SEC_OUTPUT_FRAME,
3279                                          current_event.pipe, true, stream_id);
3280                         break;
3281                 case IA_CSS_EVENT_TYPE_3A_STATISTICS_DONE:
3282                         dev_dbg(isp->dev, "event: 3A stats frame done");
3283                         atomisp_buf_done(&isp->asd, 0,
3284                                          IA_CSS_BUFFER_TYPE_3A_STATISTICS,
3285                                          current_event.pipe,
3286                                          false, stream_id);
3287                         break;
3288                 case IA_CSS_EVENT_TYPE_METADATA_DONE:
3289                         dev_dbg(isp->dev, "event: metadata frame done");
3290                         atomisp_buf_done(&isp->asd, 0,
3291                                          IA_CSS_BUFFER_TYPE_METADATA,
3292                                          current_event.pipe,
3293                                          false, stream_id);
3294                         break;
3295                 case IA_CSS_EVENT_TYPE_VF_OUTPUT_FRAME_DONE:
3296                         dev_dbg(isp->dev, "event: VF output frame done");
3297                         atomisp_buf_done(&isp->asd, 0,
3298                                          IA_CSS_BUFFER_TYPE_VF_OUTPUT_FRAME,
3299                                          current_event.pipe, true, stream_id);
3300                         break;
3301                 case IA_CSS_EVENT_TYPE_SECOND_VF_OUTPUT_FRAME_DONE:
3302                         dev_dbg(isp->dev, "event: second VF output frame done");
3303                         atomisp_buf_done(&isp->asd, 0,
3304                                          IA_CSS_BUFFER_TYPE_SEC_VF_OUTPUT_FRAME,
3305                                          current_event.pipe, true, stream_id);
3306                         break;
3307                 case IA_CSS_EVENT_TYPE_DIS_STATISTICS_DONE:
3308                         dev_dbg(isp->dev, "event: dis stats frame done");
3309                         atomisp_buf_done(&isp->asd, 0,
3310                                          IA_CSS_BUFFER_TYPE_DIS_STATISTICS,
3311                                          current_event.pipe,
3312                                          false, stream_id);
3313                         break;
3314                 case IA_CSS_EVENT_TYPE_PIPELINE_DONE:
3315                         dev_dbg(isp->dev, "event: pipeline done");
3316                         break;
3317                 case IA_CSS_EVENT_TYPE_ACC_STAGE_COMPLETE:
3318                         dev_warn(isp->dev, "unexpected event: acc stage done");
3319                         break;
3320                 default:
3321                         dev_dbg(isp->dev, "unhandled css stored event: 0x%x\n",
3322                                 current_event.event.type);
3323                         break;
3324                 }
3325         }
3326
3327         return 0;
3328 }
3329
3330 bool atomisp_css_valid_sof(struct atomisp_device *isp)
3331 {
3332         unsigned int i;
3333
3334         /* Loop for each css vc stream */
3335         for (i = 0; i < ATOMISP_INPUT_STREAM_NUM; i++) {
3336                 if (!isp->asd.stream_env[i].stream)
3337                         continue;
3338
3339                 dev_dbg(isp->dev, "stream #%d: mode: %d\n",
3340                         i, isp->asd.stream_env[i].stream_config.mode);
3341                 if (isp->asd.stream_env[i].stream_config.mode == IA_CSS_INPUT_MODE_BUFFERED_SENSOR)
3342                         return false;
3343         }
3344
3345         return true;
3346 }
3347
3348 int atomisp_css_debug_dump_isp_binary(void)
3349 {
3350         ia_css_debug_dump_isp_binary();
3351         return 0;
3352 }
3353
3354 int atomisp_css_dump_sp_raw_copy_linecount(bool reduced)
3355 {
3356         sh_css_dump_sp_raw_copy_linecount(reduced);
3357         return 0;
3358 }
3359
3360 static const char * const fw_type_name[] = {
3361         [ia_css_sp_firmware]            = "SP",
3362         [ia_css_isp_firmware]           = "ISP",
3363         [ia_css_bootloader_firmware]    = "BootLoader",
3364         [ia_css_acc_firmware]           = "accel",
3365 };
3366
3367 static const char * const fw_acc_type_name[] = {
3368         [IA_CSS_ACC_NONE] =             "Normal",
3369         [IA_CSS_ACC_OUTPUT] =           "Accel stage on output",
3370         [IA_CSS_ACC_VIEWFINDER] =       "Accel stage on viewfinder",
3371         [IA_CSS_ACC_STANDALONE] =       "Stand-alone acceleration",
3372 };
3373
3374 int atomisp_css_dump_blob_infor(struct atomisp_device *isp)
3375 {
3376         struct ia_css_blob_descr *bd = sh_css_blob_info;
3377         unsigned int i, nm = sh_css_num_binaries;
3378
3379         if (nm == 0)
3380                 return -EPERM;
3381         if (!bd)
3382                 return -EPERM;
3383
3384         /*
3385          * The sh_css_load_firmware function discard the initial
3386          * "SPS" binaries
3387          */
3388         for (i = 0; i < sh_css_num_binaries - NUM_OF_SPS; i++) {
3389                 switch (bd[i].header.type) {
3390                 case ia_css_isp_firmware:
3391                         dev_dbg(isp->dev, "Num%2d type %s (%s), binary id is %2d, name is %s\n",
3392                                 i + NUM_OF_SPS,
3393                                 fw_type_name[bd[i].header.type],
3394                                 fw_acc_type_name[bd[i].header.info.isp.type],
3395                                 bd[i].header.info.isp.sp.id,
3396                                 bd[i].name);
3397                         break;
3398                 default:
3399                         dev_dbg(isp->dev, "Num%2d type %s, name is %s\n",
3400                                 i + NUM_OF_SPS, fw_type_name[bd[i].header.type],
3401                                 bd[i].name);
3402                 }
3403         }
3404
3405         return 0;
3406 }
3407
3408 void atomisp_css_set_isp_config_id(struct atomisp_sub_device *asd,
3409                                    uint32_t isp_config_id)
3410 {
3411         asd->params.config.isp_config_id = isp_config_id;
3412 }
3413
3414 void atomisp_css_set_isp_config_applied_frame(struct atomisp_sub_device *asd,
3415         struct ia_css_frame *output_frame)
3416 {
3417         asd->params.config.output_frame = output_frame;
3418 }
3419
3420 int atomisp_get_css_dbgfunc(void)
3421 {
3422         return dbg_func;
3423 }
3424
3425 int atomisp_set_css_dbgfunc(struct atomisp_device *isp, int opt)
3426 {
3427         int ret;
3428
3429         ret = __set_css_print_env(isp, opt);
3430         if (ret == 0)
3431                 dbg_func = opt;
3432
3433         return ret;
3434 }
3435
3436 void atomisp_en_dz_capt_pipe(struct atomisp_sub_device *asd, bool enable)
3437 {
3438         ia_css_en_dz_capt_pipe(
3439             asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream,
3440             enable);
3441 }
3442
3443 struct ia_css_dvs_grid_info *atomisp_css_get_dvs_grid_info(
3444     struct ia_css_grid_info *grid_info)
3445 {
3446         if (!grid_info)
3447                 return NULL;
3448
3449 #ifdef IA_CSS_DVS_STAT_GRID_INFO_SUPPORTED
3450         return &grid_info->dvs_grid.dvs_grid_info;
3451 #else
3452         return &grid_info->dvs_grid;
3453 #endif
3454 }