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