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