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