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