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