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