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