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