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