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