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