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