1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Support for Medifield PNW Camera Imaging ISP subsystem. 4 * 5 * Copyright (c) 2010 Intel Corporation. All Rights Reserved. 6 * 7 * Copyright (c) 2010 Silicon Hive www.siliconhive.com. 8 * 9 * This program is free software; you can redistribute it and/or 10 * modify it under the terms of the GNU General Public License version 11 * 2 as published by the Free Software Foundation. 12 * 13 * This program is distributed in the hope that it will be useful, 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 * GNU General Public License for more details. 17 * 18 * 19 */ 20 #include <linux/errno.h> 21 #include <linux/firmware.h> 22 #include <linux/pci.h> 23 #include <linux/interrupt.h> 24 #include <linux/kernel.h> 25 #include <linux/kfifo.h> 26 #include <linux/pm_runtime.h> 27 #include <linux/timer.h> 28 29 #include <asm/iosf_mbi.h> 30 31 #include <media/v4l2-event.h> 32 #include <media/videobuf-vmalloc.h> 33 34 #define CREATE_TRACE_POINTS 35 #include "atomisp_trace_event.h" 36 37 #include "atomisp_cmd.h" 38 #include "atomisp_common.h" 39 #include "atomisp_fops.h" 40 #include "atomisp_internal.h" 41 #include "atomisp_ioctl.h" 42 #include "atomisp-regs.h" 43 #include "atomisp_tables.h" 44 #include "atomisp_acc.h" 45 #include "atomisp_compat.h" 46 #include "atomisp_subdev.h" 47 #include "atomisp_dfs_tables.h" 48 49 #include <hmm/hmm.h> 50 51 #include "sh_css_hrt.h" 52 #include "sh_css_defs.h" 53 #include "system_global.h" 54 #include "sh_css_internal.h" 55 #include "sh_css_sp.h" 56 #include "gp_device.h" 57 #include "device_access.h" 58 #include "irq.h" 59 60 #include "ia_css_types.h" 61 #include "ia_css_stream.h" 62 #include "ia_css_debug.h" 63 #include "bits.h" 64 65 /* We should never need to run the flash for more than 2 frames. 66 * At 15fps this means 133ms. We set the timeout a bit longer. 67 * Each flash driver is supposed to set its own timeout, but 68 * just in case someone else changed the timeout, we set it 69 * here to make sure we don't damage the flash hardware. */ 70 #define FLASH_TIMEOUT 800 /* ms */ 71 72 union host { 73 struct { 74 void *kernel_ptr; 75 void __user *user_ptr; 76 int size; 77 } scalar; 78 struct { 79 void *hmm_ptr; 80 } ptr; 81 }; 82 83 /* 84 * get sensor:dis71430/ov2720 related info from v4l2_subdev->priv data field. 85 * subdev->priv is set in mrst.c 86 */ 87 struct camera_mipi_info *atomisp_to_sensor_mipi_info(struct v4l2_subdev *sd) 88 { 89 return (struct camera_mipi_info *)v4l2_get_subdev_hostdata(sd); 90 } 91 92 /* 93 * get struct atomisp_video_pipe from v4l2 video_device 94 */ 95 struct atomisp_video_pipe *atomisp_to_video_pipe(struct video_device *dev) 96 { 97 return (struct atomisp_video_pipe *) 98 container_of(dev, struct atomisp_video_pipe, vdev); 99 } 100 101 /* 102 * get struct atomisp_acc_pipe from v4l2 video_device 103 */ 104 struct atomisp_acc_pipe *atomisp_to_acc_pipe(struct video_device *dev) 105 { 106 return (struct atomisp_acc_pipe *) 107 container_of(dev, struct atomisp_acc_pipe, vdev); 108 } 109 110 static unsigned short atomisp_get_sensor_fps(struct atomisp_sub_device *asd) 111 { 112 struct v4l2_subdev_frame_interval fi; 113 struct atomisp_device *isp = asd->isp; 114 115 unsigned short fps = 0; 116 int ret; 117 118 ret = v4l2_subdev_call(isp->inputs[asd->input_curr].camera, 119 video, g_frame_interval, &fi); 120 121 if (!ret && fi.interval.numerator) 122 fps = fi.interval.denominator / fi.interval.numerator; 123 124 return fps; 125 } 126 127 /* 128 * DFS progress is shown as follows: 129 * 1. Target frequency is calculated according to FPS/Resolution/ISP running 130 * mode. 131 * 2. Ratio is calculated using formula: 2 * HPLL / target frequency - 1 132 * with proper rounding. 133 * 3. Set ratio to ISPFREQ40, 1 to FREQVALID and ISPFREQGUAR40 134 * to 200MHz in ISPSSPM1. 135 * 4. Wait for FREQVALID to be cleared by P-Unit. 136 * 5. Wait for field ISPFREQSTAT40 in ISPSSPM1 turn to ratio set in 3. 137 */ 138 static int write_target_freq_to_hw(struct atomisp_device *isp, 139 unsigned int new_freq) 140 { 141 unsigned int ratio, timeout, guar_ratio; 142 u32 isp_sspm1 = 0; 143 int i; 144 145 if (!isp->hpll_freq) { 146 dev_err(isp->dev, "failed to get hpll_freq. no change to freq\n"); 147 return -EINVAL; 148 } 149 150 iosf_mbi_read(BT_MBI_UNIT_PMC, MBI_REG_READ, ISPSSPM1, &isp_sspm1); 151 if (isp_sspm1 & ISP_FREQ_VALID_MASK) { 152 dev_dbg(isp->dev, "clearing ISPSSPM1 valid bit.\n"); 153 iosf_mbi_write(BT_MBI_UNIT_PMC, MBI_REG_WRITE, ISPSSPM1, 154 isp_sspm1 & ~(1 << ISP_FREQ_VALID_OFFSET)); 155 } 156 157 ratio = (2 * isp->hpll_freq + new_freq / 2) / new_freq - 1; 158 guar_ratio = (2 * isp->hpll_freq + 200 / 2) / 200 - 1; 159 160 iosf_mbi_read(BT_MBI_UNIT_PMC, MBI_REG_READ, ISPSSPM1, &isp_sspm1); 161 isp_sspm1 &= ~(0x1F << ISP_REQ_FREQ_OFFSET); 162 163 for (i = 0; i < ISP_DFS_TRY_TIMES; i++) { 164 iosf_mbi_write(BT_MBI_UNIT_PMC, MBI_REG_WRITE, ISPSSPM1, 165 isp_sspm1 166 | ratio << ISP_REQ_FREQ_OFFSET 167 | 1 << ISP_FREQ_VALID_OFFSET 168 | guar_ratio << ISP_REQ_GUAR_FREQ_OFFSET); 169 170 iosf_mbi_read(BT_MBI_UNIT_PMC, MBI_REG_READ, ISPSSPM1, &isp_sspm1); 171 timeout = 20; 172 while ((isp_sspm1 & ISP_FREQ_VALID_MASK) && timeout) { 173 iosf_mbi_read(BT_MBI_UNIT_PMC, MBI_REG_READ, ISPSSPM1, &isp_sspm1); 174 dev_dbg(isp->dev, "waiting for ISPSSPM1 valid bit to be 0.\n"); 175 udelay(100); 176 timeout--; 177 } 178 179 if (timeout != 0) 180 break; 181 } 182 183 if (timeout == 0) { 184 dev_err(isp->dev, "DFS failed due to HW error.\n"); 185 return -EINVAL; 186 } 187 188 iosf_mbi_read(BT_MBI_UNIT_PMC, MBI_REG_READ, ISPSSPM1, &isp_sspm1); 189 timeout = 10; 190 while (((isp_sspm1 >> ISP_FREQ_STAT_OFFSET) != ratio) && timeout) { 191 iosf_mbi_read(BT_MBI_UNIT_PMC, MBI_REG_READ, ISPSSPM1, &isp_sspm1); 192 dev_dbg(isp->dev, "waiting for ISPSSPM1 status bit to be 0x%x.\n", 193 new_freq); 194 udelay(100); 195 timeout--; 196 } 197 if (timeout == 0) { 198 dev_err(isp->dev, "DFS target freq is rejected by HW.\n"); 199 return -EINVAL; 200 } 201 202 return 0; 203 } 204 205 int atomisp_freq_scaling(struct atomisp_device *isp, 206 enum atomisp_dfs_mode mode, 207 bool force) 208 { 209 /* FIXME! Only use subdev[0] status yet */ 210 struct atomisp_sub_device *asd = &isp->asd[0]; 211 const struct atomisp_dfs_config *dfs; 212 unsigned int new_freq; 213 struct atomisp_freq_scaling_rule curr_rules; 214 int i, ret; 215 unsigned short fps = 0; 216 217 if (isp->sw_contex.power_state != ATOM_ISP_POWER_UP) { 218 dev_err(isp->dev, "DFS cannot proceed due to no power.\n"); 219 return -EINVAL; 220 } 221 222 if ((isp->pdev->device & ATOMISP_PCI_DEVICE_SOC_MASK) == 223 ATOMISP_PCI_DEVICE_SOC_CHT && ATOMISP_USE_YUVPP(asd)) 224 isp->dfs = &dfs_config_cht_soc; 225 226 dfs = isp->dfs; 227 228 if (dfs->lowest_freq == 0 || dfs->max_freq_at_vmin == 0 || 229 dfs->highest_freq == 0 || dfs->dfs_table_size == 0 || 230 !dfs->dfs_table) { 231 dev_err(isp->dev, "DFS configuration is invalid.\n"); 232 return -EINVAL; 233 } 234 235 if (mode == ATOMISP_DFS_MODE_LOW) { 236 new_freq = dfs->lowest_freq; 237 goto done; 238 } 239 240 if (mode == ATOMISP_DFS_MODE_MAX) { 241 new_freq = dfs->highest_freq; 242 goto done; 243 } 244 245 fps = atomisp_get_sensor_fps(asd); 246 if (fps == 0) 247 return -EINVAL; 248 249 curr_rules.width = asd->fmt[asd->capture_pad].fmt.width; 250 curr_rules.height = asd->fmt[asd->capture_pad].fmt.height; 251 curr_rules.fps = fps; 252 curr_rules.run_mode = asd->run_mode->val; 253 /* 254 * For continuous mode, we need to make the capture setting applied 255 * since preview mode, because there is no chance to do this when 256 * starting image capture. 257 */ 258 if (asd->continuous_mode->val) { 259 if (asd->run_mode->val == ATOMISP_RUN_MODE_VIDEO) 260 curr_rules.run_mode = ATOMISP_RUN_MODE_SDV; 261 else 262 curr_rules.run_mode = 263 ATOMISP_RUN_MODE_CONTINUOUS_CAPTURE; 264 } 265 266 /* search for the target frequency by looping freq rules*/ 267 for (i = 0; i < dfs->dfs_table_size; i++) { 268 if (curr_rules.width != dfs->dfs_table[i].width && 269 dfs->dfs_table[i].width != ISP_FREQ_RULE_ANY) 270 continue; 271 if (curr_rules.height != dfs->dfs_table[i].height && 272 dfs->dfs_table[i].height != ISP_FREQ_RULE_ANY) 273 continue; 274 if (curr_rules.fps != dfs->dfs_table[i].fps && 275 dfs->dfs_table[i].fps != ISP_FREQ_RULE_ANY) 276 continue; 277 if (curr_rules.run_mode != dfs->dfs_table[i].run_mode && 278 dfs->dfs_table[i].run_mode != ISP_FREQ_RULE_ANY) 279 continue; 280 break; 281 } 282 283 if (i == dfs->dfs_table_size) 284 new_freq = dfs->max_freq_at_vmin; 285 else 286 new_freq = dfs->dfs_table[i].isp_freq; 287 288 done: 289 dev_dbg(isp->dev, "DFS target frequency=%d.\n", new_freq); 290 291 if ((new_freq == isp->sw_contex.running_freq) && !force) 292 return 0; 293 294 dev_dbg(isp->dev, "Programming DFS frequency to %d\n", new_freq); 295 296 ret = write_target_freq_to_hw(isp, new_freq); 297 if (!ret) { 298 isp->sw_contex.running_freq = new_freq; 299 trace_ipu_pstate(new_freq, -1); 300 } 301 return ret; 302 } 303 304 /* 305 * reset and restore ISP 306 */ 307 int atomisp_reset(struct atomisp_device *isp) 308 { 309 /* Reset ISP by power-cycling it */ 310 int ret = 0; 311 312 dev_dbg(isp->dev, "%s\n", __func__); 313 atomisp_css_suspend(isp); 314 ret = atomisp_runtime_suspend(isp->dev); 315 if (ret < 0) 316 dev_err(isp->dev, "atomisp_runtime_suspend failed, %d\n", ret); 317 ret = atomisp_mrfld_power_down(isp); 318 if (ret < 0) { 319 dev_err(isp->dev, "can not disable ISP power\n"); 320 } else { 321 ret = atomisp_mrfld_power_up(isp); 322 if (ret < 0) 323 dev_err(isp->dev, "can not enable ISP power\n"); 324 ret = atomisp_runtime_resume(isp->dev); 325 if (ret < 0) 326 dev_err(isp->dev, "atomisp_runtime_resume failed, %d\n", ret); 327 } 328 ret = atomisp_css_resume(isp); 329 if (ret) 330 isp->isp_fatal_error = true; 331 332 return ret; 333 } 334 335 /* 336 * interrupt disable functions 337 */ 338 static void disable_isp_irq(enum hrt_isp_css_irq irq) 339 { 340 irq_disable_channel(IRQ0_ID, irq); 341 342 if (irq != hrt_isp_css_irq_sp) 343 return; 344 345 cnd_sp_irq_enable(SP0_ID, false); 346 } 347 348 /* 349 * interrupt clean function 350 */ 351 static void clear_isp_irq(enum hrt_isp_css_irq irq) 352 { 353 irq_clear_all(IRQ0_ID); 354 } 355 356 void atomisp_msi_irq_init(struct atomisp_device *isp, struct pci_dev *dev) 357 { 358 u32 msg32; 359 u16 msg16; 360 361 pci_read_config_dword(dev, PCI_MSI_CAPID, &msg32); 362 msg32 |= 1 << MSI_ENABLE_BIT; 363 pci_write_config_dword(dev, PCI_MSI_CAPID, msg32); 364 365 msg32 = (1 << INTR_IER) | (1 << INTR_IIR); 366 pci_write_config_dword(dev, PCI_INTERRUPT_CTRL, msg32); 367 368 pci_read_config_word(dev, PCI_COMMAND, &msg16); 369 msg16 |= (PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER | 370 PCI_COMMAND_INTX_DISABLE); 371 pci_write_config_word(dev, PCI_COMMAND, msg16); 372 } 373 374 void atomisp_msi_irq_uninit(struct atomisp_device *isp, struct pci_dev *dev) 375 { 376 u32 msg32; 377 u16 msg16; 378 379 pci_read_config_dword(dev, PCI_MSI_CAPID, &msg32); 380 msg32 &= ~(1 << MSI_ENABLE_BIT); 381 pci_write_config_dword(dev, PCI_MSI_CAPID, msg32); 382 383 msg32 = 0x0; 384 pci_write_config_dword(dev, PCI_INTERRUPT_CTRL, msg32); 385 386 pci_read_config_word(dev, PCI_COMMAND, &msg16); 387 msg16 &= ~(PCI_COMMAND_MASTER); 388 pci_write_config_word(dev, PCI_COMMAND, msg16); 389 } 390 391 static void atomisp_sof_event(struct atomisp_sub_device *asd) 392 { 393 struct v4l2_event event = {0}; 394 395 event.type = V4L2_EVENT_FRAME_SYNC; 396 event.u.frame_sync.frame_sequence = atomic_read(&asd->sof_count); 397 398 v4l2_event_queue(asd->subdev.devnode, &event); 399 } 400 401 void atomisp_eof_event(struct atomisp_sub_device *asd, uint8_t exp_id) 402 { 403 struct v4l2_event event = {0}; 404 405 event.type = V4L2_EVENT_FRAME_END; 406 event.u.frame_sync.frame_sequence = exp_id; 407 408 v4l2_event_queue(asd->subdev.devnode, &event); 409 } 410 411 static void atomisp_3a_stats_ready_event(struct atomisp_sub_device *asd, 412 uint8_t exp_id) 413 { 414 struct v4l2_event event = {0}; 415 416 event.type = V4L2_EVENT_ATOMISP_3A_STATS_READY; 417 event.u.frame_sync.frame_sequence = exp_id; 418 419 v4l2_event_queue(asd->subdev.devnode, &event); 420 } 421 422 static void atomisp_metadata_ready_event(struct atomisp_sub_device *asd, 423 enum atomisp_metadata_type md_type) 424 { 425 struct v4l2_event event = {0}; 426 427 event.type = V4L2_EVENT_ATOMISP_METADATA_READY; 428 event.u.data[0] = md_type; 429 430 v4l2_event_queue(asd->subdev.devnode, &event); 431 } 432 433 static void atomisp_reset_event(struct atomisp_sub_device *asd) 434 { 435 struct v4l2_event event = {0}; 436 437 event.type = V4L2_EVENT_ATOMISP_CSS_RESET; 438 439 v4l2_event_queue(asd->subdev.devnode, &event); 440 } 441 442 static void print_csi_rx_errors(enum mipi_port_id port, 443 struct atomisp_device *isp) 444 { 445 u32 infos = 0; 446 447 atomisp_css_rx_get_irq_info(port, &infos); 448 449 dev_err(isp->dev, "CSI Receiver port %d errors:\n", port); 450 if (infos & IA_CSS_RX_IRQ_INFO_BUFFER_OVERRUN) 451 dev_err(isp->dev, " buffer overrun"); 452 if (infos & IA_CSS_RX_IRQ_INFO_ERR_SOT) 453 dev_err(isp->dev, " start-of-transmission error"); 454 if (infos & IA_CSS_RX_IRQ_INFO_ERR_SOT_SYNC) 455 dev_err(isp->dev, " start-of-transmission sync error"); 456 if (infos & IA_CSS_RX_IRQ_INFO_ERR_CONTROL) 457 dev_err(isp->dev, " control error"); 458 if (infos & IA_CSS_RX_IRQ_INFO_ERR_ECC_DOUBLE) 459 dev_err(isp->dev, " 2 or more ECC errors"); 460 if (infos & IA_CSS_RX_IRQ_INFO_ERR_CRC) 461 dev_err(isp->dev, " CRC mismatch"); 462 if (infos & IA_CSS_RX_IRQ_INFO_ERR_UNKNOWN_ID) 463 dev_err(isp->dev, " unknown error"); 464 if (infos & IA_CSS_RX_IRQ_INFO_ERR_FRAME_SYNC) 465 dev_err(isp->dev, " frame sync error"); 466 if (infos & IA_CSS_RX_IRQ_INFO_ERR_FRAME_DATA) 467 dev_err(isp->dev, " frame data error"); 468 if (infos & IA_CSS_RX_IRQ_INFO_ERR_DATA_TIMEOUT) 469 dev_err(isp->dev, " data timeout"); 470 if (infos & IA_CSS_RX_IRQ_INFO_ERR_UNKNOWN_ESC) 471 dev_err(isp->dev, " unknown escape command entry"); 472 if (infos & IA_CSS_RX_IRQ_INFO_ERR_LINE_SYNC) 473 dev_err(isp->dev, " line sync error"); 474 } 475 476 /* Clear irq reg */ 477 static void clear_irq_reg(struct atomisp_device *isp) 478 { 479 u32 msg_ret; 480 481 pci_read_config_dword(isp->pdev, PCI_INTERRUPT_CTRL, &msg_ret); 482 msg_ret |= 1 << INTR_IIR; 483 pci_write_config_dword(isp->pdev, PCI_INTERRUPT_CTRL, msg_ret); 484 } 485 486 static struct atomisp_sub_device * 487 __get_asd_from_port(struct atomisp_device *isp, enum mipi_port_id port) 488 { 489 int i; 490 491 /* Check which isp subdev to send eof */ 492 for (i = 0; i < isp->num_of_streams; i++) { 493 struct atomisp_sub_device *asd = &isp->asd[i]; 494 struct camera_mipi_info *mipi_info; 495 496 mipi_info = atomisp_to_sensor_mipi_info( 497 isp->inputs[asd->input_curr].camera); 498 499 if (asd->streaming == ATOMISP_DEVICE_STREAMING_ENABLED && 500 __get_mipi_port(isp, mipi_info->port) == port) { 501 return asd; 502 } 503 } 504 505 return NULL; 506 } 507 508 /* interrupt handling function*/ 509 irqreturn_t atomisp_isr(int irq, void *dev) 510 { 511 struct atomisp_device *isp = (struct atomisp_device *)dev; 512 struct atomisp_sub_device *asd; 513 struct atomisp_css_event eof_event; 514 unsigned int irq_infos = 0; 515 unsigned long flags; 516 unsigned int i; 517 int err; 518 519 spin_lock_irqsave(&isp->lock, flags); 520 if (isp->sw_contex.power_state != ATOM_ISP_POWER_UP || 521 !isp->css_initialized) { 522 spin_unlock_irqrestore(&isp->lock, flags); 523 return IRQ_HANDLED; 524 } 525 err = atomisp_css_irq_translate(isp, &irq_infos); 526 if (err) { 527 spin_unlock_irqrestore(&isp->lock, flags); 528 return IRQ_NONE; 529 } 530 531 clear_irq_reg(isp); 532 533 if (!atomisp_streaming_count(isp) && !atomisp_is_acc_enabled(isp)) 534 goto out_nowake; 535 536 for (i = 0; i < isp->num_of_streams; i++) { 537 asd = &isp->asd[i]; 538 539 if (asd->streaming != ATOMISP_DEVICE_STREAMING_ENABLED) 540 continue; 541 /* 542 * Current SOF only support one stream, so the SOF only valid 543 * either solely one stream is running 544 */ 545 if (irq_infos & IA_CSS_IRQ_INFO_CSS_RECEIVER_SOF) { 546 atomic_inc(&asd->sof_count); 547 atomisp_sof_event(asd); 548 549 /* If sequence_temp and sequence are the same 550 * there where no frames lost so we can increase 551 * sequence_temp. 552 * If not then processing of frame is still in progress 553 * and driver needs to keep old sequence_temp value. 554 * NOTE: There is assumption here that ISP will not 555 * start processing next frame from sensor before old 556 * one is completely done. */ 557 if (atomic_read(&asd->sequence) == atomic_read( 558 &asd->sequence_temp)) 559 atomic_set(&asd->sequence_temp, 560 atomic_read(&asd->sof_count)); 561 } 562 if (irq_infos & IA_CSS_IRQ_INFO_EVENTS_READY) 563 atomic_set(&asd->sequence, 564 atomic_read(&asd->sequence_temp)); 565 } 566 567 if (irq_infos & IA_CSS_IRQ_INFO_CSS_RECEIVER_SOF) { 568 dev_dbg_ratelimited(isp->dev, 569 "irq:0x%x (SOF)\n", 570 irq_infos); 571 irq_infos &= ~IA_CSS_IRQ_INFO_CSS_RECEIVER_SOF; 572 } 573 574 if ((irq_infos & IA_CSS_IRQ_INFO_INPUT_SYSTEM_ERROR) || 575 (irq_infos & IA_CSS_IRQ_INFO_IF_ERROR)) { 576 /* handle mipi receiver error */ 577 u32 rx_infos; 578 enum mipi_port_id port; 579 580 for (port = MIPI_PORT0_ID; port <= MIPI_PORT2_ID; 581 port++) { 582 print_csi_rx_errors(port, isp); 583 atomisp_css_rx_get_irq_info(port, &rx_infos); 584 atomisp_css_rx_clear_irq_info(port, rx_infos); 585 } 586 } 587 588 if (irq_infos & IA_CSS_IRQ_INFO_ISYS_EVENTS_READY) { 589 while (ia_css_dequeue_isys_event(&eof_event.event) == 590 0) { 591 /* EOF Event does not have the css_pipe returned */ 592 asd = __get_asd_from_port(isp, eof_event.event.port); 593 if (!asd) { 594 dev_err(isp->dev, "%s: ISYS event, but no subdev.event:%d", 595 __func__, eof_event.event.type); 596 continue; 597 } 598 599 atomisp_eof_event(asd, eof_event.event.exp_id); 600 dev_dbg_ratelimited(isp->dev, 601 "%s ISYS event: EOF exp_id %d, asd %d\n", 602 __func__, eof_event.event.exp_id, 603 asd->index); 604 } 605 606 irq_infos &= ~IA_CSS_IRQ_INFO_ISYS_EVENTS_READY; 607 if (irq_infos == 0) 608 goto out_nowake; 609 } 610 611 spin_unlock_irqrestore(&isp->lock, flags); 612 613 dev_dbg_ratelimited(isp->dev, "irq:0x%x (unhandled)\n", irq_infos); 614 615 return IRQ_WAKE_THREAD; 616 617 out_nowake: 618 spin_unlock_irqrestore(&isp->lock, flags); 619 620 if (irq_infos) 621 dev_dbg_ratelimited(isp->dev, "irq:0x%x (ignored, as not streaming anymore)\n", 622 irq_infos); 623 624 return IRQ_HANDLED; 625 } 626 627 void atomisp_clear_css_buffer_counters(struct atomisp_sub_device *asd) 628 { 629 int i; 630 631 memset(asd->s3a_bufs_in_css, 0, sizeof(asd->s3a_bufs_in_css)); 632 for (i = 0; i < ATOMISP_INPUT_STREAM_NUM; i++) 633 memset(asd->metadata_bufs_in_css[i], 0, 634 sizeof(asd->metadata_bufs_in_css[i])); 635 asd->dis_bufs_in_css = 0; 636 asd->video_out_capture.buffers_in_css = 0; 637 asd->video_out_vf.buffers_in_css = 0; 638 asd->video_out_preview.buffers_in_css = 0; 639 asd->video_out_video_capture.buffers_in_css = 0; 640 } 641 642 /* ISP2400 */ 643 bool atomisp_buffers_queued(struct atomisp_sub_device *asd) 644 { 645 return asd->video_out_capture.buffers_in_css || 646 asd->video_out_vf.buffers_in_css || 647 asd->video_out_preview.buffers_in_css || 648 asd->video_out_video_capture.buffers_in_css ? 649 true : false; 650 } 651 652 /* ISP2401 */ 653 bool atomisp_buffers_queued_pipe(struct atomisp_video_pipe *pipe) 654 { 655 return pipe->buffers_in_css ? true : false; 656 } 657 658 /* 0x100000 is the start of dmem inside SP */ 659 #define SP_DMEM_BASE 0x100000 660 661 void dump_sp_dmem(struct atomisp_device *isp, unsigned int addr, 662 unsigned int size) 663 { 664 unsigned int data = 0; 665 unsigned int size32 = DIV_ROUND_UP(size, sizeof(u32)); 666 667 dev_dbg(isp->dev, "atomisp_io_base:%p\n", atomisp_io_base); 668 dev_dbg(isp->dev, "%s, addr:0x%x, size: %d, size32: %d\n", __func__, 669 addr, size, size32); 670 if (size32 * 4 + addr > 0x4000) { 671 dev_err(isp->dev, "illegal size (%d) or addr (0x%x)\n", 672 size32, addr); 673 return; 674 } 675 addr += SP_DMEM_BASE; 676 do { 677 data = _hrt_master_port_uload_32(addr); 678 679 dev_dbg(isp->dev, "%s, \t [0x%x]:0x%x\n", __func__, addr, data); 680 addr += sizeof(unsigned int); 681 size32 -= 1; 682 } while (size32 > 0); 683 } 684 685 static struct videobuf_buffer *atomisp_css_frame_to_vbuf( 686 struct atomisp_video_pipe *pipe, struct ia_css_frame *frame) 687 { 688 struct videobuf_vmalloc_memory *vm_mem; 689 struct ia_css_frame *handle; 690 int i; 691 692 for (i = 0; pipe->capq.bufs[i]; i++) { 693 vm_mem = pipe->capq.bufs[i]->priv; 694 handle = vm_mem->vaddr; 695 if (handle && handle->data == frame->data) 696 return pipe->capq.bufs[i]; 697 } 698 699 return NULL; 700 } 701 702 static void atomisp_flush_video_pipe(struct atomisp_sub_device *asd, 703 struct atomisp_video_pipe *pipe) 704 { 705 unsigned long irqflags; 706 int i; 707 708 if (!pipe->users) 709 return; 710 711 for (i = 0; pipe->capq.bufs[i]; i++) { 712 spin_lock_irqsave(&pipe->irq_lock, irqflags); 713 if (pipe->capq.bufs[i]->state == VIDEOBUF_ACTIVE || 714 pipe->capq.bufs[i]->state == VIDEOBUF_QUEUED) { 715 pipe->capq.bufs[i]->ts = ktime_get_ns(); 716 pipe->capq.bufs[i]->field_count = 717 atomic_read(&asd->sequence) << 1; 718 dev_dbg(asd->isp->dev, "release buffers on device %s\n", 719 pipe->vdev.name); 720 if (pipe->capq.bufs[i]->state == VIDEOBUF_QUEUED) 721 list_del_init(&pipe->capq.bufs[i]->queue); 722 pipe->capq.bufs[i]->state = VIDEOBUF_ERROR; 723 wake_up(&pipe->capq.bufs[i]->done); 724 } 725 spin_unlock_irqrestore(&pipe->irq_lock, irqflags); 726 } 727 } 728 729 /* Returns queued buffers back to video-core */ 730 void atomisp_flush_bufs_and_wakeup(struct atomisp_sub_device *asd) 731 { 732 atomisp_flush_video_pipe(asd, &asd->video_out_capture); 733 atomisp_flush_video_pipe(asd, &asd->video_out_vf); 734 atomisp_flush_video_pipe(asd, &asd->video_out_preview); 735 atomisp_flush_video_pipe(asd, &asd->video_out_video_capture); 736 } 737 738 /* clean out the parameters that did not apply */ 739 void atomisp_flush_params_queue(struct atomisp_video_pipe *pipe) 740 { 741 struct atomisp_css_params_with_list *param; 742 743 while (!list_empty(&pipe->per_frame_params)) { 744 param = list_entry(pipe->per_frame_params.next, 745 struct atomisp_css_params_with_list, list); 746 list_del(¶m->list); 747 atomisp_free_css_parameters(¶m->params); 748 kvfree(param); 749 } 750 } 751 752 /* Re-queue per-frame parameters */ 753 static void atomisp_recover_params_queue(struct atomisp_video_pipe *pipe) 754 { 755 struct atomisp_css_params_with_list *param; 756 int i; 757 758 for (i = 0; i < VIDEO_MAX_FRAME; i++) { 759 param = pipe->frame_params[i]; 760 if (param) 761 list_add_tail(¶m->list, &pipe->per_frame_params); 762 pipe->frame_params[i] = NULL; 763 } 764 atomisp_handle_parameter_and_buffer(pipe); 765 } 766 767 /* find atomisp_video_pipe with css pipe id, buffer type and atomisp run_mode */ 768 static struct atomisp_video_pipe *__atomisp_get_pipe( 769 struct atomisp_sub_device *asd, 770 enum atomisp_input_stream_id stream_id, 771 enum ia_css_pipe_id css_pipe_id, 772 enum ia_css_buffer_type buf_type) 773 { 774 struct atomisp_device *isp = asd->isp; 775 776 if (css_pipe_id == IA_CSS_PIPE_ID_COPY && 777 isp->inputs[asd->input_curr].camera_caps-> 778 sensor[asd->sensor_curr].stream_num > 1) { 779 switch (stream_id) { 780 case ATOMISP_INPUT_STREAM_PREVIEW: 781 return &asd->video_out_preview; 782 case ATOMISP_INPUT_STREAM_POSTVIEW: 783 return &asd->video_out_vf; 784 case ATOMISP_INPUT_STREAM_VIDEO: 785 return &asd->video_out_video_capture; 786 case ATOMISP_INPUT_STREAM_CAPTURE: 787 default: 788 return &asd->video_out_capture; 789 } 790 } 791 792 /* video is same in online as in continuouscapture mode */ 793 if (asd->vfpp->val == ATOMISP_VFPP_DISABLE_LOWLAT) { 794 /* 795 * Disable vf_pp and run CSS in still capture mode. In this 796 * mode, CSS does not cause extra latency with buffering, but 797 * scaling is not available. 798 */ 799 return &asd->video_out_capture; 800 } else if (asd->vfpp->val == ATOMISP_VFPP_DISABLE_SCALER) { 801 /* 802 * Disable vf_pp and run CSS in video mode. This allows using 803 * ISP scaling but it has one frame delay due to CSS internal 804 * buffering. 805 */ 806 return &asd->video_out_video_capture; 807 } else if (css_pipe_id == IA_CSS_PIPE_ID_YUVPP) { 808 /* 809 * to SOC camera, yuvpp pipe is run for capture/video/SDV/ZSL. 810 */ 811 if (asd->continuous_mode->val) { 812 if (asd->run_mode->val == ATOMISP_RUN_MODE_VIDEO) { 813 /* SDV case */ 814 switch (buf_type) { 815 case IA_CSS_BUFFER_TYPE_SEC_OUTPUT_FRAME: 816 return &asd->video_out_video_capture; 817 case IA_CSS_BUFFER_TYPE_SEC_VF_OUTPUT_FRAME: 818 return &asd->video_out_preview; 819 case IA_CSS_BUFFER_TYPE_OUTPUT_FRAME: 820 return &asd->video_out_capture; 821 default: 822 return &asd->video_out_vf; 823 } 824 } else if (asd->run_mode->val == ATOMISP_RUN_MODE_PREVIEW) { 825 /* ZSL case */ 826 switch (buf_type) { 827 case IA_CSS_BUFFER_TYPE_SEC_OUTPUT_FRAME: 828 return &asd->video_out_preview; 829 case IA_CSS_BUFFER_TYPE_OUTPUT_FRAME: 830 return &asd->video_out_capture; 831 default: 832 return &asd->video_out_vf; 833 } 834 } 835 } else if (buf_type == IA_CSS_BUFFER_TYPE_OUTPUT_FRAME) { 836 switch (asd->run_mode->val) { 837 case ATOMISP_RUN_MODE_VIDEO: 838 return &asd->video_out_video_capture; 839 case ATOMISP_RUN_MODE_PREVIEW: 840 return &asd->video_out_preview; 841 default: 842 return &asd->video_out_capture; 843 } 844 } else if (buf_type == IA_CSS_BUFFER_TYPE_VF_OUTPUT_FRAME) { 845 if (asd->run_mode->val == ATOMISP_RUN_MODE_VIDEO) 846 return &asd->video_out_preview; 847 else 848 return &asd->video_out_vf; 849 } 850 } else if (asd->run_mode->val == ATOMISP_RUN_MODE_VIDEO) { 851 /* For online video or SDV video pipe. */ 852 if (css_pipe_id == IA_CSS_PIPE_ID_VIDEO || 853 css_pipe_id == IA_CSS_PIPE_ID_COPY) { 854 if (buf_type == IA_CSS_BUFFER_TYPE_OUTPUT_FRAME) 855 return &asd->video_out_video_capture; 856 return &asd->video_out_preview; 857 } 858 } else if (asd->run_mode->val == ATOMISP_RUN_MODE_PREVIEW) { 859 /* For online preview or ZSL preview pipe. */ 860 if (css_pipe_id == IA_CSS_PIPE_ID_PREVIEW || 861 css_pipe_id == IA_CSS_PIPE_ID_COPY) 862 return &asd->video_out_preview; 863 } 864 /* For capture pipe. */ 865 if (buf_type == IA_CSS_BUFFER_TYPE_VF_OUTPUT_FRAME) 866 return &asd->video_out_vf; 867 return &asd->video_out_capture; 868 } 869 870 enum atomisp_metadata_type 871 atomisp_get_metadata_type(struct atomisp_sub_device *asd, 872 enum ia_css_pipe_id pipe_id) { 873 if (!asd->continuous_mode->val) 874 return ATOMISP_MAIN_METADATA; 875 876 if (pipe_id == IA_CSS_PIPE_ID_CAPTURE) /* online capture pipe */ 877 return ATOMISP_SEC_METADATA; 878 else 879 return ATOMISP_MAIN_METADATA; 880 } 881 882 void atomisp_buf_done(struct atomisp_sub_device *asd, int error, 883 enum ia_css_buffer_type buf_type, 884 enum ia_css_pipe_id css_pipe_id, 885 bool q_buffers, enum atomisp_input_stream_id stream_id) 886 { 887 struct videobuf_buffer *vb = NULL; 888 struct atomisp_video_pipe *pipe = NULL; 889 struct atomisp_css_buffer buffer; 890 bool requeue = false; 891 int err; 892 unsigned long irqflags; 893 struct ia_css_frame *frame = NULL; 894 struct atomisp_s3a_buf *s3a_buf = NULL, *_s3a_buf_tmp; 895 struct atomisp_dis_buf *dis_buf = NULL, *_dis_buf_tmp; 896 struct atomisp_metadata_buf *md_buf = NULL, *_md_buf_tmp; 897 enum atomisp_metadata_type md_type; 898 struct atomisp_device *isp = asd->isp; 899 struct v4l2_control ctrl; 900 bool reset_wdt_timer = false; 901 902 if ( 903 buf_type != IA_CSS_BUFFER_TYPE_METADATA && 904 buf_type != IA_CSS_BUFFER_TYPE_3A_STATISTICS && 905 buf_type != IA_CSS_BUFFER_TYPE_DIS_STATISTICS && 906 buf_type != IA_CSS_BUFFER_TYPE_OUTPUT_FRAME && 907 buf_type != IA_CSS_BUFFER_TYPE_SEC_OUTPUT_FRAME && 908 buf_type != IA_CSS_BUFFER_TYPE_RAW_OUTPUT_FRAME && 909 buf_type != IA_CSS_BUFFER_TYPE_SEC_VF_OUTPUT_FRAME && 910 buf_type != IA_CSS_BUFFER_TYPE_VF_OUTPUT_FRAME) { 911 dev_err(isp->dev, "%s, unsupported buffer type: %d\n", 912 __func__, buf_type); 913 return; 914 } 915 916 memset(&buffer, 0, sizeof(struct atomisp_css_buffer)); 917 buffer.css_buffer.type = buf_type; 918 err = atomisp_css_dequeue_buffer(asd, stream_id, css_pipe_id, 919 buf_type, &buffer); 920 if (err) { 921 dev_err(isp->dev, 922 "atomisp_css_dequeue_buffer failed: 0x%x\n", err); 923 return; 924 } 925 926 /* need to know the atomisp pipe for frame buffers */ 927 pipe = __atomisp_get_pipe(asd, stream_id, css_pipe_id, buf_type); 928 if (!pipe) { 929 dev_err(isp->dev, "error getting atomisp pipe\n"); 930 return; 931 } 932 933 switch (buf_type) { 934 case IA_CSS_BUFFER_TYPE_3A_STATISTICS: 935 list_for_each_entry_safe(s3a_buf, _s3a_buf_tmp, 936 &asd->s3a_stats_in_css, list) { 937 if (s3a_buf->s3a_data == 938 buffer.css_buffer.data.stats_3a) { 939 list_del_init(&s3a_buf->list); 940 list_add_tail(&s3a_buf->list, 941 &asd->s3a_stats_ready); 942 break; 943 } 944 } 945 946 asd->s3a_bufs_in_css[css_pipe_id]--; 947 atomisp_3a_stats_ready_event(asd, buffer.css_buffer.exp_id); 948 dev_dbg(isp->dev, "%s: s3a stat with exp_id %d is ready\n", 949 __func__, s3a_buf->s3a_data->exp_id); 950 break; 951 case IA_CSS_BUFFER_TYPE_METADATA: 952 if (error) 953 break; 954 955 md_type = atomisp_get_metadata_type(asd, css_pipe_id); 956 list_for_each_entry_safe(md_buf, _md_buf_tmp, 957 &asd->metadata_in_css[md_type], list) { 958 if (md_buf->metadata == 959 buffer.css_buffer.data.metadata) { 960 list_del_init(&md_buf->list); 961 list_add_tail(&md_buf->list, 962 &asd->metadata_ready[md_type]); 963 break; 964 } 965 } 966 asd->metadata_bufs_in_css[stream_id][css_pipe_id]--; 967 atomisp_metadata_ready_event(asd, md_type); 968 dev_dbg(isp->dev, "%s: metadata with exp_id %d is ready\n", 969 __func__, md_buf->metadata->exp_id); 970 break; 971 case IA_CSS_BUFFER_TYPE_DIS_STATISTICS: 972 list_for_each_entry_safe(dis_buf, _dis_buf_tmp, 973 &asd->dis_stats_in_css, list) { 974 if (dis_buf->dis_data == 975 buffer.css_buffer.data.stats_dvs) { 976 spin_lock_irqsave(&asd->dis_stats_lock, 977 irqflags); 978 list_del_init(&dis_buf->list); 979 list_add(&dis_buf->list, &asd->dis_stats); 980 asd->params.dis_proj_data_valid = true; 981 spin_unlock_irqrestore(&asd->dis_stats_lock, 982 irqflags); 983 break; 984 } 985 } 986 asd->dis_bufs_in_css--; 987 dev_dbg(isp->dev, "%s: dis stat with exp_id %d is ready\n", 988 __func__, dis_buf->dis_data->exp_id); 989 break; 990 case IA_CSS_BUFFER_TYPE_VF_OUTPUT_FRAME: 991 case IA_CSS_BUFFER_TYPE_SEC_VF_OUTPUT_FRAME: 992 if (atomisp_hw_is_isp2401) 993 reset_wdt_timer = true; 994 995 pipe->buffers_in_css--; 996 frame = buffer.css_buffer.data.frame; 997 if (!frame) { 998 WARN_ON(1); 999 break; 1000 } 1001 if (!frame->valid) 1002 error = true; 1003 1004 /* FIXME: 1005 * YUVPP doesn't set postview exp_id correctlly in SDV mode. 1006 * This is a WORKAROUND to set exp_id. see HSDES-1503911606. 1007 */ 1008 if (IS_BYT && buf_type == IA_CSS_BUFFER_TYPE_SEC_VF_OUTPUT_FRAME && 1009 asd->continuous_mode->val && ATOMISP_USE_YUVPP(asd)) 1010 frame->exp_id = (asd->postview_exp_id++) % 1011 (ATOMISP_MAX_EXP_ID + 1); 1012 1013 dev_dbg(isp->dev, "%s: vf frame with exp_id %d is ready\n", 1014 __func__, frame->exp_id); 1015 if (asd->params.flash_state == ATOMISP_FLASH_ONGOING) { 1016 if (frame->flash_state 1017 == IA_CSS_FRAME_FLASH_STATE_PARTIAL) 1018 dev_dbg(isp->dev, "%s thumb partially flashed\n", 1019 __func__); 1020 else if (frame->flash_state 1021 == IA_CSS_FRAME_FLASH_STATE_FULL) 1022 dev_dbg(isp->dev, "%s thumb completely flashed\n", 1023 __func__); 1024 else 1025 dev_dbg(isp->dev, "%s thumb no flash in this frame\n", 1026 __func__); 1027 } 1028 vb = atomisp_css_frame_to_vbuf(pipe, frame); 1029 WARN_ON(!vb); 1030 if (vb) 1031 pipe->frame_config_id[vb->i] = frame->isp_config_id; 1032 if (css_pipe_id == IA_CSS_PIPE_ID_CAPTURE && 1033 asd->pending_capture_request > 0) { 1034 err = atomisp_css_offline_capture_configure(asd, 1035 asd->params.offline_parm.num_captures, 1036 asd->params.offline_parm.skip_frames, 1037 asd->params.offline_parm.offset); 1038 1039 asd->pending_capture_request--; 1040 1041 if (atomisp_hw_is_isp2401) 1042 asd->re_trigger_capture = false; 1043 1044 dev_dbg(isp->dev, "Trigger capture again for new buffer. err=%d\n", 1045 err); 1046 } else if (atomisp_hw_is_isp2401) { 1047 asd->re_trigger_capture = true; 1048 } 1049 break; 1050 case IA_CSS_BUFFER_TYPE_OUTPUT_FRAME: 1051 case IA_CSS_BUFFER_TYPE_SEC_OUTPUT_FRAME: 1052 if (atomisp_hw_is_isp2401) 1053 reset_wdt_timer = true; 1054 1055 pipe->buffers_in_css--; 1056 frame = buffer.css_buffer.data.frame; 1057 if (!frame) { 1058 WARN_ON(1); 1059 break; 1060 } 1061 1062 if (!frame->valid) 1063 error = true; 1064 1065 /* FIXME: 1066 * YUVPP doesn't set preview exp_id correctlly in ZSL mode. 1067 * This is a WORKAROUND to set exp_id. see HSDES-1503911606. 1068 */ 1069 if (IS_BYT && buf_type == IA_CSS_BUFFER_TYPE_SEC_OUTPUT_FRAME && 1070 asd->continuous_mode->val && ATOMISP_USE_YUVPP(asd)) 1071 frame->exp_id = (asd->preview_exp_id++) % 1072 (ATOMISP_MAX_EXP_ID + 1); 1073 1074 dev_dbg(isp->dev, "%s: main frame with exp_id %d is ready\n", 1075 __func__, frame->exp_id); 1076 vb = atomisp_css_frame_to_vbuf(pipe, frame); 1077 if (!vb) { 1078 WARN_ON(1); 1079 break; 1080 } 1081 1082 /* free the parameters */ 1083 if (pipe->frame_params[vb->i]) { 1084 if (asd->params.dvs_6axis == 1085 pipe->frame_params[vb->i]->params.dvs_6axis) 1086 asd->params.dvs_6axis = NULL; 1087 atomisp_free_css_parameters( 1088 &pipe->frame_params[vb->i]->params); 1089 kvfree(pipe->frame_params[vb->i]); 1090 pipe->frame_params[vb->i] = NULL; 1091 } 1092 1093 pipe->frame_config_id[vb->i] = frame->isp_config_id; 1094 ctrl.id = V4L2_CID_FLASH_MODE; 1095 if (asd->params.flash_state == ATOMISP_FLASH_ONGOING) { 1096 if (frame->flash_state 1097 == IA_CSS_FRAME_FLASH_STATE_PARTIAL) { 1098 asd->frame_status[vb->i] = 1099 ATOMISP_FRAME_STATUS_FLASH_PARTIAL; 1100 dev_dbg(isp->dev, "%s partially flashed\n", 1101 __func__); 1102 } else if (frame->flash_state 1103 == IA_CSS_FRAME_FLASH_STATE_FULL) { 1104 asd->frame_status[vb->i] = 1105 ATOMISP_FRAME_STATUS_FLASH_EXPOSED; 1106 asd->params.num_flash_frames--; 1107 dev_dbg(isp->dev, "%s completely flashed\n", 1108 __func__); 1109 } else { 1110 asd->frame_status[vb->i] = 1111 ATOMISP_FRAME_STATUS_OK; 1112 dev_dbg(isp->dev, 1113 "%s no flash in this frame\n", 1114 __func__); 1115 } 1116 1117 /* Check if flashing sequence is done */ 1118 if (asd->frame_status[vb->i] == 1119 ATOMISP_FRAME_STATUS_FLASH_EXPOSED) 1120 asd->params.flash_state = ATOMISP_FLASH_DONE; 1121 } else if (isp->flash) { 1122 if (v4l2_g_ctrl(isp->flash->ctrl_handler, &ctrl) == 1123 0 && ctrl.value == ATOMISP_FLASH_MODE_TORCH) { 1124 ctrl.id = V4L2_CID_FLASH_TORCH_INTENSITY; 1125 if (v4l2_g_ctrl(isp->flash->ctrl_handler, &ctrl) 1126 == 0 && ctrl.value > 0) { 1127 asd->frame_status[vb->i] = 1128 ATOMISP_FRAME_STATUS_FLASH_EXPOSED; 1129 } else { 1130 asd->frame_status[vb->i] = 1131 ATOMISP_FRAME_STATUS_OK; 1132 } 1133 } else 1134 asd->frame_status[vb->i] = 1135 ATOMISP_FRAME_STATUS_OK; 1136 } else { 1137 asd->frame_status[vb->i] = ATOMISP_FRAME_STATUS_OK; 1138 } 1139 1140 asd->params.last_frame_status = asd->frame_status[vb->i]; 1141 1142 if (asd->continuous_mode->val) { 1143 if (css_pipe_id == IA_CSS_PIPE_ID_PREVIEW || 1144 css_pipe_id == IA_CSS_PIPE_ID_VIDEO) { 1145 asd->latest_preview_exp_id = frame->exp_id; 1146 } else if (css_pipe_id == 1147 IA_CSS_PIPE_ID_CAPTURE) { 1148 if (asd->run_mode->val == 1149 ATOMISP_RUN_MODE_VIDEO) 1150 dev_dbg(isp->dev, "SDV capture raw buffer id: %u\n", 1151 frame->exp_id); 1152 else 1153 dev_dbg(isp->dev, "ZSL capture raw buffer id: %u\n", 1154 frame->exp_id); 1155 } 1156 } 1157 /* 1158 * Only after enabled the raw buffer lock 1159 * and in continuous mode. 1160 * in preview/video pipe, each buffer will 1161 * be locked automatically, so record it here. 1162 */ 1163 if (((css_pipe_id == IA_CSS_PIPE_ID_PREVIEW) || 1164 (css_pipe_id == IA_CSS_PIPE_ID_VIDEO)) && 1165 asd->enable_raw_buffer_lock->val && 1166 asd->continuous_mode->val) { 1167 atomisp_set_raw_buffer_bitmap(asd, frame->exp_id); 1168 WARN_ON(frame->exp_id > ATOMISP_MAX_EXP_ID); 1169 } 1170 1171 if (asd->params.css_update_params_needed) { 1172 atomisp_apply_css_parameters(asd, 1173 &asd->params.css_param); 1174 if (asd->params.css_param.update_flag.dz_config) 1175 asd->params.config.dz_config = &asd->params.css_param.dz_config; 1176 /* New global dvs 6axis config should be blocked 1177 * here if there's a buffer with per-frame parameters 1178 * pending in CSS frame buffer queue. 1179 * This is to aviod zooming vibration since global 1180 * parameters take effect immediately while 1181 * per-frame parameters are taken after previous 1182 * buffers in CSS got processed. 1183 */ 1184 if (asd->params.dvs_6axis) 1185 atomisp_css_set_dvs_6axis(asd, 1186 asd->params.dvs_6axis); 1187 else 1188 asd->params.css_update_params_needed = false; 1189 /* The update flag should not be cleaned here 1190 * since it is still going to be used to make up 1191 * following per-frame parameters. 1192 * This will introduce more copy work since each 1193 * time when updating global parameters, the whole 1194 * parameter set are applied. 1195 * FIXME: A new set of parameter copy functions can 1196 * be added to make up per-frame parameters based on 1197 * solid structures stored in asd->params.css_param 1198 * instead of using shadow pointers in update flag. 1199 */ 1200 atomisp_css_update_isp_params(asd); 1201 } 1202 break; 1203 default: 1204 break; 1205 } 1206 if (vb) 1207 { 1208 vb->ts = ktime_get_ns(); 1209 vb->field_count = atomic_read(&asd->sequence) << 1; 1210 /*mark videobuffer done for dequeue*/ 1211 spin_lock_irqsave(&pipe->irq_lock, irqflags); 1212 vb->state = !error ? VIDEOBUF_DONE : VIDEOBUF_ERROR; 1213 spin_unlock_irqrestore(&pipe->irq_lock, irqflags); 1214 1215 /* 1216 * Frame capture done, wake up any process block on 1217 * current active buffer 1218 * possibly hold by videobuf_dqbuf() 1219 */ 1220 wake_up(&vb->done); 1221 } 1222 if (atomisp_hw_is_isp2401) 1223 atomic_set(&pipe->wdt_count, 0); 1224 1225 /* 1226 * Requeue should only be done for 3a and dis buffers. 1227 * Queue/dequeue order will change if driver recycles image buffers. 1228 */ 1229 if (requeue) 1230 { 1231 err = atomisp_css_queue_buffer(asd, 1232 stream_id, css_pipe_id, 1233 buf_type, &buffer); 1234 if (err) 1235 dev_err(isp->dev, "%s, q to css fails: %d\n", 1236 __func__, err); 1237 return; 1238 } 1239 if (!error && q_buffers) 1240 atomisp_qbuffers_to_css(asd); 1241 1242 if (atomisp_hw_is_isp2401) { 1243 /* If there are no buffers queued then 1244 * delete wdt timer. */ 1245 if (asd->streaming != ATOMISP_DEVICE_STREAMING_ENABLED) 1246 return; 1247 if (!atomisp_buffers_queued_pipe(pipe)) 1248 atomisp_wdt_stop_pipe(pipe, false); 1249 else if (reset_wdt_timer) 1250 /* SOF irq should not reset wdt timer. */ 1251 atomisp_wdt_refresh_pipe(pipe, 1252 ATOMISP_WDT_KEEP_CURRENT_DELAY); 1253 } 1254 } 1255 1256 void atomisp_delayed_init_work(struct work_struct *work) 1257 { 1258 struct atomisp_sub_device *asd = container_of(work, 1259 struct atomisp_sub_device, 1260 delayed_init_work); 1261 /* 1262 * to SOC camera, use yuvpp pipe and no support continuous mode. 1263 */ 1264 if (!ATOMISP_USE_YUVPP(asd)) { 1265 struct v4l2_event event = {0}; 1266 struct ia_css_stream *stream; 1267 1268 stream = asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream; 1269 1270 1271 if (ia_css_alloc_continuous_frame_remain(stream)) 1272 return; 1273 1274 ia_css_update_continuous_frames(stream); 1275 1276 event.type = V4L2_EVENT_ATOMISP_RAW_BUFFERS_ALLOC_DONE; 1277 v4l2_event_queue(asd->subdev.devnode, &event); 1278 } 1279 1280 /* signal streamon after delayed init is done */ 1281 asd->delayed_init = ATOMISP_DELAYED_INIT_DONE; 1282 complete(&asd->init_done); 1283 } 1284 1285 static void __atomisp_css_recover(struct atomisp_device *isp, bool isp_timeout) 1286 { 1287 enum ia_css_pipe_id css_pipe_id; 1288 bool stream_restart[MAX_STREAM_NUM] = {0}; 1289 bool depth_mode = false; 1290 int i, ret, depth_cnt = 0; 1291 1292 if (!isp->sw_contex.file_input) 1293 atomisp_css_irq_enable(isp, 1294 IA_CSS_IRQ_INFO_CSS_RECEIVER_SOF, false); 1295 1296 BUG_ON(isp->num_of_streams > MAX_STREAM_NUM); 1297 1298 for (i = 0; i < isp->num_of_streams; i++) { 1299 struct atomisp_sub_device *asd = &isp->asd[i]; 1300 struct ia_css_pipeline *acc_pipeline; 1301 struct ia_css_pipe *acc_pipe = NULL; 1302 1303 if (asd->streaming != ATOMISP_DEVICE_STREAMING_ENABLED && 1304 !asd->stream_prepared) 1305 continue; 1306 1307 /* 1308 * AtomISP::waitStageUpdate is blocked when WDT happens. 1309 * By calling acc_done() for all loaded fw_handles, 1310 * HAL will be unblocked. 1311 */ 1312 acc_pipe = asd->stream_env[i].pipes[IA_CSS_PIPE_ID_ACC]; 1313 if (acc_pipe) { 1314 acc_pipeline = ia_css_pipe_get_pipeline(acc_pipe); 1315 if (acc_pipeline) { 1316 struct ia_css_pipeline_stage *stage; 1317 1318 for (stage = acc_pipeline->stages; stage; 1319 stage = stage->next) { 1320 const struct ia_css_fw_info *fw; 1321 1322 fw = stage->firmware; 1323 atomisp_acc_done(asd, fw->handle); 1324 } 1325 } 1326 } 1327 1328 depth_cnt++; 1329 1330 if (asd->delayed_init == ATOMISP_DELAYED_INIT_QUEUED) 1331 cancel_work_sync(&asd->delayed_init_work); 1332 1333 complete(&asd->init_done); 1334 asd->delayed_init = ATOMISP_DELAYED_INIT_NOT_QUEUED; 1335 1336 stream_restart[asd->index] = true; 1337 1338 asd->streaming = ATOMISP_DEVICE_STREAMING_STOPPING; 1339 1340 /* stream off sensor */ 1341 ret = v4l2_subdev_call( 1342 isp->inputs[asd->input_curr]. 1343 camera, video, s_stream, 0); 1344 if (ret) 1345 dev_warn(isp->dev, 1346 "can't stop streaming on sensor!\n"); 1347 1348 atomisp_acc_unload_extensions(asd); 1349 1350 atomisp_clear_css_buffer_counters(asd); 1351 1352 css_pipe_id = atomisp_get_css_pipe_id(asd); 1353 atomisp_css_stop(asd, css_pipe_id, true); 1354 1355 asd->streaming = ATOMISP_DEVICE_STREAMING_DISABLED; 1356 1357 asd->preview_exp_id = 1; 1358 asd->postview_exp_id = 1; 1359 /* notify HAL the CSS reset */ 1360 dev_dbg(isp->dev, 1361 "send reset event to %s\n", asd->subdev.devnode->name); 1362 atomisp_reset_event(asd); 1363 } 1364 1365 /* clear irq */ 1366 disable_isp_irq(hrt_isp_css_irq_sp); 1367 clear_isp_irq(hrt_isp_css_irq_sp); 1368 1369 /* Set the SRSE to 3 before resetting */ 1370 pci_write_config_dword(isp->pdev, PCI_I_CONTROL, isp->saved_regs.i_control | 1371 MRFLD_PCI_I_CONTROL_SRSE_RESET_MASK); 1372 1373 /* reset ISP and restore its state */ 1374 isp->isp_timeout = true; 1375 atomisp_reset(isp); 1376 isp->isp_timeout = false; 1377 1378 if (!isp_timeout) { 1379 for (i = 0; i < isp->num_of_streams; i++) { 1380 if (isp->asd[i].depth_mode->val) 1381 return; 1382 } 1383 } 1384 1385 for (i = 0; i < isp->num_of_streams; i++) { 1386 struct atomisp_sub_device *asd = &isp->asd[i]; 1387 1388 if (!stream_restart[i]) 1389 continue; 1390 1391 if (isp->inputs[asd->input_curr].type != FILE_INPUT) 1392 atomisp_css_input_set_mode(asd, 1393 IA_CSS_INPUT_MODE_BUFFERED_SENSOR); 1394 1395 css_pipe_id = atomisp_get_css_pipe_id(asd); 1396 if (atomisp_css_start(asd, css_pipe_id, true)) 1397 dev_warn(isp->dev, 1398 "start SP failed, so do not set streaming to be enable!\n"); 1399 else 1400 asd->streaming = ATOMISP_DEVICE_STREAMING_ENABLED; 1401 1402 atomisp_csi2_configure(asd); 1403 } 1404 1405 if (!isp->sw_contex.file_input) { 1406 atomisp_css_irq_enable(isp, IA_CSS_IRQ_INFO_CSS_RECEIVER_SOF, 1407 atomisp_css_valid_sof(isp)); 1408 1409 if (atomisp_freq_scaling(isp, ATOMISP_DFS_MODE_AUTO, true) < 0) 1410 dev_dbg(isp->dev, "dfs failed!\n"); 1411 } else { 1412 if (atomisp_freq_scaling(isp, ATOMISP_DFS_MODE_MAX, true) < 0) 1413 dev_dbg(isp->dev, "dfs failed!\n"); 1414 } 1415 1416 for (i = 0; i < isp->num_of_streams; i++) { 1417 struct atomisp_sub_device *asd; 1418 1419 asd = &isp->asd[i]; 1420 1421 if (!stream_restart[i]) 1422 continue; 1423 1424 if (asd->continuous_mode->val && 1425 asd->delayed_init == ATOMISP_DELAYED_INIT_NOT_QUEUED) { 1426 reinit_completion(&asd->init_done); 1427 asd->delayed_init = ATOMISP_DELAYED_INIT_QUEUED; 1428 queue_work(asd->delayed_init_workq, 1429 &asd->delayed_init_work); 1430 } 1431 /* 1432 * dequeueing buffers is not needed. CSS will recycle 1433 * buffers that it has. 1434 */ 1435 atomisp_flush_bufs_and_wakeup(asd); 1436 1437 /* Requeue unprocessed per-frame parameters. */ 1438 atomisp_recover_params_queue(&asd->video_out_capture); 1439 atomisp_recover_params_queue(&asd->video_out_preview); 1440 atomisp_recover_params_queue(&asd->video_out_video_capture); 1441 1442 if ((asd->depth_mode->val) && 1443 (depth_cnt == ATOMISP_DEPTH_SENSOR_STREAMON_COUNT)) { 1444 depth_mode = true; 1445 continue; 1446 } 1447 1448 ret = v4l2_subdev_call( 1449 isp->inputs[asd->input_curr].camera, video, 1450 s_stream, 1); 1451 if (ret) 1452 dev_warn(isp->dev, 1453 "can't start streaming on sensor!\n"); 1454 } 1455 1456 if (depth_mode) { 1457 if (atomisp_stream_on_master_slave_sensor(isp, true)) 1458 dev_warn(isp->dev, 1459 "master slave sensor stream on failed!\n"); 1460 } 1461 } 1462 1463 void atomisp_wdt_work(struct work_struct *work) 1464 { 1465 struct atomisp_device *isp = container_of(work, struct atomisp_device, 1466 wdt_work); 1467 int i; 1468 unsigned int pipe_wdt_cnt[MAX_STREAM_NUM][4] = { {0} }; 1469 bool css_recover = false; 1470 1471 rt_mutex_lock(&isp->mutex); 1472 if (!atomisp_streaming_count(isp)) { 1473 atomic_set(&isp->wdt_work_queued, 0); 1474 rt_mutex_unlock(&isp->mutex); 1475 return; 1476 } 1477 1478 if (!atomisp_hw_is_isp2401) { 1479 dev_err(isp->dev, "timeout %d of %d\n", 1480 atomic_read(&isp->wdt_count) + 1, 1481 ATOMISP_ISP_MAX_TIMEOUT_COUNT); 1482 1483 if (atomic_inc_return(&isp->wdt_count) < ATOMISP_ISP_MAX_TIMEOUT_COUNT) 1484 css_recover = true; 1485 } else { 1486 css_recover = true; 1487 1488 for (i = 0; i < isp->num_of_streams; i++) { 1489 struct atomisp_sub_device *asd = &isp->asd[i]; 1490 1491 pipe_wdt_cnt[i][0] += 1492 atomic_read(&asd->video_out_capture.wdt_count); 1493 pipe_wdt_cnt[i][1] += 1494 atomic_read(&asd->video_out_vf.wdt_count); 1495 pipe_wdt_cnt[i][2] += 1496 atomic_read(&asd->video_out_preview.wdt_count); 1497 pipe_wdt_cnt[i][3] += 1498 atomic_read(&asd->video_out_video_capture.wdt_count); 1499 css_recover = 1500 (pipe_wdt_cnt[i][0] <= ATOMISP_ISP_MAX_TIMEOUT_COUNT && 1501 pipe_wdt_cnt[i][1] <= ATOMISP_ISP_MAX_TIMEOUT_COUNT && 1502 pipe_wdt_cnt[i][2] <= ATOMISP_ISP_MAX_TIMEOUT_COUNT && 1503 pipe_wdt_cnt[i][3] <= ATOMISP_ISP_MAX_TIMEOUT_COUNT) 1504 ? true : false; 1505 dev_err(isp->dev, 1506 "pipe on asd%d timeout cnt: (%d, %d, %d, %d) of %d, recover = %d\n", 1507 asd->index, pipe_wdt_cnt[i][0], pipe_wdt_cnt[i][1], 1508 pipe_wdt_cnt[i][2], pipe_wdt_cnt[i][3], 1509 ATOMISP_ISP_MAX_TIMEOUT_COUNT, css_recover); 1510 } 1511 } 1512 1513 if (css_recover) { 1514 ia_css_debug_dump_sp_sw_debug_info(); 1515 ia_css_debug_dump_debug_info(__func__); 1516 for (i = 0; i < isp->num_of_streams; i++) { 1517 struct atomisp_sub_device *asd = &isp->asd[i]; 1518 1519 if (asd->streaming != ATOMISP_DEVICE_STREAMING_ENABLED) 1520 continue; 1521 dev_err(isp->dev, "%s, vdev %s buffers in css: %d\n", 1522 __func__, 1523 asd->video_out_capture.vdev.name, 1524 asd->video_out_capture. 1525 buffers_in_css); 1526 dev_err(isp->dev, 1527 "%s, vdev %s buffers in css: %d\n", 1528 __func__, 1529 asd->video_out_vf.vdev.name, 1530 asd->video_out_vf. 1531 buffers_in_css); 1532 dev_err(isp->dev, 1533 "%s, vdev %s buffers in css: %d\n", 1534 __func__, 1535 asd->video_out_preview.vdev.name, 1536 asd->video_out_preview. 1537 buffers_in_css); 1538 dev_err(isp->dev, 1539 "%s, vdev %s buffers in css: %d\n", 1540 __func__, 1541 asd->video_out_video_capture.vdev.name, 1542 asd->video_out_video_capture. 1543 buffers_in_css); 1544 dev_err(isp->dev, 1545 "%s, s3a buffers in css preview pipe:%d\n", 1546 __func__, 1547 asd->s3a_bufs_in_css[IA_CSS_PIPE_ID_PREVIEW]); 1548 dev_err(isp->dev, 1549 "%s, s3a buffers in css capture pipe:%d\n", 1550 __func__, 1551 asd->s3a_bufs_in_css[IA_CSS_PIPE_ID_CAPTURE]); 1552 dev_err(isp->dev, 1553 "%s, s3a buffers in css video pipe:%d\n", 1554 __func__, 1555 asd->s3a_bufs_in_css[IA_CSS_PIPE_ID_VIDEO]); 1556 dev_err(isp->dev, 1557 "%s, dis buffers in css: %d\n", 1558 __func__, asd->dis_bufs_in_css); 1559 dev_err(isp->dev, 1560 "%s, metadata buffers in css preview pipe:%d\n", 1561 __func__, 1562 asd->metadata_bufs_in_css 1563 [ATOMISP_INPUT_STREAM_GENERAL] 1564 [IA_CSS_PIPE_ID_PREVIEW]); 1565 dev_err(isp->dev, 1566 "%s, metadata buffers in css capture pipe:%d\n", 1567 __func__, 1568 asd->metadata_bufs_in_css 1569 [ATOMISP_INPUT_STREAM_GENERAL] 1570 [IA_CSS_PIPE_ID_CAPTURE]); 1571 dev_err(isp->dev, 1572 "%s, metadata buffers in css video pipe:%d\n", 1573 __func__, 1574 asd->metadata_bufs_in_css 1575 [ATOMISP_INPUT_STREAM_GENERAL] 1576 [IA_CSS_PIPE_ID_VIDEO]); 1577 if (asd->enable_raw_buffer_lock->val) { 1578 unsigned int j; 1579 1580 dev_err(isp->dev, "%s, raw_buffer_locked_count %d\n", 1581 __func__, asd->raw_buffer_locked_count); 1582 for (j = 0; j <= ATOMISP_MAX_EXP_ID / 32; j++) 1583 dev_err(isp->dev, "%s, raw_buffer_bitmap[%d]: 0x%x\n", 1584 __func__, j, 1585 asd->raw_buffer_bitmap[j]); 1586 } 1587 } 1588 1589 /*sh_css_dump_sp_state();*/ 1590 /*sh_css_dump_isp_state();*/ 1591 } else { 1592 for (i = 0; i < isp->num_of_streams; i++) { 1593 struct atomisp_sub_device *asd = &isp->asd[i]; 1594 1595 if (asd->streaming == 1596 ATOMISP_DEVICE_STREAMING_ENABLED) { 1597 atomisp_clear_css_buffer_counters(asd); 1598 atomisp_flush_bufs_and_wakeup(asd); 1599 complete(&asd->init_done); 1600 } 1601 if (atomisp_hw_is_isp2401) 1602 atomisp_wdt_stop(asd, false); 1603 } 1604 1605 if (!atomisp_hw_is_isp2401) { 1606 atomic_set(&isp->wdt_count, 0); 1607 } else { 1608 isp->isp_fatal_error = true; 1609 atomic_set(&isp->wdt_work_queued, 0); 1610 1611 rt_mutex_unlock(&isp->mutex); 1612 return; 1613 } 1614 } 1615 1616 __atomisp_css_recover(isp, true); 1617 if (atomisp_hw_is_isp2401) { 1618 for (i = 0; i < isp->num_of_streams; i++) { 1619 struct atomisp_sub_device *asd = &isp->asd[i]; 1620 1621 if (asd->streaming != ATOMISP_DEVICE_STREAMING_ENABLED) 1622 continue; 1623 1624 atomisp_wdt_refresh(asd, 1625 isp->sw_contex.file_input ? 1626 ATOMISP_ISP_FILE_TIMEOUT_DURATION : 1627 ATOMISP_ISP_TIMEOUT_DURATION); 1628 } 1629 } 1630 1631 dev_err(isp->dev, "timeout recovery handling done\n"); 1632 atomic_set(&isp->wdt_work_queued, 0); 1633 1634 rt_mutex_unlock(&isp->mutex); 1635 } 1636 1637 void atomisp_css_flush(struct atomisp_device *isp) 1638 { 1639 int i; 1640 1641 if (!atomisp_streaming_count(isp)) 1642 return; 1643 1644 /* Disable wdt */ 1645 for (i = 0; i < isp->num_of_streams; i++) { 1646 struct atomisp_sub_device *asd = &isp->asd[i]; 1647 1648 atomisp_wdt_stop(asd, true); 1649 } 1650 1651 /* Start recover */ 1652 __atomisp_css_recover(isp, false); 1653 /* Restore wdt */ 1654 for (i = 0; i < isp->num_of_streams; i++) { 1655 struct atomisp_sub_device *asd = &isp->asd[i]; 1656 1657 if (asd->streaming != 1658 ATOMISP_DEVICE_STREAMING_ENABLED) 1659 continue; 1660 1661 atomisp_wdt_refresh(asd, 1662 isp->sw_contex.file_input ? 1663 ATOMISP_ISP_FILE_TIMEOUT_DURATION : 1664 ATOMISP_ISP_TIMEOUT_DURATION); 1665 } 1666 dev_dbg(isp->dev, "atomisp css flush done\n"); 1667 } 1668 1669 void atomisp_wdt(struct timer_list *t) 1670 { 1671 struct atomisp_sub_device *asd; 1672 struct atomisp_device *isp; 1673 1674 if (!atomisp_hw_is_isp2401) { 1675 asd = from_timer(asd, t, wdt); 1676 isp = asd->isp; 1677 } else { 1678 struct atomisp_video_pipe *pipe = from_timer(pipe, t, wdt); 1679 1680 asd = pipe->asd; 1681 isp = asd->isp; 1682 1683 atomic_inc(&pipe->wdt_count); 1684 dev_warn(isp->dev, 1685 "[WARNING]asd %d pipe %s ISP timeout %d!\n", 1686 asd->index, pipe->vdev.name, 1687 atomic_read(&pipe->wdt_count)); 1688 } 1689 1690 if (atomic_read(&isp->wdt_work_queued)) { 1691 dev_dbg(isp->dev, "ISP watchdog was put into workqueue\n"); 1692 return; 1693 } 1694 atomic_set(&isp->wdt_work_queued, 1); 1695 queue_work(isp->wdt_work_queue, &isp->wdt_work); 1696 } 1697 1698 /* ISP2400 */ 1699 void atomisp_wdt_start(struct atomisp_sub_device *asd) 1700 { 1701 atomisp_wdt_refresh(asd, ATOMISP_ISP_TIMEOUT_DURATION); 1702 } 1703 1704 /* ISP2401 */ 1705 void atomisp_wdt_refresh_pipe(struct atomisp_video_pipe *pipe, 1706 unsigned int delay) 1707 { 1708 unsigned long next; 1709 1710 if (delay != ATOMISP_WDT_KEEP_CURRENT_DELAY) 1711 pipe->wdt_duration = delay; 1712 1713 next = jiffies + pipe->wdt_duration; 1714 1715 /* Override next if it has been pushed beyon the "next" time */ 1716 if (atomisp_is_wdt_running(pipe) && time_after(pipe->wdt_expires, next)) 1717 next = pipe->wdt_expires; 1718 1719 pipe->wdt_expires = next; 1720 1721 if (atomisp_is_wdt_running(pipe)) 1722 dev_dbg(pipe->asd->isp->dev, "WDT will hit after %d ms (%s)\n", 1723 ((int)(next - jiffies) * 1000 / HZ), pipe->vdev.name); 1724 else 1725 dev_dbg(pipe->asd->isp->dev, "WDT starts with %d ms period (%s)\n", 1726 ((int)(next - jiffies) * 1000 / HZ), pipe->vdev.name); 1727 1728 mod_timer(&pipe->wdt, next); 1729 } 1730 1731 void atomisp_wdt_refresh(struct atomisp_sub_device *asd, unsigned int delay) 1732 { 1733 if (!atomisp_hw_is_isp2401) { 1734 unsigned long next; 1735 1736 if (delay != ATOMISP_WDT_KEEP_CURRENT_DELAY) 1737 asd->wdt_duration = delay; 1738 1739 next = jiffies + asd->wdt_duration; 1740 1741 /* Override next if it has been pushed beyon the "next" time */ 1742 if (atomisp_is_wdt_running(asd) && time_after(asd->wdt_expires, next)) 1743 next = asd->wdt_expires; 1744 1745 asd->wdt_expires = next; 1746 1747 if (atomisp_is_wdt_running(asd)) 1748 dev_dbg(asd->isp->dev, "WDT will hit after %d ms\n", 1749 ((int)(next - jiffies) * 1000 / HZ)); 1750 else 1751 dev_dbg(asd->isp->dev, "WDT starts with %d ms period\n", 1752 ((int)(next - jiffies) * 1000 / HZ)); 1753 1754 mod_timer(&asd->wdt, next); 1755 atomic_set(&asd->isp->wdt_count, 0); 1756 } else { 1757 dev_dbg(asd->isp->dev, "WDT refresh all:\n"); 1758 if (atomisp_is_wdt_running(&asd->video_out_capture)) 1759 atomisp_wdt_refresh_pipe(&asd->video_out_capture, delay); 1760 if (atomisp_is_wdt_running(&asd->video_out_preview)) 1761 atomisp_wdt_refresh_pipe(&asd->video_out_preview, delay); 1762 if (atomisp_is_wdt_running(&asd->video_out_vf)) 1763 atomisp_wdt_refresh_pipe(&asd->video_out_vf, delay); 1764 if (atomisp_is_wdt_running(&asd->video_out_video_capture)) 1765 atomisp_wdt_refresh_pipe(&asd->video_out_video_capture, delay); 1766 } 1767 } 1768 1769 /* ISP2401 */ 1770 void atomisp_wdt_stop_pipe(struct atomisp_video_pipe *pipe, bool sync) 1771 { 1772 if (!atomisp_is_wdt_running(pipe)) 1773 return; 1774 1775 dev_dbg(pipe->asd->isp->dev, 1776 "WDT stop asd %d (%s)\n", pipe->asd->index, pipe->vdev.name); 1777 1778 if (sync) { 1779 del_timer_sync(&pipe->wdt); 1780 cancel_work_sync(&pipe->asd->isp->wdt_work); 1781 } else { 1782 del_timer(&pipe->wdt); 1783 } 1784 } 1785 1786 /* ISP 2401 */ 1787 void atomisp_wdt_start_pipe(struct atomisp_video_pipe *pipe) 1788 { 1789 atomisp_wdt_refresh_pipe(pipe, ATOMISP_ISP_TIMEOUT_DURATION); 1790 } 1791 1792 void atomisp_wdt_stop(struct atomisp_sub_device *asd, bool sync) 1793 { 1794 dev_dbg(asd->isp->dev, "WDT stop:\n"); 1795 1796 if (!atomisp_hw_is_isp2401) { 1797 if (sync) { 1798 del_timer_sync(&asd->wdt); 1799 cancel_work_sync(&asd->isp->wdt_work); 1800 } else { 1801 del_timer(&asd->wdt); 1802 } 1803 } else { 1804 atomisp_wdt_stop_pipe(&asd->video_out_capture, sync); 1805 atomisp_wdt_stop_pipe(&asd->video_out_preview, sync); 1806 atomisp_wdt_stop_pipe(&asd->video_out_vf, sync); 1807 atomisp_wdt_stop_pipe(&asd->video_out_video_capture, sync); 1808 } 1809 } 1810 1811 void atomisp_setup_flash(struct atomisp_sub_device *asd) 1812 { 1813 struct atomisp_device *isp = asd->isp; 1814 struct v4l2_control ctrl; 1815 1816 if (!isp->flash) 1817 return; 1818 1819 if (asd->params.flash_state != ATOMISP_FLASH_REQUESTED && 1820 asd->params.flash_state != ATOMISP_FLASH_DONE) 1821 return; 1822 1823 if (asd->params.num_flash_frames) { 1824 /* make sure the timeout is set before setting flash mode */ 1825 ctrl.id = V4L2_CID_FLASH_TIMEOUT; 1826 ctrl.value = FLASH_TIMEOUT; 1827 1828 if (v4l2_s_ctrl(NULL, isp->flash->ctrl_handler, &ctrl)) { 1829 dev_err(isp->dev, "flash timeout configure failed\n"); 1830 return; 1831 } 1832 1833 ia_css_stream_request_flash(asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream); 1834 1835 asd->params.flash_state = ATOMISP_FLASH_ONGOING; 1836 } else { 1837 asd->params.flash_state = ATOMISP_FLASH_IDLE; 1838 } 1839 } 1840 1841 irqreturn_t atomisp_isr_thread(int irq, void *isp_ptr) 1842 { 1843 struct atomisp_device *isp = isp_ptr; 1844 unsigned long flags; 1845 bool frame_done_found[MAX_STREAM_NUM] = {0}; 1846 bool css_pipe_done[MAX_STREAM_NUM] = {0}; 1847 unsigned int i; 1848 struct atomisp_sub_device *asd; 1849 1850 dev_dbg(isp->dev, ">%s\n", __func__); 1851 1852 spin_lock_irqsave(&isp->lock, flags); 1853 1854 if (!atomisp_streaming_count(isp) && !atomisp_is_acc_enabled(isp)) { 1855 spin_unlock_irqrestore(&isp->lock, flags); 1856 return IRQ_HANDLED; 1857 } 1858 1859 spin_unlock_irqrestore(&isp->lock, flags); 1860 1861 /* 1862 * The standard CSS2.0 API tells the following calling sequence of 1863 * dequeue ready buffers: 1864 * while (ia_css_dequeue_event(...)) { 1865 * switch (event.type) { 1866 * ... 1867 * ia_css_pipe_dequeue_buffer() 1868 * } 1869 * } 1870 * That is, dequeue event and buffer are one after another. 1871 * 1872 * But the following implementation is to first deuque all the event 1873 * to a FIFO, then process the event in the FIFO. 1874 * This will not have issue in single stream mode, but it do have some 1875 * issue in multiple stream case. The issue is that 1876 * ia_css_pipe_dequeue_buffer() will not return the corrent buffer in 1877 * a specific pipe. 1878 * 1879 * This is due to ia_css_pipe_dequeue_buffer() does not take the 1880 * ia_css_pipe parameter. 1881 * 1882 * So: 1883 * For CSS2.0: we change the way to not dequeue all the event at one 1884 * time, instead, dequue one and process one, then another 1885 */ 1886 rt_mutex_lock(&isp->mutex); 1887 if (atomisp_css_isr_thread(isp, frame_done_found, css_pipe_done)) 1888 goto out; 1889 1890 for (i = 0; i < isp->num_of_streams; i++) { 1891 asd = &isp->asd[i]; 1892 if (asd->streaming != ATOMISP_DEVICE_STREAMING_ENABLED) 1893 continue; 1894 atomisp_setup_flash(asd); 1895 } 1896 out: 1897 rt_mutex_unlock(&isp->mutex); 1898 for (i = 0; i < isp->num_of_streams; i++) { 1899 asd = &isp->asd[i]; 1900 if (asd->streaming == ATOMISP_DEVICE_STREAMING_ENABLED 1901 && css_pipe_done[asd->index] 1902 && isp->sw_contex.file_input) 1903 v4l2_subdev_call(isp->inputs[asd->input_curr].camera, 1904 video, s_stream, 1); 1905 /* FIXME! FIX ACC implementation */ 1906 if (asd->acc.pipeline && css_pipe_done[asd->index]) 1907 atomisp_css_acc_done(asd); 1908 } 1909 dev_dbg(isp->dev, "<%s\n", __func__); 1910 1911 return IRQ_HANDLED; 1912 } 1913 1914 /* 1915 * utils for buffer allocation/free 1916 */ 1917 1918 int atomisp_get_frame_pgnr(struct atomisp_device *isp, 1919 const struct ia_css_frame *frame, u32 *p_pgnr) 1920 { 1921 if (!frame) { 1922 dev_err(isp->dev, "%s: NULL frame pointer ERROR.\n", __func__); 1923 return -EINVAL; 1924 } 1925 1926 *p_pgnr = DIV_ROUND_UP(frame->data_bytes, PAGE_SIZE); 1927 return 0; 1928 } 1929 1930 /* 1931 * Get internal fmt according to V4L2 fmt 1932 */ 1933 static enum ia_css_frame_format 1934 v4l2_fmt_to_sh_fmt(u32 fmt) { 1935 switch (fmt) 1936 { 1937 case V4L2_PIX_FMT_YUV420: 1938 return IA_CSS_FRAME_FORMAT_YUV420; 1939 case V4L2_PIX_FMT_YVU420: 1940 return IA_CSS_FRAME_FORMAT_YV12; 1941 case V4L2_PIX_FMT_YUV422P: 1942 return IA_CSS_FRAME_FORMAT_YUV422; 1943 case V4L2_PIX_FMT_YUV444: 1944 return IA_CSS_FRAME_FORMAT_YUV444; 1945 case V4L2_PIX_FMT_NV12: 1946 return IA_CSS_FRAME_FORMAT_NV12; 1947 case V4L2_PIX_FMT_NV21: 1948 return IA_CSS_FRAME_FORMAT_NV21; 1949 case V4L2_PIX_FMT_NV16: 1950 return IA_CSS_FRAME_FORMAT_NV16; 1951 case V4L2_PIX_FMT_NV61: 1952 return IA_CSS_FRAME_FORMAT_NV61; 1953 case V4L2_PIX_FMT_UYVY: 1954 return IA_CSS_FRAME_FORMAT_UYVY; 1955 case V4L2_PIX_FMT_YUYV: 1956 return IA_CSS_FRAME_FORMAT_YUYV; 1957 case V4L2_PIX_FMT_RGB24: 1958 return IA_CSS_FRAME_FORMAT_PLANAR_RGB888; 1959 case V4L2_PIX_FMT_RGB32: 1960 return IA_CSS_FRAME_FORMAT_RGBA888; 1961 case V4L2_PIX_FMT_RGB565: 1962 return IA_CSS_FRAME_FORMAT_RGB565; 1963 case V4L2_PIX_FMT_JPEG: 1964 case V4L2_PIX_FMT_CUSTOM_M10MO_RAW: 1965 return IA_CSS_FRAME_FORMAT_BINARY_8; 1966 case V4L2_PIX_FMT_SBGGR16: 1967 case V4L2_PIX_FMT_SBGGR10: 1968 case V4L2_PIX_FMT_SGBRG10: 1969 case V4L2_PIX_FMT_SGRBG10: 1970 case V4L2_PIX_FMT_SRGGB10: 1971 case V4L2_PIX_FMT_SBGGR12: 1972 case V4L2_PIX_FMT_SGBRG12: 1973 case V4L2_PIX_FMT_SGRBG12: 1974 case V4L2_PIX_FMT_SRGGB12: 1975 case V4L2_PIX_FMT_SBGGR8: 1976 case V4L2_PIX_FMT_SGBRG8: 1977 case V4L2_PIX_FMT_SGRBG8: 1978 case V4L2_PIX_FMT_SRGGB8: 1979 return IA_CSS_FRAME_FORMAT_RAW; 1980 default: 1981 return -EINVAL; 1982 } 1983 } 1984 1985 /* 1986 * raw format match between SH format and V4L2 format 1987 */ 1988 static int raw_output_format_match_input(u32 input, u32 output) 1989 { 1990 if ((input == ATOMISP_INPUT_FORMAT_RAW_12) && 1991 ((output == V4L2_PIX_FMT_SRGGB12) || 1992 (output == V4L2_PIX_FMT_SGRBG12) || 1993 (output == V4L2_PIX_FMT_SBGGR12) || 1994 (output == V4L2_PIX_FMT_SGBRG12))) 1995 return 0; 1996 1997 if ((input == ATOMISP_INPUT_FORMAT_RAW_10) && 1998 ((output == V4L2_PIX_FMT_SRGGB10) || 1999 (output == V4L2_PIX_FMT_SGRBG10) || 2000 (output == V4L2_PIX_FMT_SBGGR10) || 2001 (output == V4L2_PIX_FMT_SGBRG10))) 2002 return 0; 2003 2004 if ((input == ATOMISP_INPUT_FORMAT_RAW_8) && 2005 ((output == V4L2_PIX_FMT_SRGGB8) || 2006 (output == V4L2_PIX_FMT_SGRBG8) || 2007 (output == V4L2_PIX_FMT_SBGGR8) || 2008 (output == V4L2_PIX_FMT_SGBRG8))) 2009 return 0; 2010 2011 if ((input == ATOMISP_INPUT_FORMAT_RAW_16) && (output == V4L2_PIX_FMT_SBGGR16)) 2012 return 0; 2013 2014 return -EINVAL; 2015 } 2016 2017 static u32 get_pixel_depth(u32 pixelformat) 2018 { 2019 switch (pixelformat) { 2020 case V4L2_PIX_FMT_YUV420: 2021 case V4L2_PIX_FMT_NV12: 2022 case V4L2_PIX_FMT_NV21: 2023 case V4L2_PIX_FMT_YVU420: 2024 return 12; 2025 case V4L2_PIX_FMT_YUV422P: 2026 case V4L2_PIX_FMT_YUYV: 2027 case V4L2_PIX_FMT_UYVY: 2028 case V4L2_PIX_FMT_NV16: 2029 case V4L2_PIX_FMT_NV61: 2030 case V4L2_PIX_FMT_RGB565: 2031 case V4L2_PIX_FMT_SBGGR16: 2032 case V4L2_PIX_FMT_SBGGR12: 2033 case V4L2_PIX_FMT_SGBRG12: 2034 case V4L2_PIX_FMT_SGRBG12: 2035 case V4L2_PIX_FMT_SRGGB12: 2036 case V4L2_PIX_FMT_SBGGR10: 2037 case V4L2_PIX_FMT_SGBRG10: 2038 case V4L2_PIX_FMT_SGRBG10: 2039 case V4L2_PIX_FMT_SRGGB10: 2040 return 16; 2041 case V4L2_PIX_FMT_RGB24: 2042 case V4L2_PIX_FMT_YUV444: 2043 return 24; 2044 case V4L2_PIX_FMT_RGB32: 2045 return 32; 2046 case V4L2_PIX_FMT_JPEG: 2047 case V4L2_PIX_FMT_CUSTOM_M10MO_RAW: 2048 case V4L2_PIX_FMT_SBGGR8: 2049 case V4L2_PIX_FMT_SGBRG8: 2050 case V4L2_PIX_FMT_SGRBG8: 2051 case V4L2_PIX_FMT_SRGGB8: 2052 return 8; 2053 default: 2054 return 8 * 2; /* raw type now */ 2055 } 2056 } 2057 2058 bool atomisp_is_mbuscode_raw(uint32_t code) 2059 { 2060 return code >= 0x3000 && code < 0x4000; 2061 } 2062 2063 /* 2064 * ISP features control function 2065 */ 2066 2067 /* 2068 * Set ISP capture mode based on current settings 2069 */ 2070 static void atomisp_update_capture_mode(struct atomisp_sub_device *asd) 2071 { 2072 if (asd->params.gdc_cac_en) 2073 atomisp_css_capture_set_mode(asd, IA_CSS_CAPTURE_MODE_ADVANCED); 2074 else if (asd->params.low_light) 2075 atomisp_css_capture_set_mode(asd, IA_CSS_CAPTURE_MODE_LOW_LIGHT); 2076 else if (asd->video_out_capture.sh_fmt == IA_CSS_FRAME_FORMAT_RAW) 2077 atomisp_css_capture_set_mode(asd, IA_CSS_CAPTURE_MODE_RAW); 2078 else 2079 atomisp_css_capture_set_mode(asd, IA_CSS_CAPTURE_MODE_PRIMARY); 2080 } 2081 2082 /* ISP2401 */ 2083 int atomisp_set_sensor_runmode(struct atomisp_sub_device *asd, 2084 struct atomisp_s_runmode *runmode) 2085 { 2086 struct atomisp_device *isp = asd->isp; 2087 struct v4l2_ctrl *c; 2088 int ret = 0; 2089 2090 if (!(runmode && (runmode->mode & RUNMODE_MASK))) 2091 return -EINVAL; 2092 2093 mutex_lock(asd->ctrl_handler.lock); 2094 c = v4l2_ctrl_find(isp->inputs[asd->input_curr].camera->ctrl_handler, 2095 V4L2_CID_RUN_MODE); 2096 2097 if (c) 2098 ret = v4l2_ctrl_s_ctrl(c, runmode->mode); 2099 2100 mutex_unlock(asd->ctrl_handler.lock); 2101 return ret; 2102 } 2103 2104 /* 2105 * Function to enable/disable lens geometry distortion correction (GDC) and 2106 * chromatic aberration correction (CAC) 2107 */ 2108 int atomisp_gdc_cac(struct atomisp_sub_device *asd, int flag, 2109 __s32 *value) 2110 { 2111 if (flag == 0) { 2112 *value = asd->params.gdc_cac_en; 2113 return 0; 2114 } 2115 2116 asd->params.gdc_cac_en = !!*value; 2117 if (asd->params.gdc_cac_en) { 2118 asd->params.config.morph_table = asd->params.css_param.morph_table; 2119 } else { 2120 asd->params.config.morph_table = NULL; 2121 } 2122 asd->params.css_update_params_needed = true; 2123 atomisp_update_capture_mode(asd); 2124 return 0; 2125 } 2126 2127 /* 2128 * Function to enable/disable low light mode including ANR 2129 */ 2130 int atomisp_low_light(struct atomisp_sub_device *asd, int flag, 2131 __s32 *value) 2132 { 2133 if (flag == 0) { 2134 *value = asd->params.low_light; 2135 return 0; 2136 } 2137 2138 asd->params.low_light = (*value != 0); 2139 atomisp_update_capture_mode(asd); 2140 return 0; 2141 } 2142 2143 /* 2144 * Function to enable/disable extra noise reduction (XNR) in low light 2145 * condition 2146 */ 2147 int atomisp_xnr(struct atomisp_sub_device *asd, int flag, 2148 int *xnr_enable) 2149 { 2150 if (flag == 0) { 2151 *xnr_enable = asd->params.xnr_en; 2152 return 0; 2153 } 2154 2155 atomisp_css_capture_enable_xnr(asd, !!*xnr_enable); 2156 2157 return 0; 2158 } 2159 2160 /* 2161 * Function to configure bayer noise reduction 2162 */ 2163 int atomisp_nr(struct atomisp_sub_device *asd, int flag, 2164 struct atomisp_nr_config *arg) 2165 { 2166 if (flag == 0) { 2167 /* Get nr config from current setup */ 2168 if (atomisp_css_get_nr_config(asd, arg)) 2169 return -EINVAL; 2170 } else { 2171 /* Set nr config to isp parameters */ 2172 memcpy(&asd->params.css_param.nr_config, arg, 2173 sizeof(struct ia_css_nr_config)); 2174 asd->params.config.nr_config = &asd->params.css_param.nr_config; 2175 asd->params.css_update_params_needed = true; 2176 } 2177 return 0; 2178 } 2179 2180 /* 2181 * Function to configure temporal noise reduction (TNR) 2182 */ 2183 int atomisp_tnr(struct atomisp_sub_device *asd, int flag, 2184 struct atomisp_tnr_config *config) 2185 { 2186 /* Get tnr config from current setup */ 2187 if (flag == 0) { 2188 /* Get tnr config from current setup */ 2189 if (atomisp_css_get_tnr_config(asd, config)) 2190 return -EINVAL; 2191 } else { 2192 /* Set tnr config to isp parameters */ 2193 memcpy(&asd->params.css_param.tnr_config, config, 2194 sizeof(struct ia_css_tnr_config)); 2195 asd->params.config.tnr_config = &asd->params.css_param.tnr_config; 2196 asd->params.css_update_params_needed = true; 2197 } 2198 2199 return 0; 2200 } 2201 2202 /* 2203 * Function to configure black level compensation 2204 */ 2205 int atomisp_black_level(struct atomisp_sub_device *asd, int flag, 2206 struct atomisp_ob_config *config) 2207 { 2208 if (flag == 0) { 2209 /* Get ob config from current setup */ 2210 if (atomisp_css_get_ob_config(asd, config)) 2211 return -EINVAL; 2212 } else { 2213 /* Set ob config to isp parameters */ 2214 memcpy(&asd->params.css_param.ob_config, config, 2215 sizeof(struct ia_css_ob_config)); 2216 asd->params.config.ob_config = &asd->params.css_param.ob_config; 2217 asd->params.css_update_params_needed = true; 2218 } 2219 2220 return 0; 2221 } 2222 2223 /* 2224 * Function to configure edge enhancement 2225 */ 2226 int atomisp_ee(struct atomisp_sub_device *asd, int flag, 2227 struct atomisp_ee_config *config) 2228 { 2229 if (flag == 0) { 2230 /* Get ee config from current setup */ 2231 if (atomisp_css_get_ee_config(asd, config)) 2232 return -EINVAL; 2233 } else { 2234 /* Set ee config to isp parameters */ 2235 memcpy(&asd->params.css_param.ee_config, config, 2236 sizeof(asd->params.css_param.ee_config)); 2237 asd->params.config.ee_config = &asd->params.css_param.ee_config; 2238 asd->params.css_update_params_needed = true; 2239 } 2240 2241 return 0; 2242 } 2243 2244 /* 2245 * Function to update Gamma table for gamma, brightness and contrast config 2246 */ 2247 int atomisp_gamma(struct atomisp_sub_device *asd, int flag, 2248 struct atomisp_gamma_table *config) 2249 { 2250 if (flag == 0) { 2251 /* Get gamma table from current setup */ 2252 if (atomisp_css_get_gamma_table(asd, config)) 2253 return -EINVAL; 2254 } else { 2255 /* Set gamma table to isp parameters */ 2256 memcpy(&asd->params.css_param.gamma_table, config, 2257 sizeof(asd->params.css_param.gamma_table)); 2258 asd->params.config.gamma_table = &asd->params.css_param.gamma_table; 2259 } 2260 2261 return 0; 2262 } 2263 2264 /* 2265 * Function to update Ctc table for Chroma Enhancement 2266 */ 2267 int atomisp_ctc(struct atomisp_sub_device *asd, int flag, 2268 struct atomisp_ctc_table *config) 2269 { 2270 if (flag == 0) { 2271 /* Get ctc table from current setup */ 2272 if (atomisp_css_get_ctc_table(asd, config)) 2273 return -EINVAL; 2274 } else { 2275 /* Set ctc table to isp parameters */ 2276 memcpy(&asd->params.css_param.ctc_table, config, 2277 sizeof(asd->params.css_param.ctc_table)); 2278 atomisp_css_set_ctc_table(asd, &asd->params.css_param.ctc_table); 2279 } 2280 2281 return 0; 2282 } 2283 2284 /* 2285 * Function to update gamma correction parameters 2286 */ 2287 int atomisp_gamma_correction(struct atomisp_sub_device *asd, int flag, 2288 struct atomisp_gc_config *config) 2289 { 2290 if (flag == 0) { 2291 /* Get gamma correction params from current setup */ 2292 if (atomisp_css_get_gc_config(asd, config)) 2293 return -EINVAL; 2294 } else { 2295 /* Set gamma correction params to isp parameters */ 2296 memcpy(&asd->params.css_param.gc_config, config, 2297 sizeof(asd->params.css_param.gc_config)); 2298 asd->params.config.gc_config = &asd->params.css_param.gc_config; 2299 asd->params.css_update_params_needed = true; 2300 } 2301 2302 return 0; 2303 } 2304 2305 /* 2306 * Function to update narrow gamma flag 2307 */ 2308 int atomisp_formats(struct atomisp_sub_device *asd, int flag, 2309 struct atomisp_formats_config *config) 2310 { 2311 if (flag == 0) { 2312 /* Get narrow gamma flag from current setup */ 2313 if (atomisp_css_get_formats_config(asd, config)) 2314 return -EINVAL; 2315 } else { 2316 /* Set narrow gamma flag to isp parameters */ 2317 memcpy(&asd->params.css_param.formats_config, config, 2318 sizeof(asd->params.css_param.formats_config)); 2319 asd->params.config.formats_config = &asd->params.css_param.formats_config; 2320 } 2321 2322 return 0; 2323 } 2324 2325 void atomisp_free_internal_buffers(struct atomisp_sub_device *asd) 2326 { 2327 atomisp_free_css_parameters(&asd->params.css_param); 2328 2329 if (asd->raw_output_frame) { 2330 ia_css_frame_free(asd->raw_output_frame); 2331 asd->raw_output_frame = NULL; 2332 } 2333 } 2334 2335 static void atomisp_update_grid_info(struct atomisp_sub_device *asd, 2336 enum ia_css_pipe_id pipe_id, 2337 int source_pad) 2338 { 2339 struct atomisp_device *isp = asd->isp; 2340 int err; 2341 u16 stream_id = atomisp_source_pad_to_stream_id(asd, source_pad); 2342 2343 if (atomisp_css_get_grid_info(asd, pipe_id, source_pad)) 2344 return; 2345 2346 /* We must free all buffers because they no longer match 2347 the grid size. */ 2348 atomisp_css_free_stat_buffers(asd); 2349 2350 err = atomisp_alloc_css_stat_bufs(asd, stream_id); 2351 if (err) { 2352 dev_err(isp->dev, "stat_buf allocate error\n"); 2353 goto err; 2354 } 2355 2356 if (atomisp_alloc_3a_output_buf(asd)) { 2357 /* Failure for 3A buffers does not influence DIS buffers */ 2358 if (asd->params.s3a_output_bytes != 0) { 2359 /* For SOC sensor happens s3a_output_bytes == 0, 2360 * using if condition to exclude false error log */ 2361 dev_err(isp->dev, "Failed to allocate memory for 3A statistics\n"); 2362 } 2363 goto err; 2364 } 2365 2366 if (atomisp_alloc_dis_coef_buf(asd)) { 2367 dev_err(isp->dev, 2368 "Failed to allocate memory for DIS statistics\n"); 2369 goto err; 2370 } 2371 2372 if (atomisp_alloc_metadata_output_buf(asd)) { 2373 dev_err(isp->dev, "Failed to allocate memory for metadata\n"); 2374 goto err; 2375 } 2376 2377 return; 2378 2379 err: 2380 atomisp_css_free_stat_buffers(asd); 2381 return; 2382 } 2383 2384 static void atomisp_curr_user_grid_info(struct atomisp_sub_device *asd, 2385 struct atomisp_grid_info *info) 2386 { 2387 memcpy(info, &asd->params.curr_grid_info.s3a_grid, 2388 sizeof(struct ia_css_3a_grid_info)); 2389 } 2390 2391 int atomisp_compare_grid(struct atomisp_sub_device *asd, 2392 struct atomisp_grid_info *atomgrid) 2393 { 2394 struct atomisp_grid_info tmp = {0}; 2395 2396 atomisp_curr_user_grid_info(asd, &tmp); 2397 return memcmp(atomgrid, &tmp, sizeof(tmp)); 2398 } 2399 2400 /* 2401 * Function to update Gdc table for gdc 2402 */ 2403 int atomisp_gdc_cac_table(struct atomisp_sub_device *asd, int flag, 2404 struct atomisp_morph_table *config) 2405 { 2406 int ret; 2407 int i; 2408 struct atomisp_device *isp = asd->isp; 2409 2410 if (flag == 0) { 2411 /* Get gdc table from current setup */ 2412 struct ia_css_morph_table tab = {0}; 2413 2414 atomisp_css_get_morph_table(asd, &tab); 2415 2416 config->width = tab.width; 2417 config->height = tab.height; 2418 2419 for (i = 0; i < IA_CSS_MORPH_TABLE_NUM_PLANES; i++) { 2420 ret = copy_to_user(config->coordinates_x[i], 2421 tab.coordinates_x[i], tab.height * 2422 tab.width * sizeof(*tab.coordinates_x[i])); 2423 if (ret) { 2424 dev_err(isp->dev, 2425 "Failed to copy to User for x\n"); 2426 return -EFAULT; 2427 } 2428 ret = copy_to_user(config->coordinates_y[i], 2429 tab.coordinates_y[i], tab.height * 2430 tab.width * sizeof(*tab.coordinates_y[i])); 2431 if (ret) { 2432 dev_err(isp->dev, 2433 "Failed to copy to User for y\n"); 2434 return -EFAULT; 2435 } 2436 } 2437 } else { 2438 struct ia_css_morph_table *tab = 2439 asd->params.css_param.morph_table; 2440 2441 /* free first if we have one */ 2442 if (tab) { 2443 atomisp_css_morph_table_free(tab); 2444 asd->params.css_param.morph_table = NULL; 2445 } 2446 2447 /* allocate new one */ 2448 tab = atomisp_css_morph_table_allocate(config->width, 2449 config->height); 2450 2451 if (!tab) { 2452 dev_err(isp->dev, "out of memory\n"); 2453 return -EINVAL; 2454 } 2455 2456 for (i = 0; i < IA_CSS_MORPH_TABLE_NUM_PLANES; i++) { 2457 ret = copy_from_user(tab->coordinates_x[i], 2458 config->coordinates_x[i], 2459 config->height * config->width * 2460 sizeof(*config->coordinates_x[i])); 2461 if (ret) { 2462 dev_err(isp->dev, 2463 "Failed to copy from User for x, ret %d\n", 2464 ret); 2465 atomisp_css_morph_table_free(tab); 2466 return -EFAULT; 2467 } 2468 ret = copy_from_user(tab->coordinates_y[i], 2469 config->coordinates_y[i], 2470 config->height * config->width * 2471 sizeof(*config->coordinates_y[i])); 2472 if (ret) { 2473 dev_err(isp->dev, 2474 "Failed to copy from User for y, ret is %d\n", 2475 ret); 2476 atomisp_css_morph_table_free(tab); 2477 return -EFAULT; 2478 } 2479 } 2480 asd->params.css_param.morph_table = tab; 2481 if (asd->params.gdc_cac_en) 2482 asd->params.config.morph_table = tab; 2483 } 2484 2485 return 0; 2486 } 2487 2488 int atomisp_macc_table(struct atomisp_sub_device *asd, int flag, 2489 struct atomisp_macc_config *config) 2490 { 2491 struct ia_css_macc_table *macc_table; 2492 2493 switch (config->color_effect) { 2494 case V4L2_COLORFX_NONE: 2495 macc_table = &asd->params.css_param.macc_table; 2496 break; 2497 case V4L2_COLORFX_SKY_BLUE: 2498 macc_table = &blue_macc_table; 2499 break; 2500 case V4L2_COLORFX_GRASS_GREEN: 2501 macc_table = &green_macc_table; 2502 break; 2503 case V4L2_COLORFX_SKIN_WHITEN_LOW: 2504 macc_table = &skin_low_macc_table; 2505 break; 2506 case V4L2_COLORFX_SKIN_WHITEN: 2507 macc_table = &skin_medium_macc_table; 2508 break; 2509 case V4L2_COLORFX_SKIN_WHITEN_HIGH: 2510 macc_table = &skin_high_macc_table; 2511 break; 2512 default: 2513 return -EINVAL; 2514 } 2515 2516 if (flag == 0) { 2517 /* Get macc table from current setup */ 2518 memcpy(&config->table, macc_table, 2519 sizeof(struct ia_css_macc_table)); 2520 } else { 2521 memcpy(macc_table, &config->table, 2522 sizeof(struct ia_css_macc_table)); 2523 if (config->color_effect == asd->params.color_effect) 2524 asd->params.config.macc_table = macc_table; 2525 } 2526 2527 return 0; 2528 } 2529 2530 int atomisp_set_dis_vector(struct atomisp_sub_device *asd, 2531 struct atomisp_dis_vector *vector) 2532 { 2533 atomisp_css_video_set_dis_vector(asd, vector); 2534 2535 asd->params.dis_proj_data_valid = false; 2536 asd->params.css_update_params_needed = true; 2537 return 0; 2538 } 2539 2540 /* 2541 * Function to set/get image stablization statistics 2542 */ 2543 int atomisp_get_dis_stat(struct atomisp_sub_device *asd, 2544 struct atomisp_dis_statistics *stats) 2545 { 2546 return atomisp_css_get_dis_stat(asd, stats); 2547 } 2548 2549 /* 2550 * Function set camrea_prefiles.xml current sensor pixel array size 2551 */ 2552 int atomisp_set_array_res(struct atomisp_sub_device *asd, 2553 struct atomisp_resolution *config) 2554 { 2555 dev_dbg(asd->isp->dev, ">%s start\n", __func__); 2556 if (!config) { 2557 dev_err(asd->isp->dev, "Set sensor array size is not valid\n"); 2558 return -EINVAL; 2559 } 2560 2561 asd->sensor_array_res.width = config->width; 2562 asd->sensor_array_res.height = config->height; 2563 return 0; 2564 } 2565 2566 /* 2567 * Function to get DVS2 BQ resolution settings 2568 */ 2569 int atomisp_get_dvs2_bq_resolutions(struct atomisp_sub_device *asd, 2570 struct atomisp_dvs2_bq_resolutions *bq_res) 2571 { 2572 struct ia_css_pipe_config *pipe_cfg = NULL; 2573 struct ia_css_stream_config *stream_cfg = NULL; 2574 struct ia_css_stream_input_config *input_config = NULL; 2575 2576 struct ia_css_stream *stream = 2577 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream; 2578 if (!stream) { 2579 dev_warn(asd->isp->dev, "stream is not created"); 2580 return -EAGAIN; 2581 } 2582 2583 pipe_cfg = &asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL] 2584 .pipe_configs[IA_CSS_PIPE_ID_VIDEO]; 2585 stream_cfg = &asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL] 2586 .stream_config; 2587 input_config = &stream_cfg->input_config; 2588 2589 if (!bq_res) 2590 return -EINVAL; 2591 2592 /* the GDC output resolution */ 2593 bq_res->output_bq.width_bq = pipe_cfg->output_info[0].res.width / 2; 2594 bq_res->output_bq.height_bq = pipe_cfg->output_info[0].res.height / 2; 2595 2596 bq_res->envelope_bq.width_bq = 0; 2597 bq_res->envelope_bq.height_bq = 0; 2598 /* the GDC input resolution */ 2599 if (!asd->continuous_mode->val) { 2600 bq_res->source_bq.width_bq = bq_res->output_bq.width_bq + 2601 pipe_cfg->dvs_envelope.width / 2; 2602 bq_res->source_bq.height_bq = bq_res->output_bq.height_bq + 2603 pipe_cfg->dvs_envelope.height / 2; 2604 /* 2605 * Bad pixels caused by spatial filter processing 2606 * ISP filter resolution should be given by CSS/FW, but for now 2607 * there is not such API to query, and it is fixed value, so 2608 * hardcoded here. 2609 */ 2610 bq_res->ispfilter_bq.width_bq = 12 / 2; 2611 bq_res->ispfilter_bq.height_bq = 12 / 2; 2612 /* spatial filter shift, always 4 pixels */ 2613 bq_res->gdc_shift_bq.width_bq = 4 / 2; 2614 bq_res->gdc_shift_bq.height_bq = 4 / 2; 2615 2616 if (asd->params.video_dis_en) { 2617 bq_res->envelope_bq.width_bq = pipe_cfg->dvs_envelope.width 2618 / 2 - bq_res->ispfilter_bq.width_bq; 2619 bq_res->envelope_bq.height_bq = pipe_cfg->dvs_envelope.height 2620 / 2 - bq_res->ispfilter_bq.height_bq; 2621 } 2622 } else { 2623 unsigned int w_padding; 2624 unsigned int gdc_effective_input = 0; 2625 2626 /* For GDC: 2627 * gdc_effective_input = effective_input + envelope 2628 * 2629 * From the comment and formula in BZ1786, 2630 * we see the source_bq should be: 2631 * effective_input / bayer_ds_ratio 2632 */ 2633 bq_res->source_bq.width_bq = 2634 (input_config->effective_res.width * 2635 pipe_cfg->bayer_ds_out_res.width / 2636 input_config->effective_res.width + 1) / 2; 2637 bq_res->source_bq.height_bq = 2638 (input_config->effective_res.height * 2639 pipe_cfg->bayer_ds_out_res.height / 2640 input_config->effective_res.height + 1) / 2; 2641 2642 if (!asd->params.video_dis_en) { 2643 /* 2644 * We adjust the ispfilter_bq to: 2645 * ispfilter_bq = 128/BDS 2646 * we still need firmware team to provide an offical 2647 * formula for SDV. 2648 */ 2649 bq_res->ispfilter_bq.width_bq = 128 * 2650 pipe_cfg->bayer_ds_out_res.width / 2651 input_config->effective_res.width / 2; 2652 bq_res->ispfilter_bq.height_bq = 128 * 2653 pipe_cfg->bayer_ds_out_res.width / 2654 input_config->effective_res.width / 2; 2655 2656 if (IS_HWREVISION(asd->isp, ATOMISP_HW_REVISION_ISP2401)) { 2657 /* No additional left padding for ISYS2401 */ 2658 bq_res->gdc_shift_bq.width_bq = 4 / 2; 2659 bq_res->gdc_shift_bq.height_bq = 4 / 2; 2660 } else { 2661 /* 2662 * For the w_padding and gdc_shift_bq cacluation 2663 * Please see the BZ 1786 and 4358 for more info. 2664 * Just test that this formula can work now, 2665 * but we still have no offical formula. 2666 * 2667 * w_padding = ceiling(gdc_effective_input 2668 * /128, 1) * 128 - effective_width 2669 * gdc_shift_bq = w_padding/BDS/2 + ispfilter_bq/2 2670 */ 2671 gdc_effective_input = 2672 input_config->effective_res.width + 2673 pipe_cfg->dvs_envelope.width; 2674 w_padding = roundup(gdc_effective_input, 128) - 2675 input_config->effective_res.width; 2676 w_padding = w_padding * 2677 pipe_cfg->bayer_ds_out_res.width / 2678 input_config->effective_res.width + 1; 2679 w_padding = roundup(w_padding / 2, 1); 2680 2681 bq_res->gdc_shift_bq.width_bq = bq_res->ispfilter_bq.width_bq / 2 2682 + w_padding; 2683 bq_res->gdc_shift_bq.height_bq = 4 / 2; 2684 } 2685 } else { 2686 unsigned int dvs_w, dvs_h, dvs_w_max, dvs_h_max; 2687 2688 bq_res->ispfilter_bq.width_bq = 8 / 2; 2689 bq_res->ispfilter_bq.height_bq = 8 / 2; 2690 2691 if (IS_HWREVISION(asd->isp, ATOMISP_HW_REVISION_ISP2401)) { 2692 /* No additional left padding for ISYS2401 */ 2693 bq_res->gdc_shift_bq.width_bq = 4 / 2; 2694 bq_res->gdc_shift_bq.height_bq = 4 / 2; 2695 } else { 2696 w_padding = 2697 roundup(input_config->effective_res.width, 128) - 2698 input_config->effective_res.width; 2699 if (w_padding < 12) 2700 w_padding = 12; 2701 bq_res->gdc_shift_bq.width_bq = 4 / 2 + 2702 ((w_padding - 12) * 2703 pipe_cfg->bayer_ds_out_res.width / 2704 input_config->effective_res.width + 1) / 2; 2705 bq_res->gdc_shift_bq.height_bq = 4 / 2; 2706 } 2707 2708 dvs_w = pipe_cfg->bayer_ds_out_res.width - 2709 pipe_cfg->output_info[0].res.width; 2710 dvs_h = pipe_cfg->bayer_ds_out_res.height - 2711 pipe_cfg->output_info[0].res.height; 2712 dvs_w_max = rounddown( 2713 pipe_cfg->output_info[0].res.width / 5, 2714 ATOM_ISP_STEP_WIDTH); 2715 dvs_h_max = rounddown( 2716 pipe_cfg->output_info[0].res.height / 5, 2717 ATOM_ISP_STEP_HEIGHT); 2718 bq_res->envelope_bq.width_bq = 2719 min((dvs_w / 2), (dvs_w_max / 2)) - 2720 bq_res->ispfilter_bq.width_bq; 2721 bq_res->envelope_bq.height_bq = 2722 min((dvs_h / 2), (dvs_h_max / 2)) - 2723 bq_res->ispfilter_bq.height_bq; 2724 } 2725 } 2726 2727 dev_dbg(asd->isp->dev, 2728 "source_bq.width_bq %d, source_bq.height_bq %d,\nispfilter_bq.width_bq %d, ispfilter_bq.height_bq %d,\ngdc_shift_bq.width_bq %d, gdc_shift_bq.height_bq %d,\nenvelope_bq.width_bq %d, envelope_bq.height_bq %d,\noutput_bq.width_bq %d, output_bq.height_bq %d\n", 2729 bq_res->source_bq.width_bq, bq_res->source_bq.height_bq, 2730 bq_res->ispfilter_bq.width_bq, bq_res->ispfilter_bq.height_bq, 2731 bq_res->gdc_shift_bq.width_bq, bq_res->gdc_shift_bq.height_bq, 2732 bq_res->envelope_bq.width_bq, bq_res->envelope_bq.height_bq, 2733 bq_res->output_bq.width_bq, bq_res->output_bq.height_bq); 2734 2735 return 0; 2736 } 2737 2738 int atomisp_set_dis_coefs(struct atomisp_sub_device *asd, 2739 struct atomisp_dis_coefficients *coefs) 2740 { 2741 return atomisp_css_set_dis_coefs(asd, coefs); 2742 } 2743 2744 /* 2745 * Function to set/get 3A stat from isp 2746 */ 2747 int atomisp_3a_stat(struct atomisp_sub_device *asd, int flag, 2748 struct atomisp_3a_statistics *config) 2749 { 2750 struct atomisp_device *isp = asd->isp; 2751 struct atomisp_s3a_buf *s3a_buf; 2752 unsigned long ret; 2753 2754 if (flag != 0) 2755 return -EINVAL; 2756 2757 /* sanity check to avoid writing into unallocated memory. */ 2758 if (asd->params.s3a_output_bytes == 0) 2759 return -EINVAL; 2760 2761 if (atomisp_compare_grid(asd, &config->grid_info) != 0) { 2762 /* If the grid info in the argument differs from the current 2763 grid info, we tell the caller to reset the grid size and 2764 try again. */ 2765 return -EAGAIN; 2766 } 2767 2768 if (list_empty(&asd->s3a_stats_ready)) { 2769 dev_err(isp->dev, "3a statistics is not valid.\n"); 2770 return -EAGAIN; 2771 } 2772 2773 s3a_buf = list_entry(asd->s3a_stats_ready.next, 2774 struct atomisp_s3a_buf, list); 2775 if (s3a_buf->s3a_map) 2776 ia_css_translate_3a_statistics( 2777 asd->params.s3a_user_stat, s3a_buf->s3a_map); 2778 else 2779 ia_css_get_3a_statistics(asd->params.s3a_user_stat, 2780 s3a_buf->s3a_data); 2781 2782 config->exp_id = s3a_buf->s3a_data->exp_id; 2783 config->isp_config_id = s3a_buf->s3a_data->isp_config_id; 2784 2785 ret = copy_to_user(config->data, asd->params.s3a_user_stat->data, 2786 asd->params.s3a_output_bytes); 2787 if (ret) { 2788 dev_err(isp->dev, "copy to user failed: copied %lu bytes\n", 2789 ret); 2790 return -EFAULT; 2791 } 2792 2793 /* Move to free buffer list */ 2794 list_del_init(&s3a_buf->list); 2795 list_add_tail(&s3a_buf->list, &asd->s3a_stats); 2796 dev_dbg(isp->dev, "%s: finish getting exp_id %d 3a stat, isp_config_id %d\n", 2797 __func__, 2798 config->exp_id, config->isp_config_id); 2799 return 0; 2800 } 2801 2802 int atomisp_get_metadata(struct atomisp_sub_device *asd, int flag, 2803 struct atomisp_metadata *md) 2804 { 2805 struct atomisp_device *isp = asd->isp; 2806 struct ia_css_stream_config *stream_config; 2807 struct ia_css_stream_info *stream_info; 2808 struct camera_mipi_info *mipi_info; 2809 struct atomisp_metadata_buf *md_buf; 2810 enum atomisp_metadata_type md_type = ATOMISP_MAIN_METADATA; 2811 int ret, i; 2812 2813 if (flag != 0) 2814 return -EINVAL; 2815 2816 stream_config = &asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]. 2817 stream_config; 2818 stream_info = &asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]. 2819 stream_info; 2820 2821 /* We always return the resolution and stride even if there is 2822 * no valid metadata. This allows the caller to get the information 2823 * needed to allocate user-space buffers. */ 2824 md->width = stream_info->metadata_info.resolution.width; 2825 md->height = stream_info->metadata_info.resolution.height; 2826 md->stride = stream_info->metadata_info.stride; 2827 2828 /* sanity check to avoid writing into unallocated memory. 2829 * This does not return an error because it is a valid way 2830 * for applications to detect that metadata is not enabled. */ 2831 if (md->width == 0 || md->height == 0 || !md->data) 2832 return 0; 2833 2834 /* This is done in the atomisp_buf_done() */ 2835 if (list_empty(&asd->metadata_ready[md_type])) { 2836 dev_warn(isp->dev, "Metadata queue is empty now!\n"); 2837 return -EAGAIN; 2838 } 2839 2840 mipi_info = atomisp_to_sensor_mipi_info( 2841 isp->inputs[asd->input_curr].camera); 2842 if (!mipi_info) 2843 return -EINVAL; 2844 2845 if (mipi_info->metadata_effective_width) { 2846 for (i = 0; i < md->height; i++) 2847 md->effective_width[i] = 2848 mipi_info->metadata_effective_width[i]; 2849 } 2850 2851 md_buf = list_entry(asd->metadata_ready[md_type].next, 2852 struct atomisp_metadata_buf, list); 2853 md->exp_id = md_buf->metadata->exp_id; 2854 if (md_buf->md_vptr) { 2855 ret = copy_to_user(md->data, 2856 md_buf->md_vptr, 2857 stream_info->metadata_info.size); 2858 } else { 2859 hmm_load(md_buf->metadata->address, 2860 asd->params.metadata_user[md_type], 2861 stream_info->metadata_info.size); 2862 2863 ret = copy_to_user(md->data, 2864 asd->params.metadata_user[md_type], 2865 stream_info->metadata_info.size); 2866 } 2867 if (ret) { 2868 dev_err(isp->dev, "copy to user failed: copied %d bytes\n", 2869 ret); 2870 return -EFAULT; 2871 } 2872 2873 list_del_init(&md_buf->list); 2874 list_add_tail(&md_buf->list, &asd->metadata[md_type]); 2875 2876 dev_dbg(isp->dev, "%s: HAL de-queued metadata type %d with exp_id %d\n", 2877 __func__, md_type, md->exp_id); 2878 return 0; 2879 } 2880 2881 int atomisp_get_metadata_by_type(struct atomisp_sub_device *asd, int flag, 2882 struct atomisp_metadata_with_type *md) 2883 { 2884 struct atomisp_device *isp = asd->isp; 2885 struct ia_css_stream_config *stream_config; 2886 struct ia_css_stream_info *stream_info; 2887 struct camera_mipi_info *mipi_info; 2888 struct atomisp_metadata_buf *md_buf; 2889 enum atomisp_metadata_type md_type; 2890 int ret, i; 2891 2892 if (flag != 0) 2893 return -EINVAL; 2894 2895 stream_config = &asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]. 2896 stream_config; 2897 stream_info = &asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]. 2898 stream_info; 2899 2900 /* We always return the resolution and stride even if there is 2901 * no valid metadata. This allows the caller to get the information 2902 * needed to allocate user-space buffers. */ 2903 md->width = stream_info->metadata_info.resolution.width; 2904 md->height = stream_info->metadata_info.resolution.height; 2905 md->stride = stream_info->metadata_info.stride; 2906 2907 /* sanity check to avoid writing into unallocated memory. 2908 * This does not return an error because it is a valid way 2909 * for applications to detect that metadata is not enabled. */ 2910 if (md->width == 0 || md->height == 0 || !md->data) 2911 return 0; 2912 2913 md_type = md->type; 2914 if (md_type < 0 || md_type >= ATOMISP_METADATA_TYPE_NUM) 2915 return -EINVAL; 2916 2917 /* This is done in the atomisp_buf_done() */ 2918 if (list_empty(&asd->metadata_ready[md_type])) { 2919 dev_warn(isp->dev, "Metadata queue is empty now!\n"); 2920 return -EAGAIN; 2921 } 2922 2923 mipi_info = atomisp_to_sensor_mipi_info( 2924 isp->inputs[asd->input_curr].camera); 2925 if (!mipi_info) 2926 return -EINVAL; 2927 2928 if (mipi_info->metadata_effective_width) { 2929 for (i = 0; i < md->height; i++) 2930 md->effective_width[i] = 2931 mipi_info->metadata_effective_width[i]; 2932 } 2933 2934 md_buf = list_entry(asd->metadata_ready[md_type].next, 2935 struct atomisp_metadata_buf, list); 2936 md->exp_id = md_buf->metadata->exp_id; 2937 if (md_buf->md_vptr) { 2938 ret = copy_to_user(md->data, 2939 md_buf->md_vptr, 2940 stream_info->metadata_info.size); 2941 } else { 2942 hmm_load(md_buf->metadata->address, 2943 asd->params.metadata_user[md_type], 2944 stream_info->metadata_info.size); 2945 2946 ret = copy_to_user(md->data, 2947 asd->params.metadata_user[md_type], 2948 stream_info->metadata_info.size); 2949 } 2950 if (ret) { 2951 dev_err(isp->dev, "copy to user failed: copied %d bytes\n", 2952 ret); 2953 return -EFAULT; 2954 } else { 2955 list_del_init(&md_buf->list); 2956 list_add_tail(&md_buf->list, &asd->metadata[md_type]); 2957 } 2958 dev_dbg(isp->dev, "%s: HAL de-queued metadata type %d with exp_id %d\n", 2959 __func__, md_type, md->exp_id); 2960 return 0; 2961 } 2962 2963 /* 2964 * Function to calculate real zoom region for every pipe 2965 */ 2966 int atomisp_calculate_real_zoom_region(struct atomisp_sub_device *asd, 2967 struct ia_css_dz_config *dz_config, 2968 enum ia_css_pipe_id css_pipe_id) 2969 2970 { 2971 struct atomisp_stream_env *stream_env = 2972 &asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]; 2973 struct atomisp_resolution eff_res, out_res; 2974 int w_offset, h_offset; 2975 2976 memset(&eff_res, 0, sizeof(eff_res)); 2977 memset(&out_res, 0, sizeof(out_res)); 2978 2979 if (dz_config->dx || dz_config->dy) 2980 return 0; 2981 2982 if (css_pipe_id != IA_CSS_PIPE_ID_PREVIEW 2983 && css_pipe_id != IA_CSS_PIPE_ID_CAPTURE) { 2984 dev_err(asd->isp->dev, "%s the set pipe no support crop region" 2985 , __func__); 2986 return -EINVAL; 2987 } 2988 2989 eff_res.width = 2990 stream_env->stream_config.input_config.effective_res.width; 2991 eff_res.height = 2992 stream_env->stream_config.input_config.effective_res.height; 2993 if (eff_res.width == 0 || eff_res.height == 0) { 2994 dev_err(asd->isp->dev, "%s err effective resolution" 2995 , __func__); 2996 return -EINVAL; 2997 } 2998 2999 if (dz_config->zoom_region.resolution.width 3000 == asd->sensor_array_res.width 3001 || dz_config->zoom_region.resolution.height 3002 == asd->sensor_array_res.height) { 3003 /*no need crop region*/ 3004 dz_config->zoom_region.origin.x = 0; 3005 dz_config->zoom_region.origin.y = 0; 3006 dz_config->zoom_region.resolution.width = eff_res.width; 3007 dz_config->zoom_region.resolution.height = eff_res.height; 3008 return 0; 3009 } 3010 3011 /* FIXME: 3012 * This is not the correct implementation with Google's definition, due 3013 * to firmware limitation. 3014 * map real crop region base on above calculating base max crop region. 3015 */ 3016 3017 if (!atomisp_hw_is_isp2401) { 3018 dz_config->zoom_region.origin.x = dz_config->zoom_region.origin.x 3019 * eff_res.width 3020 / asd->sensor_array_res.width; 3021 dz_config->zoom_region.origin.y = dz_config->zoom_region.origin.y 3022 * eff_res.height 3023 / asd->sensor_array_res.height; 3024 dz_config->zoom_region.resolution.width = dz_config->zoom_region.resolution.width 3025 * eff_res.width 3026 / asd->sensor_array_res.width; 3027 dz_config->zoom_region.resolution.height = dz_config->zoom_region.resolution.height 3028 * eff_res.height 3029 / asd->sensor_array_res.height; 3030 /* 3031 * Set same ratio of crop region resolution and current pipe output 3032 * resolution 3033 */ 3034 out_res.width = stream_env->pipe_configs[css_pipe_id].output_info[0].res.width; 3035 out_res.height = stream_env->pipe_configs[css_pipe_id].output_info[0].res.height; 3036 if (out_res.width == 0 || out_res.height == 0) { 3037 dev_err(asd->isp->dev, "%s err current pipe output resolution" 3038 , __func__); 3039 return -EINVAL; 3040 } 3041 } else { 3042 out_res.width = stream_env->pipe_configs[css_pipe_id].output_info[0].res.width; 3043 out_res.height = stream_env->pipe_configs[css_pipe_id].output_info[0].res.height; 3044 if (out_res.width == 0 || out_res.height == 0) { 3045 dev_err(asd->isp->dev, "%s err current pipe output resolution" 3046 , __func__); 3047 return -EINVAL; 3048 } 3049 3050 if (asd->sensor_array_res.width * out_res.height 3051 < out_res.width * asd->sensor_array_res.height) { 3052 h_offset = asd->sensor_array_res.height 3053 - asd->sensor_array_res.width 3054 * out_res.height / out_res.width; 3055 h_offset = h_offset / 2; 3056 if (dz_config->zoom_region.origin.y < h_offset) 3057 dz_config->zoom_region.origin.y = 0; 3058 else 3059 dz_config->zoom_region.origin.y = dz_config->zoom_region.origin.y - h_offset; 3060 w_offset = 0; 3061 } else { 3062 w_offset = asd->sensor_array_res.width 3063 - asd->sensor_array_res.height 3064 * out_res.width / out_res.height; 3065 w_offset = w_offset / 2; 3066 if (dz_config->zoom_region.origin.x < w_offset) 3067 dz_config->zoom_region.origin.x = 0; 3068 else 3069 dz_config->zoom_region.origin.x = dz_config->zoom_region.origin.x - w_offset; 3070 h_offset = 0; 3071 } 3072 dz_config->zoom_region.origin.x = dz_config->zoom_region.origin.x 3073 * eff_res.width 3074 / (asd->sensor_array_res.width - 2 * w_offset); 3075 dz_config->zoom_region.origin.y = dz_config->zoom_region.origin.y 3076 * eff_res.height 3077 / (asd->sensor_array_res.height - 2 * h_offset); 3078 dz_config->zoom_region.resolution.width = dz_config->zoom_region.resolution.width 3079 * eff_res.width 3080 / (asd->sensor_array_res.width - 2 * w_offset); 3081 dz_config->zoom_region.resolution.height = dz_config->zoom_region.resolution.height 3082 * eff_res.height 3083 / (asd->sensor_array_res.height - 2 * h_offset); 3084 } 3085 3086 if (out_res.width * dz_config->zoom_region.resolution.height 3087 > dz_config->zoom_region.resolution.width * out_res.height) { 3088 dz_config->zoom_region.resolution.height = 3089 dz_config->zoom_region.resolution.width 3090 * out_res.height / out_res.width; 3091 } else { 3092 dz_config->zoom_region.resolution.width = 3093 dz_config->zoom_region.resolution.height 3094 * out_res.width / out_res.height; 3095 } 3096 dev_dbg(asd->isp->dev, 3097 "%s crop region:(%d,%d),(%d,%d) eff_res(%d, %d) array_size(%d,%d) out_res(%d, %d)\n", 3098 __func__, dz_config->zoom_region.origin.x, 3099 dz_config->zoom_region.origin.y, 3100 dz_config->zoom_region.resolution.width, 3101 dz_config->zoom_region.resolution.height, 3102 eff_res.width, eff_res.height, 3103 asd->sensor_array_res.width, 3104 asd->sensor_array_res.height, 3105 out_res.width, out_res.height); 3106 3107 if ((dz_config->zoom_region.origin.x + 3108 dz_config->zoom_region.resolution.width 3109 > eff_res.width) || 3110 (dz_config->zoom_region.origin.y + 3111 dz_config->zoom_region.resolution.height 3112 > eff_res.height)) 3113 return -EINVAL; 3114 3115 return 0; 3116 } 3117 3118 /* 3119 * Function to check the zoom region whether is effective 3120 */ 3121 static bool atomisp_check_zoom_region( 3122 struct atomisp_sub_device *asd, 3123 struct ia_css_dz_config *dz_config) 3124 { 3125 struct atomisp_resolution config; 3126 bool flag = false; 3127 unsigned int w, h; 3128 3129 memset(&config, 0, sizeof(struct atomisp_resolution)); 3130 3131 if (dz_config->dx && dz_config->dy) 3132 return true; 3133 3134 config.width = asd->sensor_array_res.width; 3135 config.height = asd->sensor_array_res.height; 3136 w = dz_config->zoom_region.origin.x + 3137 dz_config->zoom_region.resolution.width; 3138 h = dz_config->zoom_region.origin.y + 3139 dz_config->zoom_region.resolution.height; 3140 3141 if ((w <= config.width) && (h <= config.height) && w > 0 && h > 0) 3142 flag = true; 3143 else 3144 /* setting error zoom region */ 3145 dev_err(asd->isp->dev, 3146 "%s zoom region ERROR:dz_config:(%d,%d),(%d,%d)array_res(%d, %d)\n", 3147 __func__, dz_config->zoom_region.origin.x, 3148 dz_config->zoom_region.origin.y, 3149 dz_config->zoom_region.resolution.width, 3150 dz_config->zoom_region.resolution.height, 3151 config.width, config.height); 3152 3153 return flag; 3154 } 3155 3156 void atomisp_apply_css_parameters( 3157 struct atomisp_sub_device *asd, 3158 struct atomisp_css_params *css_param) 3159 { 3160 if (css_param->update_flag.wb_config) 3161 asd->params.config.wb_config = &css_param->wb_config; 3162 3163 if (css_param->update_flag.ob_config) 3164 asd->params.config.ob_config = &css_param->ob_config; 3165 3166 if (css_param->update_flag.dp_config) 3167 asd->params.config.dp_config = &css_param->dp_config; 3168 3169 if (css_param->update_flag.nr_config) 3170 asd->params.config.nr_config = &css_param->nr_config; 3171 3172 if (css_param->update_flag.ee_config) 3173 asd->params.config.ee_config = &css_param->ee_config; 3174 3175 if (css_param->update_flag.tnr_config) 3176 asd->params.config.tnr_config = &css_param->tnr_config; 3177 3178 if (css_param->update_flag.a3a_config) 3179 asd->params.config.s3a_config = &css_param->s3a_config; 3180 3181 if (css_param->update_flag.ctc_config) 3182 asd->params.config.ctc_config = &css_param->ctc_config; 3183 3184 if (css_param->update_flag.cnr_config) 3185 asd->params.config.cnr_config = &css_param->cnr_config; 3186 3187 if (css_param->update_flag.ecd_config) 3188 asd->params.config.ecd_config = &css_param->ecd_config; 3189 3190 if (css_param->update_flag.ynr_config) 3191 asd->params.config.ynr_config = &css_param->ynr_config; 3192 3193 if (css_param->update_flag.fc_config) 3194 asd->params.config.fc_config = &css_param->fc_config; 3195 3196 if (css_param->update_flag.macc_config) 3197 asd->params.config.macc_config = &css_param->macc_config; 3198 3199 if (css_param->update_flag.aa_config) 3200 asd->params.config.aa_config = &css_param->aa_config; 3201 3202 if (css_param->update_flag.anr_config) 3203 asd->params.config.anr_config = &css_param->anr_config; 3204 3205 if (css_param->update_flag.xnr_config) 3206 asd->params.config.xnr_config = &css_param->xnr_config; 3207 3208 if (css_param->update_flag.yuv2rgb_cc_config) 3209 asd->params.config.yuv2rgb_cc_config = &css_param->yuv2rgb_cc_config; 3210 3211 if (css_param->update_flag.rgb2yuv_cc_config) 3212 asd->params.config.rgb2yuv_cc_config = &css_param->rgb2yuv_cc_config; 3213 3214 if (css_param->update_flag.macc_table) 3215 asd->params.config.macc_table = &css_param->macc_table; 3216 3217 if (css_param->update_flag.xnr_table) 3218 asd->params.config.xnr_table = &css_param->xnr_table; 3219 3220 if (css_param->update_flag.r_gamma_table) 3221 asd->params.config.r_gamma_table = &css_param->r_gamma_table; 3222 3223 if (css_param->update_flag.g_gamma_table) 3224 asd->params.config.g_gamma_table = &css_param->g_gamma_table; 3225 3226 if (css_param->update_flag.b_gamma_table) 3227 asd->params.config.b_gamma_table = &css_param->b_gamma_table; 3228 3229 if (css_param->update_flag.anr_thres) 3230 atomisp_css_set_anr_thres(asd, &css_param->anr_thres); 3231 3232 if (css_param->update_flag.shading_table) 3233 asd->params.config.shading_table = css_param->shading_table; 3234 3235 if (css_param->update_flag.morph_table && asd->params.gdc_cac_en) 3236 asd->params.config.morph_table = css_param->morph_table; 3237 3238 if (css_param->update_flag.dvs2_coefs) { 3239 struct ia_css_dvs_grid_info *dvs_grid_info = 3240 atomisp_css_get_dvs_grid_info( 3241 &asd->params.curr_grid_info); 3242 3243 if (dvs_grid_info && dvs_grid_info->enable) 3244 atomisp_css_set_dvs2_coefs(asd, css_param->dvs2_coeff); 3245 } 3246 3247 if (css_param->update_flag.dvs_6axis_config) 3248 atomisp_css_set_dvs_6axis(asd, css_param->dvs_6axis); 3249 3250 atomisp_css_set_isp_config_id(asd, css_param->isp_config_id); 3251 /* 3252 * These configurations are on used by ISP1.x, not for ISP2.x, 3253 * so do not handle them. see comments of ia_css_isp_config. 3254 * 1 cc_config 3255 * 2 ce_config 3256 * 3 de_config 3257 * 4 gc_config 3258 * 5 gamma_table 3259 * 6 ctc_table 3260 * 7 dvs_coefs 3261 */ 3262 } 3263 3264 static unsigned int long copy_from_compatible(void *to, const void *from, 3265 unsigned long n, bool from_user) 3266 { 3267 if (from_user) 3268 return copy_from_user(to, (void __user *)from, n); 3269 else 3270 memcpy(to, from, n); 3271 return 0; 3272 } 3273 3274 int atomisp_cp_general_isp_parameters(struct atomisp_sub_device *asd, 3275 struct atomisp_parameters *arg, 3276 struct atomisp_css_params *css_param, 3277 bool from_user) 3278 { 3279 struct atomisp_parameters *cur_config = &css_param->update_flag; 3280 3281 if (!arg || !asd || !css_param) 3282 return -EINVAL; 3283 3284 if (arg->wb_config && (from_user || !cur_config->wb_config)) { 3285 if (copy_from_compatible(&css_param->wb_config, arg->wb_config, 3286 sizeof(struct ia_css_wb_config), 3287 from_user)) 3288 return -EFAULT; 3289 css_param->update_flag.wb_config = 3290 (struct atomisp_wb_config *)&css_param->wb_config; 3291 } 3292 3293 if (arg->ob_config && (from_user || !cur_config->ob_config)) { 3294 if (copy_from_compatible(&css_param->ob_config, arg->ob_config, 3295 sizeof(struct ia_css_ob_config), 3296 from_user)) 3297 return -EFAULT; 3298 css_param->update_flag.ob_config = 3299 (struct atomisp_ob_config *)&css_param->ob_config; 3300 } 3301 3302 if (arg->dp_config && (from_user || !cur_config->dp_config)) { 3303 if (copy_from_compatible(&css_param->dp_config, arg->dp_config, 3304 sizeof(struct ia_css_dp_config), 3305 from_user)) 3306 return -EFAULT; 3307 css_param->update_flag.dp_config = 3308 (struct atomisp_dp_config *)&css_param->dp_config; 3309 } 3310 3311 if (asd->run_mode->val != ATOMISP_RUN_MODE_VIDEO) { 3312 if (arg->dz_config && (from_user || !cur_config->dz_config)) { 3313 if (copy_from_compatible(&css_param->dz_config, 3314 arg->dz_config, 3315 sizeof(struct ia_css_dz_config), 3316 from_user)) 3317 return -EFAULT; 3318 if (!atomisp_check_zoom_region(asd, 3319 &css_param->dz_config)) { 3320 dev_err(asd->isp->dev, "crop region error!"); 3321 return -EINVAL; 3322 } 3323 css_param->update_flag.dz_config = 3324 (struct atomisp_dz_config *) 3325 &css_param->dz_config; 3326 } 3327 } 3328 3329 if (arg->nr_config && (from_user || !cur_config->nr_config)) { 3330 if (copy_from_compatible(&css_param->nr_config, arg->nr_config, 3331 sizeof(struct ia_css_nr_config), 3332 from_user)) 3333 return -EFAULT; 3334 css_param->update_flag.nr_config = 3335 (struct atomisp_nr_config *)&css_param->nr_config; 3336 } 3337 3338 if (arg->ee_config && (from_user || !cur_config->ee_config)) { 3339 if (copy_from_compatible(&css_param->ee_config, arg->ee_config, 3340 sizeof(struct ia_css_ee_config), 3341 from_user)) 3342 return -EFAULT; 3343 css_param->update_flag.ee_config = 3344 (struct atomisp_ee_config *)&css_param->ee_config; 3345 } 3346 3347 if (arg->tnr_config && (from_user || !cur_config->tnr_config)) { 3348 if (copy_from_compatible(&css_param->tnr_config, 3349 arg->tnr_config, 3350 sizeof(struct ia_css_tnr_config), 3351 from_user)) 3352 return -EFAULT; 3353 css_param->update_flag.tnr_config = 3354 (struct atomisp_tnr_config *) 3355 &css_param->tnr_config; 3356 } 3357 3358 if (arg->a3a_config && (from_user || !cur_config->a3a_config)) { 3359 if (copy_from_compatible(&css_param->s3a_config, 3360 arg->a3a_config, 3361 sizeof(struct ia_css_3a_config), 3362 from_user)) 3363 return -EFAULT; 3364 css_param->update_flag.a3a_config = 3365 (struct atomisp_3a_config *)&css_param->s3a_config; 3366 } 3367 3368 if (arg->ctc_config && (from_user || !cur_config->ctc_config)) { 3369 if (copy_from_compatible(&css_param->ctc_config, 3370 arg->ctc_config, 3371 sizeof(struct ia_css_ctc_config), 3372 from_user)) 3373 return -EFAULT; 3374 css_param->update_flag.ctc_config = 3375 (struct atomisp_ctc_config *) 3376 &css_param->ctc_config; 3377 } 3378 3379 if (arg->cnr_config && (from_user || !cur_config->cnr_config)) { 3380 if (copy_from_compatible(&css_param->cnr_config, 3381 arg->cnr_config, 3382 sizeof(struct ia_css_cnr_config), 3383 from_user)) 3384 return -EFAULT; 3385 css_param->update_flag.cnr_config = 3386 (struct atomisp_cnr_config *) 3387 &css_param->cnr_config; 3388 } 3389 3390 if (arg->ecd_config && (from_user || !cur_config->ecd_config)) { 3391 if (copy_from_compatible(&css_param->ecd_config, 3392 arg->ecd_config, 3393 sizeof(struct ia_css_ecd_config), 3394 from_user)) 3395 return -EFAULT; 3396 css_param->update_flag.ecd_config = 3397 (struct atomisp_ecd_config *) 3398 &css_param->ecd_config; 3399 } 3400 3401 if (arg->ynr_config && (from_user || !cur_config->ynr_config)) { 3402 if (copy_from_compatible(&css_param->ynr_config, 3403 arg->ynr_config, 3404 sizeof(struct ia_css_ynr_config), 3405 from_user)) 3406 return -EFAULT; 3407 css_param->update_flag.ynr_config = 3408 (struct atomisp_ynr_config *) 3409 &css_param->ynr_config; 3410 } 3411 3412 if (arg->fc_config && (from_user || !cur_config->fc_config)) { 3413 if (copy_from_compatible(&css_param->fc_config, 3414 arg->fc_config, 3415 sizeof(struct ia_css_fc_config), 3416 from_user)) 3417 return -EFAULT; 3418 css_param->update_flag.fc_config = 3419 (struct atomisp_fc_config *)&css_param->fc_config; 3420 } 3421 3422 if (arg->macc_config && (from_user || !cur_config->macc_config)) { 3423 if (copy_from_compatible(&css_param->macc_config, 3424 arg->macc_config, 3425 sizeof(struct ia_css_macc_config), 3426 from_user)) 3427 return -EFAULT; 3428 css_param->update_flag.macc_config = 3429 (struct atomisp_macc_config *) 3430 &css_param->macc_config; 3431 } 3432 3433 if (arg->aa_config && (from_user || !cur_config->aa_config)) { 3434 if (copy_from_compatible(&css_param->aa_config, arg->aa_config, 3435 sizeof(struct ia_css_aa_config), 3436 from_user)) 3437 return -EFAULT; 3438 css_param->update_flag.aa_config = 3439 (struct atomisp_aa_config *)&css_param->aa_config; 3440 } 3441 3442 if (arg->anr_config && (from_user || !cur_config->anr_config)) { 3443 if (copy_from_compatible(&css_param->anr_config, 3444 arg->anr_config, 3445 sizeof(struct ia_css_anr_config), 3446 from_user)) 3447 return -EFAULT; 3448 css_param->update_flag.anr_config = 3449 (struct atomisp_anr_config *) 3450 &css_param->anr_config; 3451 } 3452 3453 if (arg->xnr_config && (from_user || !cur_config->xnr_config)) { 3454 if (copy_from_compatible(&css_param->xnr_config, 3455 arg->xnr_config, 3456 sizeof(struct ia_css_xnr_config), 3457 from_user)) 3458 return -EFAULT; 3459 css_param->update_flag.xnr_config = 3460 (struct atomisp_xnr_config *) 3461 &css_param->xnr_config; 3462 } 3463 3464 if (arg->yuv2rgb_cc_config && 3465 (from_user || !cur_config->yuv2rgb_cc_config)) { 3466 if (copy_from_compatible(&css_param->yuv2rgb_cc_config, 3467 arg->yuv2rgb_cc_config, 3468 sizeof(struct ia_css_cc_config), 3469 from_user)) 3470 return -EFAULT; 3471 css_param->update_flag.yuv2rgb_cc_config = 3472 (struct atomisp_cc_config *) 3473 &css_param->yuv2rgb_cc_config; 3474 } 3475 3476 if (arg->rgb2yuv_cc_config && 3477 (from_user || !cur_config->rgb2yuv_cc_config)) { 3478 if (copy_from_compatible(&css_param->rgb2yuv_cc_config, 3479 arg->rgb2yuv_cc_config, 3480 sizeof(struct ia_css_cc_config), 3481 from_user)) 3482 return -EFAULT; 3483 css_param->update_flag.rgb2yuv_cc_config = 3484 (struct atomisp_cc_config *) 3485 &css_param->rgb2yuv_cc_config; 3486 } 3487 3488 if (arg->macc_table && (from_user || !cur_config->macc_table)) { 3489 if (copy_from_compatible(&css_param->macc_table, 3490 arg->macc_table, 3491 sizeof(struct ia_css_macc_table), 3492 from_user)) 3493 return -EFAULT; 3494 css_param->update_flag.macc_table = 3495 (struct atomisp_macc_table *) 3496 &css_param->macc_table; 3497 } 3498 3499 if (arg->xnr_table && (from_user || !cur_config->xnr_table)) { 3500 if (copy_from_compatible(&css_param->xnr_table, 3501 arg->xnr_table, 3502 sizeof(struct ia_css_xnr_table), 3503 from_user)) 3504 return -EFAULT; 3505 css_param->update_flag.xnr_table = 3506 (struct atomisp_xnr_table *)&css_param->xnr_table; 3507 } 3508 3509 if (arg->r_gamma_table && (from_user || !cur_config->r_gamma_table)) { 3510 if (copy_from_compatible(&css_param->r_gamma_table, 3511 arg->r_gamma_table, 3512 sizeof(struct ia_css_rgb_gamma_table), 3513 from_user)) 3514 return -EFAULT; 3515 css_param->update_flag.r_gamma_table = 3516 (struct atomisp_rgb_gamma_table *) 3517 &css_param->r_gamma_table; 3518 } 3519 3520 if (arg->g_gamma_table && (from_user || !cur_config->g_gamma_table)) { 3521 if (copy_from_compatible(&css_param->g_gamma_table, 3522 arg->g_gamma_table, 3523 sizeof(struct ia_css_rgb_gamma_table), 3524 from_user)) 3525 return -EFAULT; 3526 css_param->update_flag.g_gamma_table = 3527 (struct atomisp_rgb_gamma_table *) 3528 &css_param->g_gamma_table; 3529 } 3530 3531 if (arg->b_gamma_table && (from_user || !cur_config->b_gamma_table)) { 3532 if (copy_from_compatible(&css_param->b_gamma_table, 3533 arg->b_gamma_table, 3534 sizeof(struct ia_css_rgb_gamma_table), 3535 from_user)) 3536 return -EFAULT; 3537 css_param->update_flag.b_gamma_table = 3538 (struct atomisp_rgb_gamma_table *) 3539 &css_param->b_gamma_table; 3540 } 3541 3542 if (arg->anr_thres && (from_user || !cur_config->anr_thres)) { 3543 if (copy_from_compatible(&css_param->anr_thres, arg->anr_thres, 3544 sizeof(struct ia_css_anr_thres), 3545 from_user)) 3546 return -EFAULT; 3547 css_param->update_flag.anr_thres = 3548 (struct atomisp_anr_thres *)&css_param->anr_thres; 3549 } 3550 3551 if (from_user) 3552 css_param->isp_config_id = arg->isp_config_id; 3553 /* 3554 * These configurations are on used by ISP1.x, not for ISP2.x, 3555 * so do not handle them. see comments of ia_css_isp_config. 3556 * 1 cc_config 3557 * 2 ce_config 3558 * 3 de_config 3559 * 4 gc_config 3560 * 5 gamma_table 3561 * 6 ctc_table 3562 * 7 dvs_coefs 3563 */ 3564 return 0; 3565 } 3566 3567 int atomisp_cp_lsc_table(struct atomisp_sub_device *asd, 3568 struct atomisp_shading_table *source_st, 3569 struct atomisp_css_params *css_param, 3570 bool from_user) 3571 { 3572 unsigned int i; 3573 unsigned int len_table; 3574 struct ia_css_shading_table *shading_table; 3575 struct ia_css_shading_table *old_table; 3576 struct atomisp_shading_table *st, dest_st; 3577 3578 if (!source_st) 3579 return 0; 3580 3581 if (!css_param) 3582 return -EINVAL; 3583 3584 if (!from_user && css_param->update_flag.shading_table) 3585 return 0; 3586 3587 if (atomisp_hw_is_isp2401) { 3588 if (copy_from_compatible(&dest_st, source_st, 3589 sizeof(struct atomisp_shading_table), 3590 from_user)) { 3591 dev_err(asd->isp->dev, "copy shading table failed!"); 3592 return -EFAULT; 3593 } 3594 st = &dest_st; 3595 } else { 3596 st = source_st; 3597 } 3598 3599 old_table = css_param->shading_table; 3600 3601 /* user config is to disable the shading table. */ 3602 if (!st->enable) { 3603 /* Generate a minimum table with enable = 0. */ 3604 shading_table = atomisp_css_shading_table_alloc(1, 1); 3605 if (!shading_table) 3606 return -ENOMEM; 3607 shading_table->enable = 0; 3608 goto set_lsc; 3609 } 3610 3611 /* Setting a new table. Validate first - all tables must be set */ 3612 for (i = 0; i < ATOMISP_NUM_SC_COLORS; i++) { 3613 if (!st->data[i]) { 3614 dev_err(asd->isp->dev, "shading table validate failed"); 3615 return -EINVAL; 3616 } 3617 } 3618 3619 /* Shading table size per color */ 3620 if (!atomisp_hw_is_isp2401) { 3621 if (st->width > ISP2400_SH_CSS_MAX_SCTBL_WIDTH_PER_COLOR || 3622 st->height > ISP2400_SH_CSS_MAX_SCTBL_HEIGHT_PER_COLOR) { 3623 dev_err(asd->isp->dev, "shading table w/h validate failed!"); 3624 return -EINVAL; 3625 } 3626 } else { 3627 if (st->width > ISP2401_SH_CSS_MAX_SCTBL_WIDTH_PER_COLOR || 3628 st->height > ISP2401_SH_CSS_MAX_SCTBL_HEIGHT_PER_COLOR) { 3629 dev_err(asd->isp->dev, "shading table w/h validate failed!"); 3630 return -EINVAL; 3631 } 3632 } 3633 3634 shading_table = atomisp_css_shading_table_alloc(st->width, st->height); 3635 if (!shading_table) 3636 return -ENOMEM; 3637 3638 len_table = st->width * st->height * ATOMISP_SC_TYPE_SIZE; 3639 for (i = 0; i < ATOMISP_NUM_SC_COLORS; i++) { 3640 if (copy_from_compatible(shading_table->data[i], 3641 st->data[i], len_table, from_user)) { 3642 atomisp_css_shading_table_free(shading_table); 3643 return -EFAULT; 3644 } 3645 } 3646 shading_table->sensor_width = st->sensor_width; 3647 shading_table->sensor_height = st->sensor_height; 3648 shading_table->fraction_bits = st->fraction_bits; 3649 shading_table->enable = st->enable; 3650 3651 /* No need to update shading table if it is the same */ 3652 if (old_table && 3653 old_table->sensor_width == shading_table->sensor_width && 3654 old_table->sensor_height == shading_table->sensor_height && 3655 old_table->width == shading_table->width && 3656 old_table->height == shading_table->height && 3657 old_table->fraction_bits == shading_table->fraction_bits && 3658 old_table->enable == shading_table->enable) { 3659 bool data_is_same = true; 3660 3661 for (i = 0; i < ATOMISP_NUM_SC_COLORS; i++) { 3662 if (memcmp(shading_table->data[i], old_table->data[i], 3663 len_table) != 0) { 3664 data_is_same = false; 3665 break; 3666 } 3667 } 3668 3669 if (data_is_same) { 3670 atomisp_css_shading_table_free(shading_table); 3671 return 0; 3672 } 3673 } 3674 3675 set_lsc: 3676 /* set LSC to CSS */ 3677 css_param->shading_table = shading_table; 3678 css_param->update_flag.shading_table = (struct atomisp_shading_table *)shading_table; 3679 asd->params.sc_en = shading_table; 3680 3681 if (old_table) 3682 atomisp_css_shading_table_free(old_table); 3683 3684 return 0; 3685 } 3686 3687 int atomisp_css_cp_dvs2_coefs(struct atomisp_sub_device *asd, 3688 struct ia_css_dvs2_coefficients *coefs, 3689 struct atomisp_css_params *css_param, 3690 bool from_user) 3691 { 3692 struct ia_css_dvs_grid_info *cur = 3693 atomisp_css_get_dvs_grid_info(&asd->params.curr_grid_info); 3694 int dvs_hor_coef_bytes, dvs_ver_coef_bytes; 3695 struct ia_css_dvs2_coefficients dvs2_coefs; 3696 3697 if (!coefs || !cur) 3698 return 0; 3699 3700 if (!from_user && css_param->update_flag.dvs2_coefs) 3701 return 0; 3702 3703 if (!atomisp_hw_is_isp2401) { 3704 if (sizeof(*cur) != sizeof(coefs->grid) || 3705 memcmp(&coefs->grid, cur, sizeof(coefs->grid))) { 3706 dev_err(asd->isp->dev, "dvs grid mis-match!\n"); 3707 /* If the grid info in the argument differs from the current 3708 grid info, we tell the caller to reset the grid size and 3709 try again. */ 3710 return -EAGAIN; 3711 } 3712 3713 if (!coefs->hor_coefs.odd_real || 3714 !coefs->hor_coefs.odd_imag || 3715 !coefs->hor_coefs.even_real || 3716 !coefs->hor_coefs.even_imag || 3717 !coefs->ver_coefs.odd_real || 3718 !coefs->ver_coefs.odd_imag || 3719 !coefs->ver_coefs.even_real || 3720 !coefs->ver_coefs.even_imag) 3721 return -EINVAL; 3722 3723 if (!css_param->dvs2_coeff) { 3724 /* DIS coefficients. */ 3725 css_param->dvs2_coeff = ia_css_dvs2_coefficients_allocate(cur); 3726 if (!css_param->dvs2_coeff) 3727 return -ENOMEM; 3728 } 3729 3730 dvs_hor_coef_bytes = asd->params.dvs_hor_coef_bytes; 3731 dvs_ver_coef_bytes = asd->params.dvs_ver_coef_bytes; 3732 if (copy_from_compatible(css_param->dvs2_coeff->hor_coefs.odd_real, 3733 coefs->hor_coefs.odd_real, dvs_hor_coef_bytes, from_user) || 3734 copy_from_compatible(css_param->dvs2_coeff->hor_coefs.odd_imag, 3735 coefs->hor_coefs.odd_imag, dvs_hor_coef_bytes, from_user) || 3736 copy_from_compatible(css_param->dvs2_coeff->hor_coefs.even_real, 3737 coefs->hor_coefs.even_real, dvs_hor_coef_bytes, from_user) || 3738 copy_from_compatible(css_param->dvs2_coeff->hor_coefs.even_imag, 3739 coefs->hor_coefs.even_imag, dvs_hor_coef_bytes, from_user) || 3740 copy_from_compatible(css_param->dvs2_coeff->ver_coefs.odd_real, 3741 coefs->ver_coefs.odd_real, dvs_ver_coef_bytes, from_user) || 3742 copy_from_compatible(css_param->dvs2_coeff->ver_coefs.odd_imag, 3743 coefs->ver_coefs.odd_imag, dvs_ver_coef_bytes, from_user) || 3744 copy_from_compatible(css_param->dvs2_coeff->ver_coefs.even_real, 3745 coefs->ver_coefs.even_real, dvs_ver_coef_bytes, from_user) || 3746 copy_from_compatible(css_param->dvs2_coeff->ver_coefs.even_imag, 3747 coefs->ver_coefs.even_imag, dvs_ver_coef_bytes, from_user)) { 3748 ia_css_dvs2_coefficients_free(css_param->dvs2_coeff); 3749 css_param->dvs2_coeff = NULL; 3750 return -EFAULT; 3751 } 3752 } else { 3753 if (copy_from_compatible(&dvs2_coefs, coefs, 3754 sizeof(struct ia_css_dvs2_coefficients), 3755 from_user)) { 3756 dev_err(asd->isp->dev, "copy dvs2 coef failed"); 3757 return -EFAULT; 3758 } 3759 3760 if (sizeof(*cur) != sizeof(dvs2_coefs.grid) || 3761 memcmp(&dvs2_coefs.grid, cur, sizeof(dvs2_coefs.grid))) { 3762 dev_err(asd->isp->dev, "dvs grid mis-match!\n"); 3763 /* If the grid info in the argument differs from the current 3764 grid info, we tell the caller to reset the grid size and 3765 try again. */ 3766 return -EAGAIN; 3767 } 3768 3769 if (!dvs2_coefs.hor_coefs.odd_real || 3770 !dvs2_coefs.hor_coefs.odd_imag || 3771 !dvs2_coefs.hor_coefs.even_real || 3772 !dvs2_coefs.hor_coefs.even_imag || 3773 !dvs2_coefs.ver_coefs.odd_real || 3774 !dvs2_coefs.ver_coefs.odd_imag || 3775 !dvs2_coefs.ver_coefs.even_real || 3776 !dvs2_coefs.ver_coefs.even_imag) 3777 return -EINVAL; 3778 3779 if (!css_param->dvs2_coeff) { 3780 /* DIS coefficients. */ 3781 css_param->dvs2_coeff = ia_css_dvs2_coefficients_allocate(cur); 3782 if (!css_param->dvs2_coeff) 3783 return -ENOMEM; 3784 } 3785 3786 dvs_hor_coef_bytes = asd->params.dvs_hor_coef_bytes; 3787 dvs_ver_coef_bytes = asd->params.dvs_ver_coef_bytes; 3788 if (copy_from_compatible(css_param->dvs2_coeff->hor_coefs.odd_real, 3789 dvs2_coefs.hor_coefs.odd_real, dvs_hor_coef_bytes, from_user) || 3790 copy_from_compatible(css_param->dvs2_coeff->hor_coefs.odd_imag, 3791 dvs2_coefs.hor_coefs.odd_imag, dvs_hor_coef_bytes, from_user) || 3792 copy_from_compatible(css_param->dvs2_coeff->hor_coefs.even_real, 3793 dvs2_coefs.hor_coefs.even_real, dvs_hor_coef_bytes, from_user) || 3794 copy_from_compatible(css_param->dvs2_coeff->hor_coefs.even_imag, 3795 dvs2_coefs.hor_coefs.even_imag, dvs_hor_coef_bytes, from_user) || 3796 copy_from_compatible(css_param->dvs2_coeff->ver_coefs.odd_real, 3797 dvs2_coefs.ver_coefs.odd_real, dvs_ver_coef_bytes, from_user) || 3798 copy_from_compatible(css_param->dvs2_coeff->ver_coefs.odd_imag, 3799 dvs2_coefs.ver_coefs.odd_imag, dvs_ver_coef_bytes, from_user) || 3800 copy_from_compatible(css_param->dvs2_coeff->ver_coefs.even_real, 3801 dvs2_coefs.ver_coefs.even_real, dvs_ver_coef_bytes, from_user) || 3802 copy_from_compatible(css_param->dvs2_coeff->ver_coefs.even_imag, 3803 dvs2_coefs.ver_coefs.even_imag, dvs_ver_coef_bytes, from_user)) { 3804 ia_css_dvs2_coefficients_free(css_param->dvs2_coeff); 3805 css_param->dvs2_coeff = NULL; 3806 return -EFAULT; 3807 } 3808 } 3809 3810 css_param->update_flag.dvs2_coefs = 3811 (struct atomisp_dis_coefficients *)css_param->dvs2_coeff; 3812 return 0; 3813 } 3814 3815 int atomisp_cp_dvs_6axis_config(struct atomisp_sub_device *asd, 3816 struct atomisp_dvs_6axis_config *source_6axis_config, 3817 struct atomisp_css_params *css_param, 3818 bool from_user) 3819 { 3820 struct ia_css_dvs_6axis_config *dvs_6axis_config; 3821 struct ia_css_dvs_6axis_config *old_6axis_config; 3822 struct ia_css_stream *stream = 3823 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream; 3824 struct ia_css_dvs_grid_info *dvs_grid_info = 3825 atomisp_css_get_dvs_grid_info(&asd->params.curr_grid_info); 3826 int ret = -EFAULT; 3827 3828 if (!stream) { 3829 dev_err(asd->isp->dev, "%s: internal error!", __func__); 3830 return -EINVAL; 3831 } 3832 3833 if (!source_6axis_config || !dvs_grid_info) 3834 return 0; 3835 3836 if (!dvs_grid_info->enable) 3837 return 0; 3838 3839 if (!from_user && css_param->update_flag.dvs_6axis_config) 3840 return 0; 3841 3842 /* check whether need to reallocate for 6 axis config */ 3843 old_6axis_config = css_param->dvs_6axis; 3844 dvs_6axis_config = old_6axis_config; 3845 3846 if (atomisp_hw_is_isp2401) { 3847 struct ia_css_dvs_6axis_config t_6axis_config; 3848 3849 if (copy_from_compatible(&t_6axis_config, source_6axis_config, 3850 sizeof(struct atomisp_dvs_6axis_config), 3851 from_user)) { 3852 dev_err(asd->isp->dev, "copy morph table failed!"); 3853 return -EFAULT; 3854 } 3855 3856 if (old_6axis_config && 3857 (old_6axis_config->width_y != t_6axis_config.width_y || 3858 old_6axis_config->height_y != t_6axis_config.height_y || 3859 old_6axis_config->width_uv != t_6axis_config.width_uv || 3860 old_6axis_config->height_uv != t_6axis_config.height_uv)) { 3861 ia_css_dvs2_6axis_config_free(css_param->dvs_6axis); 3862 css_param->dvs_6axis = NULL; 3863 3864 dvs_6axis_config = ia_css_dvs2_6axis_config_allocate(stream); 3865 if (!dvs_6axis_config) 3866 return -ENOMEM; 3867 } else if (!dvs_6axis_config) { 3868 dvs_6axis_config = ia_css_dvs2_6axis_config_allocate(stream); 3869 if (!dvs_6axis_config) 3870 return -ENOMEM; 3871 } 3872 3873 dvs_6axis_config->exp_id = t_6axis_config.exp_id; 3874 3875 if (copy_from_compatible(dvs_6axis_config->xcoords_y, 3876 t_6axis_config.xcoords_y, 3877 t_6axis_config.width_y * 3878 t_6axis_config.height_y * 3879 sizeof(*dvs_6axis_config->xcoords_y), 3880 from_user)) 3881 goto error; 3882 if (copy_from_compatible(dvs_6axis_config->ycoords_y, 3883 t_6axis_config.ycoords_y, 3884 t_6axis_config.width_y * 3885 t_6axis_config.height_y * 3886 sizeof(*dvs_6axis_config->ycoords_y), 3887 from_user)) 3888 goto error; 3889 if (copy_from_compatible(dvs_6axis_config->xcoords_uv, 3890 t_6axis_config.xcoords_uv, 3891 t_6axis_config.width_uv * 3892 t_6axis_config.height_uv * 3893 sizeof(*dvs_6axis_config->xcoords_uv), 3894 from_user)) 3895 goto error; 3896 if (copy_from_compatible(dvs_6axis_config->ycoords_uv, 3897 t_6axis_config.ycoords_uv, 3898 t_6axis_config.width_uv * 3899 t_6axis_config.height_uv * 3900 sizeof(*dvs_6axis_config->ycoords_uv), 3901 from_user)) 3902 goto error; 3903 } else { 3904 if (old_6axis_config && 3905 (old_6axis_config->width_y != source_6axis_config->width_y || 3906 old_6axis_config->height_y != source_6axis_config->height_y || 3907 old_6axis_config->width_uv != source_6axis_config->width_uv || 3908 old_6axis_config->height_uv != source_6axis_config->height_uv)) { 3909 ia_css_dvs2_6axis_config_free(css_param->dvs_6axis); 3910 css_param->dvs_6axis = NULL; 3911 3912 dvs_6axis_config = ia_css_dvs2_6axis_config_allocate(stream); 3913 if (!dvs_6axis_config) 3914 return -ENOMEM; 3915 } else if (!dvs_6axis_config) { 3916 dvs_6axis_config = ia_css_dvs2_6axis_config_allocate(stream); 3917 if (!dvs_6axis_config) 3918 return -ENOMEM; 3919 } 3920 3921 dvs_6axis_config->exp_id = source_6axis_config->exp_id; 3922 3923 if (copy_from_compatible(dvs_6axis_config->xcoords_y, 3924 source_6axis_config->xcoords_y, 3925 source_6axis_config->width_y * 3926 source_6axis_config->height_y * 3927 sizeof(*source_6axis_config->xcoords_y), 3928 from_user)) 3929 goto error; 3930 if (copy_from_compatible(dvs_6axis_config->ycoords_y, 3931 source_6axis_config->ycoords_y, 3932 source_6axis_config->width_y * 3933 source_6axis_config->height_y * 3934 sizeof(*source_6axis_config->ycoords_y), 3935 from_user)) 3936 goto error; 3937 if (copy_from_compatible(dvs_6axis_config->xcoords_uv, 3938 source_6axis_config->xcoords_uv, 3939 source_6axis_config->width_uv * 3940 source_6axis_config->height_uv * 3941 sizeof(*source_6axis_config->xcoords_uv), 3942 from_user)) 3943 goto error; 3944 if (copy_from_compatible(dvs_6axis_config->ycoords_uv, 3945 source_6axis_config->ycoords_uv, 3946 source_6axis_config->width_uv * 3947 source_6axis_config->height_uv * 3948 sizeof(*source_6axis_config->ycoords_uv), 3949 from_user)) 3950 goto error; 3951 } 3952 css_param->dvs_6axis = dvs_6axis_config; 3953 css_param->update_flag.dvs_6axis_config = 3954 (struct atomisp_dvs_6axis_config *)dvs_6axis_config; 3955 return 0; 3956 3957 error: 3958 if (dvs_6axis_config) 3959 ia_css_dvs2_6axis_config_free(dvs_6axis_config); 3960 return ret; 3961 } 3962 3963 int atomisp_cp_morph_table(struct atomisp_sub_device *asd, 3964 struct atomisp_morph_table *source_morph_table, 3965 struct atomisp_css_params *css_param, 3966 bool from_user) 3967 { 3968 int ret = -EFAULT; 3969 unsigned int i; 3970 struct ia_css_morph_table *morph_table; 3971 struct ia_css_morph_table *old_morph_table; 3972 3973 if (!source_morph_table) 3974 return 0; 3975 3976 if (!from_user && css_param->update_flag.morph_table) 3977 return 0; 3978 3979 old_morph_table = css_param->morph_table; 3980 3981 if (atomisp_hw_is_isp2401) { 3982 struct ia_css_morph_table mtbl; 3983 3984 if (copy_from_compatible(&mtbl, source_morph_table, 3985 sizeof(struct atomisp_morph_table), 3986 from_user)) { 3987 dev_err(asd->isp->dev, "copy morph table failed!"); 3988 return -EFAULT; 3989 } 3990 3991 morph_table = atomisp_css_morph_table_allocate( 3992 mtbl.width, 3993 mtbl.height); 3994 if (!morph_table) 3995 return -ENOMEM; 3996 3997 for (i = 0; i < IA_CSS_MORPH_TABLE_NUM_PLANES; i++) { 3998 if (copy_from_compatible(morph_table->coordinates_x[i], 3999 (__force void *)source_morph_table->coordinates_x[i], 4000 mtbl.height * mtbl.width * 4001 sizeof(*morph_table->coordinates_x[i]), 4002 from_user)) 4003 goto error; 4004 4005 if (copy_from_compatible(morph_table->coordinates_y[i], 4006 (__force void *)source_morph_table->coordinates_y[i], 4007 mtbl.height * mtbl.width * 4008 sizeof(*morph_table->coordinates_y[i]), 4009 from_user)) 4010 goto error; 4011 } 4012 } else { 4013 morph_table = atomisp_css_morph_table_allocate( 4014 source_morph_table->width, 4015 source_morph_table->height); 4016 if (!morph_table) 4017 return -ENOMEM; 4018 4019 for (i = 0; i < IA_CSS_MORPH_TABLE_NUM_PLANES; i++) { 4020 if (copy_from_compatible(morph_table->coordinates_x[i], 4021 (__force void *)source_morph_table->coordinates_x[i], 4022 source_morph_table->height * source_morph_table->width * 4023 sizeof(*source_morph_table->coordinates_x[i]), 4024 from_user)) 4025 goto error; 4026 4027 if (copy_from_compatible(morph_table->coordinates_y[i], 4028 (__force void *)source_morph_table->coordinates_y[i], 4029 source_morph_table->height * source_morph_table->width * 4030 sizeof(*source_morph_table->coordinates_y[i]), 4031 from_user)) 4032 goto error; 4033 } 4034 } 4035 4036 css_param->morph_table = morph_table; 4037 if (old_morph_table) 4038 atomisp_css_morph_table_free(old_morph_table); 4039 css_param->update_flag.morph_table = 4040 (struct atomisp_morph_table *)morph_table; 4041 return 0; 4042 4043 error: 4044 if (morph_table) 4045 atomisp_css_morph_table_free(morph_table); 4046 return ret; 4047 } 4048 4049 int atomisp_makeup_css_parameters(struct atomisp_sub_device *asd, 4050 struct atomisp_parameters *arg, 4051 struct atomisp_css_params *css_param) 4052 { 4053 int ret; 4054 4055 ret = atomisp_cp_general_isp_parameters(asd, arg, css_param, false); 4056 if (ret) 4057 return ret; 4058 ret = atomisp_cp_lsc_table(asd, arg->shading_table, css_param, false); 4059 if (ret) 4060 return ret; 4061 ret = atomisp_cp_morph_table(asd, arg->morph_table, css_param, false); 4062 if (ret) 4063 return ret; 4064 ret = atomisp_css_cp_dvs2_coefs(asd, 4065 (struct ia_css_dvs2_coefficients *)arg->dvs2_coefs, 4066 css_param, false); 4067 if (ret) 4068 return ret; 4069 ret = atomisp_cp_dvs_6axis_config(asd, arg->dvs_6axis_config, 4070 css_param, false); 4071 return ret; 4072 } 4073 4074 void atomisp_free_css_parameters(struct atomisp_css_params *css_param) 4075 { 4076 if (css_param->dvs_6axis) { 4077 ia_css_dvs2_6axis_config_free(css_param->dvs_6axis); 4078 css_param->dvs_6axis = NULL; 4079 } 4080 if (css_param->dvs2_coeff) { 4081 ia_css_dvs2_coefficients_free(css_param->dvs2_coeff); 4082 css_param->dvs2_coeff = NULL; 4083 } 4084 if (css_param->shading_table) { 4085 ia_css_shading_table_free(css_param->shading_table); 4086 css_param->shading_table = NULL; 4087 } 4088 if (css_param->morph_table) { 4089 ia_css_morph_table_free(css_param->morph_table); 4090 css_param->morph_table = NULL; 4091 } 4092 } 4093 4094 /* 4095 * Check parameter queue list and buffer queue list to find out if matched items 4096 * and then set parameter to CSS and enqueue buffer to CSS. 4097 * Of course, if the buffer in buffer waiting list is not bound to a per-frame 4098 * parameter, it will be enqueued into CSS as long as the per-frame setting 4099 * buffers before it get enqueued. 4100 */ 4101 void atomisp_handle_parameter_and_buffer(struct atomisp_video_pipe *pipe) 4102 { 4103 struct atomisp_sub_device *asd = pipe->asd; 4104 struct videobuf_buffer *vb = NULL, *vb_tmp; 4105 struct atomisp_css_params_with_list *param = NULL, *param_tmp; 4106 struct videobuf_vmalloc_memory *vm_mem = NULL; 4107 unsigned long irqflags; 4108 bool need_to_enqueue_buffer = false; 4109 4110 if (atomisp_is_vf_pipe(pipe)) 4111 return; 4112 4113 /* 4114 * CSS/FW requires set parameter and enqueue buffer happen after ISP 4115 * is streamon. 4116 */ 4117 if (asd->streaming != ATOMISP_DEVICE_STREAMING_ENABLED) 4118 return; 4119 4120 if (list_empty(&pipe->per_frame_params) || 4121 list_empty(&pipe->buffers_waiting_for_param)) 4122 return; 4123 4124 list_for_each_entry_safe(vb, vb_tmp, 4125 &pipe->buffers_waiting_for_param, queue) { 4126 if (pipe->frame_request_config_id[vb->i]) { 4127 list_for_each_entry_safe(param, param_tmp, 4128 &pipe->per_frame_params, list) { 4129 if (pipe->frame_request_config_id[vb->i] != 4130 param->params.isp_config_id) 4131 continue; 4132 4133 list_del(¶m->list); 4134 list_del(&vb->queue); 4135 /* 4136 * clear the request config id as the buffer 4137 * will be handled and enqueued into CSS soon 4138 */ 4139 pipe->frame_request_config_id[vb->i] = 0; 4140 pipe->frame_params[vb->i] = param; 4141 vm_mem = vb->priv; 4142 BUG_ON(!vm_mem); 4143 break; 4144 } 4145 4146 if (vm_mem) { 4147 spin_lock_irqsave(&pipe->irq_lock, irqflags); 4148 list_add_tail(&vb->queue, &pipe->activeq); 4149 spin_unlock_irqrestore(&pipe->irq_lock, irqflags); 4150 vm_mem = NULL; 4151 need_to_enqueue_buffer = true; 4152 } else { 4153 /* The is the end, stop further loop */ 4154 break; 4155 } 4156 } else { 4157 list_del(&vb->queue); 4158 pipe->frame_params[vb->i] = NULL; 4159 spin_lock_irqsave(&pipe->irq_lock, irqflags); 4160 list_add_tail(&vb->queue, &pipe->activeq); 4161 spin_unlock_irqrestore(&pipe->irq_lock, irqflags); 4162 need_to_enqueue_buffer = true; 4163 } 4164 } 4165 4166 if (!need_to_enqueue_buffer) 4167 return; 4168 4169 atomisp_qbuffers_to_css(asd); 4170 4171 if (!atomisp_hw_is_isp2401) { 4172 if (!atomisp_is_wdt_running(asd) && atomisp_buffers_queued(asd)) 4173 atomisp_wdt_start(asd); 4174 } else { 4175 if (atomisp_buffers_queued_pipe(pipe)) { 4176 if (!atomisp_is_wdt_running(pipe)) 4177 atomisp_wdt_start_pipe(pipe); 4178 else 4179 atomisp_wdt_refresh_pipe(pipe, 4180 ATOMISP_WDT_KEEP_CURRENT_DELAY); 4181 } 4182 } 4183 } 4184 4185 /* 4186 * Function to configure ISP parameters 4187 */ 4188 int atomisp_set_parameters(struct video_device *vdev, 4189 struct atomisp_parameters *arg) 4190 { 4191 struct atomisp_video_pipe *pipe = atomisp_to_video_pipe(vdev); 4192 struct atomisp_sub_device *asd = pipe->asd; 4193 struct atomisp_css_params_with_list *param = NULL; 4194 struct atomisp_css_params *css_param = &asd->params.css_param; 4195 int ret; 4196 4197 if (!asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream) { 4198 dev_err(asd->isp->dev, "%s: internal error!\n", __func__); 4199 return -EINVAL; 4200 } 4201 4202 dev_dbg(asd->isp->dev, 4203 "%s: set parameter(per_frame_setting %d) for asd%d with isp_config_id %d of %s\n", 4204 __func__, arg->per_frame_setting, asd->index, 4205 arg->isp_config_id, vdev->name); 4206 4207 if (atomisp_hw_is_isp2401) { 4208 if (atomisp_is_vf_pipe(pipe) && arg->per_frame_setting) { 4209 dev_err(asd->isp->dev, "%s: vf pipe not support per_frame_setting", 4210 __func__); 4211 return -EINVAL; 4212 } 4213 } 4214 4215 if (arg->per_frame_setting && !atomisp_is_vf_pipe(pipe)) { 4216 /* 4217 * Per-frame setting enabled, we allocate a new parameter 4218 * buffer to cache the parameters and only when frame buffers 4219 * are ready, the parameters will be set to CSS. 4220 * per-frame setting only works for the main output frame. 4221 */ 4222 param = kvzalloc(sizeof(*param), GFP_KERNEL); 4223 if (!param) { 4224 dev_err(asd->isp->dev, "%s: failed to alloc params buffer\n", 4225 __func__); 4226 return -ENOMEM; 4227 } 4228 css_param = ¶m->params; 4229 } 4230 4231 ret = atomisp_cp_general_isp_parameters(asd, arg, css_param, true); 4232 if (ret) 4233 goto apply_parameter_failed; 4234 4235 ret = atomisp_cp_lsc_table(asd, arg->shading_table, css_param, true); 4236 if (ret) 4237 goto apply_parameter_failed; 4238 4239 ret = atomisp_cp_morph_table(asd, arg->morph_table, css_param, true); 4240 if (ret) 4241 goto apply_parameter_failed; 4242 4243 ret = atomisp_css_cp_dvs2_coefs(asd, 4244 (struct ia_css_dvs2_coefficients *)arg->dvs2_coefs, 4245 css_param, true); 4246 if (ret) 4247 goto apply_parameter_failed; 4248 4249 ret = atomisp_cp_dvs_6axis_config(asd, arg->dvs_6axis_config, 4250 css_param, true); 4251 if (ret) 4252 goto apply_parameter_failed; 4253 4254 if (!(arg->per_frame_setting && !atomisp_is_vf_pipe(pipe))) { 4255 /* indicate to CSS that we have parameters to be updated */ 4256 asd->params.css_update_params_needed = true; 4257 } else { 4258 list_add_tail(¶m->list, &pipe->per_frame_params); 4259 atomisp_handle_parameter_and_buffer(pipe); 4260 } 4261 4262 return 0; 4263 4264 apply_parameter_failed: 4265 if (css_param) 4266 atomisp_free_css_parameters(css_param); 4267 if (param) 4268 kvfree(param); 4269 4270 return ret; 4271 } 4272 4273 /* 4274 * Function to set/get isp parameters to isp 4275 */ 4276 int atomisp_param(struct atomisp_sub_device *asd, int flag, 4277 struct atomisp_parm *config) 4278 { 4279 struct ia_css_pipe_config *vp_cfg = 4280 &asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]. 4281 pipe_configs[IA_CSS_PIPE_ID_VIDEO]; 4282 4283 /* Read parameter for 3A binary info */ 4284 if (flag == 0) { 4285 struct ia_css_dvs_grid_info *dvs_grid_info = 4286 atomisp_css_get_dvs_grid_info( 4287 &asd->params.curr_grid_info); 4288 4289 atomisp_curr_user_grid_info(asd, &config->info); 4290 4291 /* We always return the resolution and stride even if there is 4292 * no valid metadata. This allows the caller to get the 4293 * information needed to allocate user-space buffers. */ 4294 config->metadata_config.metadata_height = asd-> 4295 stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream_info. 4296 metadata_info.resolution.height; 4297 config->metadata_config.metadata_stride = asd-> 4298 stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream_info. 4299 metadata_info.stride; 4300 4301 /* update dvs grid info */ 4302 if (dvs_grid_info) 4303 memcpy(&config->dvs_grid, 4304 dvs_grid_info, 4305 sizeof(struct ia_css_dvs_grid_info)); 4306 4307 if (asd->run_mode->val != ATOMISP_RUN_MODE_VIDEO) { 4308 config->dvs_envelop.width = 0; 4309 config->dvs_envelop.height = 0; 4310 return 0; 4311 } 4312 4313 /* update dvs envelop info */ 4314 if (!asd->continuous_mode->val) { 4315 config->dvs_envelop.width = vp_cfg->dvs_envelope.width; 4316 config->dvs_envelop.height = 4317 vp_cfg->dvs_envelope.height; 4318 } else { 4319 unsigned int dvs_w, dvs_h, dvs_w_max, dvs_h_max; 4320 4321 dvs_w = vp_cfg->bayer_ds_out_res.width - 4322 vp_cfg->output_info[0].res.width; 4323 dvs_h = vp_cfg->bayer_ds_out_res.height - 4324 vp_cfg->output_info[0].res.height; 4325 dvs_w_max = rounddown( 4326 vp_cfg->output_info[0].res.width / 5, 4327 ATOM_ISP_STEP_WIDTH); 4328 dvs_h_max = rounddown( 4329 vp_cfg->output_info[0].res.height / 5, 4330 ATOM_ISP_STEP_HEIGHT); 4331 4332 config->dvs_envelop.width = min(dvs_w, dvs_w_max); 4333 config->dvs_envelop.height = min(dvs_h, dvs_h_max); 4334 } 4335 4336 return 0; 4337 } 4338 4339 memcpy(&asd->params.css_param.wb_config, &config->wb_config, 4340 sizeof(struct ia_css_wb_config)); 4341 memcpy(&asd->params.css_param.ob_config, &config->ob_config, 4342 sizeof(struct ia_css_ob_config)); 4343 memcpy(&asd->params.css_param.dp_config, &config->dp_config, 4344 sizeof(struct ia_css_dp_config)); 4345 memcpy(&asd->params.css_param.de_config, &config->de_config, 4346 sizeof(struct ia_css_de_config)); 4347 memcpy(&asd->params.css_param.dz_config, &config->dz_config, 4348 sizeof(struct ia_css_dz_config)); 4349 memcpy(&asd->params.css_param.ce_config, &config->ce_config, 4350 sizeof(struct ia_css_ce_config)); 4351 memcpy(&asd->params.css_param.nr_config, &config->nr_config, 4352 sizeof(struct ia_css_nr_config)); 4353 memcpy(&asd->params.css_param.ee_config, &config->ee_config, 4354 sizeof(struct ia_css_ee_config)); 4355 memcpy(&asd->params.css_param.tnr_config, &config->tnr_config, 4356 sizeof(struct ia_css_tnr_config)); 4357 4358 if (asd->params.color_effect == V4L2_COLORFX_NEGATIVE) { 4359 asd->params.css_param.cc_config.matrix[3] = -config->cc_config.matrix[3]; 4360 asd->params.css_param.cc_config.matrix[4] = -config->cc_config.matrix[4]; 4361 asd->params.css_param.cc_config.matrix[5] = -config->cc_config.matrix[5]; 4362 asd->params.css_param.cc_config.matrix[6] = -config->cc_config.matrix[6]; 4363 asd->params.css_param.cc_config.matrix[7] = -config->cc_config.matrix[7]; 4364 asd->params.css_param.cc_config.matrix[8] = -config->cc_config.matrix[8]; 4365 } 4366 4367 if (asd->params.color_effect != V4L2_COLORFX_SEPIA && 4368 asd->params.color_effect != V4L2_COLORFX_BW) { 4369 memcpy(&asd->params.css_param.cc_config, &config->cc_config, 4370 sizeof(struct ia_css_cc_config)); 4371 asd->params.config.cc_config = &asd->params.css_param.cc_config; 4372 } 4373 4374 asd->params.config.wb_config = &asd->params.css_param.wb_config; 4375 asd->params.config.ob_config = &asd->params.css_param.ob_config; 4376 asd->params.config.de_config = &asd->params.css_param.de_config; 4377 asd->params.config.dz_config = &asd->params.css_param.dz_config; 4378 asd->params.config.ce_config = &asd->params.css_param.ce_config; 4379 asd->params.config.dp_config = &asd->params.css_param.dp_config; 4380 asd->params.config.nr_config = &asd->params.css_param.nr_config; 4381 asd->params.config.ee_config = &asd->params.css_param.ee_config; 4382 asd->params.config.tnr_config = &asd->params.css_param.tnr_config; 4383 asd->params.css_update_params_needed = true; 4384 4385 return 0; 4386 } 4387 4388 /* 4389 * Function to configure color effect of the image 4390 */ 4391 int atomisp_color_effect(struct atomisp_sub_device *asd, int flag, 4392 __s32 *effect) 4393 { 4394 struct ia_css_cc_config *cc_config = NULL; 4395 struct ia_css_macc_table *macc_table = NULL; 4396 struct ia_css_ctc_table *ctc_table = NULL; 4397 int ret = 0; 4398 struct v4l2_control control; 4399 struct atomisp_device *isp = asd->isp; 4400 4401 if (flag == 0) { 4402 *effect = asd->params.color_effect; 4403 return 0; 4404 } 4405 4406 control.id = V4L2_CID_COLORFX; 4407 control.value = *effect; 4408 ret = 4409 v4l2_s_ctrl(NULL, isp->inputs[asd->input_curr].camera->ctrl_handler, 4410 &control); 4411 /* 4412 * if set color effect to sensor successfully, return 4413 * 0 directly. 4414 */ 4415 if (!ret) { 4416 asd->params.color_effect = (u32)*effect; 4417 return 0; 4418 } 4419 4420 if (*effect == asd->params.color_effect) 4421 return 0; 4422 4423 /* 4424 * isp_subdev->params.macc_en should be set to false. 4425 */ 4426 asd->params.macc_en = false; 4427 4428 switch (*effect) { 4429 case V4L2_COLORFX_NONE: 4430 macc_table = &asd->params.css_param.macc_table; 4431 asd->params.macc_en = true; 4432 break; 4433 case V4L2_COLORFX_SEPIA: 4434 cc_config = &sepia_cc_config; 4435 break; 4436 case V4L2_COLORFX_NEGATIVE: 4437 cc_config = &nega_cc_config; 4438 break; 4439 case V4L2_COLORFX_BW: 4440 cc_config = &mono_cc_config; 4441 break; 4442 case V4L2_COLORFX_SKY_BLUE: 4443 macc_table = &blue_macc_table; 4444 asd->params.macc_en = true; 4445 break; 4446 case V4L2_COLORFX_GRASS_GREEN: 4447 macc_table = &green_macc_table; 4448 asd->params.macc_en = true; 4449 break; 4450 case V4L2_COLORFX_SKIN_WHITEN_LOW: 4451 macc_table = &skin_low_macc_table; 4452 asd->params.macc_en = true; 4453 break; 4454 case V4L2_COLORFX_SKIN_WHITEN: 4455 macc_table = &skin_medium_macc_table; 4456 asd->params.macc_en = true; 4457 break; 4458 case V4L2_COLORFX_SKIN_WHITEN_HIGH: 4459 macc_table = &skin_high_macc_table; 4460 asd->params.macc_en = true; 4461 break; 4462 case V4L2_COLORFX_VIVID: 4463 ctc_table = &vivid_ctc_table; 4464 break; 4465 default: 4466 return -EINVAL; 4467 } 4468 atomisp_update_capture_mode(asd); 4469 4470 if (cc_config) 4471 asd->params.config.cc_config = cc_config; 4472 if (macc_table) 4473 asd->params.config.macc_table = macc_table; 4474 if (ctc_table) 4475 atomisp_css_set_ctc_table(asd, ctc_table); 4476 asd->params.color_effect = (u32)*effect; 4477 asd->params.css_update_params_needed = true; 4478 return 0; 4479 } 4480 4481 /* 4482 * Function to configure bad pixel correction 4483 */ 4484 int atomisp_bad_pixel(struct atomisp_sub_device *asd, int flag, 4485 __s32 *value) 4486 { 4487 if (flag == 0) { 4488 *value = asd->params.bad_pixel_en; 4489 return 0; 4490 } 4491 asd->params.bad_pixel_en = !!*value; 4492 4493 return 0; 4494 } 4495 4496 /* 4497 * Function to configure bad pixel correction params 4498 */ 4499 int atomisp_bad_pixel_param(struct atomisp_sub_device *asd, int flag, 4500 struct atomisp_dp_config *config) 4501 { 4502 if (flag == 0) { 4503 /* Get bad pixel from current setup */ 4504 if (atomisp_css_get_dp_config(asd, config)) 4505 return -EINVAL; 4506 } else { 4507 /* Set bad pixel to isp parameters */ 4508 memcpy(&asd->params.css_param.dp_config, config, 4509 sizeof(asd->params.css_param.dp_config)); 4510 asd->params.config.dp_config = &asd->params.css_param.dp_config; 4511 asd->params.css_update_params_needed = true; 4512 } 4513 4514 return 0; 4515 } 4516 4517 /* 4518 * Function to enable/disable video image stablization 4519 */ 4520 int atomisp_video_stable(struct atomisp_sub_device *asd, int flag, 4521 __s32 *value) 4522 { 4523 if (flag == 0) 4524 *value = asd->params.video_dis_en; 4525 else 4526 asd->params.video_dis_en = !!*value; 4527 4528 return 0; 4529 } 4530 4531 /* 4532 * Function to configure fixed pattern noise 4533 */ 4534 int atomisp_fixed_pattern(struct atomisp_sub_device *asd, int flag, 4535 __s32 *value) 4536 { 4537 if (flag == 0) { 4538 *value = asd->params.fpn_en; 4539 return 0; 4540 } 4541 4542 if (*value == 0) { 4543 asd->params.fpn_en = false; 4544 return 0; 4545 } 4546 4547 /* Add function to get black from from sensor with shutter off */ 4548 return 0; 4549 } 4550 4551 static unsigned int 4552 atomisp_bytesperline_to_padded_width(unsigned int bytesperline, 4553 enum ia_css_frame_format format) 4554 { 4555 switch (format) { 4556 case IA_CSS_FRAME_FORMAT_UYVY: 4557 case IA_CSS_FRAME_FORMAT_YUYV: 4558 case IA_CSS_FRAME_FORMAT_RAW: 4559 case IA_CSS_FRAME_FORMAT_RGB565: 4560 return bytesperline / 2; 4561 case IA_CSS_FRAME_FORMAT_RGBA888: 4562 return bytesperline / 4; 4563 /* The following cases could be removed, but we leave them 4564 in to document the formats that are included. */ 4565 case IA_CSS_FRAME_FORMAT_NV11: 4566 case IA_CSS_FRAME_FORMAT_NV12: 4567 case IA_CSS_FRAME_FORMAT_NV16: 4568 case IA_CSS_FRAME_FORMAT_NV21: 4569 case IA_CSS_FRAME_FORMAT_NV61: 4570 case IA_CSS_FRAME_FORMAT_YV12: 4571 case IA_CSS_FRAME_FORMAT_YV16: 4572 case IA_CSS_FRAME_FORMAT_YUV420: 4573 case IA_CSS_FRAME_FORMAT_YUV420_16: 4574 case IA_CSS_FRAME_FORMAT_YUV422: 4575 case IA_CSS_FRAME_FORMAT_YUV422_16: 4576 case IA_CSS_FRAME_FORMAT_YUV444: 4577 case IA_CSS_FRAME_FORMAT_YUV_LINE: 4578 case IA_CSS_FRAME_FORMAT_PLANAR_RGB888: 4579 case IA_CSS_FRAME_FORMAT_QPLANE6: 4580 case IA_CSS_FRAME_FORMAT_BINARY_8: 4581 default: 4582 return bytesperline; 4583 } 4584 } 4585 4586 static int 4587 atomisp_v4l2_framebuffer_to_css_frame(const struct v4l2_framebuffer *arg, 4588 struct ia_css_frame **result) 4589 { 4590 struct ia_css_frame *res = NULL; 4591 unsigned int padded_width; 4592 enum ia_css_frame_format sh_format; 4593 char *tmp_buf = NULL; 4594 int ret = 0; 4595 4596 sh_format = v4l2_fmt_to_sh_fmt(arg->fmt.pixelformat); 4597 padded_width = atomisp_bytesperline_to_padded_width( 4598 arg->fmt.bytesperline, sh_format); 4599 4600 /* Note: the padded width on an ia_css_frame is in elements, not in 4601 bytes. The RAW frame we use here should always be a 16bit RAW 4602 frame. This is why we bytesperline/2 is equal to the padded with */ 4603 if (ia_css_frame_allocate(&res, arg->fmt.width, arg->fmt.height, 4604 sh_format, padded_width, 0)) { 4605 ret = -ENOMEM; 4606 goto err; 4607 } 4608 4609 tmp_buf = vmalloc(arg->fmt.sizeimage); 4610 if (!tmp_buf) { 4611 ret = -ENOMEM; 4612 goto err; 4613 } 4614 if (copy_from_user(tmp_buf, (void __user __force *)arg->base, 4615 arg->fmt.sizeimage)) { 4616 ret = -EFAULT; 4617 goto err; 4618 } 4619 4620 if (hmm_store(res->data, tmp_buf, arg->fmt.sizeimage)) { 4621 ret = -EINVAL; 4622 goto err; 4623 } 4624 4625 err: 4626 if (ret && res) 4627 ia_css_frame_free(res); 4628 if (tmp_buf) 4629 vfree(tmp_buf); 4630 if (ret == 0) 4631 *result = res; 4632 return ret; 4633 } 4634 4635 /* 4636 * Function to configure fixed pattern noise table 4637 */ 4638 int atomisp_fixed_pattern_table(struct atomisp_sub_device *asd, 4639 struct v4l2_framebuffer *arg) 4640 { 4641 struct ia_css_frame *raw_black_frame = NULL; 4642 int ret; 4643 4644 if (!arg) 4645 return -EINVAL; 4646 4647 ret = atomisp_v4l2_framebuffer_to_css_frame(arg, &raw_black_frame); 4648 if (ret) 4649 return ret; 4650 4651 if (sh_css_set_black_frame(asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream, 4652 raw_black_frame) != 0) 4653 return -ENOMEM; 4654 4655 ia_css_frame_free(raw_black_frame); 4656 return ret; 4657 } 4658 4659 /* 4660 * Function to configure false color correction 4661 */ 4662 int atomisp_false_color(struct atomisp_sub_device *asd, int flag, 4663 __s32 *value) 4664 { 4665 /* Get nr config from current setup */ 4666 if (flag == 0) { 4667 *value = asd->params.false_color; 4668 return 0; 4669 } 4670 4671 /* Set nr config to isp parameters */ 4672 if (*value) { 4673 asd->params.config.de_config = NULL; 4674 } else { 4675 asd->params.css_param.de_config.pixelnoise = 0; 4676 asd->params.config.de_config = &asd->params.css_param.de_config; 4677 } 4678 asd->params.css_update_params_needed = true; 4679 asd->params.false_color = *value; 4680 return 0; 4681 } 4682 4683 /* 4684 * Function to configure bad pixel correction params 4685 */ 4686 int atomisp_false_color_param(struct atomisp_sub_device *asd, int flag, 4687 struct atomisp_de_config *config) 4688 { 4689 if (flag == 0) { 4690 /* Get false color from current setup */ 4691 if (atomisp_css_get_de_config(asd, config)) 4692 return -EINVAL; 4693 } else { 4694 /* Set false color to isp parameters */ 4695 memcpy(&asd->params.css_param.de_config, config, 4696 sizeof(asd->params.css_param.de_config)); 4697 asd->params.config.de_config = &asd->params.css_param.de_config; 4698 asd->params.css_update_params_needed = true; 4699 } 4700 4701 return 0; 4702 } 4703 4704 /* 4705 * Function to configure white balance params 4706 */ 4707 int atomisp_white_balance_param(struct atomisp_sub_device *asd, int flag, 4708 struct atomisp_wb_config *config) 4709 { 4710 if (flag == 0) { 4711 /* Get white balance from current setup */ 4712 if (atomisp_css_get_wb_config(asd, config)) 4713 return -EINVAL; 4714 } else { 4715 /* Set white balance to isp parameters */ 4716 memcpy(&asd->params.css_param.wb_config, config, 4717 sizeof(asd->params.css_param.wb_config)); 4718 asd->params.config.wb_config = &asd->params.css_param.wb_config; 4719 asd->params.css_update_params_needed = true; 4720 } 4721 4722 return 0; 4723 } 4724 4725 int atomisp_3a_config_param(struct atomisp_sub_device *asd, int flag, 4726 struct atomisp_3a_config *config) 4727 { 4728 struct atomisp_device *isp = asd->isp; 4729 4730 dev_dbg(isp->dev, ">%s %d\n", __func__, flag); 4731 4732 if (flag == 0) { 4733 /* Get white balance from current setup */ 4734 if (atomisp_css_get_3a_config(asd, config)) 4735 return -EINVAL; 4736 } else { 4737 /* Set white balance to isp parameters */ 4738 memcpy(&asd->params.css_param.s3a_config, config, 4739 sizeof(asd->params.css_param.s3a_config)); 4740 asd->params.config.s3a_config = &asd->params.css_param.s3a_config; 4741 asd->params.css_update_params_needed = true; 4742 } 4743 4744 dev_dbg(isp->dev, "<%s %d\n", __func__, flag); 4745 return 0; 4746 } 4747 4748 /* 4749 * Function to setup digital zoom 4750 */ 4751 int atomisp_digital_zoom(struct atomisp_sub_device *asd, int flag, 4752 __s32 *value) 4753 { 4754 u32 zoom; 4755 struct atomisp_device *isp = asd->isp; 4756 4757 unsigned int max_zoom = MRFLD_MAX_ZOOM_FACTOR; 4758 4759 if (flag == 0) { 4760 atomisp_css_get_zoom_factor(asd, &zoom); 4761 *value = max_zoom - zoom; 4762 } else { 4763 if (*value < 0) 4764 return -EINVAL; 4765 4766 zoom = max_zoom - min_t(u32, max_zoom - 1, *value); 4767 atomisp_css_set_zoom_factor(asd, zoom); 4768 4769 dev_dbg(isp->dev, "%s, zoom: %d\n", __func__, zoom); 4770 asd->params.css_update_params_needed = true; 4771 } 4772 4773 return 0; 4774 } 4775 4776 /* 4777 * Function to get sensor specific info for current resolution, 4778 * which will be used for auto exposure conversion. 4779 */ 4780 int atomisp_get_sensor_mode_data(struct atomisp_sub_device *asd, 4781 struct atomisp_sensor_mode_data *config) 4782 { 4783 struct camera_mipi_info *mipi_info; 4784 struct atomisp_device *isp = asd->isp; 4785 4786 mipi_info = atomisp_to_sensor_mipi_info( 4787 isp->inputs[asd->input_curr].camera); 4788 if (!mipi_info) 4789 return -EINVAL; 4790 4791 memcpy(config, &mipi_info->data, sizeof(*config)); 4792 return 0; 4793 } 4794 4795 int atomisp_get_fmt(struct video_device *vdev, struct v4l2_format *f) 4796 { 4797 struct atomisp_video_pipe *pipe = atomisp_to_video_pipe(vdev); 4798 4799 f->fmt.pix = pipe->pix; 4800 4801 return 0; 4802 } 4803 4804 static void __atomisp_update_stream_env(struct atomisp_sub_device *asd, 4805 u16 stream_index, struct atomisp_input_stream_info *stream_info) 4806 { 4807 int i; 4808 4809 /* assign virtual channel id return from sensor driver query */ 4810 asd->stream_env[stream_index].ch_id = stream_info->ch_id; 4811 asd->stream_env[stream_index].isys_configs = stream_info->isys_configs; 4812 for (i = 0; i < stream_info->isys_configs; i++) { 4813 asd->stream_env[stream_index].isys_info[i].input_format = 4814 stream_info->isys_info[i].input_format; 4815 asd->stream_env[stream_index].isys_info[i].width = 4816 stream_info->isys_info[i].width; 4817 asd->stream_env[stream_index].isys_info[i].height = 4818 stream_info->isys_info[i].height; 4819 } 4820 } 4821 4822 static void __atomisp_init_stream_info(u16 stream_index, 4823 struct atomisp_input_stream_info *stream_info) 4824 { 4825 int i; 4826 4827 stream_info->enable = 1; 4828 stream_info->stream = stream_index; 4829 stream_info->ch_id = 0; 4830 stream_info->isys_configs = 0; 4831 for (i = 0; i < MAX_STREAMS_PER_CHANNEL; i++) { 4832 stream_info->isys_info[i].input_format = 0; 4833 stream_info->isys_info[i].width = 0; 4834 stream_info->isys_info[i].height = 0; 4835 } 4836 } 4837 4838 /* This function looks up the closest available resolution. */ 4839 int atomisp_try_fmt(struct video_device *vdev, struct v4l2_format *f, 4840 bool *res_overflow) 4841 { 4842 struct atomisp_device *isp = video_get_drvdata(vdev); 4843 struct atomisp_sub_device *asd = atomisp_to_video_pipe(vdev)->asd; 4844 struct v4l2_subdev_pad_config pad_cfg; 4845 struct v4l2_subdev_format format = { 4846 .which = V4L2_SUBDEV_FORMAT_TRY, 4847 }; 4848 4849 struct v4l2_mbus_framefmt *snr_mbus_fmt = &format.format; 4850 const struct atomisp_format_bridge *fmt; 4851 struct atomisp_input_stream_info *stream_info = 4852 (struct atomisp_input_stream_info *)snr_mbus_fmt->reserved; 4853 u16 stream_index; 4854 int source_pad = atomisp_subdev_source_pad(vdev); 4855 int ret; 4856 4857 if (!isp->inputs[asd->input_curr].camera) 4858 return -EINVAL; 4859 4860 stream_index = atomisp_source_pad_to_stream_id(asd, source_pad); 4861 fmt = atomisp_get_format_bridge(f->fmt.pix.pixelformat); 4862 if (!fmt) { 4863 dev_err(isp->dev, "unsupported pixelformat!\n"); 4864 fmt = atomisp_output_fmts; 4865 } 4866 4867 if (f->fmt.pix.width <= 0 || f->fmt.pix.height <= 0) 4868 return -EINVAL; 4869 4870 snr_mbus_fmt->code = fmt->mbus_code; 4871 snr_mbus_fmt->width = f->fmt.pix.width; 4872 snr_mbus_fmt->height = f->fmt.pix.height; 4873 4874 __atomisp_init_stream_info(stream_index, stream_info); 4875 4876 dev_dbg(isp->dev, "try_mbus_fmt: asking for %ux%u\n", 4877 snr_mbus_fmt->width, snr_mbus_fmt->height); 4878 4879 ret = v4l2_subdev_call(isp->inputs[asd->input_curr].camera, 4880 pad, set_fmt, &pad_cfg, &format); 4881 if (ret) 4882 return ret; 4883 4884 dev_dbg(isp->dev, "try_mbus_fmt: got %ux%u\n", 4885 snr_mbus_fmt->width, snr_mbus_fmt->height); 4886 4887 fmt = atomisp_get_format_bridge_from_mbus(snr_mbus_fmt->code); 4888 if (!fmt) { 4889 dev_err(isp->dev, "unknown sensor format 0x%8.8x\n", 4890 snr_mbus_fmt->code); 4891 return -EINVAL; 4892 } 4893 4894 f->fmt.pix.pixelformat = fmt->pixelformat; 4895 4896 /* 4897 * If the format is jpeg or custom RAW, then the width and height will 4898 * not satisfy the normal atomisp requirements and no need to check 4899 * the below conditions. So just assign to what is being returned from 4900 * the sensor driver. 4901 */ 4902 if (f->fmt.pix.pixelformat == V4L2_PIX_FMT_JPEG || 4903 f->fmt.pix.pixelformat == V4L2_PIX_FMT_CUSTOM_M10MO_RAW) { 4904 f->fmt.pix.width = snr_mbus_fmt->width; 4905 f->fmt.pix.height = snr_mbus_fmt->height; 4906 return 0; 4907 } 4908 4909 if (snr_mbus_fmt->width < f->fmt.pix.width 4910 && snr_mbus_fmt->height < f->fmt.pix.height) { 4911 f->fmt.pix.width = snr_mbus_fmt->width; 4912 f->fmt.pix.height = snr_mbus_fmt->height; 4913 /* Set the flag when resolution requested is 4914 * beyond the max value supported by sensor 4915 */ 4916 if (res_overflow) 4917 *res_overflow = true; 4918 } 4919 4920 /* app vs isp */ 4921 f->fmt.pix.width = rounddown( 4922 clamp_t(u32, f->fmt.pix.width, ATOM_ISP_MIN_WIDTH, 4923 ATOM_ISP_MAX_WIDTH), ATOM_ISP_STEP_WIDTH); 4924 f->fmt.pix.height = rounddown( 4925 clamp_t(u32, f->fmt.pix.height, ATOM_ISP_MIN_HEIGHT, 4926 ATOM_ISP_MAX_HEIGHT), ATOM_ISP_STEP_HEIGHT); 4927 4928 return 0; 4929 } 4930 4931 static int 4932 atomisp_try_fmt_file(struct atomisp_device *isp, struct v4l2_format *f) 4933 { 4934 u32 width = f->fmt.pix.width; 4935 u32 height = f->fmt.pix.height; 4936 u32 pixelformat = f->fmt.pix.pixelformat; 4937 enum v4l2_field field = f->fmt.pix.field; 4938 u32 depth; 4939 4940 if (!atomisp_get_format_bridge(pixelformat)) { 4941 dev_err(isp->dev, "Wrong output pixelformat\n"); 4942 return -EINVAL; 4943 } 4944 4945 depth = get_pixel_depth(pixelformat); 4946 4947 if (field == V4L2_FIELD_ANY) 4948 field = V4L2_FIELD_NONE; 4949 else if (field != V4L2_FIELD_NONE) { 4950 dev_err(isp->dev, "Wrong output field\n"); 4951 return -EINVAL; 4952 } 4953 4954 f->fmt.pix.field = field; 4955 f->fmt.pix.width = clamp_t(u32, 4956 rounddown(width, (u32)ATOM_ISP_STEP_WIDTH), 4957 ATOM_ISP_MIN_WIDTH, ATOM_ISP_MAX_WIDTH); 4958 f->fmt.pix.height = clamp_t(u32, rounddown(height, 4959 (u32)ATOM_ISP_STEP_HEIGHT), 4960 ATOM_ISP_MIN_HEIGHT, ATOM_ISP_MAX_HEIGHT); 4961 f->fmt.pix.bytesperline = (width * depth) >> 3; 4962 4963 return 0; 4964 } 4965 4966 enum mipi_port_id __get_mipi_port(struct atomisp_device *isp, 4967 enum atomisp_camera_port port) 4968 { 4969 switch (port) { 4970 case ATOMISP_CAMERA_PORT_PRIMARY: 4971 return MIPI_PORT0_ID; 4972 case ATOMISP_CAMERA_PORT_SECONDARY: 4973 return MIPI_PORT1_ID; 4974 case ATOMISP_CAMERA_PORT_TERTIARY: 4975 if (MIPI_PORT1_ID + 1 != N_MIPI_PORT_ID) { 4976 return MIPI_PORT1_ID + 1; 4977 } 4978 /* fall through */ 4979 default: 4980 dev_err(isp->dev, "unsupported port: %d\n", port); 4981 return MIPI_PORT0_ID; 4982 } 4983 } 4984 4985 static inline int atomisp_set_sensor_mipi_to_isp( 4986 struct atomisp_sub_device *asd, 4987 enum atomisp_input_stream_id stream_id, 4988 struct camera_mipi_info *mipi_info) 4989 { 4990 struct v4l2_control ctrl; 4991 struct atomisp_device *isp = asd->isp; 4992 const struct atomisp_in_fmt_conv *fc; 4993 int mipi_freq = 0; 4994 unsigned int input_format, bayer_order; 4995 4996 ctrl.id = V4L2_CID_LINK_FREQ; 4997 if (v4l2_g_ctrl 4998 (isp->inputs[asd->input_curr].camera->ctrl_handler, &ctrl) == 0) 4999 mipi_freq = ctrl.value; 5000 5001 if (asd->stream_env[stream_id].isys_configs == 1) { 5002 input_format = 5003 asd->stream_env[stream_id].isys_info[0].input_format; 5004 atomisp_css_isys_set_format(asd, stream_id, 5005 input_format, IA_CSS_STREAM_DEFAULT_ISYS_STREAM_IDX); 5006 } else if (asd->stream_env[stream_id].isys_configs == 2) { 5007 atomisp_css_isys_two_stream_cfg_update_stream1( 5008 asd, stream_id, 5009 asd->stream_env[stream_id].isys_info[0].input_format, 5010 asd->stream_env[stream_id].isys_info[0].width, 5011 asd->stream_env[stream_id].isys_info[0].height); 5012 5013 atomisp_css_isys_two_stream_cfg_update_stream2( 5014 asd, stream_id, 5015 asd->stream_env[stream_id].isys_info[1].input_format, 5016 asd->stream_env[stream_id].isys_info[1].width, 5017 asd->stream_env[stream_id].isys_info[1].height); 5018 } 5019 5020 /* Compatibility for sensors which provide no media bus code 5021 * in s_mbus_framefmt() nor support pad formats. */ 5022 if (mipi_info->input_format != -1) { 5023 bayer_order = mipi_info->raw_bayer_order; 5024 5025 /* Input stream config is still needs configured */ 5026 /* TODO: Check if this is necessary */ 5027 fc = atomisp_find_in_fmt_conv_by_atomisp_in_fmt( 5028 mipi_info->input_format); 5029 if (!fc) 5030 return -EINVAL; 5031 input_format = fc->atomisp_in_fmt; 5032 } else { 5033 struct v4l2_mbus_framefmt *sink; 5034 5035 sink = atomisp_subdev_get_ffmt(&asd->subdev, NULL, 5036 V4L2_SUBDEV_FORMAT_ACTIVE, 5037 ATOMISP_SUBDEV_PAD_SINK); 5038 fc = atomisp_find_in_fmt_conv(sink->code); 5039 if (!fc) 5040 return -EINVAL; 5041 input_format = fc->atomisp_in_fmt; 5042 bayer_order = fc->bayer_order; 5043 } 5044 5045 atomisp_css_input_set_format(asd, stream_id, input_format); 5046 atomisp_css_input_set_bayer_order(asd, stream_id, bayer_order); 5047 5048 fc = atomisp_find_in_fmt_conv_by_atomisp_in_fmt( 5049 mipi_info->metadata_format); 5050 if (!fc) 5051 return -EINVAL; 5052 input_format = fc->atomisp_in_fmt; 5053 atomisp_css_input_configure_port(asd, 5054 __get_mipi_port(asd->isp, mipi_info->port), 5055 mipi_info->num_lanes, 5056 0xffff4, mipi_freq, 5057 input_format, 5058 mipi_info->metadata_width, 5059 mipi_info->metadata_height); 5060 return 0; 5061 } 5062 5063 static int __enable_continuous_mode(struct atomisp_sub_device *asd, 5064 bool enable) 5065 { 5066 struct atomisp_device *isp = asd->isp; 5067 5068 dev_dbg(isp->dev, 5069 "continuous mode %d, raw buffers %d, stop preview %d\n", 5070 enable, asd->continuous_raw_buffer_size->val, 5071 !asd->continuous_viewfinder->val); 5072 5073 if (!atomisp_hw_is_isp2401) 5074 atomisp_css_capture_set_mode(asd, IA_CSS_CAPTURE_MODE_PRIMARY); 5075 else 5076 atomisp_update_capture_mode(asd); 5077 5078 /* in case of ANR, force capture pipe to offline mode */ 5079 atomisp_css_capture_enable_online(asd, ATOMISP_INPUT_STREAM_GENERAL, 5080 asd->params.low_light ? false : !enable); 5081 atomisp_css_preview_enable_online(asd, ATOMISP_INPUT_STREAM_GENERAL, 5082 !enable); 5083 atomisp_css_enable_continuous(asd, enable); 5084 atomisp_css_enable_cvf(asd, asd->continuous_viewfinder->val); 5085 5086 if (atomisp_css_continuous_set_num_raw_frames(asd, 5087 asd->continuous_raw_buffer_size->val)) { 5088 dev_err(isp->dev, "css_continuous_set_num_raw_frames failed\n"); 5089 return -EINVAL; 5090 } 5091 5092 if (!enable) { 5093 atomisp_css_enable_raw_binning(asd, false); 5094 atomisp_css_input_set_two_pixels_per_clock(asd, false); 5095 } 5096 5097 if (isp->inputs[asd->input_curr].type != FILE_INPUT) 5098 atomisp_css_input_set_mode(asd, IA_CSS_INPUT_MODE_BUFFERED_SENSOR); 5099 5100 return atomisp_update_run_mode(asd); 5101 } 5102 5103 static int configure_pp_input_nop(struct atomisp_sub_device *asd, 5104 unsigned int width, unsigned int height) 5105 { 5106 return 0; 5107 } 5108 5109 static int configure_output_nop(struct atomisp_sub_device *asd, 5110 unsigned int width, unsigned int height, 5111 unsigned int min_width, 5112 enum ia_css_frame_format sh_fmt) 5113 { 5114 return 0; 5115 } 5116 5117 static int get_frame_info_nop(struct atomisp_sub_device *asd, 5118 struct ia_css_frame_info *finfo) 5119 { 5120 return 0; 5121 } 5122 5123 /* 5124 * Resets CSS parameters that depend on input resolution. 5125 * 5126 * Update params like CSS RAW binning, 2ppc mode and pp_input 5127 * which depend on input size, but are not automatically 5128 * handled in CSS when the input resolution is changed. 5129 */ 5130 static int css_input_resolution_changed(struct atomisp_sub_device *asd, 5131 struct v4l2_mbus_framefmt *ffmt) 5132 { 5133 struct atomisp_metadata_buf *md_buf = NULL, *_md_buf; 5134 unsigned int i; 5135 5136 dev_dbg(asd->isp->dev, "css_input_resolution_changed to %ux%u\n", 5137 ffmt->width, ffmt->height); 5138 5139 #if defined(ISP2401_NEW_INPUT_SYSTEM) 5140 atomisp_css_input_set_two_pixels_per_clock(asd, false); 5141 #else 5142 atomisp_css_input_set_two_pixels_per_clock(asd, true); 5143 #endif 5144 if (asd->continuous_mode->val) { 5145 /* Note for all checks: ffmt includes pad_w+pad_h */ 5146 if (asd->run_mode->val == ATOMISP_RUN_MODE_VIDEO || 5147 (ffmt->width >= 2048 || ffmt->height >= 1536)) { 5148 /* 5149 * For preview pipe, enable only if resolution 5150 * is >= 3M for ISP2400. 5151 */ 5152 atomisp_css_enable_raw_binning(asd, true); 5153 } 5154 } 5155 /* 5156 * If sensor input changed, which means metadata resolution changed 5157 * together. Release all metadata buffers here to let it re-allocated 5158 * next time in reqbufs. 5159 */ 5160 for (i = 0; i < ATOMISP_METADATA_TYPE_NUM; i++) { 5161 list_for_each_entry_safe(md_buf, _md_buf, &asd->metadata[i], 5162 list) { 5163 atomisp_css_free_metadata_buffer(md_buf); 5164 list_del(&md_buf->list); 5165 kfree(md_buf); 5166 } 5167 } 5168 return 0; 5169 5170 /* 5171 * TODO: atomisp_css_preview_configure_pp_input() not 5172 * reset due to CSS bug tracked as PSI BZ 115124 5173 */ 5174 } 5175 5176 static int atomisp_set_fmt_to_isp(struct video_device *vdev, 5177 struct ia_css_frame_info *output_info, 5178 struct ia_css_frame_info *raw_output_info, 5179 struct v4l2_pix_format *pix, 5180 unsigned int source_pad) 5181 { 5182 struct camera_mipi_info *mipi_info; 5183 struct atomisp_device *isp = video_get_drvdata(vdev); 5184 struct atomisp_sub_device *asd = atomisp_to_video_pipe(vdev)->asd; 5185 const struct atomisp_format_bridge *format; 5186 struct v4l2_rect *isp_sink_crop; 5187 enum ia_css_pipe_id pipe_id; 5188 struct v4l2_subdev_fh fh; 5189 int (*configure_output)(struct atomisp_sub_device *asd, 5190 unsigned int width, unsigned int height, 5191 unsigned int min_width, 5192 enum ia_css_frame_format sh_fmt) = 5193 configure_output_nop; 5194 int (*get_frame_info)(struct atomisp_sub_device *asd, 5195 struct ia_css_frame_info *finfo) = 5196 get_frame_info_nop; 5197 int (*configure_pp_input)(struct atomisp_sub_device *asd, 5198 unsigned int width, unsigned int height) = 5199 configure_pp_input_nop; 5200 u16 stream_index = atomisp_source_pad_to_stream_id(asd, source_pad); 5201 const struct atomisp_in_fmt_conv *fc; 5202 int ret, i; 5203 5204 v4l2_fh_init(&fh.vfh, vdev); 5205 5206 isp_sink_crop = atomisp_subdev_get_rect( 5207 &asd->subdev, NULL, V4L2_SUBDEV_FORMAT_ACTIVE, 5208 ATOMISP_SUBDEV_PAD_SINK, V4L2_SEL_TGT_CROP); 5209 5210 format = atomisp_get_format_bridge(pix->pixelformat); 5211 if (!format) 5212 return -EINVAL; 5213 5214 if (isp->inputs[asd->input_curr].type != TEST_PATTERN && 5215 isp->inputs[asd->input_curr].type != FILE_INPUT) { 5216 mipi_info = atomisp_to_sensor_mipi_info( 5217 isp->inputs[asd->input_curr].camera); 5218 if (!mipi_info) { 5219 dev_err(isp->dev, "mipi_info is NULL\n"); 5220 return -EINVAL; 5221 } 5222 if (atomisp_set_sensor_mipi_to_isp(asd, stream_index, 5223 mipi_info)) 5224 return -EINVAL; 5225 fc = atomisp_find_in_fmt_conv_by_atomisp_in_fmt( 5226 mipi_info->input_format); 5227 if (!fc) 5228 fc = atomisp_find_in_fmt_conv( 5229 atomisp_subdev_get_ffmt(&asd->subdev, 5230 NULL, V4L2_SUBDEV_FORMAT_ACTIVE, 5231 ATOMISP_SUBDEV_PAD_SINK)->code); 5232 if (!fc) 5233 return -EINVAL; 5234 if (format->sh_fmt == IA_CSS_FRAME_FORMAT_RAW && 5235 raw_output_format_match_input(fc->atomisp_in_fmt, 5236 pix->pixelformat)) 5237 return -EINVAL; 5238 } 5239 5240 /* 5241 * Configure viewfinder also when vfpp is disabled: the 5242 * CSS still requires viewfinder configuration. 5243 */ 5244 if (asd->fmt_auto->val || 5245 asd->vfpp->val != ATOMISP_VFPP_ENABLE) { 5246 struct v4l2_rect vf_size = {0}; 5247 struct v4l2_mbus_framefmt vf_ffmt = {0}; 5248 5249 if (pix->width < 640 || pix->height < 480) { 5250 vf_size.width = pix->width; 5251 vf_size.height = pix->height; 5252 } else { 5253 vf_size.width = 640; 5254 vf_size.height = 480; 5255 } 5256 5257 /* FIXME: proper format name for this one. See 5258 atomisp_output_fmts[] in atomisp_v4l2.c */ 5259 vf_ffmt.code = V4L2_MBUS_FMT_CUSTOM_YUV420; 5260 5261 atomisp_subdev_set_selection(&asd->subdev, fh.pad, 5262 V4L2_SUBDEV_FORMAT_ACTIVE, 5263 ATOMISP_SUBDEV_PAD_SOURCE_VF, 5264 V4L2_SEL_TGT_COMPOSE, 0, &vf_size); 5265 atomisp_subdev_set_ffmt(&asd->subdev, fh.pad, 5266 V4L2_SUBDEV_FORMAT_ACTIVE, 5267 ATOMISP_SUBDEV_PAD_SOURCE_VF, &vf_ffmt); 5268 asd->video_out_vf.sh_fmt = IA_CSS_FRAME_FORMAT_NV12; 5269 5270 if (asd->vfpp->val == ATOMISP_VFPP_DISABLE_SCALER) { 5271 atomisp_css_video_configure_viewfinder(asd, 5272 vf_size.width, vf_size.height, 0, 5273 asd->video_out_vf.sh_fmt); 5274 } else if (asd->run_mode->val == ATOMISP_RUN_MODE_VIDEO) { 5275 if (source_pad == ATOMISP_SUBDEV_PAD_SOURCE_PREVIEW || 5276 source_pad == ATOMISP_SUBDEV_PAD_SOURCE_VIDEO) 5277 atomisp_css_video_configure_viewfinder(asd, 5278 vf_size.width, vf_size.height, 0, 5279 asd->video_out_vf.sh_fmt); 5280 else 5281 atomisp_css_capture_configure_viewfinder(asd, 5282 vf_size.width, vf_size.height, 0, 5283 asd->video_out_vf.sh_fmt); 5284 } else if (source_pad != ATOMISP_SUBDEV_PAD_SOURCE_PREVIEW || 5285 asd->vfpp->val == ATOMISP_VFPP_DISABLE_LOWLAT) { 5286 atomisp_css_capture_configure_viewfinder(asd, 5287 vf_size.width, vf_size.height, 0, 5288 asd->video_out_vf.sh_fmt); 5289 } 5290 } 5291 5292 if (asd->continuous_mode->val) { 5293 ret = __enable_continuous_mode(asd, true); 5294 if (ret) 5295 return -EINVAL; 5296 } 5297 5298 atomisp_css_input_set_mode(asd, IA_CSS_INPUT_MODE_BUFFERED_SENSOR); 5299 5300 for (i = 0; i < IA_CSS_PIPE_ID_NUM; i++) 5301 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].pipe_extra_configs[i].disable_vf_pp = asd->vfpp->val != ATOMISP_VFPP_ENABLE; 5302 5303 /* ISP2401 new input system need to use copy pipe */ 5304 if (asd->copy_mode) { 5305 pipe_id = IA_CSS_PIPE_ID_COPY; 5306 atomisp_css_capture_enable_online(asd, stream_index, false); 5307 } else if (asd->vfpp->val == ATOMISP_VFPP_DISABLE_SCALER) { 5308 /* video same in continuouscapture and online modes */ 5309 configure_output = atomisp_css_video_configure_output; 5310 get_frame_info = atomisp_css_video_get_output_frame_info; 5311 pipe_id = IA_CSS_PIPE_ID_VIDEO; 5312 } else if (asd->run_mode->val == ATOMISP_RUN_MODE_VIDEO) { 5313 if (!asd->continuous_mode->val) { 5314 configure_output = atomisp_css_video_configure_output; 5315 get_frame_info = 5316 atomisp_css_video_get_output_frame_info; 5317 pipe_id = IA_CSS_PIPE_ID_VIDEO; 5318 } else { 5319 if (source_pad == ATOMISP_SUBDEV_PAD_SOURCE_PREVIEW || 5320 source_pad == ATOMISP_SUBDEV_PAD_SOURCE_VIDEO) { 5321 configure_output = 5322 atomisp_css_video_configure_output; 5323 get_frame_info = 5324 atomisp_css_video_get_output_frame_info; 5325 configure_pp_input = 5326 atomisp_css_video_configure_pp_input; 5327 pipe_id = IA_CSS_PIPE_ID_VIDEO; 5328 } else { 5329 configure_output = 5330 atomisp_css_capture_configure_output; 5331 get_frame_info = 5332 atomisp_css_capture_get_output_frame_info; 5333 configure_pp_input = 5334 atomisp_css_capture_configure_pp_input; 5335 pipe_id = IA_CSS_PIPE_ID_CAPTURE; 5336 5337 atomisp_update_capture_mode(asd); 5338 atomisp_css_capture_enable_online(asd, stream_index, false); 5339 } 5340 } 5341 } else if (source_pad == ATOMISP_SUBDEV_PAD_SOURCE_PREVIEW) { 5342 configure_output = atomisp_css_preview_configure_output; 5343 get_frame_info = atomisp_css_preview_get_output_frame_info; 5344 configure_pp_input = atomisp_css_preview_configure_pp_input; 5345 pipe_id = IA_CSS_PIPE_ID_PREVIEW; 5346 } else { 5347 /* CSS doesn't support low light mode on SOC cameras, so disable 5348 * it. FIXME: if this is done elsewhere, it gives corrupted 5349 * colors into thumbnail image. 5350 */ 5351 if (isp->inputs[asd->input_curr].type == SOC_CAMERA) 5352 asd->params.low_light = false; 5353 5354 if (format->sh_fmt == IA_CSS_FRAME_FORMAT_RAW) { 5355 atomisp_css_capture_set_mode(asd, IA_CSS_CAPTURE_MODE_RAW); 5356 atomisp_css_enable_dz(asd, false); 5357 } else { 5358 atomisp_update_capture_mode(asd); 5359 } 5360 5361 if (!asd->continuous_mode->val) 5362 /* in case of ANR, force capture pipe to offline mode */ 5363 atomisp_css_capture_enable_online(asd, stream_index, 5364 asd->params.low_light ? 5365 false : asd->params.online_process); 5366 5367 configure_output = atomisp_css_capture_configure_output; 5368 get_frame_info = atomisp_css_capture_get_output_frame_info; 5369 configure_pp_input = atomisp_css_capture_configure_pp_input; 5370 pipe_id = IA_CSS_PIPE_ID_CAPTURE; 5371 5372 if (!asd->params.online_process && 5373 !asd->continuous_mode->val) { 5374 ret = atomisp_css_capture_get_output_raw_frame_info(asd, 5375 raw_output_info); 5376 if (ret) 5377 return ret; 5378 } 5379 if (!asd->continuous_mode->val && asd->run_mode->val 5380 != ATOMISP_RUN_MODE_STILL_CAPTURE) { 5381 dev_err(isp->dev, 5382 "Need to set the running mode first\n"); 5383 asd->run_mode->val = ATOMISP_RUN_MODE_STILL_CAPTURE; 5384 } 5385 } 5386 5387 /* 5388 * to SOC camera, use yuvpp pipe. 5389 */ 5390 if (ATOMISP_USE_YUVPP(asd)) 5391 pipe_id = IA_CSS_PIPE_ID_YUVPP; 5392 5393 if (asd->copy_mode) 5394 ret = atomisp_css_copy_configure_output(asd, stream_index, 5395 pix->width, pix->height, 5396 format->planar ? pix->bytesperline : 5397 pix->bytesperline * 8 / format->depth, 5398 format->sh_fmt); 5399 else 5400 ret = configure_output(asd, pix->width, pix->height, 5401 format->planar ? pix->bytesperline : 5402 pix->bytesperline * 8 / format->depth, 5403 format->sh_fmt); 5404 if (ret) { 5405 dev_err(isp->dev, "configure_output %ux%u, format %8.8x\n", 5406 pix->width, pix->height, format->sh_fmt); 5407 return -EINVAL; 5408 } 5409 5410 if (asd->continuous_mode->val && 5411 (configure_pp_input == atomisp_css_preview_configure_pp_input || 5412 configure_pp_input == atomisp_css_video_configure_pp_input)) { 5413 /* for isp 2.2, configure pp input is available for continuous 5414 * mode */ 5415 ret = configure_pp_input(asd, isp_sink_crop->width, 5416 isp_sink_crop->height); 5417 if (ret) { 5418 dev_err(isp->dev, "configure_pp_input %ux%u\n", 5419 isp_sink_crop->width, 5420 isp_sink_crop->height); 5421 return -EINVAL; 5422 } 5423 } else { 5424 ret = configure_pp_input(asd, isp_sink_crop->width, 5425 isp_sink_crop->height); 5426 if (ret) { 5427 dev_err(isp->dev, "configure_pp_input %ux%u\n", 5428 isp_sink_crop->width, isp_sink_crop->height); 5429 return -EINVAL; 5430 } 5431 } 5432 if (asd->copy_mode) 5433 ret = atomisp_css_copy_get_output_frame_info(asd, stream_index, 5434 output_info); 5435 else 5436 ret = get_frame_info(asd, output_info); 5437 if (ret) { 5438 dev_err(isp->dev, "get_frame_info %ux%u (padded to %u)\n", 5439 pix->width, pix->height, pix->bytesperline); 5440 return -EINVAL; 5441 } 5442 5443 atomisp_update_grid_info(asd, pipe_id, source_pad); 5444 5445 /* Free the raw_dump buffer first */ 5446 ia_css_frame_free(asd->raw_output_frame); 5447 asd->raw_output_frame = NULL; 5448 5449 if (!asd->continuous_mode->val && 5450 !asd->params.online_process && !isp->sw_contex.file_input && 5451 ia_css_frame_allocate_from_info(&asd->raw_output_frame, 5452 raw_output_info)) 5453 return -ENOMEM; 5454 5455 return 0; 5456 } 5457 5458 static void atomisp_get_dis_envelop(struct atomisp_sub_device *asd, 5459 unsigned int width, unsigned int height, 5460 unsigned int *dvs_env_w, unsigned int *dvs_env_h) 5461 { 5462 struct atomisp_device *isp = asd->isp; 5463 5464 /* if subdev type is SOC camera,we do not need to set DVS */ 5465 if (isp->inputs[asd->input_curr].type == SOC_CAMERA) 5466 asd->params.video_dis_en = false; 5467 5468 if (asd->params.video_dis_en && 5469 asd->run_mode->val == ATOMISP_RUN_MODE_VIDEO) { 5470 /* envelope is 20% of the output resolution */ 5471 /* 5472 * dvs envelope cannot be round up. 5473 * it would cause ISP timeout and color switch issue 5474 */ 5475 *dvs_env_w = rounddown(width / 5, ATOM_ISP_STEP_WIDTH); 5476 *dvs_env_h = rounddown(height / 5, ATOM_ISP_STEP_HEIGHT); 5477 } 5478 5479 asd->params.dis_proj_data_valid = false; 5480 asd->params.css_update_params_needed = true; 5481 } 5482 5483 static void atomisp_check_copy_mode(struct atomisp_sub_device *asd, 5484 int source_pad, struct v4l2_format *f) 5485 { 5486 #if defined(ISP2401_NEW_INPUT_SYSTEM) 5487 struct v4l2_mbus_framefmt *sink, *src; 5488 5489 sink = atomisp_subdev_get_ffmt(&asd->subdev, NULL, 5490 V4L2_SUBDEV_FORMAT_ACTIVE, ATOMISP_SUBDEV_PAD_SINK); 5491 src = atomisp_subdev_get_ffmt(&asd->subdev, NULL, 5492 V4L2_SUBDEV_FORMAT_ACTIVE, source_pad); 5493 5494 if ((sink->code == src->code && 5495 sink->width == f->fmt.pix.width && 5496 sink->height == f->fmt.pix.height) || 5497 ((asd->isp->inputs[asd->input_curr].type == SOC_CAMERA) && 5498 (asd->isp->inputs[asd->input_curr].camera_caps-> 5499 sensor[asd->sensor_curr].stream_num > 1))) 5500 asd->copy_mode = true; 5501 else 5502 #endif 5503 /* Only used for the new input system */ 5504 asd->copy_mode = false; 5505 5506 dev_dbg(asd->isp->dev, "copy_mode: %d\n", asd->copy_mode); 5507 } 5508 5509 static int atomisp_set_fmt_to_snr(struct video_device *vdev, 5510 struct v4l2_format *f, unsigned int pixelformat, 5511 unsigned int padding_w, unsigned int padding_h, 5512 unsigned int dvs_env_w, unsigned int dvs_env_h) 5513 { 5514 struct atomisp_sub_device *asd = atomisp_to_video_pipe(vdev)->asd; 5515 const struct atomisp_format_bridge *format; 5516 struct v4l2_subdev_pad_config pad_cfg; 5517 struct v4l2_subdev_format vformat = { 5518 .which = V4L2_SUBDEV_FORMAT_TRY, 5519 }; 5520 struct v4l2_mbus_framefmt *ffmt = &vformat.format; 5521 struct v4l2_mbus_framefmt *req_ffmt; 5522 struct atomisp_device *isp = asd->isp; 5523 struct atomisp_input_stream_info *stream_info = 5524 (struct atomisp_input_stream_info *)ffmt->reserved; 5525 u16 stream_index = ATOMISP_INPUT_STREAM_GENERAL; 5526 int source_pad = atomisp_subdev_source_pad(vdev); 5527 struct v4l2_subdev_fh fh; 5528 int ret; 5529 5530 v4l2_fh_init(&fh.vfh, vdev); 5531 5532 stream_index = atomisp_source_pad_to_stream_id(asd, source_pad); 5533 5534 format = atomisp_get_format_bridge(pixelformat); 5535 if (!format) 5536 return -EINVAL; 5537 5538 v4l2_fill_mbus_format(ffmt, &f->fmt.pix, format->mbus_code); 5539 ffmt->height += padding_h + dvs_env_h; 5540 ffmt->width += padding_w + dvs_env_w; 5541 5542 dev_dbg(isp->dev, "s_mbus_fmt: ask %ux%u (padding %ux%u, dvs %ux%u)\n", 5543 ffmt->width, ffmt->height, padding_w, padding_h, 5544 dvs_env_w, dvs_env_h); 5545 5546 __atomisp_init_stream_info(stream_index, stream_info); 5547 5548 req_ffmt = ffmt; 5549 5550 /* Disable dvs if resolution can't be supported by sensor */ 5551 if (asd->params.video_dis_en && 5552 source_pad == ATOMISP_SUBDEV_PAD_SOURCE_VIDEO) { 5553 vformat.which = V4L2_SUBDEV_FORMAT_TRY; 5554 ret = v4l2_subdev_call(isp->inputs[asd->input_curr].camera, 5555 pad, set_fmt, &pad_cfg, &vformat); 5556 if (ret) 5557 return ret; 5558 if (ffmt->width < req_ffmt->width || 5559 ffmt->height < req_ffmt->height) { 5560 req_ffmt->height -= dvs_env_h; 5561 req_ffmt->width -= dvs_env_w; 5562 ffmt = req_ffmt; 5563 dev_warn(isp->dev, 5564 "can not enable video dis due to sensor limitation."); 5565 asd->params.video_dis_en = false; 5566 } 5567 } 5568 dev_dbg(isp->dev, "sensor width: %d, height: %d\n", 5569 ffmt->width, ffmt->height); 5570 vformat.which = V4L2_SUBDEV_FORMAT_ACTIVE; 5571 ret = v4l2_subdev_call(isp->inputs[asd->input_curr].camera, pad, 5572 set_fmt, NULL, &vformat); 5573 if (ret) 5574 return ret; 5575 5576 __atomisp_update_stream_env(asd, stream_index, stream_info); 5577 5578 dev_dbg(isp->dev, "sensor width: %d, height: %d\n", 5579 ffmt->width, ffmt->height); 5580 5581 if (ffmt->width < ATOM_ISP_STEP_WIDTH || 5582 ffmt->height < ATOM_ISP_STEP_HEIGHT) 5583 return -EINVAL; 5584 5585 if (asd->params.video_dis_en && 5586 source_pad == ATOMISP_SUBDEV_PAD_SOURCE_VIDEO && 5587 (ffmt->width < req_ffmt->width || ffmt->height < req_ffmt->height)) { 5588 dev_warn(isp->dev, 5589 "can not enable video dis due to sensor limitation."); 5590 asd->params.video_dis_en = false; 5591 } 5592 5593 atomisp_subdev_set_ffmt(&asd->subdev, fh.pad, 5594 V4L2_SUBDEV_FORMAT_ACTIVE, 5595 ATOMISP_SUBDEV_PAD_SINK, ffmt); 5596 5597 return css_input_resolution_changed(asd, ffmt); 5598 } 5599 5600 int atomisp_set_fmt(struct video_device *vdev, struct v4l2_format *f) 5601 { 5602 struct atomisp_device *isp = video_get_drvdata(vdev); 5603 struct atomisp_video_pipe *pipe = atomisp_to_video_pipe(vdev); 5604 struct atomisp_sub_device *asd = pipe->asd; 5605 const struct atomisp_format_bridge *format_bridge; 5606 const struct atomisp_format_bridge *snr_format_bridge; 5607 struct ia_css_frame_info output_info, raw_output_info; 5608 struct v4l2_format snr_fmt = *f; 5609 struct v4l2_format backup_fmt = *f, s_fmt = *f; 5610 unsigned int dvs_env_w = 0, dvs_env_h = 0; 5611 unsigned int padding_w = pad_w, padding_h = pad_h; 5612 bool res_overflow = false, crop_needs_override = false; 5613 struct v4l2_mbus_framefmt *isp_sink_fmt; 5614 struct v4l2_mbus_framefmt isp_source_fmt = {0}; 5615 struct v4l2_rect isp_sink_crop; 5616 u16 source_pad = atomisp_subdev_source_pad(vdev); 5617 struct v4l2_subdev_fh fh; 5618 int ret; 5619 5620 if (source_pad >= ATOMISP_SUBDEV_PADS_NUM) 5621 return -EINVAL; 5622 5623 if (asd->streaming == ATOMISP_DEVICE_STREAMING_ENABLED) { 5624 dev_warn(isp->dev, "ISP does not support set format while at streaming!\n"); 5625 return -EBUSY; 5626 } 5627 5628 dev_dbg(isp->dev, 5629 "setting resolution %ux%u on pad %u for asd%d, bytesperline %u\n", 5630 f->fmt.pix.width, f->fmt.pix.height, source_pad, 5631 asd->index, f->fmt.pix.bytesperline); 5632 5633 v4l2_fh_init(&fh.vfh, vdev); 5634 5635 format_bridge = atomisp_get_format_bridge(f->fmt.pix.pixelformat); 5636 if (!format_bridge) 5637 return -EINVAL; 5638 5639 pipe->sh_fmt = format_bridge->sh_fmt; 5640 pipe->pix.pixelformat = f->fmt.pix.pixelformat; 5641 5642 if (source_pad == ATOMISP_SUBDEV_PAD_SOURCE_VF || 5643 (source_pad == ATOMISP_SUBDEV_PAD_SOURCE_PREVIEW 5644 && asd->run_mode->val == ATOMISP_RUN_MODE_VIDEO)) { 5645 if (asd->fmt_auto->val) { 5646 struct v4l2_rect *capture_comp; 5647 struct v4l2_rect r = {0}; 5648 5649 r.width = f->fmt.pix.width; 5650 r.height = f->fmt.pix.height; 5651 5652 if (source_pad == ATOMISP_SUBDEV_PAD_SOURCE_PREVIEW) 5653 capture_comp = atomisp_subdev_get_rect( 5654 &asd->subdev, NULL, 5655 V4L2_SUBDEV_FORMAT_ACTIVE, 5656 ATOMISP_SUBDEV_PAD_SOURCE_VIDEO, 5657 V4L2_SEL_TGT_COMPOSE); 5658 else 5659 capture_comp = atomisp_subdev_get_rect( 5660 &asd->subdev, NULL, 5661 V4L2_SUBDEV_FORMAT_ACTIVE, 5662 ATOMISP_SUBDEV_PAD_SOURCE_CAPTURE, 5663 V4L2_SEL_TGT_COMPOSE); 5664 5665 if (capture_comp->width < r.width 5666 || capture_comp->height < r.height) { 5667 r.width = capture_comp->width; 5668 r.height = capture_comp->height; 5669 } 5670 5671 atomisp_subdev_set_selection( 5672 &asd->subdev, fh.pad, 5673 V4L2_SUBDEV_FORMAT_ACTIVE, source_pad, 5674 V4L2_SEL_TGT_COMPOSE, 0, &r); 5675 5676 f->fmt.pix.width = r.width; 5677 f->fmt.pix.height = r.height; 5678 } 5679 5680 if (source_pad == ATOMISP_SUBDEV_PAD_SOURCE_PREVIEW && 5681 (asd->isp->inputs[asd->input_curr].type == SOC_CAMERA) && 5682 (asd->isp->inputs[asd->input_curr].camera_caps-> 5683 sensor[asd->sensor_curr].stream_num > 1)) { 5684 /* For M10MO outputing YUV preview images. */ 5685 u16 video_index = 5686 atomisp_source_pad_to_stream_id(asd, 5687 ATOMISP_SUBDEV_PAD_SOURCE_VIDEO); 5688 5689 ret = atomisp_css_copy_get_output_frame_info(asd, 5690 video_index, &output_info); 5691 if (ret) { 5692 dev_err(isp->dev, 5693 "copy_get_output_frame_info ret %i", ret); 5694 return -EINVAL; 5695 } 5696 if (!asd->yuvpp_mode) { 5697 /* 5698 * If viewfinder was configured into copy_mode, 5699 * we switch to using yuvpp pipe instead. 5700 */ 5701 asd->yuvpp_mode = true; 5702 ret = atomisp_css_copy_configure_output( 5703 asd, video_index, 0, 0, 0, 0); 5704 if (ret) { 5705 dev_err(isp->dev, 5706 "failed to disable copy pipe"); 5707 return -EINVAL; 5708 } 5709 ret = atomisp_css_yuvpp_configure_output( 5710 asd, video_index, 5711 output_info.res.width, 5712 output_info.res.height, 5713 output_info.padded_width, 5714 output_info.format); 5715 if (ret) { 5716 dev_err(isp->dev, 5717 "failed to set up yuvpp pipe\n"); 5718 return -EINVAL; 5719 } 5720 atomisp_css_video_enable_online(asd, false); 5721 atomisp_css_preview_enable_online(asd, 5722 ATOMISP_INPUT_STREAM_GENERAL, false); 5723 } 5724 atomisp_css_yuvpp_configure_viewfinder(asd, video_index, 5725 f->fmt.pix.width, f->fmt.pix.height, 5726 format_bridge->planar ? f->fmt.pix.bytesperline 5727 : f->fmt.pix.bytesperline * 8 5728 / format_bridge->depth, format_bridge->sh_fmt); 5729 atomisp_css_yuvpp_get_viewfinder_frame_info( 5730 asd, video_index, &output_info); 5731 } else if (source_pad == ATOMISP_SUBDEV_PAD_SOURCE_PREVIEW) { 5732 atomisp_css_video_configure_viewfinder(asd, 5733 f->fmt.pix.width, f->fmt.pix.height, 5734 format_bridge->planar ? f->fmt.pix.bytesperline 5735 : f->fmt.pix.bytesperline * 8 5736 / format_bridge->depth, format_bridge->sh_fmt); 5737 atomisp_css_video_get_viewfinder_frame_info(asd, 5738 &output_info); 5739 asd->copy_mode = false; 5740 } else { 5741 atomisp_css_capture_configure_viewfinder(asd, 5742 f->fmt.pix.width, f->fmt.pix.height, 5743 format_bridge->planar ? f->fmt.pix.bytesperline 5744 : f->fmt.pix.bytesperline * 8 5745 / format_bridge->depth, format_bridge->sh_fmt); 5746 atomisp_css_capture_get_viewfinder_frame_info(asd, 5747 &output_info); 5748 asd->copy_mode = false; 5749 } 5750 5751 goto done; 5752 } 5753 /* 5754 * Check whether main resolution configured smaller 5755 * than snapshot resolution. If so, force main resolution 5756 * to be the same as snapshot resolution 5757 */ 5758 if (source_pad == ATOMISP_SUBDEV_PAD_SOURCE_CAPTURE) { 5759 struct v4l2_rect *r; 5760 5761 r = atomisp_subdev_get_rect( 5762 &asd->subdev, NULL, 5763 V4L2_SUBDEV_FORMAT_ACTIVE, 5764 ATOMISP_SUBDEV_PAD_SOURCE_VF, V4L2_SEL_TGT_COMPOSE); 5765 5766 if (r->width && r->height 5767 && (r->width > f->fmt.pix.width 5768 || r->height > f->fmt.pix.height)) 5769 dev_warn(isp->dev, 5770 "Main Resolution config smaller then Vf Resolution. Force to be equal with Vf Resolution."); 5771 } 5772 5773 /* Pipeline configuration done through subdevs. Bail out now. */ 5774 if (!asd->fmt_auto->val) 5775 goto set_fmt_to_isp; 5776 5777 /* get sensor resolution and format */ 5778 ret = atomisp_try_fmt(vdev, &snr_fmt, &res_overflow); 5779 if (ret) { 5780 dev_warn(isp->dev, "Try format failed with error %d\n", ret); 5781 return ret; 5782 } 5783 f->fmt.pix.width = snr_fmt.fmt.pix.width; 5784 f->fmt.pix.height = snr_fmt.fmt.pix.height; 5785 5786 snr_format_bridge = 5787 atomisp_get_format_bridge(snr_fmt.fmt.pix.pixelformat); 5788 if (!snr_format_bridge) { 5789 dev_warn(isp->dev, "Can't find bridge format\n"); 5790 return -EINVAL; 5791 } 5792 5793 atomisp_subdev_get_ffmt(&asd->subdev, NULL, 5794 V4L2_SUBDEV_FORMAT_ACTIVE, 5795 ATOMISP_SUBDEV_PAD_SINK)->code = 5796 snr_format_bridge->mbus_code; 5797 5798 isp_sink_fmt = atomisp_subdev_get_ffmt(&asd->subdev, NULL, 5799 V4L2_SUBDEV_FORMAT_ACTIVE, 5800 ATOMISP_SUBDEV_PAD_SINK); 5801 5802 isp_source_fmt.code = format_bridge->mbus_code; 5803 atomisp_subdev_set_ffmt(&asd->subdev, fh.pad, 5804 V4L2_SUBDEV_FORMAT_ACTIVE, 5805 source_pad, &isp_source_fmt); 5806 5807 if (!atomisp_subdev_format_conversion(asd, source_pad)) { 5808 padding_w = 0; 5809 padding_h = 0; 5810 } else if (IS_BYT) { 5811 padding_w = 12; 5812 padding_h = 12; 5813 } 5814 5815 /* construct resolution supported by isp */ 5816 if (res_overflow && !asd->continuous_mode->val) { 5817 f->fmt.pix.width = rounddown( 5818 clamp_t(u32, f->fmt.pix.width - padding_w, 5819 ATOM_ISP_MIN_WIDTH, 5820 ATOM_ISP_MAX_WIDTH), ATOM_ISP_STEP_WIDTH); 5821 f->fmt.pix.height = rounddown( 5822 clamp_t(u32, f->fmt.pix.height - padding_h, 5823 ATOM_ISP_MIN_HEIGHT, 5824 ATOM_ISP_MAX_HEIGHT), ATOM_ISP_STEP_HEIGHT); 5825 } 5826 5827 atomisp_get_dis_envelop(asd, f->fmt.pix.width, f->fmt.pix.height, 5828 &dvs_env_w, &dvs_env_h); 5829 5830 if (asd->continuous_mode->val) { 5831 struct v4l2_rect *r; 5832 5833 r = atomisp_subdev_get_rect( 5834 &asd->subdev, NULL, 5835 V4L2_SUBDEV_FORMAT_ACTIVE, 5836 ATOMISP_SUBDEV_PAD_SOURCE_CAPTURE, 5837 V4L2_SEL_TGT_COMPOSE); 5838 /* 5839 * The ATOMISP_SUBDEV_PAD_SOURCE_CAPTURE should get resolutions 5840 * properly set otherwise, it should not be the capture_pad. 5841 */ 5842 if (r->width && r->height) 5843 asd->capture_pad = ATOMISP_SUBDEV_PAD_SOURCE_CAPTURE; 5844 else 5845 asd->capture_pad = source_pad; 5846 } else { 5847 asd->capture_pad = source_pad; 5848 } 5849 /* 5850 * set format info to sensor 5851 * In continuous mode, resolution is set only if it is higher than 5852 * existing value. This because preview pipe will be configured after 5853 * capture pipe and usually has lower resolution than capture pipe. 5854 */ 5855 if (!asd->continuous_mode->val || 5856 isp_sink_fmt->width < (f->fmt.pix.width + padding_w + dvs_env_w) || 5857 isp_sink_fmt->height < (f->fmt.pix.height + padding_h + 5858 dvs_env_h)) { 5859 /* 5860 * For jpeg or custom raw format the sensor will return constant 5861 * width and height. Because we already had quried try_mbus_fmt, 5862 * f->fmt.pix.width and f->fmt.pix.height has been changed to 5863 * this fixed width and height. So we cannot select the correct 5864 * resolution with that information. So use the original width 5865 * and height while set_mbus_fmt() so actual resolutions are 5866 * being used in while set media bus format. 5867 */ 5868 s_fmt = *f; 5869 if (f->fmt.pix.pixelformat == V4L2_PIX_FMT_JPEG || 5870 f->fmt.pix.pixelformat == V4L2_PIX_FMT_CUSTOM_M10MO_RAW) { 5871 s_fmt.fmt.pix.width = backup_fmt.fmt.pix.width; 5872 s_fmt.fmt.pix.height = backup_fmt.fmt.pix.height; 5873 } 5874 ret = atomisp_set_fmt_to_snr(vdev, &s_fmt, 5875 f->fmt.pix.pixelformat, padding_w, 5876 padding_h, dvs_env_w, dvs_env_h); 5877 if (ret) { 5878 dev_warn(isp->dev, 5879 "Set format to sensor failed with %d\n", ret); 5880 return -EINVAL; 5881 } 5882 5883 atomisp_csi_lane_config(isp); 5884 crop_needs_override = true; 5885 } 5886 5887 atomisp_check_copy_mode(asd, source_pad, &backup_fmt); 5888 asd->yuvpp_mode = false; /* Reset variable */ 5889 5890 isp_sink_crop = *atomisp_subdev_get_rect(&asd->subdev, NULL, 5891 V4L2_SUBDEV_FORMAT_ACTIVE, 5892 ATOMISP_SUBDEV_PAD_SINK, 5893 V4L2_SEL_TGT_CROP); 5894 5895 /* Try to enable YUV downscaling if ISP input is 10 % (either 5896 * width or height) bigger than the desired result. */ 5897 if (isp_sink_crop.width * 9 / 10 < f->fmt.pix.width || 5898 isp_sink_crop.height * 9 / 10 < f->fmt.pix.height || 5899 (atomisp_subdev_format_conversion(asd, source_pad) && 5900 ((asd->run_mode->val == ATOMISP_RUN_MODE_VIDEO && 5901 !asd->continuous_mode->val) || 5902 asd->vfpp->val == ATOMISP_VFPP_DISABLE_SCALER))) { 5903 /* for continuous mode, preview size might be smaller than 5904 * still capture size. if preview size still needs crop, 5905 * pick the larger one between crop size of preview and 5906 * still capture. 5907 */ 5908 if (asd->continuous_mode->val 5909 && source_pad == ATOMISP_SUBDEV_PAD_SOURCE_PREVIEW 5910 && !crop_needs_override) { 5911 isp_sink_crop.width = 5912 max_t(unsigned int, f->fmt.pix.width, 5913 isp_sink_crop.width); 5914 isp_sink_crop.height = 5915 max_t(unsigned int, f->fmt.pix.height, 5916 isp_sink_crop.height); 5917 } else { 5918 isp_sink_crop.width = f->fmt.pix.width; 5919 isp_sink_crop.height = f->fmt.pix.height; 5920 } 5921 5922 atomisp_subdev_set_selection(&asd->subdev, fh.pad, 5923 V4L2_SUBDEV_FORMAT_ACTIVE, 5924 ATOMISP_SUBDEV_PAD_SINK, 5925 V4L2_SEL_TGT_CROP, 5926 V4L2_SEL_FLAG_KEEP_CONFIG, 5927 &isp_sink_crop); 5928 atomisp_subdev_set_selection(&asd->subdev, fh.pad, 5929 V4L2_SUBDEV_FORMAT_ACTIVE, 5930 source_pad, V4L2_SEL_TGT_COMPOSE, 5931 0, &isp_sink_crop); 5932 } else if (IS_MOFD) { 5933 struct v4l2_rect main_compose = {0}; 5934 5935 main_compose.width = isp_sink_crop.width; 5936 main_compose.height = 5937 DIV_ROUND_UP(main_compose.width * f->fmt.pix.height, 5938 f->fmt.pix.width); 5939 if (main_compose.height > isp_sink_crop.height) { 5940 main_compose.height = isp_sink_crop.height; 5941 main_compose.width = 5942 DIV_ROUND_UP(main_compose.height * 5943 f->fmt.pix.width, 5944 f->fmt.pix.height); 5945 } 5946 5947 atomisp_subdev_set_selection(&asd->subdev, fh.pad, 5948 V4L2_SUBDEV_FORMAT_ACTIVE, 5949 source_pad, 5950 V4L2_SEL_TGT_COMPOSE, 0, 5951 &main_compose); 5952 } else { 5953 struct v4l2_rect sink_crop = {0}; 5954 struct v4l2_rect main_compose = {0}; 5955 5956 main_compose.width = f->fmt.pix.width; 5957 main_compose.height = f->fmt.pix.height; 5958 5959 /* WORKAROUND: this override is universally enabled in 5960 * GMIN to work around a CTS failures (GMINL-539) 5961 * which appears to be related by a hardware 5962 * performance limitation. It's unclear why this 5963 * particular code triggers the issue. */ 5964 if (!atomisp_hw_is_isp2401 || crop_needs_override) { 5965 if (isp_sink_crop.width * main_compose.height > 5966 isp_sink_crop.height * main_compose.width) { 5967 sink_crop.height = isp_sink_crop.height; 5968 sink_crop.width = DIV_NEAREST_STEP( 5969 sink_crop.height * 5970 f->fmt.pix.width, 5971 f->fmt.pix.height, 5972 ATOM_ISP_STEP_WIDTH); 5973 } else { 5974 sink_crop.width = isp_sink_crop.width; 5975 sink_crop.height = DIV_NEAREST_STEP( 5976 sink_crop.width * 5977 f->fmt.pix.height, 5978 f->fmt.pix.width, 5979 ATOM_ISP_STEP_HEIGHT); 5980 } 5981 atomisp_subdev_set_selection(&asd->subdev, fh.pad, 5982 V4L2_SUBDEV_FORMAT_ACTIVE, 5983 ATOMISP_SUBDEV_PAD_SINK, 5984 V4L2_SEL_TGT_CROP, 5985 V4L2_SEL_FLAG_KEEP_CONFIG, 5986 &sink_crop); 5987 } 5988 atomisp_subdev_set_selection(&asd->subdev, fh.pad, 5989 V4L2_SUBDEV_FORMAT_ACTIVE, 5990 source_pad, 5991 V4L2_SEL_TGT_COMPOSE, 0, 5992 &main_compose); 5993 } 5994 5995 set_fmt_to_isp: 5996 ret = atomisp_set_fmt_to_isp(vdev, &output_info, &raw_output_info, 5997 &f->fmt.pix, source_pad); 5998 if (ret) { 5999 dev_warn(isp->dev, "Can't set format on ISP. Error %d\n", ret); 6000 return -EINVAL; 6001 } 6002 done: 6003 pipe->pix.width = f->fmt.pix.width; 6004 pipe->pix.height = f->fmt.pix.height; 6005 pipe->pix.pixelformat = f->fmt.pix.pixelformat; 6006 if (format_bridge->planar) { 6007 pipe->pix.bytesperline = output_info.padded_width; 6008 pipe->pix.sizeimage = PAGE_ALIGN(f->fmt.pix.height * 6009 DIV_ROUND_UP(format_bridge->depth * 6010 output_info.padded_width, 8)); 6011 } else { 6012 pipe->pix.bytesperline = 6013 DIV_ROUND_UP(format_bridge->depth * 6014 output_info.padded_width, 8); 6015 pipe->pix.sizeimage = 6016 PAGE_ALIGN(f->fmt.pix.height * pipe->pix.bytesperline); 6017 } 6018 dev_dbg(isp->dev, "%s: image size: %d, %d bytes per line\n", 6019 __func__, pipe->pix.sizeimage, pipe->pix.bytesperline); 6020 6021 if (f->fmt.pix.field == V4L2_FIELD_ANY) 6022 f->fmt.pix.field = V4L2_FIELD_NONE; 6023 pipe->pix.field = f->fmt.pix.field; 6024 6025 f->fmt.pix = pipe->pix; 6026 f->fmt.pix.priv = PAGE_ALIGN(pipe->pix.width * 6027 pipe->pix.height * 2); 6028 6029 pipe->capq.field = f->fmt.pix.field; 6030 6031 /* 6032 * If in video 480P case, no GFX throttle 6033 */ 6034 if (asd->run_mode->val == ATOMISP_SUBDEV_PAD_SOURCE_VIDEO && 6035 f->fmt.pix.width == 720 && f->fmt.pix.height == 480) 6036 isp->need_gfx_throttle = false; 6037 else 6038 isp->need_gfx_throttle = true; 6039 6040 return 0; 6041 } 6042 6043 int atomisp_set_fmt_file(struct video_device *vdev, struct v4l2_format *f) 6044 { 6045 struct atomisp_device *isp = video_get_drvdata(vdev); 6046 struct atomisp_video_pipe *pipe = atomisp_to_video_pipe(vdev); 6047 struct atomisp_sub_device *asd = pipe->asd; 6048 struct v4l2_mbus_framefmt ffmt = {0}; 6049 const struct atomisp_format_bridge *format_bridge; 6050 struct v4l2_subdev_fh fh; 6051 int ret; 6052 6053 v4l2_fh_init(&fh.vfh, vdev); 6054 6055 dev_dbg(isp->dev, "setting fmt %ux%u 0x%x for file inject\n", 6056 f->fmt.pix.width, f->fmt.pix.height, f->fmt.pix.pixelformat); 6057 ret = atomisp_try_fmt_file(isp, f); 6058 if (ret) { 6059 dev_err(isp->dev, "atomisp_try_fmt_file err: %d\n", ret); 6060 return ret; 6061 } 6062 6063 format_bridge = atomisp_get_format_bridge(f->fmt.pix.pixelformat); 6064 if (!format_bridge) { 6065 dev_dbg(isp->dev, "atomisp_get_format_bridge err! fmt:0x%x\n", 6066 f->fmt.pix.pixelformat); 6067 return -EINVAL; 6068 } 6069 6070 pipe->pix = f->fmt.pix; 6071 atomisp_css_input_set_mode(asd, IA_CSS_INPUT_MODE_FIFO); 6072 atomisp_css_input_configure_port(asd, 6073 __get_mipi_port(isp, ATOMISP_CAMERA_PORT_PRIMARY), 2, 0xffff4, 6074 0, 0, 0, 0); 6075 ffmt.width = f->fmt.pix.width; 6076 ffmt.height = f->fmt.pix.height; 6077 ffmt.code = format_bridge->mbus_code; 6078 6079 atomisp_subdev_set_ffmt(&asd->subdev, fh.pad, V4L2_SUBDEV_FORMAT_ACTIVE, 6080 ATOMISP_SUBDEV_PAD_SINK, &ffmt); 6081 6082 return 0; 6083 } 6084 6085 int atomisp_set_shading_table(struct atomisp_sub_device *asd, 6086 struct atomisp_shading_table *user_shading_table) 6087 { 6088 struct ia_css_shading_table *shading_table; 6089 struct ia_css_shading_table *free_table; 6090 unsigned int len_table; 6091 int i; 6092 int ret = 0; 6093 6094 if (!user_shading_table) 6095 return -EINVAL; 6096 6097 if (!user_shading_table->enable) { 6098 asd->params.config.shading_table = NULL; 6099 asd->params.sc_en = false; 6100 return 0; 6101 } 6102 6103 /* If enabling, all tables must be set */ 6104 for (i = 0; i < ATOMISP_NUM_SC_COLORS; i++) { 6105 if (!user_shading_table->data[i]) 6106 return -EINVAL; 6107 } 6108 6109 /* Shading table size per color */ 6110 if (!atomisp_hw_is_isp2401) { 6111 if (user_shading_table->width > ISP2400_SH_CSS_MAX_SCTBL_WIDTH_PER_COLOR || 6112 user_shading_table->height > ISP2400_SH_CSS_MAX_SCTBL_HEIGHT_PER_COLOR) 6113 return -EINVAL; 6114 } else { 6115 if (user_shading_table->width > ISP2401_SH_CSS_MAX_SCTBL_WIDTH_PER_COLOR || 6116 user_shading_table->height > ISP2401_SH_CSS_MAX_SCTBL_HEIGHT_PER_COLOR) 6117 return -EINVAL; 6118 } 6119 6120 shading_table = atomisp_css_shading_table_alloc( 6121 user_shading_table->width, user_shading_table->height); 6122 if (!shading_table) 6123 return -ENOMEM; 6124 6125 len_table = user_shading_table->width * user_shading_table->height * 6126 ATOMISP_SC_TYPE_SIZE; 6127 for (i = 0; i < ATOMISP_NUM_SC_COLORS; i++) { 6128 ret = copy_from_user(shading_table->data[i], 6129 (void __user *)user_shading_table->data[i], 6130 len_table); 6131 if (ret) { 6132 free_table = shading_table; 6133 ret = -EFAULT; 6134 goto out; 6135 } 6136 } 6137 shading_table->sensor_width = user_shading_table->sensor_width; 6138 shading_table->sensor_height = user_shading_table->sensor_height; 6139 shading_table->fraction_bits = user_shading_table->fraction_bits; 6140 6141 free_table = asd->params.css_param.shading_table; 6142 asd->params.css_param.shading_table = shading_table; 6143 asd->params.config.shading_table = shading_table; 6144 asd->params.sc_en = true; 6145 6146 out: 6147 if (free_table) 6148 atomisp_css_shading_table_free(free_table); 6149 6150 return ret; 6151 } 6152 6153 /*Turn off ISP dphy */ 6154 int atomisp_ospm_dphy_down(struct atomisp_device *isp) 6155 { 6156 unsigned long flags; 6157 u32 reg; 6158 6159 dev_dbg(isp->dev, "%s\n", __func__); 6160 6161 /* if ISP timeout, we can force powerdown */ 6162 if (isp->isp_timeout) 6163 goto done; 6164 6165 if (!atomisp_dev_users(isp)) 6166 goto done; 6167 6168 spin_lock_irqsave(&isp->lock, flags); 6169 isp->sw_contex.power_state = ATOM_ISP_POWER_DOWN; 6170 spin_unlock_irqrestore(&isp->lock, flags); 6171 done: 6172 /* 6173 * MRFLD IUNIT DPHY is located in an always-power-on island 6174 * MRFLD HW design need all CSI ports are disabled before 6175 * powering down the IUNIT. 6176 */ 6177 pci_read_config_dword(isp->pdev, MRFLD_PCI_CSI_CONTROL, ®); 6178 reg |= MRFLD_ALL_CSI_PORTS_OFF_MASK; 6179 pci_write_config_dword(isp->pdev, MRFLD_PCI_CSI_CONTROL, reg); 6180 return 0; 6181 } 6182 6183 /*Turn on ISP dphy */ 6184 int atomisp_ospm_dphy_up(struct atomisp_device *isp) 6185 { 6186 unsigned long flags; 6187 6188 dev_dbg(isp->dev, "%s\n", __func__); 6189 6190 spin_lock_irqsave(&isp->lock, flags); 6191 isp->sw_contex.power_state = ATOM_ISP_POWER_UP; 6192 spin_unlock_irqrestore(&isp->lock, flags); 6193 6194 return 0; 6195 } 6196 6197 int atomisp_exif_makernote(struct atomisp_sub_device *asd, 6198 struct atomisp_makernote_info *config) 6199 { 6200 struct v4l2_control ctrl; 6201 struct atomisp_device *isp = asd->isp; 6202 6203 ctrl.id = V4L2_CID_FOCAL_ABSOLUTE; 6204 if (v4l2_g_ctrl 6205 (isp->inputs[asd->input_curr].camera->ctrl_handler, &ctrl)) { 6206 dev_warn(isp->dev, "failed to g_ctrl for focal length\n"); 6207 return -EINVAL; 6208 } else { 6209 config->focal_length = ctrl.value; 6210 } 6211 6212 ctrl.id = V4L2_CID_FNUMBER_ABSOLUTE; 6213 if (v4l2_g_ctrl 6214 (isp->inputs[asd->input_curr].camera->ctrl_handler, &ctrl)) { 6215 dev_warn(isp->dev, "failed to g_ctrl for f-number\n"); 6216 return -EINVAL; 6217 } else { 6218 config->f_number_curr = ctrl.value; 6219 } 6220 6221 ctrl.id = V4L2_CID_FNUMBER_RANGE; 6222 if (v4l2_g_ctrl 6223 (isp->inputs[asd->input_curr].camera->ctrl_handler, &ctrl)) { 6224 dev_warn(isp->dev, "failed to g_ctrl for f number range\n"); 6225 return -EINVAL; 6226 } else { 6227 config->f_number_range = ctrl.value; 6228 } 6229 6230 return 0; 6231 } 6232 6233 int atomisp_offline_capture_configure(struct atomisp_sub_device *asd, 6234 struct atomisp_cont_capture_conf *cvf_config) 6235 { 6236 struct v4l2_ctrl *c; 6237 6238 /* 6239 * In case of M10MO ZSL capture case, we need to issue a separate 6240 * capture request to M10MO which will output captured jpeg image 6241 */ 6242 c = v4l2_ctrl_find( 6243 asd->isp->inputs[asd->input_curr].camera->ctrl_handler, 6244 V4L2_CID_START_ZSL_CAPTURE); 6245 if (c) { 6246 int ret; 6247 6248 dev_dbg(asd->isp->dev, "%s trigger ZSL capture request\n", 6249 __func__); 6250 /* TODO: use the cvf_config */ 6251 ret = v4l2_ctrl_s_ctrl(c, 1); 6252 if (ret) 6253 return ret; 6254 6255 return v4l2_ctrl_s_ctrl(c, 0); 6256 } 6257 6258 asd->params.offline_parm = *cvf_config; 6259 6260 if (asd->params.offline_parm.num_captures) { 6261 if (asd->streaming == ATOMISP_DEVICE_STREAMING_DISABLED) { 6262 unsigned int init_raw_num; 6263 6264 if (asd->enable_raw_buffer_lock->val) { 6265 init_raw_num = 6266 ATOMISP_CSS2_NUM_OFFLINE_INIT_CONTINUOUS_FRAMES_LOCK_EN; 6267 if (asd->run_mode->val == ATOMISP_RUN_MODE_VIDEO && 6268 asd->params.video_dis_en) 6269 init_raw_num += 6270 ATOMISP_CSS2_NUM_DVS_FRAME_DELAY; 6271 } else { 6272 init_raw_num = 6273 ATOMISP_CSS2_NUM_OFFLINE_INIT_CONTINUOUS_FRAMES; 6274 } 6275 6276 /* TODO: this can be removed once user-space 6277 * has been updated to use control API */ 6278 asd->continuous_raw_buffer_size->val = 6279 max_t(int, 6280 asd->continuous_raw_buffer_size->val, 6281 asd->params.offline_parm. 6282 num_captures + init_raw_num); 6283 asd->continuous_raw_buffer_size->val = 6284 min_t(int, ATOMISP_CONT_RAW_FRAMES, 6285 asd->continuous_raw_buffer_size->val); 6286 } 6287 asd->continuous_mode->val = true; 6288 } else { 6289 asd->continuous_mode->val = false; 6290 __enable_continuous_mode(asd, false); 6291 } 6292 6293 return 0; 6294 } 6295 6296 /* 6297 * set auto exposure metering window to camera sensor 6298 */ 6299 int atomisp_s_ae_window(struct atomisp_sub_device *asd, 6300 struct atomisp_ae_window *arg) 6301 { 6302 struct atomisp_device *isp = asd->isp; 6303 /* Coverity CID 298071 - initialzize struct */ 6304 struct v4l2_subdev_selection sel = { 0 }; 6305 6306 sel.r.left = arg->x_left; 6307 sel.r.top = arg->y_top; 6308 sel.r.width = arg->x_right - arg->x_left + 1; 6309 sel.r.height = arg->y_bottom - arg->y_top + 1; 6310 6311 if (v4l2_subdev_call(isp->inputs[asd->input_curr].camera, 6312 pad, set_selection, NULL, &sel)) { 6313 dev_err(isp->dev, "failed to call sensor set_selection.\n"); 6314 return -EINVAL; 6315 } 6316 6317 return 0; 6318 } 6319 6320 int atomisp_flash_enable(struct atomisp_sub_device *asd, int num_frames) 6321 { 6322 struct atomisp_device *isp = asd->isp; 6323 6324 if (num_frames < 0) { 6325 dev_dbg(isp->dev, "%s ERROR: num_frames: %d\n", __func__, 6326 num_frames); 6327 return -EINVAL; 6328 } 6329 /* a requested flash is still in progress. */ 6330 if (num_frames && asd->params.flash_state != ATOMISP_FLASH_IDLE) { 6331 dev_dbg(isp->dev, "%s flash busy: %d frames left: %d\n", 6332 __func__, asd->params.flash_state, 6333 asd->params.num_flash_frames); 6334 return -EBUSY; 6335 } 6336 6337 asd->params.num_flash_frames = num_frames; 6338 asd->params.flash_state = ATOMISP_FLASH_REQUESTED; 6339 return 0; 6340 } 6341 6342 int atomisp_source_pad_to_stream_id(struct atomisp_sub_device *asd, 6343 uint16_t source_pad) 6344 { 6345 int stream_id; 6346 struct atomisp_device *isp = asd->isp; 6347 6348 if (isp->inputs[asd->input_curr].camera_caps-> 6349 sensor[asd->sensor_curr].stream_num == 1) 6350 return ATOMISP_INPUT_STREAM_GENERAL; 6351 6352 switch (source_pad) { 6353 case ATOMISP_SUBDEV_PAD_SOURCE_CAPTURE: 6354 stream_id = ATOMISP_INPUT_STREAM_CAPTURE; 6355 break; 6356 case ATOMISP_SUBDEV_PAD_SOURCE_VF: 6357 stream_id = ATOMISP_INPUT_STREAM_POSTVIEW; 6358 break; 6359 case ATOMISP_SUBDEV_PAD_SOURCE_PREVIEW: 6360 stream_id = ATOMISP_INPUT_STREAM_PREVIEW; 6361 break; 6362 case ATOMISP_SUBDEV_PAD_SOURCE_VIDEO: 6363 stream_id = ATOMISP_INPUT_STREAM_VIDEO; 6364 break; 6365 default: 6366 stream_id = ATOMISP_INPUT_STREAM_GENERAL; 6367 } 6368 6369 return stream_id; 6370 } 6371 6372 bool atomisp_is_vf_pipe(struct atomisp_video_pipe *pipe) 6373 { 6374 struct atomisp_sub_device *asd = pipe->asd; 6375 6376 if (pipe == &asd->video_out_vf) 6377 return true; 6378 6379 if (asd->run_mode->val == ATOMISP_RUN_MODE_VIDEO && 6380 pipe == &asd->video_out_preview) 6381 return true; 6382 6383 return false; 6384 } 6385 6386 static int __checking_exp_id(struct atomisp_sub_device *asd, int exp_id) 6387 { 6388 struct atomisp_device *isp = asd->isp; 6389 6390 if (!asd->enable_raw_buffer_lock->val) { 6391 dev_warn(isp->dev, "%s Raw Buffer Lock is disable.\n", __func__); 6392 return -EINVAL; 6393 } 6394 if (asd->streaming != ATOMISP_DEVICE_STREAMING_ENABLED) { 6395 dev_err(isp->dev, "%s streaming %d invalid exp_id %d.\n", 6396 __func__, exp_id, asd->streaming); 6397 return -EINVAL; 6398 } 6399 if ((exp_id > ATOMISP_MAX_EXP_ID) || (exp_id <= 0)) { 6400 dev_err(isp->dev, "%s exp_id %d invalid.\n", __func__, exp_id); 6401 return -EINVAL; 6402 } 6403 return 0; 6404 } 6405 6406 void atomisp_init_raw_buffer_bitmap(struct atomisp_sub_device *asd) 6407 { 6408 unsigned long flags; 6409 6410 spin_lock_irqsave(&asd->raw_buffer_bitmap_lock, flags); 6411 memset(asd->raw_buffer_bitmap, 0, sizeof(asd->raw_buffer_bitmap)); 6412 asd->raw_buffer_locked_count = 0; 6413 spin_unlock_irqrestore(&asd->raw_buffer_bitmap_lock, flags); 6414 } 6415 6416 int atomisp_set_raw_buffer_bitmap(struct atomisp_sub_device *asd, int exp_id) 6417 { 6418 int *bitmap, bit; 6419 unsigned long flags; 6420 6421 if (__checking_exp_id(asd, exp_id)) 6422 return -EINVAL; 6423 6424 bitmap = asd->raw_buffer_bitmap + exp_id / 32; 6425 bit = exp_id % 32; 6426 spin_lock_irqsave(&asd->raw_buffer_bitmap_lock, flags); 6427 (*bitmap) |= (1 << bit); 6428 asd->raw_buffer_locked_count++; 6429 spin_unlock_irqrestore(&asd->raw_buffer_bitmap_lock, flags); 6430 6431 dev_dbg(asd->isp->dev, "%s: exp_id %d, raw_buffer_locked_count %d\n", 6432 __func__, exp_id, asd->raw_buffer_locked_count); 6433 6434 /* Check if the raw buffer after next is still locked!!! */ 6435 exp_id += 2; 6436 if (exp_id > ATOMISP_MAX_EXP_ID) 6437 exp_id -= ATOMISP_MAX_EXP_ID; 6438 bitmap = asd->raw_buffer_bitmap + exp_id / 32; 6439 bit = exp_id % 32; 6440 if ((*bitmap) & (1 << bit)) { 6441 int ret; 6442 6443 /* WORKAROUND unlock the raw buffer compulsively */ 6444 ret = atomisp_css_exp_id_unlock(asd, exp_id); 6445 if (ret) { 6446 dev_err(asd->isp->dev, 6447 "%s exp_id is wrapping back to %d but force unlock failed,, err %d.\n", 6448 __func__, exp_id, ret); 6449 return ret; 6450 } 6451 6452 spin_lock_irqsave(&asd->raw_buffer_bitmap_lock, flags); 6453 (*bitmap) &= ~(1 << bit); 6454 asd->raw_buffer_locked_count--; 6455 spin_unlock_irqrestore(&asd->raw_buffer_bitmap_lock, flags); 6456 dev_warn(asd->isp->dev, 6457 "%s exp_id is wrapping back to %d but it is still locked so force unlock it, raw_buffer_locked_count %d\n", 6458 __func__, exp_id, asd->raw_buffer_locked_count); 6459 } 6460 return 0; 6461 } 6462 6463 static int __is_raw_buffer_locked(struct atomisp_sub_device *asd, int exp_id) 6464 { 6465 int *bitmap, bit; 6466 unsigned long flags; 6467 int ret; 6468 6469 if (__checking_exp_id(asd, exp_id)) 6470 return -EINVAL; 6471 6472 bitmap = asd->raw_buffer_bitmap + exp_id / 32; 6473 bit = exp_id % 32; 6474 spin_lock_irqsave(&asd->raw_buffer_bitmap_lock, flags); 6475 ret = ((*bitmap) & (1 << bit)); 6476 spin_unlock_irqrestore(&asd->raw_buffer_bitmap_lock, flags); 6477 return !ret; 6478 } 6479 6480 static int __clear_raw_buffer_bitmap(struct atomisp_sub_device *asd, int exp_id) 6481 { 6482 int *bitmap, bit; 6483 unsigned long flags; 6484 6485 if (__is_raw_buffer_locked(asd, exp_id)) 6486 return -EINVAL; 6487 6488 bitmap = asd->raw_buffer_bitmap + exp_id / 32; 6489 bit = exp_id % 32; 6490 spin_lock_irqsave(&asd->raw_buffer_bitmap_lock, flags); 6491 (*bitmap) &= ~(1 << bit); 6492 asd->raw_buffer_locked_count--; 6493 spin_unlock_irqrestore(&asd->raw_buffer_bitmap_lock, flags); 6494 6495 dev_dbg(asd->isp->dev, "%s: exp_id %d, raw_buffer_locked_count %d\n", 6496 __func__, exp_id, asd->raw_buffer_locked_count); 6497 return 0; 6498 } 6499 6500 int atomisp_exp_id_capture(struct atomisp_sub_device *asd, int *exp_id) 6501 { 6502 struct atomisp_device *isp = asd->isp; 6503 int value = *exp_id; 6504 int ret; 6505 6506 ret = __is_raw_buffer_locked(asd, value); 6507 if (ret) { 6508 dev_err(isp->dev, "%s exp_id %d invalid %d.\n", __func__, value, ret); 6509 return -EINVAL; 6510 } 6511 6512 dev_dbg(isp->dev, "%s exp_id %d\n", __func__, value); 6513 ret = atomisp_css_exp_id_capture(asd, value); 6514 if (ret) { 6515 dev_err(isp->dev, "%s exp_id %d failed.\n", __func__, value); 6516 return -EIO; 6517 } 6518 return 0; 6519 } 6520 6521 int atomisp_exp_id_unlock(struct atomisp_sub_device *asd, int *exp_id) 6522 { 6523 struct atomisp_device *isp = asd->isp; 6524 int value = *exp_id; 6525 int ret; 6526 6527 ret = __clear_raw_buffer_bitmap(asd, value); 6528 if (ret) { 6529 dev_err(isp->dev, "%s exp_id %d invalid %d.\n", __func__, value, ret); 6530 return -EINVAL; 6531 } 6532 6533 dev_dbg(isp->dev, "%s exp_id %d\n", __func__, value); 6534 ret = atomisp_css_exp_id_unlock(asd, value); 6535 if (ret) 6536 dev_err(isp->dev, "%s exp_id %d failed, err %d.\n", 6537 __func__, value, ret); 6538 6539 return ret; 6540 } 6541 6542 int atomisp_enable_dz_capt_pipe(struct atomisp_sub_device *asd, 6543 unsigned int *enable) 6544 { 6545 bool value; 6546 6547 if (!enable) 6548 return -EINVAL; 6549 6550 value = *enable > 0 ? true : false; 6551 6552 atomisp_en_dz_capt_pipe(asd, value); 6553 6554 return 0; 6555 } 6556 6557 int atomisp_inject_a_fake_event(struct atomisp_sub_device *asd, int *event) 6558 { 6559 if (!event || asd->streaming != ATOMISP_DEVICE_STREAMING_ENABLED) 6560 return -EINVAL; 6561 6562 dev_dbg(asd->isp->dev, "%s: trying to inject a fake event 0x%x\n", 6563 __func__, *event); 6564 6565 switch (*event) { 6566 case V4L2_EVENT_FRAME_SYNC: 6567 atomisp_sof_event(asd); 6568 break; 6569 case V4L2_EVENT_FRAME_END: 6570 atomisp_eof_event(asd, 0); 6571 break; 6572 case V4L2_EVENT_ATOMISP_3A_STATS_READY: 6573 atomisp_3a_stats_ready_event(asd, 0); 6574 break; 6575 case V4L2_EVENT_ATOMISP_METADATA_READY: 6576 atomisp_metadata_ready_event(asd, 0); 6577 break; 6578 default: 6579 return -EINVAL; 6580 } 6581 6582 return 0; 6583 } 6584 6585 static int atomisp_get_pipe_id(struct atomisp_video_pipe *pipe) 6586 { 6587 struct atomisp_sub_device *asd = pipe->asd; 6588 6589 if (ATOMISP_USE_YUVPP(asd)) 6590 return IA_CSS_PIPE_ID_YUVPP; 6591 else if (asd->vfpp->val == ATOMISP_VFPP_DISABLE_SCALER) 6592 return IA_CSS_PIPE_ID_VIDEO; 6593 else if (asd->vfpp->val == ATOMISP_VFPP_DISABLE_LOWLAT) 6594 return IA_CSS_PIPE_ID_CAPTURE; 6595 else if (pipe == &asd->video_out_video_capture) 6596 return IA_CSS_PIPE_ID_VIDEO; 6597 else if (pipe == &asd->video_out_vf) 6598 return IA_CSS_PIPE_ID_CAPTURE; 6599 else if (pipe == &asd->video_out_preview) { 6600 if (asd->run_mode->val == ATOMISP_RUN_MODE_VIDEO) 6601 return IA_CSS_PIPE_ID_VIDEO; 6602 else 6603 return IA_CSS_PIPE_ID_PREVIEW; 6604 } else if (pipe == &asd->video_out_capture) { 6605 if (asd->copy_mode) 6606 return IA_CSS_PIPE_ID_COPY; 6607 else 6608 return IA_CSS_PIPE_ID_CAPTURE; 6609 } 6610 6611 /* fail through */ 6612 dev_warn(asd->isp->dev, "%s failed to find proper pipe\n", 6613 __func__); 6614 return IA_CSS_PIPE_ID_CAPTURE; 6615 } 6616 6617 int atomisp_get_invalid_frame_num(struct video_device *vdev, 6618 int *invalid_frame_num) 6619 { 6620 struct atomisp_video_pipe *pipe = atomisp_to_video_pipe(vdev); 6621 struct atomisp_sub_device *asd = pipe->asd; 6622 enum ia_css_pipe_id pipe_id; 6623 struct ia_css_pipe_info p_info; 6624 int ret; 6625 6626 if (asd->isp->inputs[asd->input_curr].camera_caps-> 6627 sensor[asd->sensor_curr].stream_num > 1) { 6628 /* External ISP */ 6629 *invalid_frame_num = 0; 6630 return 0; 6631 } 6632 6633 pipe_id = atomisp_get_pipe_id(pipe); 6634 if (!asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].pipes[pipe_id]) { 6635 dev_warn(asd->isp->dev, 6636 "%s pipe %d has not been created yet, do SET_FMT first!\n", 6637 __func__, pipe_id); 6638 return -EINVAL; 6639 } 6640 6641 ret = ia_css_pipe_get_info( 6642 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL] 6643 .pipes[pipe_id], &p_info); 6644 if (!ret) { 6645 *invalid_frame_num = p_info.num_invalid_frames; 6646 return 0; 6647 } else { 6648 dev_warn(asd->isp->dev, "%s get pipe infor failed %d\n", 6649 __func__, ret); 6650 return -EINVAL; 6651 } 6652 } 6653