Merge tag 'for-6.4/block-2023-05-06' of git://git.kernel.dk/linux
[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_CONTINUOUS_CAPTURE:
654                 if (pipe_id == IA_CSS_PIPE_ID_CAPTURE ||
655                     pipe_id == IA_CSS_PIPE_ID_PREVIEW)
656                         return true;
657
658                 return false;
659         case ATOMISP_RUN_MODE_VIDEO:
660                 if (pipe_id == IA_CSS_PIPE_ID_VIDEO || pipe_id == IA_CSS_PIPE_ID_YUVPP)
661                         return true;
662
663                 return false;
664         case ATOMISP_RUN_MODE_SDV:
665                 if (pipe_id == IA_CSS_PIPE_ID_CAPTURE ||
666                     pipe_id == IA_CSS_PIPE_ID_VIDEO)
667                         return true;
668
669                 return false;
670         }
671
672         return false;
673 }
674
675 static int __create_pipe(struct atomisp_sub_device *asd,
676                          struct atomisp_stream_env *stream_env,
677                          enum ia_css_pipe_id pipe_id)
678 {
679         struct atomisp_device *isp = asd->isp;
680         struct ia_css_pipe_extra_config extra_config;
681         int ret;
682
683         if (pipe_id >= IA_CSS_PIPE_ID_NUM)
684                 return -EINVAL;
685
686         if (!stream_env->pipe_configs[pipe_id].output_info[0].res.width)
687                 return 0;
688
689         if (!is_pipe_valid_to_current_run_mode(asd, pipe_id))
690                 return 0;
691
692         ia_css_pipe_extra_config_defaults(&extra_config);
693
694         __apply_additional_pipe_config(asd, stream_env, pipe_id);
695         if (!memcmp(&extra_config,
696                     &stream_env->pipe_extra_configs[pipe_id],
697                     sizeof(extra_config)))
698                 ret = ia_css_pipe_create(
699                           &stream_env->pipe_configs[pipe_id],
700                           &stream_env->pipes[pipe_id]);
701         else
702                 ret = ia_css_pipe_create_extra(
703                           &stream_env->pipe_configs[pipe_id],
704                           &stream_env->pipe_extra_configs[pipe_id],
705                           &stream_env->pipes[pipe_id]);
706         if (ret)
707                 dev_err(isp->dev, "create pipe[%d] error.\n", pipe_id);
708         return ret;
709 }
710
711 static int __create_pipes(struct atomisp_sub_device *asd)
712 {
713         int ret;
714         int i, j;
715
716         for (i = 0; i < ATOMISP_INPUT_STREAM_NUM; i++) {
717                 for (j = 0; j < IA_CSS_PIPE_ID_NUM; j++) {
718                         ret = __create_pipe(asd, &asd->stream_env[i], j);
719                         if (ret)
720                                 break;
721                 }
722                 if (j < IA_CSS_PIPE_ID_NUM)
723                         goto pipe_err;
724         }
725         return 0;
726 pipe_err:
727         for (; i >= 0; i--) {
728                 for (j--; j >= 0; j--) {
729                         if (asd->stream_env[i].pipes[j]) {
730                                 ia_css_pipe_destroy(asd->stream_env[i].pipes[j]);
731                                 asd->stream_env[i].pipes[j] = NULL;
732                         }
733                 }
734                 j = IA_CSS_PIPE_ID_NUM;
735         }
736         return -EINVAL;
737 }
738
739 int atomisp_create_pipes_stream(struct atomisp_sub_device *asd)
740 {
741         int ret;
742
743         ret = __create_pipes(asd);
744         if (ret) {
745                 dev_err(asd->isp->dev, "create pipe failed %d.\n", ret);
746                 return ret;
747         }
748
749         ret = __create_streams(asd);
750         if (ret) {
751                 dev_warn(asd->isp->dev, "create stream failed %d.\n", ret);
752                 __destroy_pipes(asd);
753                 return ret;
754         }
755
756         return 0;
757 }
758
759 int atomisp_css_update_stream(struct atomisp_sub_device *asd)
760 {
761         atomisp_destroy_pipes_stream_force(asd);
762         return atomisp_create_pipes_stream(asd);
763 }
764
765 int atomisp_css_init(struct atomisp_device *isp)
766 {
767         unsigned int mmu_base_addr;
768         int ret;
769         int err;
770
771         ret = hmm_get_mmu_base_addr(isp->dev, &mmu_base_addr);
772         if (ret)
773                 return ret;
774
775         /* Init ISP */
776         err = ia_css_init(isp->dev, &isp->css_env.isp_css_env, NULL,
777                           (uint32_t)mmu_base_addr, IA_CSS_IRQ_TYPE_PULSE);
778         if (err) {
779                 dev_err(isp->dev, "css init failed --- bad firmware?\n");
780                 return -EINVAL;
781         }
782         ia_css_enable_isys_event_queue(true);
783
784         isp->css_initialized = true;
785         dev_dbg(isp->dev, "sh_css_init success\n");
786
787         return 0;
788 }
789
790 static inline int __set_css_print_env(struct atomisp_device *isp, int opt)
791 {
792         int ret = 0;
793
794         if (opt == 0)
795                 isp->css_env.isp_css_env.print_env.debug_print = NULL;
796         else if (opt == 1)
797                 isp->css_env.isp_css_env.print_env.debug_print = atomisp_vprintk;
798         else
799                 ret = -EINVAL;
800
801         return ret;
802 }
803
804 int atomisp_css_load_firmware(struct atomisp_device *isp)
805 {
806         int err;
807
808         /* set css env */
809         isp->css_env.isp_css_fw.data = (void *)isp->firmware->data;
810         isp->css_env.isp_css_fw.bytes = isp->firmware->size;
811
812         isp->css_env.isp_css_env.hw_access_env.store_8 =
813             atomisp_css2_hw_store_8;
814         isp->css_env.isp_css_env.hw_access_env.store_16 =
815             atomisp_css2_hw_store_16;
816         isp->css_env.isp_css_env.hw_access_env.store_32 =
817             atomisp_css2_hw_store_32;
818
819         isp->css_env.isp_css_env.hw_access_env.load_8 = atomisp_css2_hw_load_8;
820         isp->css_env.isp_css_env.hw_access_env.load_16 =
821             atomisp_css2_hw_load_16;
822         isp->css_env.isp_css_env.hw_access_env.load_32 =
823             atomisp_css2_hw_load_32;
824
825         isp->css_env.isp_css_env.hw_access_env.load = atomisp_css2_hw_load;
826         isp->css_env.isp_css_env.hw_access_env.store = atomisp_css2_hw_store;
827
828         __set_css_print_env(isp, dbg_func);
829
830         isp->css_env.isp_css_env.print_env.error_print = atomisp_vprintk;
831
832         /* load isp fw into ISP memory */
833         err = ia_css_load_firmware(isp->dev, &isp->css_env.isp_css_env,
834                                    &isp->css_env.isp_css_fw);
835         if (err) {
836                 dev_err(isp->dev, "css load fw failed.\n");
837                 return -EINVAL;
838         }
839
840         return 0;
841 }
842
843 void atomisp_css_uninit(struct atomisp_device *isp)
844 {
845         isp->css_initialized = false;
846         ia_css_uninit();
847 }
848
849 int atomisp_css_irq_translate(struct atomisp_device *isp,
850                               unsigned int *infos)
851 {
852         int err;
853
854         err = ia_css_irq_translate(infos);
855         if (err) {
856                 dev_warn(isp->dev,
857                          "%s:failed to translate irq (err = %d,infos = %d)\n",
858                          __func__, err, *infos);
859                 return -EINVAL;
860         }
861
862         return 0;
863 }
864
865 void atomisp_css_rx_get_irq_info(enum mipi_port_id port,
866                                  unsigned int *infos)
867 {
868 #ifndef ISP2401
869         ia_css_isys_rx_get_irq_info(port, infos);
870 #else
871         *infos = 0;
872 #endif
873 }
874
875 void atomisp_css_rx_clear_irq_info(enum mipi_port_id port,
876                                    unsigned int infos)
877 {
878 #ifndef ISP2401
879         ia_css_isys_rx_clear_irq_info(port, infos);
880 #endif
881 }
882
883 int atomisp_css_irq_enable(struct atomisp_device *isp,
884                            enum ia_css_irq_info info, bool enable)
885 {
886         dev_dbg(isp->dev, "%s: css irq info 0x%08x: %s (%d).\n",
887                 __func__, info,
888                 enable ? "enable" : "disable", enable);
889         if (ia_css_irq_enable(info, enable)) {
890                 dev_warn(isp->dev, "%s:Invalid irq info: 0x%08x when %s.\n",
891                          __func__, info,
892                          enable ? "enabling" : "disabling");
893                 return -EINVAL;
894         }
895
896         return 0;
897 }
898
899 void atomisp_css_init_struct(struct atomisp_sub_device *asd)
900 {
901         int i, j;
902
903         for (i = 0; i < ATOMISP_INPUT_STREAM_NUM; i++) {
904                 asd->stream_env[i].stream = NULL;
905                 for (j = 0; j < IA_CSS_PIPE_MODE_NUM; j++) {
906                         asd->stream_env[i].pipes[j] = NULL;
907                         asd->stream_env[i].update_pipe[j] = false;
908                         ia_css_pipe_config_defaults(
909                             &asd->stream_env[i].pipe_configs[j]);
910                         ia_css_pipe_extra_config_defaults(
911                             &asd->stream_env[i].pipe_extra_configs[j]);
912                 }
913                 ia_css_stream_config_defaults(&asd->stream_env[i].stream_config);
914         }
915 }
916
917 int atomisp_q_video_buffer_to_css(struct atomisp_sub_device *asd,
918                                   struct ia_css_frame *frame,
919                                   enum atomisp_input_stream_id stream_id,
920                                   enum ia_css_buffer_type css_buf_type,
921                                   enum ia_css_pipe_id css_pipe_id)
922 {
923         struct atomisp_stream_env *stream_env = &asd->stream_env[stream_id];
924         struct ia_css_buffer css_buf = {0};
925         int err;
926
927         css_buf.type = css_buf_type;
928         css_buf.data.frame = frame;
929
930         err = ia_css_pipe_enqueue_buffer(
931                   stream_env->pipes[css_pipe_id], &css_buf);
932         if (err)
933                 return -EINVAL;
934
935         return 0;
936 }
937
938 int atomisp_q_metadata_buffer_to_css(struct atomisp_sub_device *asd,
939                                      struct atomisp_metadata_buf *metadata_buf,
940                                      enum atomisp_input_stream_id stream_id,
941                                      enum ia_css_pipe_id css_pipe_id)
942 {
943         struct atomisp_stream_env *stream_env = &asd->stream_env[stream_id];
944         struct ia_css_buffer buffer = {0};
945         struct atomisp_device *isp = asd->isp;
946
947         buffer.type = IA_CSS_BUFFER_TYPE_METADATA;
948         buffer.data.metadata = metadata_buf->metadata;
949         if (ia_css_pipe_enqueue_buffer(stream_env->pipes[css_pipe_id],
950                                        &buffer)) {
951                 dev_err(isp->dev, "failed to q meta data buffer\n");
952                 return -EINVAL;
953         }
954
955         return 0;
956 }
957
958 int atomisp_q_s3a_buffer_to_css(struct atomisp_sub_device *asd,
959                                 struct atomisp_s3a_buf *s3a_buf,
960                                 enum atomisp_input_stream_id stream_id,
961                                 enum ia_css_pipe_id css_pipe_id)
962 {
963         struct atomisp_stream_env *stream_env = &asd->stream_env[stream_id];
964         struct ia_css_buffer buffer = {0};
965         struct atomisp_device *isp = asd->isp;
966
967         buffer.type = IA_CSS_BUFFER_TYPE_3A_STATISTICS;
968         buffer.data.stats_3a = s3a_buf->s3a_data;
969         if (ia_css_pipe_enqueue_buffer(
970                 stream_env->pipes[css_pipe_id],
971                 &buffer)) {
972                 dev_dbg(isp->dev, "failed to q s3a stat buffer\n");
973                 return -EINVAL;
974         }
975
976         return 0;
977 }
978
979 int atomisp_q_dis_buffer_to_css(struct atomisp_sub_device *asd,
980                                 struct atomisp_dis_buf *dis_buf,
981                                 enum atomisp_input_stream_id stream_id,
982                                 enum ia_css_pipe_id css_pipe_id)
983 {
984         struct atomisp_stream_env *stream_env = &asd->stream_env[stream_id];
985         struct ia_css_buffer buffer = {0};
986         struct atomisp_device *isp = asd->isp;
987
988         buffer.type = IA_CSS_BUFFER_TYPE_DIS_STATISTICS;
989         buffer.data.stats_dvs = dis_buf->dis_data;
990         if (ia_css_pipe_enqueue_buffer(
991                 stream_env->pipes[css_pipe_id],
992                 &buffer)) {
993                 dev_dbg(isp->dev, "failed to q dvs stat buffer\n");
994                 return -EINVAL;
995         }
996
997         return 0;
998 }
999
1000 int atomisp_css_start(struct atomisp_sub_device *asd,
1001                       enum ia_css_pipe_id pipe_id, bool in_reset)
1002 {
1003         struct atomisp_device *isp = asd->isp;
1004         bool sp_is_started = false;
1005         int ret = 0, i = 0;
1006
1007         if (in_reset) {
1008                 ret = atomisp_css_update_stream(asd);
1009                 if (ret)
1010                         return ret;
1011
1012                 /* Invalidate caches. FIXME: should flush only necessary buffers */
1013                 wbinvd();
1014         }
1015
1016         /*
1017          * For dual steam case, it is possible that:
1018          * 1: for this stream, it is at the stage that:
1019          * - after set_fmt is called
1020          * - before stream on is called
1021          * 2: for the other stream, the stream off is called which css reset
1022          * has been done.
1023          *
1024          * Thus the stream created in set_fmt get destroyed and need to be
1025          * recreated in the next stream on.
1026          */
1027         if (!asd->stream_prepared) {
1028                 ret = atomisp_create_pipes_stream(asd);
1029                 if (ret)
1030                         return ret;
1031         }
1032         /*
1033          * SP can only be started one time
1034          * if atomisp_subdev_streaming_count() tell there already has some
1035          * subdev at streamming, then SP should already be started previously,
1036          * so need to skip start sp procedure
1037          */
1038         if (atomisp_streaming_count(isp)) {
1039                 dev_dbg(isp->dev, "skip start sp\n");
1040         } else {
1041                 if (!sh_css_hrt_system_is_idle())
1042                         dev_err(isp->dev, "CSS HW not idle before starting SP\n");
1043                 if (ia_css_start_sp()) {
1044                         dev_err(isp->dev, "start sp error.\n");
1045                         ret = -EINVAL;
1046                         goto start_err;
1047                 } else {
1048                         sp_is_started = true;
1049                 }
1050         }
1051
1052         for (i = 0; i < ATOMISP_INPUT_STREAM_NUM; i++) {
1053                 if (asd->stream_env[i].stream) {
1054                         if (ia_css_stream_start(asd->stream_env[i]
1055                                                 .stream) != 0) {
1056                                 dev_err(isp->dev, "stream[%d] start error.\n", i);
1057                                 ret = -EINVAL;
1058                                 goto start_err;
1059                         } else {
1060                                 asd->stream_env[i].stream_state = CSS_STREAM_STARTED;
1061                                 dev_dbg(isp->dev, "stream[%d] started.\n", i);
1062                         }
1063                 }
1064         }
1065
1066         return 0;
1067
1068 start_err:
1069         atomisp_destroy_pipes_stream_force(asd);
1070
1071         /* css 2.0 API limitation: ia_css_stop_sp() could be only called after
1072          * destroy all pipes
1073          */
1074         /*
1075          * SP can not be stop if other streams are in use
1076          */
1077         if ((atomisp_streaming_count(isp) == 0) && sp_is_started)
1078                 ia_css_stop_sp();
1079
1080         return ret;
1081 }
1082
1083 void atomisp_css_update_isp_params(struct atomisp_sub_device *asd)
1084 {
1085         /*
1086          * FIXME!
1087          * for ISP2401 new input system, this api is under development.
1088          * Calling it would cause kernel panic.
1089          *
1090          * VIED BZ: 1458
1091          *
1092          * Check if it is Cherry Trail and also new input system
1093          */
1094         if (asd->copy_mode) {
1095                 dev_warn(asd->isp->dev,
1096                          "%s: ia_css_stream_set_isp_config() not supported in copy mode!.\n",
1097                          __func__);
1098                 return;
1099         }
1100
1101         ia_css_stream_set_isp_config(
1102             asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream,
1103             &asd->params.config);
1104         memset(&asd->params.config, 0, sizeof(asd->params.config));
1105 }
1106
1107 void atomisp_css_update_isp_params_on_pipe(struct atomisp_sub_device *asd,
1108         struct ia_css_pipe *pipe)
1109 {
1110         int ret;
1111
1112         if (!pipe) {
1113                 atomisp_css_update_isp_params(asd);
1114                 return;
1115         }
1116
1117         dev_dbg(asd->isp->dev,
1118                 "%s: apply parameter for ia_css_frame %p with isp_config_id %d on pipe %p.\n",
1119                 __func__, asd->params.config.output_frame,
1120                 asd->params.config.isp_config_id, pipe);
1121
1122         ret = ia_css_stream_set_isp_config_on_pipe(
1123                   asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream,
1124                   &asd->params.config, pipe);
1125         if (ret)
1126                 dev_warn(asd->isp->dev, "%s: ia_css_stream_set_isp_config_on_pipe failed %d\n",
1127                          __func__, ret);
1128         memset(&asd->params.config, 0, sizeof(asd->params.config));
1129 }
1130
1131 int atomisp_css_queue_buffer(struct atomisp_sub_device *asd,
1132                              enum atomisp_input_stream_id stream_id,
1133                              enum ia_css_pipe_id pipe_id,
1134                              enum ia_css_buffer_type buf_type,
1135                              struct atomisp_css_buffer *isp_css_buffer)
1136 {
1137         if (ia_css_pipe_enqueue_buffer(
1138                 asd->stream_env[stream_id].pipes[pipe_id],
1139                 &isp_css_buffer->css_buffer)
1140             != 0)
1141                 return -EINVAL;
1142
1143         return 0;
1144 }
1145
1146 int atomisp_css_dequeue_buffer(struct atomisp_sub_device *asd,
1147                                enum atomisp_input_stream_id stream_id,
1148                                enum ia_css_pipe_id pipe_id,
1149                                enum ia_css_buffer_type buf_type,
1150                                struct atomisp_css_buffer *isp_css_buffer)
1151 {
1152         struct atomisp_device *isp = asd->isp;
1153         int err;
1154
1155         err = ia_css_pipe_dequeue_buffer(
1156                   asd->stream_env[stream_id].pipes[pipe_id],
1157                   &isp_css_buffer->css_buffer);
1158         if (err) {
1159                 dev_err(isp->dev,
1160                         "ia_css_pipe_dequeue_buffer failed: 0x%x\n", err);
1161                 return -EINVAL;
1162         }
1163
1164         return 0;
1165 }
1166
1167 int atomisp_css_allocate_stat_buffers(struct atomisp_sub_device   *asd,
1168                                       u16 stream_id,
1169                                       struct atomisp_s3a_buf      *s3a_buf,
1170                                       struct atomisp_dis_buf      *dis_buf,
1171                                       struct atomisp_metadata_buf *md_buf)
1172 {
1173         struct atomisp_device *isp = asd->isp;
1174         struct ia_css_dvs_grid_info *dvs_grid_info =
1175             atomisp_css_get_dvs_grid_info(&asd->params.curr_grid_info);
1176
1177         if (s3a_buf && asd->params.curr_grid_info.s3a_grid.enable) {
1178                 void *s3a_ptr;
1179
1180                 s3a_buf->s3a_data = ia_css_isp_3a_statistics_allocate(
1181                                         &asd->params.curr_grid_info.s3a_grid);
1182                 if (!s3a_buf->s3a_data) {
1183                         dev_err(isp->dev, "3a buf allocation failed.\n");
1184                         return -EINVAL;
1185                 }
1186
1187                 s3a_ptr = hmm_vmap(s3a_buf->s3a_data->data_ptr, true);
1188                 s3a_buf->s3a_map = ia_css_isp_3a_statistics_map_allocate(
1189                                        s3a_buf->s3a_data, s3a_ptr);
1190         }
1191
1192         if (dis_buf && dvs_grid_info && dvs_grid_info->enable) {
1193                 void *dvs_ptr;
1194
1195                 dis_buf->dis_data = ia_css_isp_dvs2_statistics_allocate(
1196                                         dvs_grid_info);
1197                 if (!dis_buf->dis_data) {
1198                         dev_err(isp->dev, "dvs buf allocation failed.\n");
1199                         if (s3a_buf)
1200                                 ia_css_isp_3a_statistics_free(s3a_buf->s3a_data);
1201                         return -EINVAL;
1202                 }
1203
1204                 dvs_ptr = hmm_vmap(dis_buf->dis_data->data_ptr, true);
1205                 dis_buf->dvs_map = ia_css_isp_dvs_statistics_map_allocate(
1206                                        dis_buf->dis_data, dvs_ptr);
1207         }
1208
1209         if (asd->stream_env[stream_id].stream_info.
1210             metadata_info.size && md_buf) {
1211                 md_buf->metadata = ia_css_metadata_allocate(
1212                                        &asd->stream_env[stream_id].stream_info.metadata_info);
1213                 if (!md_buf->metadata) {
1214                         if (s3a_buf)
1215                                 ia_css_isp_3a_statistics_free(s3a_buf->s3a_data);
1216                         if (dis_buf)
1217                                 ia_css_isp_dvs2_statistics_free(dis_buf->dis_data);
1218                         dev_err(isp->dev, "metadata buf allocation failed.\n");
1219                         return -EINVAL;
1220                 }
1221                 md_buf->md_vptr = hmm_vmap(md_buf->metadata->address, false);
1222         }
1223
1224         return 0;
1225 }
1226
1227 void atomisp_css_free_3a_buffer(struct atomisp_s3a_buf *s3a_buf)
1228 {
1229         if (s3a_buf->s3a_data)
1230                 hmm_vunmap(s3a_buf->s3a_data->data_ptr);
1231
1232         ia_css_isp_3a_statistics_map_free(s3a_buf->s3a_map);
1233         s3a_buf->s3a_map = NULL;
1234         ia_css_isp_3a_statistics_free(s3a_buf->s3a_data);
1235 }
1236
1237 void atomisp_css_free_dis_buffer(struct atomisp_dis_buf *dis_buf)
1238 {
1239         if (dis_buf->dis_data)
1240                 hmm_vunmap(dis_buf->dis_data->data_ptr);
1241
1242         ia_css_isp_dvs_statistics_map_free(dis_buf->dvs_map);
1243         dis_buf->dvs_map = NULL;
1244         ia_css_isp_dvs2_statistics_free(dis_buf->dis_data);
1245 }
1246
1247 void atomisp_css_free_metadata_buffer(struct atomisp_metadata_buf *metadata_buf)
1248 {
1249         if (metadata_buf->md_vptr) {
1250                 hmm_vunmap(metadata_buf->metadata->address);
1251                 metadata_buf->md_vptr = NULL;
1252         }
1253         ia_css_metadata_free(metadata_buf->metadata);
1254 }
1255
1256 void atomisp_css_free_stat_buffers(struct atomisp_sub_device *asd)
1257 {
1258         struct atomisp_s3a_buf *s3a_buf, *_s3a_buf;
1259         struct atomisp_dis_buf *dis_buf, *_dis_buf;
1260         struct atomisp_metadata_buf *md_buf, *_md_buf;
1261         struct ia_css_dvs_grid_info *dvs_grid_info =
1262             atomisp_css_get_dvs_grid_info(&asd->params.curr_grid_info);
1263         unsigned int i;
1264
1265         /* 3A statistics use vmalloc, DIS use kmalloc */
1266         if (dvs_grid_info && dvs_grid_info->enable) {
1267                 ia_css_dvs2_coefficients_free(asd->params.css_param.dvs2_coeff);
1268                 ia_css_dvs2_statistics_free(asd->params.dvs_stat);
1269                 asd->params.css_param.dvs2_coeff = NULL;
1270                 asd->params.dvs_stat = NULL;
1271                 asd->params.dvs_hor_proj_bytes = 0;
1272                 asd->params.dvs_ver_proj_bytes = 0;
1273                 asd->params.dvs_hor_coef_bytes = 0;
1274                 asd->params.dvs_ver_coef_bytes = 0;
1275                 asd->params.dis_proj_data_valid = false;
1276                 list_for_each_entry_safe(dis_buf, _dis_buf,
1277                                          &asd->dis_stats, list) {
1278                         atomisp_css_free_dis_buffer(dis_buf);
1279                         list_del(&dis_buf->list);
1280                         kfree(dis_buf);
1281                 }
1282                 list_for_each_entry_safe(dis_buf, _dis_buf,
1283                                          &asd->dis_stats_in_css, list) {
1284                         atomisp_css_free_dis_buffer(dis_buf);
1285                         list_del(&dis_buf->list);
1286                         kfree(dis_buf);
1287                 }
1288         }
1289         if (asd->params.curr_grid_info.s3a_grid.enable) {
1290                 ia_css_3a_statistics_free(asd->params.s3a_user_stat);
1291                 asd->params.s3a_user_stat = NULL;
1292                 asd->params.s3a_output_bytes = 0;
1293                 list_for_each_entry_safe(s3a_buf, _s3a_buf,
1294                                          &asd->s3a_stats, list) {
1295                         atomisp_css_free_3a_buffer(s3a_buf);
1296                         list_del(&s3a_buf->list);
1297                         kfree(s3a_buf);
1298                 }
1299                 list_for_each_entry_safe(s3a_buf, _s3a_buf,
1300                                          &asd->s3a_stats_in_css, list) {
1301                         atomisp_css_free_3a_buffer(s3a_buf);
1302                         list_del(&s3a_buf->list);
1303                         kfree(s3a_buf);
1304                 }
1305                 list_for_each_entry_safe(s3a_buf, _s3a_buf,
1306                                          &asd->s3a_stats_ready, list) {
1307                         atomisp_css_free_3a_buffer(s3a_buf);
1308                         list_del(&s3a_buf->list);
1309                         kfree(s3a_buf);
1310                 }
1311         }
1312
1313         if (asd->params.css_param.dvs_6axis) {
1314                 ia_css_dvs2_6axis_config_free(asd->params.css_param.dvs_6axis);
1315                 asd->params.css_param.dvs_6axis = NULL;
1316         }
1317
1318         for (i = 0; i < ATOMISP_METADATA_TYPE_NUM; i++) {
1319                 list_for_each_entry_safe(md_buf, _md_buf,
1320                                          &asd->metadata[i], list) {
1321                         atomisp_css_free_metadata_buffer(md_buf);
1322                         list_del(&md_buf->list);
1323                         kfree(md_buf);
1324                 }
1325                 list_for_each_entry_safe(md_buf, _md_buf,
1326                                          &asd->metadata_in_css[i], list) {
1327                         atomisp_css_free_metadata_buffer(md_buf);
1328                         list_del(&md_buf->list);
1329                         kfree(md_buf);
1330                 }
1331                 list_for_each_entry_safe(md_buf, _md_buf,
1332                                          &asd->metadata_ready[i], list) {
1333                         atomisp_css_free_metadata_buffer(md_buf);
1334                         list_del(&md_buf->list);
1335                         kfree(md_buf);
1336                 }
1337         }
1338         asd->params.metadata_width_size = 0;
1339         atomisp_free_metadata_output_buf(asd);
1340 }
1341
1342 int atomisp_css_get_grid_info(struct atomisp_sub_device *asd,
1343                               enum ia_css_pipe_id pipe_id,
1344                               int source_pad)
1345 {
1346         struct ia_css_pipe_info p_info;
1347         struct ia_css_grid_info old_info;
1348         struct atomisp_device *isp = asd->isp;
1349         int md_width = asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].
1350                        stream_config.metadata_config.resolution.width;
1351
1352         memset(&p_info, 0, sizeof(struct ia_css_pipe_info));
1353         memset(&old_info, 0, sizeof(struct ia_css_grid_info));
1354
1355         if (ia_css_pipe_get_info(
1356                 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].pipes[pipe_id],
1357                 &p_info) != 0) {
1358                 dev_err(isp->dev, "ia_css_pipe_get_info failed\n");
1359                 return -EINVAL;
1360         }
1361
1362         memcpy(&old_info, &asd->params.curr_grid_info,
1363                sizeof(struct ia_css_grid_info));
1364         memcpy(&asd->params.curr_grid_info, &p_info.grid_info,
1365                sizeof(struct ia_css_grid_info));
1366         /*
1367          * Record which css pipe enables s3a_grid.
1368          * Currently would have one css pipe that need it
1369          */
1370         if (asd->params.curr_grid_info.s3a_grid.enable) {
1371                 if (asd->params.s3a_enabled_pipe != IA_CSS_PIPE_ID_NUM)
1372                         dev_dbg(isp->dev, "css pipe %d enabled s3a grid replaced by: %d.\n",
1373                                 asd->params.s3a_enabled_pipe, pipe_id);
1374                 asd->params.s3a_enabled_pipe = pipe_id;
1375         }
1376
1377         /* If the grid info has not changed and the buffers for 3A and
1378          * DIS statistics buffers are allocated or buffer size would be zero
1379          * then no need to do anything. */
1380         if (((!memcmp(&old_info, &asd->params.curr_grid_info, sizeof(old_info))
1381               && asd->params.s3a_user_stat && asd->params.dvs_stat)
1382              || asd->params.curr_grid_info.s3a_grid.width == 0
1383              || asd->params.curr_grid_info.s3a_grid.height == 0)
1384             && asd->params.metadata_width_size == md_width) {
1385                 dev_dbg(isp->dev,
1386                         "grid info change escape. memcmp=%d, s3a_user_stat=%d,dvs_stat=%d, s3a.width=%d, s3a.height=%d, metadata width =%d\n",
1387                         !memcmp(&old_info, &asd->params.curr_grid_info,
1388                                 sizeof(old_info)),
1389                         !!asd->params.s3a_user_stat, !!asd->params.dvs_stat,
1390                         asd->params.curr_grid_info.s3a_grid.width,
1391                         asd->params.curr_grid_info.s3a_grid.height,
1392                         asd->params.metadata_width_size);
1393                 return -EINVAL;
1394         }
1395         asd->params.metadata_width_size = md_width;
1396
1397         return 0;
1398 }
1399
1400 int atomisp_alloc_3a_output_buf(struct atomisp_sub_device *asd)
1401 {
1402         if (!asd->params.curr_grid_info.s3a_grid.width ||
1403             !asd->params.curr_grid_info.s3a_grid.height)
1404                 return 0;
1405
1406         asd->params.s3a_user_stat = ia_css_3a_statistics_allocate(
1407                                         &asd->params.curr_grid_info.s3a_grid);
1408         if (!asd->params.s3a_user_stat)
1409                 return -ENOMEM;
1410         /* 3A statistics. These can be big, so we use vmalloc. */
1411         asd->params.s3a_output_bytes =
1412             asd->params.curr_grid_info.s3a_grid.width *
1413             asd->params.curr_grid_info.s3a_grid.height *
1414             sizeof(*asd->params.s3a_user_stat->data);
1415
1416         return 0;
1417 }
1418
1419 int atomisp_alloc_dis_coef_buf(struct atomisp_sub_device *asd)
1420 {
1421         struct ia_css_dvs_grid_info *dvs_grid =
1422             atomisp_css_get_dvs_grid_info(&asd->params.curr_grid_info);
1423
1424         if (!dvs_grid)
1425                 return 0;
1426
1427         if (!dvs_grid->enable) {
1428                 dev_dbg(asd->isp->dev, "%s: dvs_grid not enabled.\n", __func__);
1429                 return 0;
1430         }
1431
1432         /* DIS coefficients. */
1433         asd->params.css_param.dvs2_coeff = ia_css_dvs2_coefficients_allocate(
1434                                                dvs_grid);
1435         if (!asd->params.css_param.dvs2_coeff)
1436                 return -ENOMEM;
1437
1438         asd->params.dvs_hor_coef_bytes = dvs_grid->num_hor_coefs *
1439                                          sizeof(*asd->params.css_param.dvs2_coeff->hor_coefs.odd_real);
1440
1441         asd->params.dvs_ver_coef_bytes = dvs_grid->num_ver_coefs *
1442                                          sizeof(*asd->params.css_param.dvs2_coeff->ver_coefs.odd_real);
1443
1444         /* DIS projections. */
1445         asd->params.dis_proj_data_valid = false;
1446         asd->params.dvs_stat = ia_css_dvs2_statistics_allocate(dvs_grid);
1447         if (!asd->params.dvs_stat)
1448                 return -ENOMEM;
1449
1450         asd->params.dvs_hor_proj_bytes =
1451             dvs_grid->aligned_height * dvs_grid->aligned_width *
1452             sizeof(*asd->params.dvs_stat->hor_prod.odd_real);
1453
1454         asd->params.dvs_ver_proj_bytes =
1455             dvs_grid->aligned_height * dvs_grid->aligned_width *
1456             sizeof(*asd->params.dvs_stat->ver_prod.odd_real);
1457
1458         return 0;
1459 }
1460
1461 int atomisp_alloc_metadata_output_buf(struct atomisp_sub_device *asd)
1462 {
1463         int i;
1464
1465         /* We allocate the cpu-side buffer used for communication with user
1466          * space */
1467         for (i = 0; i < ATOMISP_METADATA_TYPE_NUM; i++) {
1468                 asd->params.metadata_user[i] = kvmalloc(
1469                                                    asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].
1470                                                    stream_info.metadata_info.size, GFP_KERNEL);
1471                 if (!asd->params.metadata_user[i]) {
1472                         while (--i >= 0) {
1473                                 kvfree(asd->params.metadata_user[i]);
1474                                 asd->params.metadata_user[i] = NULL;
1475                         }
1476                         return -ENOMEM;
1477                 }
1478         }
1479
1480         return 0;
1481 }
1482
1483 void atomisp_free_metadata_output_buf(struct atomisp_sub_device *asd)
1484 {
1485         unsigned int i;
1486
1487         for (i = 0; i < ATOMISP_METADATA_TYPE_NUM; i++) {
1488                 if (asd->params.metadata_user[i]) {
1489                         kvfree(asd->params.metadata_user[i]);
1490                         asd->params.metadata_user[i] = NULL;
1491                 }
1492         }
1493 }
1494
1495 void atomisp_css_temp_pipe_to_pipe_id(struct atomisp_sub_device *asd,
1496                                       struct atomisp_css_event *current_event)
1497 {
1498         /*
1499          * FIXME!
1500          * Pipe ID reported in CSS event is not correct for new system's
1501          * copy pipe.
1502          * VIED BZ: 1463
1503          */
1504         ia_css_temp_pipe_to_pipe_id(current_event->event.pipe,
1505                                     &current_event->pipe);
1506         if (asd && asd->copy_mode &&
1507             current_event->pipe == IA_CSS_PIPE_ID_CAPTURE)
1508                 current_event->pipe = IA_CSS_PIPE_ID_COPY;
1509 }
1510
1511 int atomisp_css_isys_set_resolution(struct atomisp_sub_device *asd,
1512                                     enum atomisp_input_stream_id stream_id,
1513                                     struct v4l2_mbus_framefmt *ffmt,
1514                                     int isys_stream)
1515 {
1516         struct ia_css_stream_config *s_config =
1517                     &asd->stream_env[stream_id].stream_config;
1518
1519         if (isys_stream >= IA_CSS_STREAM_MAX_ISYS_STREAM_PER_CH)
1520                 return -EINVAL;
1521
1522         s_config->isys_config[isys_stream].input_res.width = ffmt->width;
1523         s_config->isys_config[isys_stream].input_res.height = ffmt->height;
1524         return 0;
1525 }
1526
1527 int atomisp_css_input_set_resolution(struct atomisp_sub_device *asd,
1528                                      enum atomisp_input_stream_id stream_id,
1529                                      struct v4l2_mbus_framefmt *ffmt)
1530 {
1531         struct ia_css_stream_config *s_config =
1532                     &asd->stream_env[stream_id].stream_config;
1533
1534         s_config->input_config.input_res.width = ffmt->width;
1535         s_config->input_config.input_res.height = ffmt->height;
1536         return 0;
1537 }
1538
1539 void atomisp_css_input_set_binning_factor(struct atomisp_sub_device *asd,
1540         enum atomisp_input_stream_id stream_id,
1541         unsigned int bin_factor)
1542 {
1543         asd->stream_env[stream_id]
1544         .stream_config.sensor_binning_factor = bin_factor;
1545 }
1546
1547 void atomisp_css_input_set_bayer_order(struct atomisp_sub_device *asd,
1548                                        enum atomisp_input_stream_id stream_id,
1549                                        enum ia_css_bayer_order bayer_order)
1550 {
1551         struct ia_css_stream_config *s_config =
1552                     &asd->stream_env[stream_id].stream_config;
1553         s_config->input_config.bayer_order = bayer_order;
1554 }
1555
1556 void atomisp_css_isys_set_link(struct atomisp_sub_device *asd,
1557                                enum atomisp_input_stream_id stream_id,
1558                                int link,
1559                                int isys_stream)
1560 {
1561         struct ia_css_stream_config *s_config =
1562                     &asd->stream_env[stream_id].stream_config;
1563
1564         s_config->isys_config[isys_stream].linked_isys_stream_id = link;
1565 }
1566
1567 void atomisp_css_isys_set_valid(struct atomisp_sub_device *asd,
1568                                 enum atomisp_input_stream_id stream_id,
1569                                 bool valid,
1570                                 int isys_stream)
1571 {
1572         struct ia_css_stream_config *s_config =
1573                     &asd->stream_env[stream_id].stream_config;
1574
1575         s_config->isys_config[isys_stream].valid = valid;
1576 }
1577
1578 void atomisp_css_isys_set_format(struct atomisp_sub_device *asd,
1579                                  enum atomisp_input_stream_id stream_id,
1580                                  enum atomisp_input_format format,
1581                                  int isys_stream)
1582 {
1583         struct ia_css_stream_config *s_config =
1584                     &asd->stream_env[stream_id].stream_config;
1585
1586         s_config->isys_config[isys_stream].format = format;
1587 }
1588
1589 void atomisp_css_input_set_format(struct atomisp_sub_device *asd,
1590                                   enum atomisp_input_stream_id stream_id,
1591                                   enum atomisp_input_format format)
1592 {
1593         struct ia_css_stream_config *s_config =
1594                     &asd->stream_env[stream_id].stream_config;
1595
1596         s_config->input_config.format = format;
1597 }
1598
1599 int atomisp_css_set_default_isys_config(struct atomisp_sub_device *asd,
1600                                         enum atomisp_input_stream_id stream_id,
1601                                         struct v4l2_mbus_framefmt *ffmt)
1602 {
1603         int i;
1604         struct ia_css_stream_config *s_config =
1605                     &asd->stream_env[stream_id].stream_config;
1606         /*
1607          * Set all isys configs to not valid.
1608          * Currently we support only one stream per channel
1609          */
1610         for (i = IA_CSS_STREAM_ISYS_STREAM_0;
1611              i < IA_CSS_STREAM_MAX_ISYS_STREAM_PER_CH; i++)
1612                 s_config->isys_config[i].valid = false;
1613
1614         atomisp_css_isys_set_resolution(asd, stream_id, ffmt,
1615                                         IA_CSS_STREAM_DEFAULT_ISYS_STREAM_IDX);
1616         atomisp_css_isys_set_format(asd, stream_id,
1617                                     s_config->input_config.format,
1618                                     IA_CSS_STREAM_DEFAULT_ISYS_STREAM_IDX);
1619         atomisp_css_isys_set_link(asd, stream_id, NO_LINK,
1620                                   IA_CSS_STREAM_DEFAULT_ISYS_STREAM_IDX);
1621         atomisp_css_isys_set_valid(asd, stream_id, true,
1622                                    IA_CSS_STREAM_DEFAULT_ISYS_STREAM_IDX);
1623
1624         return 0;
1625 }
1626
1627 int atomisp_css_isys_two_stream_cfg(struct atomisp_sub_device *asd,
1628                                     enum atomisp_input_stream_id stream_id,
1629                                     enum atomisp_input_format input_format)
1630 {
1631         struct ia_css_stream_config *s_config =
1632                     &asd->stream_env[stream_id].stream_config;
1633
1634         s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_1].input_res.width =
1635             s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_0].input_res.width;
1636
1637         s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_1].input_res.height =
1638             s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_0].input_res.height / 2;
1639
1640         s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_1].linked_isys_stream_id
1641             = IA_CSS_STREAM_ISYS_STREAM_0;
1642         s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_0].format =
1643             ATOMISP_INPUT_FORMAT_USER_DEF1;
1644         s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_1].format =
1645             ATOMISP_INPUT_FORMAT_USER_DEF2;
1646         s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_1].valid = true;
1647         return 0;
1648 }
1649
1650 void atomisp_css_isys_two_stream_cfg_update_stream1(
1651     struct atomisp_sub_device *asd,
1652     enum atomisp_input_stream_id stream_id,
1653     enum atomisp_input_format input_format,
1654     unsigned int width, unsigned int height)
1655 {
1656         struct ia_css_stream_config *s_config =
1657                     &asd->stream_env[stream_id].stream_config;
1658
1659         s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_0].input_res.width =
1660             width;
1661         s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_0].input_res.height =
1662             height;
1663         s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_0].format =
1664             input_format;
1665         s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_0].valid = true;
1666 }
1667
1668 void atomisp_css_isys_two_stream_cfg_update_stream2(
1669     struct atomisp_sub_device *asd,
1670     enum atomisp_input_stream_id stream_id,
1671     enum atomisp_input_format input_format,
1672     unsigned int width, unsigned int height)
1673 {
1674         struct ia_css_stream_config *s_config =
1675                     &asd->stream_env[stream_id].stream_config;
1676
1677         s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_1].input_res.width =
1678             width;
1679         s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_1].input_res.height =
1680             height;
1681         s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_1].linked_isys_stream_id
1682             = IA_CSS_STREAM_ISYS_STREAM_0;
1683         s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_1].format =
1684             input_format;
1685         s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_1].valid = true;
1686 }
1687
1688 int atomisp_css_input_set_effective_resolution(
1689     struct atomisp_sub_device *asd,
1690     enum atomisp_input_stream_id stream_id,
1691     unsigned int width, unsigned int height)
1692 {
1693         struct ia_css_stream_config *s_config =
1694                     &asd->stream_env[stream_id].stream_config;
1695         s_config->input_config.effective_res.width = width;
1696         s_config->input_config.effective_res.height = height;
1697         return 0;
1698 }
1699
1700 void atomisp_css_video_set_dis_envelope(struct atomisp_sub_device *asd,
1701                                         unsigned int dvs_w, unsigned int dvs_h)
1702 {
1703         asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]
1704         .pipe_configs[IA_CSS_PIPE_ID_VIDEO].dvs_envelope.width = dvs_w;
1705         asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]
1706         .pipe_configs[IA_CSS_PIPE_ID_VIDEO].dvs_envelope.height = dvs_h;
1707 }
1708
1709 void atomisp_css_input_set_two_pixels_per_clock(
1710     struct atomisp_sub_device *asd,
1711     bool two_ppc)
1712 {
1713         int i;
1714
1715         if (asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]
1716             .stream_config.pixels_per_clock == (two_ppc ? 2 : 1))
1717                 return;
1718
1719         asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]
1720         .stream_config.pixels_per_clock = (two_ppc ? 2 : 1);
1721         for (i = 0; i < IA_CSS_PIPE_ID_NUM; i++)
1722                 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]
1723                 .update_pipe[i] = true;
1724 }
1725
1726 void atomisp_css_enable_dz(struct atomisp_sub_device *asd, bool enable)
1727 {
1728         int i;
1729
1730         for (i = 0; i < IA_CSS_PIPE_ID_NUM; i++)
1731                 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]
1732                 .pipe_configs[i].enable_dz = enable;
1733 }
1734
1735 void atomisp_css_capture_set_mode(struct atomisp_sub_device *asd,
1736                                   enum ia_css_capture_mode mode)
1737 {
1738         struct atomisp_stream_env *stream_env =
1739                     &asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL];
1740
1741         if (stream_env->pipe_configs[IA_CSS_PIPE_ID_CAPTURE]
1742             .default_capture_config.mode == mode)
1743                 return;
1744
1745         stream_env->pipe_configs[IA_CSS_PIPE_ID_CAPTURE].
1746         default_capture_config.mode = mode;
1747         stream_env->update_pipe[IA_CSS_PIPE_ID_CAPTURE] = true;
1748 }
1749
1750 void atomisp_css_input_set_mode(struct atomisp_sub_device *asd,
1751                                 enum ia_css_input_mode mode)
1752 {
1753         int i;
1754         struct atomisp_device *isp = asd->isp;
1755         unsigned int size_mem_words;
1756
1757         for (i = 0; i < ATOMISP_INPUT_STREAM_NUM; i++)
1758                 asd->stream_env[i].stream_config.mode = mode;
1759
1760         if (isp->inputs[asd->input_curr].type == TEST_PATTERN) {
1761                 struct ia_css_stream_config *s_config =
1762                             &asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream_config;
1763                 s_config->mode = IA_CSS_INPUT_MODE_TPG;
1764                 s_config->source.tpg.mode = IA_CSS_TPG_MODE_CHECKERBOARD;
1765                 s_config->source.tpg.x_mask = (1 << 4) - 1;
1766                 s_config->source.tpg.x_delta = -2;
1767                 s_config->source.tpg.y_mask = (1 << 4) - 1;
1768                 s_config->source.tpg.y_delta = 3;
1769                 s_config->source.tpg.xy_mask = (1 << 8) - 1;
1770                 return;
1771         }
1772
1773         if (mode != IA_CSS_INPUT_MODE_BUFFERED_SENSOR)
1774                 return;
1775
1776         for (i = 0; i < ATOMISP_INPUT_STREAM_NUM; i++) {
1777                 /*
1778                  * TODO: sensor needs to export the embedded_data_size_words
1779                  * information to atomisp for each setting.
1780                  * Here using a large safe value.
1781                  */
1782                 struct ia_css_stream_config *s_config =
1783                             &asd->stream_env[i].stream_config;
1784
1785                 if (s_config->input_config.input_res.width == 0)
1786                         continue;
1787
1788                 if (ia_css_mipi_frame_calculate_size(
1789                         s_config->input_config.input_res.width,
1790                         s_config->input_config.input_res.height,
1791                         s_config->input_config.format,
1792                         true,
1793                         0x13000,
1794                         &size_mem_words) != 0) {
1795                         if (IS_MRFD)
1796                                 size_mem_words = CSS_MIPI_FRAME_BUFFER_SIZE_2;
1797                         else
1798                                 size_mem_words = CSS_MIPI_FRAME_BUFFER_SIZE_1;
1799                         dev_warn(asd->isp->dev,
1800                                  "ia_css_mipi_frame_calculate_size failed,applying pre-defined MIPI buffer size %u.\n",
1801                                  size_mem_words);
1802                 }
1803                 s_config->mipi_buffer_config.size_mem_words = size_mem_words;
1804                 s_config->mipi_buffer_config.nof_mipi_buffers = 2;
1805         }
1806 }
1807
1808 void atomisp_css_capture_enable_online(struct atomisp_sub_device *asd,
1809                                        unsigned short stream_index, bool enable)
1810 {
1811         struct atomisp_stream_env *stream_env =
1812                     &asd->stream_env[stream_index];
1813
1814         if (stream_env->stream_config.online == !!enable)
1815                 return;
1816
1817         stream_env->stream_config.online = !!enable;
1818         stream_env->update_pipe[IA_CSS_PIPE_ID_CAPTURE] = true;
1819 }
1820
1821 void atomisp_css_preview_enable_online(struct atomisp_sub_device *asd,
1822                                        unsigned short stream_index, bool enable)
1823 {
1824         struct atomisp_stream_env *stream_env =
1825                     &asd->stream_env[stream_index];
1826         int i;
1827
1828         if (stream_env->stream_config.online != !!enable) {
1829                 stream_env->stream_config.online = !!enable;
1830                 for (i = 0; i < IA_CSS_PIPE_ID_NUM; i++)
1831                         stream_env->update_pipe[i] = true;
1832         }
1833 }
1834
1835 void atomisp_css_video_enable_online(struct atomisp_sub_device *asd,
1836                                      bool enable)
1837 {
1838         struct atomisp_stream_env *stream_env =
1839                     &asd->stream_env[ATOMISP_INPUT_STREAM_VIDEO];
1840         int i;
1841
1842         if (stream_env->stream_config.online != enable) {
1843                 stream_env->stream_config.online = enable;
1844                 for (i = 0; i < IA_CSS_PIPE_ID_NUM; i++)
1845                         stream_env->update_pipe[i] = true;
1846         }
1847 }
1848
1849 void atomisp_css_enable_continuous(struct atomisp_sub_device *asd,
1850                                    bool enable)
1851 {
1852         struct atomisp_stream_env *stream_env =
1853                     &asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL];
1854         int i;
1855
1856         if (stream_env->stream_config.continuous != !!enable) {
1857                 stream_env->stream_config.continuous = !!enable;
1858                 stream_env->stream_config.pack_raw_pixels = true;
1859                 for (i = 0; i < IA_CSS_PIPE_ID_NUM; i++)
1860                         stream_env->update_pipe[i] = true;
1861         }
1862 }
1863
1864 void atomisp_css_enable_cvf(struct atomisp_sub_device *asd,
1865                             bool enable)
1866 {
1867         struct atomisp_stream_env *stream_env =
1868                     &asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL];
1869         int i;
1870
1871         if (stream_env->stream_config.disable_cont_viewfinder != !enable) {
1872                 stream_env->stream_config.disable_cont_viewfinder = !enable;
1873                 for (i = 0; i < IA_CSS_PIPE_ID_NUM; i++)
1874                         stream_env->update_pipe[i] = true;
1875         }
1876 }
1877
1878 int atomisp_css_input_configure_port(
1879     struct atomisp_sub_device *asd,
1880     enum mipi_port_id port,
1881     unsigned int num_lanes,
1882     unsigned int timeout,
1883     unsigned int mipi_freq,
1884     enum atomisp_input_format metadata_format,
1885     unsigned int metadata_width,
1886     unsigned int metadata_height)
1887 {
1888         int i;
1889         struct atomisp_stream_env *stream_env;
1890         /*
1891          * Calculate rx_count as follows:
1892          * Input: mipi_freq                 : CSI-2 bus frequency in Hz
1893          * UI = 1 / (2 * mipi_freq)         : period of one bit on the bus
1894          * min = 85e-9 + 6 * UI             : Limits for rx_count in seconds
1895          * max = 145e-9 + 10 * UI
1896          * rxcount0 = min / (4 / mipi_freq) : convert seconds to byte clocks
1897          * rxcount = rxcount0 - 2           : adjust for better results
1898          * The formula below is simplified version of the above with
1899          * 10-bit fixed points for improved accuracy.
1900          */
1901         const unsigned int rxcount =
1902             min(((mipi_freq / 46000) - 1280) >> 10, 0xffU) * 0x01010101U;
1903
1904         for (i = 0; i < ATOMISP_INPUT_STREAM_NUM; i++) {
1905                 stream_env = &asd->stream_env[i];
1906                 stream_env->stream_config.source.port.port = port;
1907                 stream_env->stream_config.source.port.num_lanes = num_lanes;
1908                 stream_env->stream_config.source.port.timeout = timeout;
1909                 if (mipi_freq)
1910                         stream_env->stream_config.source.port.rxcount = rxcount;
1911                 stream_env->stream_config.
1912                 metadata_config.data_type = metadata_format;
1913                 stream_env->stream_config.
1914                 metadata_config.resolution.width = metadata_width;
1915                 stream_env->stream_config.
1916                 metadata_config.resolution.height = metadata_height;
1917         }
1918
1919         return 0;
1920 }
1921
1922 void atomisp_css_stop(struct atomisp_sub_device *asd,
1923                       enum ia_css_pipe_id pipe_id, bool in_reset)
1924 {
1925         struct atomisp_device *isp = asd->isp;
1926         unsigned long irqflags;
1927         unsigned int i;
1928
1929         /* if is called in atomisp_reset(), force destroy streams and pipes */
1930         atomisp_destroy_pipes_stream_force(asd);
1931
1932         atomisp_init_raw_buffer_bitmap(asd);
1933
1934         /*
1935          * SP can not be stop if other streams are in use
1936          */
1937         if (atomisp_streaming_count(isp) == 0)
1938                 ia_css_stop_sp();
1939
1940         if (!in_reset) {
1941                 struct atomisp_stream_env *stream_env;
1942                 int i, j;
1943
1944                 for (i = 0; i < ATOMISP_INPUT_STREAM_NUM; i++) {
1945                         stream_env = &asd->stream_env[i];
1946                         for (j = 0; j < IA_CSS_PIPE_ID_NUM; j++) {
1947                                 ia_css_pipe_config_defaults(
1948                                     &stream_env->pipe_configs[j]);
1949                                 ia_css_pipe_extra_config_defaults(
1950                                     &stream_env->pipe_extra_configs[j]);
1951                         }
1952                         ia_css_stream_config_defaults(
1953                             &stream_env->stream_config);
1954                 }
1955                 memset(&asd->params.config, 0, sizeof(asd->params.config));
1956                 asd->params.css_update_params_needed = false;
1957         }
1958
1959         /* move stats buffers to free queue list */
1960         list_splice_init(&asd->s3a_stats_in_css, &asd->s3a_stats);
1961         list_splice_init(&asd->s3a_stats_ready, &asd->s3a_stats);
1962
1963         spin_lock_irqsave(&asd->dis_stats_lock, irqflags);
1964         list_splice_init(&asd->dis_stats_in_css, &asd->dis_stats);
1965         asd->params.dis_proj_data_valid = false;
1966         spin_unlock_irqrestore(&asd->dis_stats_lock, irqflags);
1967
1968         for (i = 0; i < ATOMISP_METADATA_TYPE_NUM; i++) {
1969                 list_splice_init(&asd->metadata_in_css[i], &asd->metadata[i]);
1970                 list_splice_init(&asd->metadata_ready[i], &asd->metadata[i]);
1971         }
1972
1973         atomisp_flush_params_queue(&asd->video_out_capture);
1974         atomisp_flush_params_queue(&asd->video_out_vf);
1975         atomisp_flush_params_queue(&asd->video_out_preview);
1976         atomisp_flush_params_queue(&asd->video_out_video_capture);
1977         atomisp_free_css_parameters(&asd->params.css_param);
1978         memset(&asd->params.css_param, 0, sizeof(asd->params.css_param));
1979 }
1980
1981 void atomisp_css_continuous_set_num_raw_frames(
1982      struct atomisp_sub_device *asd,
1983      int num_frames)
1984 {
1985         if (asd->enable_raw_buffer_lock->val) {
1986                 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]
1987                 .stream_config.init_num_cont_raw_buf =
1988                     ATOMISP_CSS2_NUM_OFFLINE_INIT_CONTINUOUS_FRAMES_LOCK_EN;
1989                 if (asd->run_mode->val == ATOMISP_RUN_MODE_VIDEO &&
1990                     asd->params.video_dis_en)
1991                         asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]
1992                         .stream_config.init_num_cont_raw_buf +=
1993                             ATOMISP_CSS2_NUM_DVS_FRAME_DELAY;
1994         } else {
1995                 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]
1996                 .stream_config.init_num_cont_raw_buf =
1997                     ATOMISP_CSS2_NUM_OFFLINE_INIT_CONTINUOUS_FRAMES;
1998         }
1999
2000         if (asd->params.video_dis_en)
2001                 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]
2002                 .stream_config.init_num_cont_raw_buf +=
2003                     ATOMISP_CSS2_NUM_DVS_FRAME_DELAY;
2004
2005         asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]
2006         .stream_config.target_num_cont_raw_buf = num_frames;
2007 }
2008
2009 static enum ia_css_pipe_mode __pipe_id_to_pipe_mode(
2010     struct atomisp_sub_device *asd,
2011     enum ia_css_pipe_id pipe_id)
2012 {
2013         struct atomisp_device *isp = asd->isp;
2014         struct camera_mipi_info *mipi_info = atomisp_to_sensor_mipi_info(
2015                 isp->inputs[asd->input_curr].camera);
2016
2017         switch (pipe_id) {
2018         case IA_CSS_PIPE_ID_COPY:
2019                 /* Currently only YUVPP mode supports YUV420_Legacy format.
2020                  * Revert this when other pipe modes can support
2021                  * YUV420_Legacy format.
2022                  */
2023                 if (mipi_info && mipi_info->input_format ==
2024                     ATOMISP_INPUT_FORMAT_YUV420_8_LEGACY)
2025                         return IA_CSS_PIPE_MODE_YUVPP;
2026                 return IA_CSS_PIPE_MODE_COPY;
2027         case IA_CSS_PIPE_ID_PREVIEW:
2028                 return IA_CSS_PIPE_MODE_PREVIEW;
2029         case IA_CSS_PIPE_ID_CAPTURE:
2030                 return IA_CSS_PIPE_MODE_CAPTURE;
2031         case IA_CSS_PIPE_ID_VIDEO:
2032                 return IA_CSS_PIPE_MODE_VIDEO;
2033         case IA_CSS_PIPE_ID_YUVPP:
2034                 return IA_CSS_PIPE_MODE_YUVPP;
2035         default:
2036                 WARN_ON(1);
2037                 return IA_CSS_PIPE_MODE_PREVIEW;
2038         }
2039 }
2040
2041 static void __configure_output(struct atomisp_sub_device *asd,
2042                                unsigned int stream_index,
2043                                unsigned int width, unsigned int height,
2044                                unsigned int min_width,
2045                                enum ia_css_frame_format format,
2046                                enum ia_css_pipe_id pipe_id)
2047 {
2048         struct atomisp_device *isp = asd->isp;
2049         struct atomisp_stream_env *stream_env =
2050                     &asd->stream_env[stream_index];
2051         struct ia_css_stream_config *s_config = &stream_env->stream_config;
2052
2053         stream_env->pipe_configs[pipe_id].mode =
2054             __pipe_id_to_pipe_mode(asd, pipe_id);
2055         stream_env->update_pipe[pipe_id] = true;
2056
2057         stream_env->pipe_configs[pipe_id].output_info[0].res.width = width;
2058         stream_env->pipe_configs[pipe_id].output_info[0].res.height = height;
2059         stream_env->pipe_configs[pipe_id].output_info[0].format = format;
2060         stream_env->pipe_configs[pipe_id].output_info[0].padded_width = min_width;
2061
2062         /* isp binary 2.2 specific setting*/
2063         if (width > s_config->input_config.effective_res.width ||
2064             height > s_config->input_config.effective_res.height) {
2065                 s_config->input_config.effective_res.width = width;
2066                 s_config->input_config.effective_res.height = height;
2067         }
2068
2069         dev_dbg(isp->dev, "configuring pipe[%d] output info w=%d.h=%d.f=%d.\n",
2070                 pipe_id, width, height, format);
2071 }
2072
2073 /*
2074  * For CSS2.1, capture pipe uses capture_pp_in_res to configure yuv
2075  * downscaling input resolution.
2076  */
2077 static void __configure_capture_pp_input(struct atomisp_sub_device *asd,
2078         unsigned int width, unsigned int height,
2079         enum ia_css_pipe_id pipe_id)
2080 {
2081         struct atomisp_device *isp = asd->isp;
2082         struct atomisp_stream_env *stream_env =
2083                     &asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL];
2084         struct ia_css_stream_config *stream_config = &stream_env->stream_config;
2085         struct ia_css_pipe_config *pipe_configs =
2086                     &stream_env->pipe_configs[pipe_id];
2087         struct ia_css_pipe_extra_config *pipe_extra_configs =
2088                     &stream_env->pipe_extra_configs[pipe_id];
2089         unsigned int hor_ds_factor = 0, ver_ds_factor = 0;
2090
2091         if (width == 0 && height == 0)
2092                 return;
2093
2094         if (width * 9 / 10 < pipe_configs->output_info[0].res.width ||
2095             height * 9 / 10 < pipe_configs->output_info[0].res.height)
2096                 return;
2097         /* here just copy the calculation in css */
2098         hor_ds_factor = CEIL_DIV(width >> 1,
2099                                  pipe_configs->output_info[0].res.width);
2100         ver_ds_factor = CEIL_DIV(height >> 1,
2101                                  pipe_configs->output_info[0].res.height);
2102
2103         if ((asd->isp->media_dev.hw_revision <
2104              (ATOMISP_HW_REVISION_ISP2401 << ATOMISP_HW_REVISION_SHIFT) ||
2105              IS_CHT) && hor_ds_factor != ver_ds_factor) {
2106                 dev_warn(asd->isp->dev,
2107                          "Cropping for capture due to FW limitation");
2108                 return;
2109         }
2110
2111         pipe_configs->mode = __pipe_id_to_pipe_mode(asd, pipe_id);
2112         stream_env->update_pipe[pipe_id] = true;
2113
2114         pipe_extra_configs->enable_yuv_ds = true;
2115
2116         pipe_configs->capt_pp_in_res.width =
2117             stream_config->input_config.effective_res.width;
2118         pipe_configs->capt_pp_in_res.height =
2119             stream_config->input_config.effective_res.height;
2120
2121         dev_dbg(isp->dev, "configuring pipe[%d]capture pp input w=%d.h=%d.\n",
2122                 pipe_id, width, height);
2123 }
2124
2125 /*
2126  * For CSS2.1, preview pipe could support bayer downscaling, yuv decimation and
2127  * yuv downscaling, which needs addtional configurations.
2128  */
2129 static void __configure_preview_pp_input(struct atomisp_sub_device *asd,
2130         unsigned int width, unsigned int height,
2131         enum ia_css_pipe_id pipe_id)
2132 {
2133         struct atomisp_device *isp = asd->isp;
2134         int out_width, out_height, yuv_ds_in_width, yuv_ds_in_height;
2135         struct atomisp_stream_env *stream_env =
2136                     &asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL];
2137         struct ia_css_stream_config *stream_config = &stream_env->stream_config;
2138         struct ia_css_pipe_config *pipe_configs =
2139                     &stream_env->pipe_configs[pipe_id];
2140         struct ia_css_pipe_extra_config *pipe_extra_configs =
2141                     &stream_env->pipe_extra_configs[pipe_id];
2142         struct ia_css_resolution *bayer_ds_out_res =
2143                     &pipe_configs->bayer_ds_out_res;
2144         struct ia_css_resolution *vf_pp_in_res =
2145                     &pipe_configs->vf_pp_in_res;
2146         struct ia_css_resolution  *effective_res =
2147                     &stream_config->input_config.effective_res;
2148
2149         static const struct bayer_ds_factor bds_fct[] = {{2, 1}, {3, 2}, {5, 4} };
2150         /*
2151          * BZ201033: YUV decimation factor of 4 causes couple of rightmost
2152          * columns to be shaded. Remove this factor to work around the CSS bug.
2153          * const unsigned int yuv_dec_fct[] = {4, 2};
2154          */
2155         static const unsigned int yuv_dec_fct[] = { 2 };
2156         unsigned int i;
2157
2158         if (width == 0 && height == 0)
2159                 return;
2160
2161         pipe_configs->mode = __pipe_id_to_pipe_mode(asd, pipe_id);
2162         stream_env->update_pipe[pipe_id] = true;
2163
2164         out_width = pipe_configs->output_info[0].res.width;
2165         out_height = pipe_configs->output_info[0].res.height;
2166
2167         /*
2168          * The ISP could do bayer downscaling, yuv decimation and yuv
2169          * downscaling:
2170          * 1: Bayer Downscaling: between effective resolution and
2171          * bayer_ds_res_out;
2172          * 2: YUV Decimation: between bayer_ds_res_out and vf_pp_in_res;
2173          * 3: YUV Downscaling: between vf_pp_in_res and final vf output
2174          *
2175          * Rule for Bayer Downscaling: support factor 2, 1.5 and 1.25
2176          * Rule for YUV Decimation: support factor 2, 4
2177          * Rule for YUV Downscaling: arbitrary value below 2
2178          *
2179          * General rule of factor distribution among these stages:
2180          * 1: try to do Bayer downscaling first if not in online mode.
2181          * 2: try to do maximum of 2 for YUV downscaling
2182          * 3: the remainling for YUV decimation
2183          *
2184          * Note:
2185          * Do not configure bayer_ds_out_res if:
2186          * online == 1 or continuous == 0 or raw_binning = 0
2187          */
2188         if (stream_config->online || !stream_config->continuous ||
2189             !pipe_extra_configs->enable_raw_binning) {
2190                 bayer_ds_out_res->width = 0;
2191                 bayer_ds_out_res->height = 0;
2192         } else {
2193                 bayer_ds_out_res->width = effective_res->width;
2194                 bayer_ds_out_res->height = effective_res->height;
2195
2196                 for (i = 0; i < ARRAY_SIZE(bds_fct); i++) {
2197                         if (effective_res->width >= out_width *
2198                             bds_fct[i].numerator / bds_fct[i].denominator &&
2199                             effective_res->height >= out_height *
2200                             bds_fct[i].numerator / bds_fct[i].denominator) {
2201                                 bayer_ds_out_res->width =
2202                                     effective_res->width *
2203                                     bds_fct[i].denominator /
2204                                     bds_fct[i].numerator;
2205                                 bayer_ds_out_res->height =
2206                                     effective_res->height *
2207                                     bds_fct[i].denominator /
2208                                     bds_fct[i].numerator;
2209                                 break;
2210                         }
2211                 }
2212         }
2213         /*
2214          * calculate YUV Decimation, YUV downscaling facor:
2215          * YUV Downscaling factor must not exceed 2.
2216          * YUV Decimation factor could be 2, 4.
2217          */
2218         /* first decide the yuv_ds input resolution */
2219         if (bayer_ds_out_res->width == 0) {
2220                 yuv_ds_in_width = effective_res->width;
2221                 yuv_ds_in_height = effective_res->height;
2222         } else {
2223                 yuv_ds_in_width = bayer_ds_out_res->width;
2224                 yuv_ds_in_height = bayer_ds_out_res->height;
2225         }
2226
2227         vf_pp_in_res->width = yuv_ds_in_width;
2228         vf_pp_in_res->height = yuv_ds_in_height;
2229
2230         /* find out the yuv decimation factor */
2231         for (i = 0; i < ARRAY_SIZE(yuv_dec_fct); i++) {
2232                 if (yuv_ds_in_width >= out_width * yuv_dec_fct[i] &&
2233                     yuv_ds_in_height >= out_height * yuv_dec_fct[i]) {
2234                         vf_pp_in_res->width = yuv_ds_in_width / yuv_dec_fct[i];
2235                         vf_pp_in_res->height = yuv_ds_in_height / yuv_dec_fct[i];
2236                         break;
2237                 }
2238         }
2239
2240         if (vf_pp_in_res->width == out_width &&
2241             vf_pp_in_res->height == out_height) {
2242                 pipe_extra_configs->enable_yuv_ds = false;
2243                 vf_pp_in_res->width = 0;
2244                 vf_pp_in_res->height = 0;
2245         } else {
2246                 pipe_extra_configs->enable_yuv_ds = true;
2247         }
2248
2249         dev_dbg(isp->dev, "configuring pipe[%d]preview pp input w=%d.h=%d.\n",
2250                 pipe_id, width, height);
2251 }
2252
2253 /*
2254  * For CSS2.1, offline video pipe could support bayer decimation, and
2255  * yuv downscaling, which needs addtional configurations.
2256  */
2257 static void __configure_video_pp_input(struct atomisp_sub_device *asd,
2258                                        unsigned int width, unsigned int height,
2259                                        enum ia_css_pipe_id pipe_id)
2260 {
2261         struct atomisp_device *isp = asd->isp;
2262         int out_width, out_height;
2263         struct atomisp_stream_env *stream_env =
2264                     &asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL];
2265         struct ia_css_stream_config *stream_config = &stream_env->stream_config;
2266         struct ia_css_pipe_config *pipe_configs =
2267                     &stream_env->pipe_configs[pipe_id];
2268         struct ia_css_pipe_extra_config *pipe_extra_configs =
2269                     &stream_env->pipe_extra_configs[pipe_id];
2270         struct ia_css_resolution *bayer_ds_out_res =
2271                     &pipe_configs->bayer_ds_out_res;
2272         struct ia_css_resolution  *effective_res =
2273                     &stream_config->input_config.effective_res;
2274
2275         static const struct bayer_ds_factor bds_factors[] = {
2276                 {8, 1}, {6, 1}, {4, 1}, {3, 1}, {2, 1}, {3, 2}
2277         };
2278         unsigned int i;
2279
2280         if (width == 0 && height == 0)
2281                 return;
2282
2283         pipe_configs->mode = __pipe_id_to_pipe_mode(asd, pipe_id);
2284         stream_env->update_pipe[pipe_id] = true;
2285
2286         pipe_extra_configs->enable_yuv_ds = false;
2287
2288         /*
2289          * If DVS is enabled,  video binary will take care the dvs envelope
2290          * and usually the bayer_ds_out_res should be larger than 120% of
2291          * destination resolution, the extra 20% will be cropped as DVS
2292          * envelope. But,  if the bayer_ds_out_res is less than 120% of the
2293          * destination. The ISP can still work,  but DVS quality is not good.
2294          */
2295         /* taking at least 10% as envelope */
2296         if (asd->params.video_dis_en) {
2297                 out_width = pipe_configs->output_info[0].res.width * 110 / 100;
2298                 out_height = pipe_configs->output_info[0].res.height * 110 / 100;
2299         } else {
2300                 out_width = pipe_configs->output_info[0].res.width;
2301                 out_height = pipe_configs->output_info[0].res.height;
2302         }
2303
2304         /*
2305          * calculate bayer decimate factor:
2306          * 1: only 1.5, 2, 4 and 8 get supported
2307          * 2: Do not configure bayer_ds_out_res if:
2308          *    online == 1 or continuous == 0 or raw_binning = 0
2309          */
2310         if (stream_config->online || !stream_config->continuous) {
2311                 bayer_ds_out_res->width = 0;
2312                 bayer_ds_out_res->height = 0;
2313                 goto done;
2314         }
2315
2316         pipe_extra_configs->enable_raw_binning = true;
2317         bayer_ds_out_res->width = effective_res->width;
2318         bayer_ds_out_res->height = effective_res->height;
2319
2320         for (i = 0; i < sizeof(bds_factors) / sizeof(struct bayer_ds_factor);
2321              i++) {
2322                 if (effective_res->width >= out_width *
2323                     bds_factors[i].numerator / bds_factors[i].denominator &&
2324                     effective_res->height >= out_height *
2325                     bds_factors[i].numerator / bds_factors[i].denominator) {
2326                         bayer_ds_out_res->width = effective_res->width *
2327                                                   bds_factors[i].denominator /
2328                                                   bds_factors[i].numerator;
2329                         bayer_ds_out_res->height = effective_res->height *
2330                                                    bds_factors[i].denominator /
2331                                                    bds_factors[i].numerator;
2332                         break;
2333                 }
2334         }
2335
2336         /*
2337          * DVS is cropped from BDS output, so we do not really need to set the
2338          * envelope to 20% of output resolution here. always set it to 12x12
2339          * per firmware requirement.
2340          */
2341         pipe_configs->dvs_envelope.width = 12;
2342         pipe_configs->dvs_envelope.height = 12;
2343
2344 done:
2345         if (pipe_id == IA_CSS_PIPE_ID_YUVPP)
2346                 stream_config->left_padding = -1;
2347         else
2348                 stream_config->left_padding = 12;
2349         dev_dbg(isp->dev, "configuring pipe[%d]video pp input w=%d.h=%d.\n",
2350                 pipe_id, width, height);
2351 }
2352
2353 static void __configure_vf_output(struct atomisp_sub_device *asd,
2354                                   unsigned int width, unsigned int height,
2355                                   unsigned int min_width,
2356                                   enum ia_css_frame_format format,
2357                                   enum ia_css_pipe_id pipe_id)
2358 {
2359         struct atomisp_device *isp = asd->isp;
2360         struct atomisp_stream_env *stream_env =
2361                     &asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL];
2362         stream_env->pipe_configs[pipe_id].mode =
2363             __pipe_id_to_pipe_mode(asd, pipe_id);
2364         stream_env->update_pipe[pipe_id] = true;
2365
2366         stream_env->pipe_configs[pipe_id].vf_output_info[0].res.width = width;
2367         stream_env->pipe_configs[pipe_id].vf_output_info[0].res.height = height;
2368         stream_env->pipe_configs[pipe_id].vf_output_info[0].format = format;
2369         stream_env->pipe_configs[pipe_id].vf_output_info[0].padded_width =
2370             min_width;
2371         dev_dbg(isp->dev,
2372                 "configuring pipe[%d] vf output info w=%d.h=%d.f=%d.\n",
2373                 pipe_id, width, height, format);
2374 }
2375
2376 static int __get_frame_info(struct atomisp_sub_device *asd,
2377                             unsigned int stream_index,
2378                             struct ia_css_frame_info *info,
2379                             enum frame_info_type type,
2380                             enum ia_css_pipe_id pipe_id)
2381 {
2382         struct atomisp_device *isp = asd->isp;
2383         int ret;
2384         struct ia_css_pipe_info p_info;
2385
2386         /* FIXME! No need to destroy/recreate all streams */
2387         ret = atomisp_css_update_stream(asd);
2388         if (ret)
2389                 return ret;
2390
2391         ret = ia_css_pipe_get_info(asd->stream_env[stream_index].pipes[pipe_id],
2392                                    &p_info);
2393         if (ret) {
2394                 dev_err(isp->dev, "can't get info from pipe\n");
2395                 goto get_info_err;
2396         }
2397
2398         switch (type) {
2399         case ATOMISP_CSS_VF_FRAME:
2400                 *info = p_info.vf_output_info[0];
2401                 dev_dbg(isp->dev, "getting vf frame info.\n");
2402                 break;
2403         case ATOMISP_CSS_SECOND_VF_FRAME:
2404                 *info = p_info.vf_output_info[1];
2405                 dev_dbg(isp->dev, "getting second vf frame info.\n");
2406                 break;
2407         case ATOMISP_CSS_OUTPUT_FRAME:
2408                 *info = p_info.output_info[0];
2409                 dev_dbg(isp->dev, "getting main frame info.\n");
2410                 break;
2411         case ATOMISP_CSS_SECOND_OUTPUT_FRAME:
2412                 *info = p_info.output_info[1];
2413                 dev_dbg(isp->dev, "getting second main frame info.\n");
2414                 break;
2415         default:
2416         case ATOMISP_CSS_RAW_FRAME:
2417                 *info = p_info.raw_output_info;
2418                 dev_dbg(isp->dev, "getting raw frame info.\n");
2419                 break;
2420         }
2421         dev_dbg(isp->dev, "get frame info: w=%d, h=%d, num_invalid_frames %d.\n",
2422                 info->res.width, info->res.height, p_info.num_invalid_frames);
2423
2424         return 0;
2425
2426 get_info_err:
2427         atomisp_destroy_pipes_stream_force(asd);
2428         return -EINVAL;
2429 }
2430
2431 static unsigned int atomisp_get_pipe_index(struct atomisp_sub_device *asd,
2432         uint16_t source_pad)
2433 {
2434         struct atomisp_device *isp = asd->isp;
2435
2436         switch (source_pad) {
2437         case ATOMISP_SUBDEV_PAD_SOURCE_VIDEO:
2438                 if (asd->copy_mode)
2439                         return IA_CSS_PIPE_ID_COPY;
2440                 if (asd->run_mode->val == ATOMISP_RUN_MODE_VIDEO
2441                     || asd->vfpp->val == ATOMISP_VFPP_DISABLE_SCALER)
2442                         return IA_CSS_PIPE_ID_VIDEO;
2443
2444                 return IA_CSS_PIPE_ID_CAPTURE;
2445         case ATOMISP_SUBDEV_PAD_SOURCE_CAPTURE:
2446                 if (asd->copy_mode)
2447                         return IA_CSS_PIPE_ID_COPY;
2448
2449                 return IA_CSS_PIPE_ID_CAPTURE;
2450         case ATOMISP_SUBDEV_PAD_SOURCE_VF:
2451                 if (!atomisp_is_mbuscode_raw(asd->fmt[asd->capture_pad].fmt.code)) {
2452                         return IA_CSS_PIPE_ID_CAPTURE;
2453                 }
2454                 fallthrough;
2455         case ATOMISP_SUBDEV_PAD_SOURCE_PREVIEW:
2456                 if (asd->copy_mode)
2457                         return IA_CSS_PIPE_ID_COPY;
2458                 if (asd->run_mode->val == ATOMISP_RUN_MODE_VIDEO)
2459                         return IA_CSS_PIPE_ID_VIDEO;
2460
2461                 return IA_CSS_PIPE_ID_PREVIEW;
2462         }
2463         dev_warn(isp->dev,
2464                  "invalid source pad:%d, return default preview pipe index.\n",
2465                  source_pad);
2466         return IA_CSS_PIPE_ID_PREVIEW;
2467 }
2468
2469 int atomisp_get_css_frame_info(struct atomisp_sub_device *asd,
2470                                u16 source_pad,
2471                                struct ia_css_frame_info *frame_info)
2472 {
2473         struct ia_css_pipe_info info;
2474         int pipe_index = atomisp_get_pipe_index(asd, source_pad);
2475         int stream_index;
2476         struct atomisp_device *isp = asd->isp;
2477
2478         stream_index = (pipe_index == IA_CSS_PIPE_ID_YUVPP) ?
2479                                ATOMISP_INPUT_STREAM_VIDEO :
2480                                ATOMISP_INPUT_STREAM_GENERAL;
2481
2482         if (0 != ia_css_pipe_get_info(asd->stream_env[stream_index]
2483                 .pipes[pipe_index], &info)) {
2484                 dev_dbg(isp->dev, "ia_css_pipe_get_info FAILED");
2485                 return -EINVAL;
2486         }
2487
2488         switch (source_pad) {
2489         case ATOMISP_SUBDEV_PAD_SOURCE_CAPTURE:
2490                 *frame_info = info.output_info[0];
2491                 break;
2492         case ATOMISP_SUBDEV_PAD_SOURCE_VIDEO:
2493                 *frame_info = info.output_info[ATOMISP_CSS_OUTPUT_DEFAULT_INDEX];
2494                 break;
2495         case ATOMISP_SUBDEV_PAD_SOURCE_VF:
2496                 if (stream_index == ATOMISP_INPUT_STREAM_POSTVIEW)
2497                         *frame_info = info.output_info[0];
2498                 else
2499                         *frame_info = info.vf_output_info[0];
2500                 break;
2501         case ATOMISP_SUBDEV_PAD_SOURCE_PREVIEW:
2502                 if (asd->run_mode->val == ATOMISP_RUN_MODE_VIDEO &&
2503                     (pipe_index == IA_CSS_PIPE_ID_VIDEO ||
2504                      pipe_index == IA_CSS_PIPE_ID_YUVPP))
2505                         *frame_info = info.vf_output_info[ATOMISP_CSS_OUTPUT_DEFAULT_INDEX];
2506                 else
2507                         *frame_info =
2508                             info.output_info[ATOMISP_CSS_OUTPUT_DEFAULT_INDEX];
2509
2510                 break;
2511         default:
2512                 frame_info = NULL;
2513                 break;
2514         }
2515         return frame_info ? 0 : -EINVAL;
2516 }
2517
2518 int atomisp_css_copy_configure_output(struct atomisp_sub_device *asd,
2519                                       unsigned int stream_index,
2520                                       unsigned int width, unsigned int height,
2521                                       unsigned int padded_width,
2522                                       enum ia_css_frame_format format)
2523 {
2524         asd->stream_env[stream_index].pipe_configs[IA_CSS_PIPE_ID_COPY].
2525         default_capture_config.mode =
2526             IA_CSS_CAPTURE_MODE_RAW;
2527
2528         __configure_output(asd, stream_index, width, height, padded_width,
2529                            format, IA_CSS_PIPE_ID_COPY);
2530         return 0;
2531 }
2532
2533 int atomisp_css_yuvpp_configure_output(struct atomisp_sub_device *asd,
2534                                        unsigned int stream_index,
2535                                        unsigned int width, unsigned int height,
2536                                        unsigned int padded_width,
2537                                        enum ia_css_frame_format format)
2538 {
2539         asd->stream_env[stream_index].pipe_configs[IA_CSS_PIPE_ID_YUVPP].
2540         default_capture_config.mode =
2541             IA_CSS_CAPTURE_MODE_RAW;
2542
2543         __configure_output(asd, stream_index, width, height, padded_width,
2544                            format, IA_CSS_PIPE_ID_YUVPP);
2545         return 0;
2546 }
2547
2548 int atomisp_css_yuvpp_get_output_frame_info(
2549     struct atomisp_sub_device *asd,
2550     unsigned int stream_index,
2551     struct ia_css_frame_info *info)
2552 {
2553         return __get_frame_info(asd, stream_index, info,
2554                                 ATOMISP_CSS_OUTPUT_FRAME, IA_CSS_PIPE_ID_YUVPP);
2555 }
2556
2557 int atomisp_css_yuvpp_get_viewfinder_frame_info(
2558     struct atomisp_sub_device *asd,
2559     unsigned int stream_index,
2560     struct ia_css_frame_info *info)
2561 {
2562         return __get_frame_info(asd, stream_index, info,
2563                                 ATOMISP_CSS_VF_FRAME, IA_CSS_PIPE_ID_YUVPP);
2564 }
2565
2566 int atomisp_css_preview_configure_output(struct atomisp_sub_device *asd,
2567         unsigned int width, unsigned int height,
2568         unsigned int min_width,
2569         enum ia_css_frame_format format)
2570 {
2571         __configure_output(asd, ATOMISP_INPUT_STREAM_GENERAL, width, height,
2572                            min_width, format, IA_CSS_PIPE_ID_PREVIEW);
2573         return 0;
2574 }
2575
2576 int atomisp_css_capture_configure_output(struct atomisp_sub_device *asd,
2577         unsigned int width, unsigned int height,
2578         unsigned int min_width,
2579         enum ia_css_frame_format format)
2580 {
2581         __configure_output(asd, ATOMISP_INPUT_STREAM_GENERAL, width, height,
2582                            min_width, format, IA_CSS_PIPE_ID_CAPTURE);
2583         return 0;
2584 }
2585
2586 int atomisp_css_video_configure_output(struct atomisp_sub_device *asd,
2587                                        unsigned int width, unsigned int height,
2588                                        unsigned int min_width,
2589                                        enum ia_css_frame_format format)
2590 {
2591         __configure_output(asd, ATOMISP_INPUT_STREAM_GENERAL, width, height,
2592                            min_width, format, IA_CSS_PIPE_ID_VIDEO);
2593         return 0;
2594 }
2595
2596 int atomisp_css_video_configure_viewfinder(
2597     struct atomisp_sub_device *asd,
2598     unsigned int width, unsigned int height,
2599     unsigned int min_width,
2600     enum ia_css_frame_format format)
2601 {
2602         __configure_vf_output(asd, width, height, min_width, format,
2603                               IA_CSS_PIPE_ID_VIDEO);
2604         return 0;
2605 }
2606
2607 int atomisp_css_capture_configure_viewfinder(
2608     struct atomisp_sub_device *asd,
2609     unsigned int width, unsigned int height,
2610     unsigned int min_width,
2611     enum ia_css_frame_format format)
2612 {
2613         __configure_vf_output(asd, width, height, min_width, format, IA_CSS_PIPE_ID_CAPTURE);
2614         return 0;
2615 }
2616
2617 int atomisp_css_video_get_viewfinder_frame_info(
2618     struct atomisp_sub_device *asd,
2619     struct ia_css_frame_info *info)
2620 {
2621         return __get_frame_info(asd, ATOMISP_INPUT_STREAM_GENERAL, info,
2622                                 ATOMISP_CSS_VF_FRAME, IA_CSS_PIPE_ID_VIDEO);
2623 }
2624
2625 int atomisp_css_capture_get_viewfinder_frame_info(
2626     struct atomisp_sub_device *asd,
2627     struct ia_css_frame_info *info)
2628 {
2629         return __get_frame_info(asd, ATOMISP_INPUT_STREAM_GENERAL, info,
2630                                 ATOMISP_CSS_VF_FRAME, IA_CSS_PIPE_ID_CAPTURE);
2631 }
2632
2633 int atomisp_css_copy_get_output_frame_info(
2634     struct atomisp_sub_device *asd,
2635     unsigned int stream_index,
2636     struct ia_css_frame_info *info)
2637 {
2638         return __get_frame_info(asd, stream_index, info,
2639                                 ATOMISP_CSS_OUTPUT_FRAME, IA_CSS_PIPE_ID_COPY);
2640 }
2641
2642 int atomisp_css_preview_get_output_frame_info(
2643     struct atomisp_sub_device *asd,
2644     struct ia_css_frame_info *info)
2645 {
2646         return __get_frame_info(asd, ATOMISP_INPUT_STREAM_GENERAL, info,
2647                                 ATOMISP_CSS_OUTPUT_FRAME, IA_CSS_PIPE_ID_PREVIEW);
2648 }
2649
2650 int atomisp_css_capture_get_output_frame_info(
2651     struct atomisp_sub_device *asd,
2652     struct ia_css_frame_info *info)
2653 {
2654         return __get_frame_info(asd, ATOMISP_INPUT_STREAM_GENERAL, info,
2655                                 ATOMISP_CSS_OUTPUT_FRAME, IA_CSS_PIPE_ID_CAPTURE);
2656 }
2657
2658 int atomisp_css_video_get_output_frame_info(
2659     struct atomisp_sub_device *asd,
2660     struct ia_css_frame_info *info)
2661 {
2662         return __get_frame_info(asd, ATOMISP_INPUT_STREAM_GENERAL, info,
2663                                 ATOMISP_CSS_OUTPUT_FRAME, IA_CSS_PIPE_ID_VIDEO);
2664 }
2665
2666 int atomisp_css_preview_configure_pp_input(
2667     struct atomisp_sub_device *asd,
2668     unsigned int width, unsigned int height)
2669 {
2670         struct atomisp_stream_env *stream_env =
2671                     &asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL];
2672         __configure_preview_pp_input(asd, width, height, IA_CSS_PIPE_ID_PREVIEW);
2673
2674         if (width > stream_env->pipe_configs[IA_CSS_PIPE_ID_CAPTURE].
2675             capt_pp_in_res.width)
2676                 __configure_capture_pp_input(asd, width, height, IA_CSS_PIPE_ID_CAPTURE);
2677
2678         return 0;
2679 }
2680
2681 int atomisp_css_capture_configure_pp_input(
2682     struct atomisp_sub_device *asd,
2683     unsigned int width, unsigned int height)
2684 {
2685         __configure_capture_pp_input(asd, width, height, IA_CSS_PIPE_ID_CAPTURE);
2686         return 0;
2687 }
2688
2689 int atomisp_css_video_configure_pp_input(
2690     struct atomisp_sub_device *asd,
2691     unsigned int width, unsigned int height)
2692 {
2693         struct atomisp_stream_env *stream_env =
2694                     &asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL];
2695
2696         __configure_video_pp_input(asd, width, height, IA_CSS_PIPE_ID_VIDEO);
2697
2698         if (width > stream_env->pipe_configs[IA_CSS_PIPE_ID_CAPTURE].
2699             capt_pp_in_res.width)
2700                 __configure_capture_pp_input(asd, width, height, IA_CSS_PIPE_ID_CAPTURE);
2701
2702         return 0;
2703 }
2704
2705 int atomisp_css_offline_capture_configure(struct atomisp_sub_device *asd,
2706         int num_captures, unsigned int skip, int offset)
2707 {
2708         int ret;
2709
2710         dev_dbg(asd->isp->dev, "%s num_capture:%d skip:%d offset:%d\n",
2711                 __func__, num_captures, skip, offset);
2712
2713         ret = ia_css_stream_capture(
2714                   asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream,
2715                   num_captures, skip, offset);
2716         if (ret)
2717                 return -EINVAL;
2718
2719         return 0;
2720 }
2721
2722 int atomisp_css_exp_id_capture(struct atomisp_sub_device *asd, int exp_id)
2723 {
2724         int ret;
2725
2726         ret = ia_css_stream_capture_frame(
2727                   asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream,
2728                   exp_id);
2729         if (ret == -ENOBUFS) {
2730                 /* capture cmd queue is full */
2731                 return -EBUSY;
2732         } else if (ret) {
2733                 return -EIO;
2734         }
2735
2736         return 0;
2737 }
2738
2739 int atomisp_css_exp_id_unlock(struct atomisp_sub_device *asd, int exp_id)
2740 {
2741         int ret;
2742
2743         ret = ia_css_unlock_raw_frame(
2744                   asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream,
2745                   exp_id);
2746         if (ret == -ENOBUFS)
2747                 return -EAGAIN;
2748         else if (ret)
2749                 return -EIO;
2750
2751         return 0;
2752 }
2753
2754 int atomisp_css_capture_enable_xnr(struct atomisp_sub_device *asd,
2755                                    bool enable)
2756 {
2757         asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]
2758         .pipe_configs[IA_CSS_PIPE_ID_CAPTURE]
2759         .default_capture_config.enable_xnr = enable;
2760         asd->params.capture_config.enable_xnr = enable;
2761         asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]
2762         .update_pipe[IA_CSS_PIPE_ID_CAPTURE] = true;
2763
2764         return 0;
2765 }
2766
2767 void atomisp_css_set_ctc_table(struct atomisp_sub_device *asd,
2768                                struct ia_css_ctc_table *ctc_table)
2769 {
2770         int i;
2771         u16 *vamem_ptr = ctc_table->data.vamem_1;
2772         int data_size = IA_CSS_VAMEM_1_CTC_TABLE_SIZE;
2773         bool valid = false;
2774
2775         /* workaround: if ctc_table is all 0, do not apply it */
2776         if (ctc_table->vamem_type == IA_CSS_VAMEM_TYPE_2) {
2777                 vamem_ptr = ctc_table->data.vamem_2;
2778                 data_size = IA_CSS_VAMEM_2_CTC_TABLE_SIZE;
2779         }
2780
2781         for (i = 0; i < data_size; i++) {
2782                 if (*(vamem_ptr + i)) {
2783                         valid = true;
2784                         break;
2785                 }
2786         }
2787
2788         if (valid)
2789                 asd->params.config.ctc_table = ctc_table;
2790         else
2791                 dev_warn(asd->isp->dev, "Bypass the invalid ctc_table.\n");
2792 }
2793
2794 void atomisp_css_set_anr_thres(struct atomisp_sub_device *asd,
2795                                struct ia_css_anr_thres *anr_thres)
2796 {
2797         asd->params.config.anr_thres = anr_thres;
2798 }
2799
2800 void atomisp_css_set_dvs_6axis(struct atomisp_sub_device *asd,
2801                                struct ia_css_dvs_6axis_config *dvs_6axis)
2802 {
2803         asd->params.config.dvs_6axis_config = dvs_6axis;
2804 }
2805
2806 void atomisp_css_video_set_dis_vector(struct atomisp_sub_device *asd,
2807                                       struct atomisp_dis_vector *vector)
2808 {
2809         if (!asd->params.config.motion_vector)
2810                 asd->params.config.motion_vector = &asd->params.css_param.motion_vector;
2811
2812         memset(asd->params.config.motion_vector,
2813                0, sizeof(struct ia_css_vector));
2814         asd->params.css_param.motion_vector.x = vector->x;
2815         asd->params.css_param.motion_vector.y = vector->y;
2816 }
2817
2818 static int atomisp_compare_dvs_grid(struct atomisp_sub_device *asd,
2819                                     struct atomisp_dvs_grid_info *atomgrid)
2820 {
2821         struct ia_css_dvs_grid_info *cur =
2822             atomisp_css_get_dvs_grid_info(&asd->params.curr_grid_info);
2823
2824         if (!cur) {
2825                 dev_err(asd->isp->dev, "dvs grid not available!\n");
2826                 return -EINVAL;
2827         }
2828
2829         if (sizeof(*cur) != sizeof(*atomgrid)) {
2830                 dev_err(asd->isp->dev, "dvs grid mismatch!\n");
2831                 return -EINVAL;
2832         }
2833
2834         if (!cur->enable) {
2835                 dev_err(asd->isp->dev, "dvs not enabled!\n");
2836                 return -EINVAL;
2837         }
2838
2839         return memcmp(atomgrid, cur, sizeof(*cur));
2840 }
2841
2842 void  atomisp_css_set_dvs2_coefs(struct atomisp_sub_device *asd,
2843                                  struct ia_css_dvs2_coefficients *coefs)
2844 {
2845         asd->params.config.dvs2_coefs = coefs;
2846 }
2847
2848 int atomisp_css_set_dis_coefs(struct atomisp_sub_device *asd,
2849                               struct atomisp_dis_coefficients *coefs)
2850 {
2851         if (atomisp_compare_dvs_grid(asd, &coefs->grid_info) != 0)
2852                 /* If the grid info in the argument differs from the current
2853                    grid info, we tell the caller to reset the grid size and
2854                    try again. */
2855                 return -EAGAIN;
2856
2857         if (!coefs->hor_coefs.odd_real ||
2858             !coefs->hor_coefs.odd_imag ||
2859             !coefs->hor_coefs.even_real ||
2860             !coefs->hor_coefs.even_imag ||
2861             !coefs->ver_coefs.odd_real ||
2862             !coefs->ver_coefs.odd_imag ||
2863             !coefs->ver_coefs.even_real ||
2864             !coefs->ver_coefs.even_imag ||
2865             !asd->params.css_param.dvs2_coeff->hor_coefs.odd_real ||
2866             !asd->params.css_param.dvs2_coeff->hor_coefs.odd_imag ||
2867             !asd->params.css_param.dvs2_coeff->hor_coefs.even_real ||
2868             !asd->params.css_param.dvs2_coeff->hor_coefs.even_imag ||
2869             !asd->params.css_param.dvs2_coeff->ver_coefs.odd_real ||
2870             !asd->params.css_param.dvs2_coeff->ver_coefs.odd_imag ||
2871             !asd->params.css_param.dvs2_coeff->ver_coefs.even_real ||
2872             !asd->params.css_param.dvs2_coeff->ver_coefs.even_imag)
2873                 return -EINVAL;
2874
2875         if (copy_from_user(asd->params.css_param.dvs2_coeff->hor_coefs.odd_real,
2876                            coefs->hor_coefs.odd_real, asd->params.dvs_hor_coef_bytes))
2877                 return -EFAULT;
2878         if (copy_from_user(asd->params.css_param.dvs2_coeff->hor_coefs.odd_imag,
2879                            coefs->hor_coefs.odd_imag, asd->params.dvs_hor_coef_bytes))
2880                 return -EFAULT;
2881         if (copy_from_user(asd->params.css_param.dvs2_coeff->hor_coefs.even_real,
2882                            coefs->hor_coefs.even_real, asd->params.dvs_hor_coef_bytes))
2883                 return -EFAULT;
2884         if (copy_from_user(asd->params.css_param.dvs2_coeff->hor_coefs.even_imag,
2885                            coefs->hor_coefs.even_imag, asd->params.dvs_hor_coef_bytes))
2886                 return -EFAULT;
2887
2888         if (copy_from_user(asd->params.css_param.dvs2_coeff->ver_coefs.odd_real,
2889                            coefs->ver_coefs.odd_real, asd->params.dvs_ver_coef_bytes))
2890                 return -EFAULT;
2891         if (copy_from_user(asd->params.css_param.dvs2_coeff->ver_coefs.odd_imag,
2892                            coefs->ver_coefs.odd_imag, asd->params.dvs_ver_coef_bytes))
2893                 return -EFAULT;
2894         if (copy_from_user(asd->params.css_param.dvs2_coeff->ver_coefs.even_real,
2895                            coefs->ver_coefs.even_real, asd->params.dvs_ver_coef_bytes))
2896                 return -EFAULT;
2897         if (copy_from_user(asd->params.css_param.dvs2_coeff->ver_coefs.even_imag,
2898                            coefs->ver_coefs.even_imag, asd->params.dvs_ver_coef_bytes))
2899                 return -EFAULT;
2900
2901         asd->params.css_param.update_flag.dvs2_coefs =
2902                 (struct atomisp_dis_coefficients *)
2903                 asd->params.css_param.dvs2_coeff;
2904         /* FIXME! */
2905         /*      asd->params.dis_proj_data_valid = false; */
2906         asd->params.css_update_params_needed = true;
2907
2908         return 0;
2909 }
2910
2911 void atomisp_css_set_zoom_factor(struct atomisp_sub_device *asd,
2912                                  unsigned int zoom)
2913 {
2914         struct atomisp_device *isp = asd->isp;
2915
2916         if (zoom == asd->params.css_param.dz_config.dx &&
2917             zoom == asd->params.css_param.dz_config.dy) {
2918                 dev_dbg(isp->dev, "same zoom scale. skipped.\n");
2919                 return;
2920         }
2921
2922         memset(&asd->params.css_param.dz_config, 0,
2923                sizeof(struct ia_css_dz_config));
2924         asd->params.css_param.dz_config.dx = zoom;
2925         asd->params.css_param.dz_config.dy = zoom;
2926
2927         asd->params.css_param.update_flag.dz_config =
2928             (struct atomisp_dz_config *)&asd->params.css_param.dz_config;
2929         asd->params.css_update_params_needed = true;
2930 }
2931
2932 void atomisp_css_set_formats_config(struct atomisp_sub_device *asd,
2933                                     struct ia_css_formats_config *formats_config)
2934 {
2935         asd->params.config.formats_config = formats_config;
2936 }
2937
2938 int atomisp_css_get_wb_config(struct atomisp_sub_device *asd,
2939                               struct atomisp_wb_config *config)
2940 {
2941         struct ia_css_wb_config wb_config;
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         memset(&wb_config, 0, sizeof(struct ia_css_wb_config));
2951         memset(&isp_config, 0, sizeof(struct ia_css_isp_config));
2952         isp_config.wb_config = &wb_config;
2953         ia_css_stream_get_isp_config(
2954             asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream,
2955             &isp_config);
2956         memcpy(config, &wb_config, sizeof(*config));
2957
2958         return 0;
2959 }
2960
2961 int atomisp_css_get_ob_config(struct atomisp_sub_device *asd,
2962                               struct atomisp_ob_config *config)
2963 {
2964         struct ia_css_ob_config ob_config;
2965         struct ia_css_isp_config isp_config;
2966         struct atomisp_device *isp = asd->isp;
2967
2968         if (!asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream) {
2969                 dev_err(isp->dev, "%s called after streamoff, skipping.\n",
2970                         __func__);
2971                 return -EINVAL;
2972         }
2973         memset(&ob_config, 0, sizeof(struct ia_css_ob_config));
2974         memset(&isp_config, 0, sizeof(struct ia_css_isp_config));
2975         isp_config.ob_config = &ob_config;
2976         ia_css_stream_get_isp_config(
2977             asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream,
2978             &isp_config);
2979         memcpy(config, &ob_config, sizeof(*config));
2980
2981         return 0;
2982 }
2983
2984 int atomisp_css_get_dp_config(struct atomisp_sub_device *asd,
2985                               struct atomisp_dp_config *config)
2986 {
2987         struct ia_css_dp_config dp_config;
2988         struct ia_css_isp_config isp_config;
2989         struct atomisp_device *isp = asd->isp;
2990
2991         if (!asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream) {
2992                 dev_err(isp->dev, "%s called after streamoff, skipping.\n",
2993                         __func__);
2994                 return -EINVAL;
2995         }
2996         memset(&dp_config, 0, sizeof(struct ia_css_dp_config));
2997         memset(&isp_config, 0, sizeof(struct ia_css_isp_config));
2998         isp_config.dp_config = &dp_config;
2999         ia_css_stream_get_isp_config(
3000             asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream,
3001             &isp_config);
3002         memcpy(config, &dp_config, sizeof(*config));
3003
3004         return 0;
3005 }
3006
3007 int atomisp_css_get_de_config(struct atomisp_sub_device *asd,
3008                               struct atomisp_de_config *config)
3009 {
3010         struct ia_css_de_config de_config;
3011         struct ia_css_isp_config isp_config;
3012         struct atomisp_device *isp = asd->isp;
3013
3014         if (!asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream) {
3015                 dev_err(isp->dev, "%s called after streamoff, skipping.\n",
3016                         __func__);
3017                 return -EINVAL;
3018         }
3019         memset(&de_config, 0, sizeof(struct ia_css_de_config));
3020         memset(&isp_config, 0, sizeof(struct ia_css_isp_config));
3021         isp_config.de_config = &de_config;
3022         ia_css_stream_get_isp_config(
3023             asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream,
3024             &isp_config);
3025         memcpy(config, &de_config, sizeof(*config));
3026
3027         return 0;
3028 }
3029
3030 int atomisp_css_get_nr_config(struct atomisp_sub_device *asd,
3031                               struct atomisp_nr_config *config)
3032 {
3033         struct ia_css_nr_config nr_config;
3034         struct ia_css_isp_config isp_config;
3035         struct atomisp_device *isp = asd->isp;
3036
3037         if (!asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream) {
3038                 dev_err(isp->dev, "%s called after streamoff, skipping.\n",
3039                         __func__);
3040                 return -EINVAL;
3041         }
3042         memset(&nr_config, 0, sizeof(struct ia_css_nr_config));
3043         memset(&isp_config, 0, sizeof(struct ia_css_isp_config));
3044
3045         isp_config.nr_config = &nr_config;
3046         ia_css_stream_get_isp_config(
3047             asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream,
3048             &isp_config);
3049         memcpy(config, &nr_config, sizeof(*config));
3050
3051         return 0;
3052 }
3053
3054 int atomisp_css_get_ee_config(struct atomisp_sub_device *asd,
3055                               struct atomisp_ee_config *config)
3056 {
3057         struct ia_css_ee_config ee_config;
3058         struct ia_css_isp_config isp_config;
3059         struct atomisp_device *isp = asd->isp;
3060
3061         if (!asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream) {
3062                 dev_err(isp->dev, "%s called after streamoff, skipping.\n",
3063                         __func__);
3064                 return -EINVAL;
3065         }
3066         memset(&ee_config, 0, sizeof(struct ia_css_ee_config));
3067         memset(&isp_config, 0, sizeof(struct ia_css_isp_config));
3068         isp_config.ee_config = &ee_config;
3069         ia_css_stream_get_isp_config(
3070             asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream,
3071             &isp_config);
3072         memcpy(config, &ee_config, sizeof(*config));
3073
3074         return 0;
3075 }
3076
3077 int atomisp_css_get_tnr_config(struct atomisp_sub_device *asd,
3078                                struct atomisp_tnr_config *config)
3079 {
3080         struct ia_css_tnr_config tnr_config;
3081         struct ia_css_isp_config isp_config;
3082         struct atomisp_device *isp = asd->isp;
3083
3084         if (!asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream) {
3085                 dev_err(isp->dev, "%s called after streamoff, skipping.\n",
3086                         __func__);
3087                 return -EINVAL;
3088         }
3089         memset(&tnr_config, 0, sizeof(struct ia_css_tnr_config));
3090         memset(&isp_config, 0, sizeof(struct ia_css_isp_config));
3091         isp_config.tnr_config = &tnr_config;
3092         ia_css_stream_get_isp_config(
3093             asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream,
3094             &isp_config);
3095         memcpy(config, &tnr_config, sizeof(*config));
3096
3097         return 0;
3098 }
3099
3100 int atomisp_css_get_ctc_table(struct atomisp_sub_device *asd,
3101                               struct atomisp_ctc_table *config)
3102 {
3103         struct ia_css_ctc_table *tab;
3104         struct ia_css_isp_config isp_config;
3105         struct atomisp_device *isp = asd->isp;
3106
3107         if (!asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream) {
3108                 dev_err(isp->dev, "%s called after streamoff, skipping.\n",
3109                         __func__);
3110                 return -EINVAL;
3111         }
3112
3113         tab = vzalloc(sizeof(struct ia_css_ctc_table));
3114         if (!tab)
3115                 return -ENOMEM;
3116
3117         memset(&isp_config, 0, sizeof(struct ia_css_isp_config));
3118         isp_config.ctc_table = tab;
3119         ia_css_stream_get_isp_config(
3120             asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream,
3121             &isp_config);
3122         memcpy(config, tab, sizeof(*tab));
3123         vfree(tab);
3124
3125         return 0;
3126 }
3127
3128 int atomisp_css_get_gamma_table(struct atomisp_sub_device *asd,
3129                                 struct atomisp_gamma_table *config)
3130 {
3131         struct ia_css_gamma_table *tab;
3132         struct ia_css_isp_config isp_config;
3133         struct atomisp_device *isp = asd->isp;
3134
3135         if (!asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream) {
3136                 dev_err(isp->dev, "%s called after streamoff, skipping.\n",
3137                         __func__);
3138                 return -EINVAL;
3139         }
3140
3141         tab = vzalloc(sizeof(struct ia_css_gamma_table));
3142         if (!tab)
3143                 return -ENOMEM;
3144
3145         memset(&isp_config, 0, sizeof(struct ia_css_isp_config));
3146         isp_config.gamma_table = tab;
3147         ia_css_stream_get_isp_config(
3148             asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream,
3149             &isp_config);
3150         memcpy(config, tab, sizeof(*tab));
3151         vfree(tab);
3152
3153         return 0;
3154 }
3155
3156 int atomisp_css_get_gc_config(struct atomisp_sub_device *asd,
3157                               struct atomisp_gc_config *config)
3158 {
3159         struct ia_css_gc_config gc_config;
3160         struct ia_css_isp_config isp_config;
3161         struct atomisp_device *isp = asd->isp;
3162
3163         if (!asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream) {
3164                 dev_err(isp->dev, "%s called after streamoff, skipping.\n",
3165                         __func__);
3166                 return -EINVAL;
3167         }
3168         memset(&gc_config, 0, sizeof(struct ia_css_gc_config));
3169         memset(&isp_config, 0, sizeof(struct ia_css_isp_config));
3170         isp_config.gc_config = &gc_config;
3171         ia_css_stream_get_isp_config(
3172             asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream,
3173             &isp_config);
3174         /* Get gamma correction params from current setup */
3175         memcpy(config, &gc_config, sizeof(*config));
3176
3177         return 0;
3178 }
3179
3180 int atomisp_css_get_3a_config(struct atomisp_sub_device *asd,
3181                               struct atomisp_3a_config *config)
3182 {
3183         struct ia_css_3a_config s3a_config;
3184         struct ia_css_isp_config isp_config;
3185         struct atomisp_device *isp = asd->isp;
3186
3187         if (!asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream) {
3188                 dev_err(isp->dev, "%s called after streamoff, skipping.\n",
3189                         __func__);
3190                 return -EINVAL;
3191         }
3192         memset(&s3a_config, 0, sizeof(struct ia_css_3a_config));
3193         memset(&isp_config, 0, sizeof(struct ia_css_isp_config));
3194         isp_config.s3a_config = &s3a_config;
3195         ia_css_stream_get_isp_config(
3196             asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream,
3197             &isp_config);
3198         /* Get white balance from current setup */
3199         memcpy(config, &s3a_config, sizeof(*config));
3200
3201         return 0;
3202 }
3203
3204 int atomisp_css_get_formats_config(struct atomisp_sub_device *asd,
3205                                    struct atomisp_formats_config *config)
3206 {
3207         struct ia_css_formats_config formats_config;
3208         struct ia_css_isp_config isp_config;
3209         struct atomisp_device *isp = asd->isp;
3210
3211         if (!asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream) {
3212                 dev_err(isp->dev, "%s called after streamoff, skipping.\n",
3213                         __func__);
3214                 return -EINVAL;
3215         }
3216         memset(&formats_config, 0, sizeof(formats_config));
3217         memset(&isp_config, 0, sizeof(isp_config));
3218         isp_config.formats_config = &formats_config;
3219         ia_css_stream_get_isp_config(
3220             asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream,
3221             &isp_config);
3222         /* Get narrow gamma from current setup */
3223         memcpy(config, &formats_config, sizeof(*config));
3224
3225         return 0;
3226 }
3227
3228 int atomisp_css_get_zoom_factor(struct atomisp_sub_device *asd,
3229                                 unsigned int *zoom)
3230 {
3231         struct ia_css_dz_config dz_config;  /** Digital Zoom */
3232         struct ia_css_isp_config isp_config;
3233         struct atomisp_device *isp = asd->isp;
3234
3235         if (!asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream) {
3236                 dev_err(isp->dev, "%s called after streamoff, skipping.\n",
3237                         __func__);
3238                 return -EINVAL;
3239         }
3240         memset(&dz_config, 0, sizeof(struct ia_css_dz_config));
3241         memset(&isp_config, 0, sizeof(struct ia_css_isp_config));
3242         isp_config.dz_config = &dz_config;
3243         ia_css_stream_get_isp_config(
3244             asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream,
3245             &isp_config);
3246         *zoom = dz_config.dx;
3247
3248         return 0;
3249 }
3250
3251 /*
3252  * Function to set/get image stablization statistics
3253  */
3254 int atomisp_css_get_dis_stat(struct atomisp_sub_device *asd,
3255                              struct atomisp_dis_statistics *stats)
3256 {
3257         struct atomisp_device *isp = asd->isp;
3258         struct atomisp_dis_buf *dis_buf;
3259         unsigned long flags;
3260
3261         lockdep_assert_held(&isp->mutex);
3262
3263         if (!asd->params.dvs_stat->hor_prod.odd_real ||
3264             !asd->params.dvs_stat->hor_prod.odd_imag ||
3265             !asd->params.dvs_stat->hor_prod.even_real ||
3266             !asd->params.dvs_stat->hor_prod.even_imag ||
3267             !asd->params.dvs_stat->ver_prod.odd_real ||
3268             !asd->params.dvs_stat->ver_prod.odd_imag ||
3269             !asd->params.dvs_stat->ver_prod.even_real ||
3270             !asd->params.dvs_stat->ver_prod.even_imag)
3271                 return -EINVAL;
3272
3273         /* isp needs to be streaming to get DIS statistics */
3274         if (asd->streaming != ATOMISP_DEVICE_STREAMING_ENABLED)
3275                 return -EINVAL;
3276
3277         if (atomisp_compare_dvs_grid(asd, &stats->dvs2_stat.grid_info) != 0)
3278                 /* If the grid info in the argument differs from the current
3279                    grid info, we tell the caller to reset the grid size and
3280                    try again. */
3281                 return -EAGAIN;
3282
3283         spin_lock_irqsave(&asd->dis_stats_lock, flags);
3284         if (!asd->params.dis_proj_data_valid || list_empty(&asd->dis_stats)) {
3285                 spin_unlock_irqrestore(&asd->dis_stats_lock, flags);
3286                 dev_err(isp->dev, "dis statistics is not valid.\n");
3287                 return -EAGAIN;
3288         }
3289
3290         dis_buf = list_entry(asd->dis_stats.next,
3291                              struct atomisp_dis_buf, list);
3292         list_del_init(&dis_buf->list);
3293         spin_unlock_irqrestore(&asd->dis_stats_lock, flags);
3294
3295         if (dis_buf->dvs_map)
3296                 ia_css_translate_dvs2_statistics(
3297                     asd->params.dvs_stat, dis_buf->dvs_map);
3298         else
3299                 ia_css_get_dvs2_statistics(asd->params.dvs_stat,
3300                                            dis_buf->dis_data);
3301         stats->exp_id = dis_buf->dis_data->exp_id;
3302
3303         spin_lock_irqsave(&asd->dis_stats_lock, flags);
3304         list_add_tail(&dis_buf->list, &asd->dis_stats);
3305         spin_unlock_irqrestore(&asd->dis_stats_lock, flags);
3306
3307         if (copy_to_user(stats->dvs2_stat.ver_prod.odd_real,
3308                          asd->params.dvs_stat->ver_prod.odd_real,
3309                          asd->params.dvs_ver_proj_bytes))
3310                 return -EFAULT;
3311         if (copy_to_user(stats->dvs2_stat.ver_prod.odd_imag,
3312                          asd->params.dvs_stat->ver_prod.odd_imag,
3313                          asd->params.dvs_ver_proj_bytes))
3314                 return -EFAULT;
3315         if (copy_to_user(stats->dvs2_stat.ver_prod.even_real,
3316                          asd->params.dvs_stat->ver_prod.even_real,
3317                          asd->params.dvs_ver_proj_bytes))
3318                 return -EFAULT;
3319         if (copy_to_user(stats->dvs2_stat.ver_prod.even_imag,
3320                          asd->params.dvs_stat->ver_prod.even_imag,
3321                          asd->params.dvs_ver_proj_bytes))
3322                 return -EFAULT;
3323         if (copy_to_user(stats->dvs2_stat.hor_prod.odd_real,
3324                          asd->params.dvs_stat->hor_prod.odd_real,
3325                          asd->params.dvs_hor_proj_bytes))
3326                 return -EFAULT;
3327         if (copy_to_user(stats->dvs2_stat.hor_prod.odd_imag,
3328                          asd->params.dvs_stat->hor_prod.odd_imag,
3329                          asd->params.dvs_hor_proj_bytes))
3330                 return -EFAULT;
3331         if (copy_to_user(stats->dvs2_stat.hor_prod.even_real,
3332                          asd->params.dvs_stat->hor_prod.even_real,
3333                          asd->params.dvs_hor_proj_bytes))
3334                 return -EFAULT;
3335         if (copy_to_user(stats->dvs2_stat.hor_prod.even_imag,
3336                          asd->params.dvs_stat->hor_prod.even_imag,
3337                          asd->params.dvs_hor_proj_bytes))
3338                 return -EFAULT;
3339
3340         return 0;
3341 }
3342
3343 struct ia_css_shading_table *atomisp_css_shading_table_alloc(
3344     unsigned int width, unsigned int height)
3345 {
3346         return ia_css_shading_table_alloc(width, height);
3347 }
3348
3349 void atomisp_css_set_shading_table(struct atomisp_sub_device *asd,
3350                                    struct ia_css_shading_table *table)
3351 {
3352         asd->params.config.shading_table = table;
3353 }
3354
3355 void atomisp_css_shading_table_free(struct ia_css_shading_table *table)
3356 {
3357         ia_css_shading_table_free(table);
3358 }
3359
3360 struct ia_css_morph_table *atomisp_css_morph_table_allocate(
3361     unsigned int width, unsigned int height)
3362 {
3363         return ia_css_morph_table_allocate(width, height);
3364 }
3365
3366 void atomisp_css_set_morph_table(struct atomisp_sub_device *asd,
3367                                  struct ia_css_morph_table *table)
3368 {
3369         asd->params.config.morph_table = table;
3370 }
3371
3372 void atomisp_css_get_morph_table(struct atomisp_sub_device *asd,
3373                                  struct ia_css_morph_table *table)
3374 {
3375         struct ia_css_isp_config isp_config;
3376         struct atomisp_device *isp = asd->isp;
3377
3378         if (!asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream) {
3379                 dev_err(isp->dev,
3380                         "%s called after streamoff, skipping.\n", __func__);
3381                 return;
3382         }
3383         memset(table, 0, sizeof(struct ia_css_morph_table));
3384         memset(&isp_config, 0, sizeof(struct ia_css_isp_config));
3385         isp_config.morph_table = table;
3386         ia_css_stream_get_isp_config(
3387             asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream,
3388             &isp_config);
3389 }
3390
3391 void atomisp_css_morph_table_free(struct ia_css_morph_table *table)
3392 {
3393         ia_css_morph_table_free(table);
3394 }
3395
3396 static bool atomisp_css_isr_get_stream_id(struct ia_css_pipe *css_pipe,
3397                                           struct atomisp_device *isp,
3398                                           enum atomisp_input_stream_id *stream_id)
3399 {
3400         struct atomisp_stream_env *stream_env;
3401         int i, j;
3402
3403         if (isp->asd.streaming == ATOMISP_DEVICE_STREAMING_DISABLED)
3404                 return false;
3405
3406         for (i = 0; i < ATOMISP_INPUT_STREAM_NUM; i++) {
3407                 stream_env = &isp->asd.stream_env[i];
3408                 for (j = 0; j < IA_CSS_PIPE_ID_NUM; j++) {
3409                         if (stream_env->pipes[j] && stream_env->pipes[j] == css_pipe) {
3410                                 *stream_id = i;
3411                                 return true;
3412                         }
3413                 }
3414         }
3415
3416         return false;
3417 }
3418
3419 int atomisp_css_isr_thread(struct atomisp_device *isp)
3420 {
3421         enum atomisp_input_stream_id stream_id = 0;
3422         struct atomisp_css_event current_event;
3423
3424         lockdep_assert_held(&isp->mutex);
3425
3426         while (!ia_css_dequeue_psys_event(&current_event.event)) {
3427                 if (current_event.event.type ==
3428                     IA_CSS_EVENT_TYPE_FW_ASSERT) {
3429                         /*
3430                          * Received FW assertion signal,
3431                          * trigger WDT to recover
3432                          */
3433                         dev_err(isp->dev,
3434                                 "%s: ISP reports FW_ASSERT event! fw_assert_module_id %d fw_assert_line_no %d\n",
3435                                 __func__,
3436                                 current_event.event.fw_assert_module_id,
3437                                 current_event.event.fw_assert_line_no);
3438
3439                         queue_work(system_long_wq, &isp->assert_recovery_work);
3440                         return -EINVAL;
3441                 } else if (current_event.event.type == IA_CSS_EVENT_TYPE_FW_WARNING) {
3442                         dev_warn(isp->dev, "%s: ISP reports warning, code is %d, exp_id %d\n",
3443                                  __func__, current_event.event.fw_warning,
3444                                  current_event.event.exp_id);
3445                         continue;
3446                 }
3447
3448                 if (!atomisp_css_isr_get_stream_id(current_event.event.pipe, isp, &stream_id)) {
3449                         if (current_event.event.type == IA_CSS_EVENT_TYPE_TIMER)
3450                                 dev_dbg(isp->dev,
3451                                         "event: Timer event.");
3452                         else
3453                                 dev_warn(isp->dev, "%s:no subdev.event:%d",
3454                                          __func__,
3455                                          current_event.event.type);
3456                         continue;
3457                 }
3458
3459                 atomisp_css_temp_pipe_to_pipe_id(&isp->asd, &current_event);
3460                 switch (current_event.event.type) {
3461                 case IA_CSS_EVENT_TYPE_OUTPUT_FRAME_DONE:
3462                         dev_dbg(isp->dev, "event: Output frame done");
3463                         atomisp_buf_done(&isp->asd, 0, IA_CSS_BUFFER_TYPE_OUTPUT_FRAME,
3464                                          current_event.pipe, true, stream_id);
3465                         break;
3466                 case IA_CSS_EVENT_TYPE_SECOND_OUTPUT_FRAME_DONE:
3467                         dev_dbg(isp->dev, "event: Second output frame done");
3468                         atomisp_buf_done(&isp->asd, 0, IA_CSS_BUFFER_TYPE_SEC_OUTPUT_FRAME,
3469                                          current_event.pipe, true, stream_id);
3470                         break;
3471                 case IA_CSS_EVENT_TYPE_3A_STATISTICS_DONE:
3472                         dev_dbg(isp->dev, "event: 3A stats frame done");
3473                         atomisp_buf_done(&isp->asd, 0,
3474                                          IA_CSS_BUFFER_TYPE_3A_STATISTICS,
3475                                          current_event.pipe,
3476                                          false, stream_id);
3477                         break;
3478                 case IA_CSS_EVENT_TYPE_METADATA_DONE:
3479                         dev_dbg(isp->dev, "event: metadata frame done");
3480                         atomisp_buf_done(&isp->asd, 0,
3481                                          IA_CSS_BUFFER_TYPE_METADATA,
3482                                          current_event.pipe,
3483                                          false, stream_id);
3484                         break;
3485                 case IA_CSS_EVENT_TYPE_VF_OUTPUT_FRAME_DONE:
3486                         dev_dbg(isp->dev, "event: VF output frame done");
3487                         atomisp_buf_done(&isp->asd, 0,
3488                                          IA_CSS_BUFFER_TYPE_VF_OUTPUT_FRAME,
3489                                          current_event.pipe, true, stream_id);
3490                         break;
3491                 case IA_CSS_EVENT_TYPE_SECOND_VF_OUTPUT_FRAME_DONE:
3492                         dev_dbg(isp->dev, "event: second VF output frame done");
3493                         atomisp_buf_done(&isp->asd, 0,
3494                                          IA_CSS_BUFFER_TYPE_SEC_VF_OUTPUT_FRAME,
3495                                          current_event.pipe, true, stream_id);
3496                         break;
3497                 case IA_CSS_EVENT_TYPE_DIS_STATISTICS_DONE:
3498                         dev_dbg(isp->dev, "event: dis stats frame done");
3499                         atomisp_buf_done(&isp->asd, 0,
3500                                          IA_CSS_BUFFER_TYPE_DIS_STATISTICS,
3501                                          current_event.pipe,
3502                                          false, stream_id);
3503                         break;
3504                 case IA_CSS_EVENT_TYPE_PIPELINE_DONE:
3505                         dev_dbg(isp->dev, "event: pipeline done");
3506                         break;
3507                 case IA_CSS_EVENT_TYPE_ACC_STAGE_COMPLETE:
3508                         dev_warn(isp->dev, "unexpected event: acc stage done");
3509                         break;
3510                 default:
3511                         dev_dbg(isp->dev, "unhandled css stored event: 0x%x\n",
3512                                 current_event.event.type);
3513                         break;
3514                 }
3515         }
3516
3517         return 0;
3518 }
3519
3520 bool atomisp_css_valid_sof(struct atomisp_device *isp)
3521 {
3522         unsigned int i;
3523
3524         /* Loop for each css vc stream */
3525         for (i = 0; i < ATOMISP_INPUT_STREAM_NUM; i++) {
3526                 if (!isp->asd.stream_env[i].stream)
3527                         continue;
3528
3529                 dev_dbg(isp->dev, "stream #%d: mode: %d\n",
3530                         i, isp->asd.stream_env[i].stream_config.mode);
3531                 if (isp->asd.stream_env[i].stream_config.mode == IA_CSS_INPUT_MODE_BUFFERED_SENSOR)
3532                         return false;
3533         }
3534
3535         return true;
3536 }
3537
3538 int atomisp_css_debug_dump_isp_binary(void)
3539 {
3540         ia_css_debug_dump_isp_binary();
3541         return 0;
3542 }
3543
3544 int atomisp_css_dump_sp_raw_copy_linecount(bool reduced)
3545 {
3546         sh_css_dump_sp_raw_copy_linecount(reduced);
3547         return 0;
3548 }
3549
3550 static const char * const fw_type_name[] = {
3551         [ia_css_sp_firmware]            = "SP",
3552         [ia_css_isp_firmware]           = "ISP",
3553         [ia_css_bootloader_firmware]    = "BootLoader",
3554         [ia_css_acc_firmware]           = "accel",
3555 };
3556
3557 static const char * const fw_acc_type_name[] = {
3558         [IA_CSS_ACC_NONE] =             "Normal",
3559         [IA_CSS_ACC_OUTPUT] =           "Accel stage on output",
3560         [IA_CSS_ACC_VIEWFINDER] =       "Accel stage on viewfinder",
3561         [IA_CSS_ACC_STANDALONE] =       "Stand-alone acceleration",
3562 };
3563
3564 int atomisp_css_dump_blob_infor(struct atomisp_device *isp)
3565 {
3566         struct ia_css_blob_descr *bd = sh_css_blob_info;
3567         unsigned int i, nm = sh_css_num_binaries;
3568
3569         if (nm == 0)
3570                 return -EPERM;
3571         if (!bd)
3572                 return -EPERM;
3573
3574         /*
3575          * The sh_css_load_firmware function discard the initial
3576          * "SPS" binaries
3577          */
3578         for (i = 0; i < sh_css_num_binaries - NUM_OF_SPS; i++) {
3579                 switch (bd[i].header.type) {
3580                 case ia_css_isp_firmware:
3581                         dev_dbg(isp->dev, "Num%2d type %s (%s), binary id is %2d, name is %s\n",
3582                                 i + NUM_OF_SPS,
3583                                 fw_type_name[bd[i].header.type],
3584                                 fw_acc_type_name[bd[i].header.info.isp.type],
3585                                 bd[i].header.info.isp.sp.id,
3586                                 bd[i].name);
3587                         break;
3588                 default:
3589                         dev_dbg(isp->dev, "Num%2d type %s, name is %s\n",
3590                                 i + NUM_OF_SPS, fw_type_name[bd[i].header.type],
3591                                 bd[i].name);
3592                 }
3593         }
3594
3595         return 0;
3596 }
3597
3598 void atomisp_css_set_isp_config_id(struct atomisp_sub_device *asd,
3599                                    uint32_t isp_config_id)
3600 {
3601         asd->params.config.isp_config_id = isp_config_id;
3602 }
3603
3604 void atomisp_css_set_isp_config_applied_frame(struct atomisp_sub_device *asd,
3605         struct ia_css_frame *output_frame)
3606 {
3607         asd->params.config.output_frame = output_frame;
3608 }
3609
3610 int atomisp_get_css_dbgfunc(void)
3611 {
3612         return dbg_func;
3613 }
3614
3615 int atomisp_set_css_dbgfunc(struct atomisp_device *isp, int opt)
3616 {
3617         int ret;
3618
3619         ret = __set_css_print_env(isp, opt);
3620         if (ret == 0)
3621                 dbg_func = opt;
3622
3623         return ret;
3624 }
3625
3626 void atomisp_en_dz_capt_pipe(struct atomisp_sub_device *asd, bool enable)
3627 {
3628         ia_css_en_dz_capt_pipe(
3629             asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream,
3630             enable);
3631 }
3632
3633 struct ia_css_dvs_grid_info *atomisp_css_get_dvs_grid_info(
3634     struct ia_css_grid_info *grid_info)
3635 {
3636         if (!grid_info)
3637                 return NULL;
3638
3639 #ifdef IA_CSS_DVS_STAT_GRID_INFO_SUPPORTED
3640         return &grid_info->dvs_grid.dvs_grid_info;
3641 #else
3642         return &grid_info->dvs_grid;
3643 #endif
3644 }