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