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 34 #define CREATE_TRACE_POINTS 35 #include "atomisp_trace_event.h" 36 37 #include "atomisp_cmd.h" 38 #include "atomisp_common.h" 39 #include "atomisp_fops.h" 40 #include "atomisp_internal.h" 41 #include "atomisp_ioctl.h" 42 #include "atomisp-regs.h" 43 #include "atomisp_tables.h" 44 #include "atomisp_compat.h" 45 #include "atomisp_subdev.h" 46 #include "atomisp_dfs_tables.h" 47 48 #include <hmm/hmm.h> 49 50 #include "sh_css_hrt.h" 51 #include "sh_css_defs.h" 52 #include "system_global.h" 53 #include "sh_css_internal.h" 54 #include "sh_css_sp.h" 55 #include "gp_device.h" 56 #include "device_access.h" 57 #include "irq.h" 58 59 #include "ia_css_types.h" 60 #include "ia_css_stream.h" 61 #include "ia_css_debug.h" 62 #include "bits.h" 63 64 /* We should never need to run the flash for more than 2 frames. 65 * At 15fps this means 133ms. We set the timeout a bit longer. 66 * Each flash driver is supposed to set its own timeout, but 67 * just in case someone else changed the timeout, we set it 68 * here to make sure we don't damage the flash hardware. */ 69 #define FLASH_TIMEOUT 800 /* ms */ 70 71 union host { 72 struct { 73 void *kernel_ptr; 74 void __user *user_ptr; 75 int size; 76 } scalar; 77 struct { 78 void *hmm_ptr; 79 } ptr; 80 }; 81 82 /* 83 * get sensor:dis71430/ov2720 related info from v4l2_subdev->priv data field. 84 * subdev->priv is set in mrst.c 85 */ 86 struct camera_mipi_info *atomisp_to_sensor_mipi_info(struct v4l2_subdev *sd) 87 { 88 return (struct camera_mipi_info *)v4l2_get_subdev_hostdata(sd); 89 } 90 91 /* 92 * get struct atomisp_video_pipe from v4l2 video_device 93 */ 94 struct atomisp_video_pipe *atomisp_to_video_pipe(struct video_device *dev) 95 { 96 return (struct atomisp_video_pipe *) 97 container_of(dev, struct atomisp_video_pipe, vdev); 98 } 99 100 static unsigned short atomisp_get_sensor_fps(struct atomisp_sub_device *asd) 101 { 102 struct v4l2_subdev_frame_interval fi = { 0 }; 103 struct atomisp_device *isp = asd->isp; 104 105 unsigned short fps = 0; 106 int ret; 107 108 ret = v4l2_subdev_call(isp->inputs[asd->input_curr].camera, 109 video, g_frame_interval, &fi); 110 111 if (!ret && fi.interval.numerator) 112 fps = fi.interval.denominator / fi.interval.numerator; 113 114 return fps; 115 } 116 117 /* 118 * DFS progress is shown as follows: 119 * 1. Target frequency is calculated according to FPS/Resolution/ISP running 120 * mode. 121 * 2. Ratio is calculated using formula: 2 * HPLL / target frequency - 1 122 * with proper rounding. 123 * 3. Set ratio to ISPFREQ40, 1 to FREQVALID and ISPFREQGUAR40 124 * to 200MHz in ISPSSPM1. 125 * 4. Wait for FREQVALID to be cleared by P-Unit. 126 * 5. Wait for field ISPFREQSTAT40 in ISPSSPM1 turn to ratio set in 3. 127 */ 128 static int write_target_freq_to_hw(struct atomisp_device *isp, 129 unsigned int new_freq) 130 { 131 unsigned int ratio, timeout, guar_ratio; 132 u32 isp_sspm1 = 0; 133 int i; 134 135 if (!isp->hpll_freq) { 136 dev_err(isp->dev, "failed to get hpll_freq. no change to freq\n"); 137 return -EINVAL; 138 } 139 140 iosf_mbi_read(BT_MBI_UNIT_PMC, MBI_REG_READ, ISPSSPM1, &isp_sspm1); 141 if (isp_sspm1 & ISP_FREQ_VALID_MASK) { 142 dev_dbg(isp->dev, "clearing ISPSSPM1 valid bit.\n"); 143 iosf_mbi_write(BT_MBI_UNIT_PMC, MBI_REG_WRITE, ISPSSPM1, 144 isp_sspm1 & ~(1 << ISP_FREQ_VALID_OFFSET)); 145 } 146 147 ratio = (2 * isp->hpll_freq + new_freq / 2) / new_freq - 1; 148 guar_ratio = (2 * isp->hpll_freq + 200 / 2) / 200 - 1; 149 150 iosf_mbi_read(BT_MBI_UNIT_PMC, MBI_REG_READ, ISPSSPM1, &isp_sspm1); 151 isp_sspm1 &= ~(0x1F << ISP_REQ_FREQ_OFFSET); 152 153 for (i = 0; i < ISP_DFS_TRY_TIMES; i++) { 154 iosf_mbi_write(BT_MBI_UNIT_PMC, MBI_REG_WRITE, ISPSSPM1, 155 isp_sspm1 156 | ratio << ISP_REQ_FREQ_OFFSET 157 | 1 << ISP_FREQ_VALID_OFFSET 158 | guar_ratio << ISP_REQ_GUAR_FREQ_OFFSET); 159 160 iosf_mbi_read(BT_MBI_UNIT_PMC, MBI_REG_READ, ISPSSPM1, &isp_sspm1); 161 timeout = 20; 162 while ((isp_sspm1 & ISP_FREQ_VALID_MASK) && timeout) { 163 iosf_mbi_read(BT_MBI_UNIT_PMC, MBI_REG_READ, ISPSSPM1, &isp_sspm1); 164 dev_dbg(isp->dev, "waiting for ISPSSPM1 valid bit to be 0.\n"); 165 udelay(100); 166 timeout--; 167 } 168 169 if (timeout != 0) 170 break; 171 } 172 173 if (timeout == 0) { 174 dev_err(isp->dev, "DFS failed due to HW error.\n"); 175 return -EINVAL; 176 } 177 178 iosf_mbi_read(BT_MBI_UNIT_PMC, MBI_REG_READ, ISPSSPM1, &isp_sspm1); 179 timeout = 10; 180 while (((isp_sspm1 >> ISP_FREQ_STAT_OFFSET) != ratio) && timeout) { 181 iosf_mbi_read(BT_MBI_UNIT_PMC, MBI_REG_READ, ISPSSPM1, &isp_sspm1); 182 dev_dbg(isp->dev, "waiting for ISPSSPM1 status bit to be 0x%x.\n", 183 new_freq); 184 udelay(100); 185 timeout--; 186 } 187 if (timeout == 0) { 188 dev_err(isp->dev, "DFS target freq is rejected by HW.\n"); 189 return -EINVAL; 190 } 191 192 return 0; 193 } 194 195 int atomisp_freq_scaling(struct atomisp_device *isp, 196 enum atomisp_dfs_mode mode, 197 bool force) 198 { 199 const struct atomisp_dfs_config *dfs; 200 unsigned int new_freq; 201 struct atomisp_freq_scaling_rule curr_rules; 202 int i, ret; 203 unsigned short fps = 0; 204 205 dfs = isp->dfs; 206 207 if (dfs->lowest_freq == 0 || dfs->max_freq_at_vmin == 0 || 208 dfs->highest_freq == 0 || dfs->dfs_table_size == 0 || 209 !dfs->dfs_table) { 210 dev_err(isp->dev, "DFS configuration is invalid.\n"); 211 return -EINVAL; 212 } 213 214 if (mode == ATOMISP_DFS_MODE_LOW) { 215 new_freq = dfs->lowest_freq; 216 goto done; 217 } 218 219 if (mode == ATOMISP_DFS_MODE_MAX) { 220 new_freq = dfs->highest_freq; 221 goto done; 222 } 223 224 fps = atomisp_get_sensor_fps(&isp->asd); 225 if (fps == 0) { 226 dev_info(isp->dev, 227 "Sensor didn't report FPS. Using DFS max mode.\n"); 228 new_freq = dfs->highest_freq; 229 goto done; 230 } 231 232 curr_rules.width = isp->asd.fmt[isp->asd.capture_pad].fmt.width; 233 curr_rules.height = isp->asd.fmt[isp->asd.capture_pad].fmt.height; 234 curr_rules.fps = fps; 235 curr_rules.run_mode = isp->asd.run_mode->val; 236 237 /* search for the target frequency by looping freq rules*/ 238 for (i = 0; i < dfs->dfs_table_size; i++) { 239 if (curr_rules.width != dfs->dfs_table[i].width && 240 dfs->dfs_table[i].width != ISP_FREQ_RULE_ANY) 241 continue; 242 if (curr_rules.height != dfs->dfs_table[i].height && 243 dfs->dfs_table[i].height != ISP_FREQ_RULE_ANY) 244 continue; 245 if (curr_rules.fps != dfs->dfs_table[i].fps && 246 dfs->dfs_table[i].fps != ISP_FREQ_RULE_ANY) 247 continue; 248 if (curr_rules.run_mode != dfs->dfs_table[i].run_mode && 249 dfs->dfs_table[i].run_mode != ISP_FREQ_RULE_ANY) 250 continue; 251 break; 252 } 253 254 if (i == dfs->dfs_table_size) 255 new_freq = dfs->max_freq_at_vmin; 256 else 257 new_freq = dfs->dfs_table[i].isp_freq; 258 259 done: 260 dev_dbg(isp->dev, "DFS target frequency=%d.\n", new_freq); 261 262 if ((new_freq == isp->running_freq) && !force) 263 return 0; 264 265 dev_dbg(isp->dev, "Programming DFS frequency to %d\n", new_freq); 266 267 ret = write_target_freq_to_hw(isp, new_freq); 268 if (!ret) { 269 isp->running_freq = new_freq; 270 trace_ipu_pstate(new_freq, -1); 271 } 272 return ret; 273 } 274 275 /* 276 * reset and restore ISP 277 */ 278 int atomisp_reset(struct atomisp_device *isp) 279 { 280 /* Reset ISP by power-cycling it */ 281 int ret = 0; 282 283 dev_dbg(isp->dev, "%s\n", __func__); 284 285 ret = atomisp_power_off(isp->dev); 286 if (ret < 0) 287 dev_err(isp->dev, "atomisp_power_off failed, %d\n", ret); 288 289 ret = atomisp_power_on(isp->dev); 290 if (ret < 0) { 291 dev_err(isp->dev, "atomisp_power_on failed, %d\n", ret); 292 isp->isp_fatal_error = true; 293 } 294 295 return ret; 296 } 297 298 /* 299 * interrupt disable functions 300 */ 301 static void disable_isp_irq(enum hrt_isp_css_irq irq) 302 { 303 irq_disable_channel(IRQ0_ID, irq); 304 305 if (irq != hrt_isp_css_irq_sp) 306 return; 307 308 cnd_sp_irq_enable(SP0_ID, false); 309 } 310 311 /* 312 * interrupt clean function 313 */ 314 static void clear_isp_irq(enum hrt_isp_css_irq irq) 315 { 316 irq_clear_all(IRQ0_ID); 317 } 318 319 void atomisp_msi_irq_init(struct atomisp_device *isp) 320 { 321 struct pci_dev *pdev = to_pci_dev(isp->dev); 322 u32 msg32; 323 u16 msg16; 324 325 pci_read_config_dword(pdev, PCI_MSI_CAPID, &msg32); 326 msg32 |= 1 << MSI_ENABLE_BIT; 327 pci_write_config_dword(pdev, PCI_MSI_CAPID, msg32); 328 329 msg32 = (1 << INTR_IER) | (1 << INTR_IIR); 330 pci_write_config_dword(pdev, PCI_INTERRUPT_CTRL, msg32); 331 332 pci_read_config_word(pdev, PCI_COMMAND, &msg16); 333 msg16 |= (PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER | 334 PCI_COMMAND_INTX_DISABLE); 335 pci_write_config_word(pdev, PCI_COMMAND, msg16); 336 } 337 338 void atomisp_msi_irq_uninit(struct atomisp_device *isp) 339 { 340 struct pci_dev *pdev = to_pci_dev(isp->dev); 341 u32 msg32; 342 u16 msg16; 343 344 pci_read_config_dword(pdev, PCI_MSI_CAPID, &msg32); 345 msg32 &= ~(1 << MSI_ENABLE_BIT); 346 pci_write_config_dword(pdev, PCI_MSI_CAPID, msg32); 347 348 msg32 = 0x0; 349 pci_write_config_dword(pdev, PCI_INTERRUPT_CTRL, msg32); 350 351 pci_read_config_word(pdev, PCI_COMMAND, &msg16); 352 msg16 &= ~(PCI_COMMAND_MASTER); 353 pci_write_config_word(pdev, PCI_COMMAND, msg16); 354 } 355 356 static void atomisp_sof_event(struct atomisp_sub_device *asd) 357 { 358 struct v4l2_event event = {0}; 359 360 event.type = V4L2_EVENT_FRAME_SYNC; 361 event.u.frame_sync.frame_sequence = atomic_read(&asd->sof_count); 362 363 v4l2_event_queue(asd->subdev.devnode, &event); 364 } 365 366 void atomisp_eof_event(struct atomisp_sub_device *asd, uint8_t exp_id) 367 { 368 struct v4l2_event event = {0}; 369 370 event.type = V4L2_EVENT_FRAME_END; 371 event.u.frame_sync.frame_sequence = exp_id; 372 373 v4l2_event_queue(asd->subdev.devnode, &event); 374 } 375 376 static void atomisp_3a_stats_ready_event(struct atomisp_sub_device *asd, 377 uint8_t exp_id) 378 { 379 struct v4l2_event event = {0}; 380 381 event.type = V4L2_EVENT_ATOMISP_3A_STATS_READY; 382 event.u.frame_sync.frame_sequence = exp_id; 383 384 v4l2_event_queue(asd->subdev.devnode, &event); 385 } 386 387 static void atomisp_metadata_ready_event(struct atomisp_sub_device *asd, 388 enum atomisp_metadata_type md_type) 389 { 390 struct v4l2_event event = {0}; 391 392 event.type = V4L2_EVENT_ATOMISP_METADATA_READY; 393 event.u.data[0] = md_type; 394 395 v4l2_event_queue(asd->subdev.devnode, &event); 396 } 397 398 static void atomisp_reset_event(struct atomisp_sub_device *asd) 399 { 400 struct v4l2_event event = {0}; 401 402 event.type = V4L2_EVENT_ATOMISP_CSS_RESET; 403 404 v4l2_event_queue(asd->subdev.devnode, &event); 405 } 406 407 static void print_csi_rx_errors(enum mipi_port_id port, 408 struct atomisp_device *isp) 409 { 410 u32 infos = 0; 411 412 atomisp_css_rx_get_irq_info(port, &infos); 413 414 dev_err(isp->dev, "CSI Receiver port %d errors:\n", port); 415 if (infos & IA_CSS_RX_IRQ_INFO_BUFFER_OVERRUN) 416 dev_err(isp->dev, " buffer overrun"); 417 if (infos & IA_CSS_RX_IRQ_INFO_ERR_SOT) 418 dev_err(isp->dev, " start-of-transmission error"); 419 if (infos & IA_CSS_RX_IRQ_INFO_ERR_SOT_SYNC) 420 dev_err(isp->dev, " start-of-transmission sync error"); 421 if (infos & IA_CSS_RX_IRQ_INFO_ERR_CONTROL) 422 dev_err(isp->dev, " control error"); 423 if (infos & IA_CSS_RX_IRQ_INFO_ERR_ECC_DOUBLE) 424 dev_err(isp->dev, " 2 or more ECC errors"); 425 if (infos & IA_CSS_RX_IRQ_INFO_ERR_CRC) 426 dev_err(isp->dev, " CRC mismatch"); 427 if (infos & IA_CSS_RX_IRQ_INFO_ERR_UNKNOWN_ID) 428 dev_err(isp->dev, " unknown error"); 429 if (infos & IA_CSS_RX_IRQ_INFO_ERR_FRAME_SYNC) 430 dev_err(isp->dev, " frame sync error"); 431 if (infos & IA_CSS_RX_IRQ_INFO_ERR_FRAME_DATA) 432 dev_err(isp->dev, " frame data error"); 433 if (infos & IA_CSS_RX_IRQ_INFO_ERR_DATA_TIMEOUT) 434 dev_err(isp->dev, " data timeout"); 435 if (infos & IA_CSS_RX_IRQ_INFO_ERR_UNKNOWN_ESC) 436 dev_err(isp->dev, " unknown escape command entry"); 437 if (infos & IA_CSS_RX_IRQ_INFO_ERR_LINE_SYNC) 438 dev_err(isp->dev, " line sync error"); 439 } 440 441 /* Clear irq reg */ 442 static void clear_irq_reg(struct atomisp_device *isp) 443 { 444 struct pci_dev *pdev = to_pci_dev(isp->dev); 445 u32 msg_ret; 446 447 pci_read_config_dword(pdev, PCI_INTERRUPT_CTRL, &msg_ret); 448 msg_ret |= 1 << INTR_IIR; 449 pci_write_config_dword(pdev, PCI_INTERRUPT_CTRL, msg_ret); 450 } 451 452 /* interrupt handling function*/ 453 irqreturn_t atomisp_isr(int irq, void *dev) 454 { 455 struct atomisp_device *isp = (struct atomisp_device *)dev; 456 struct atomisp_css_event eof_event; 457 unsigned int irq_infos = 0; 458 unsigned long flags; 459 int err; 460 461 spin_lock_irqsave(&isp->lock, flags); 462 463 if (!isp->css_initialized) { 464 spin_unlock_irqrestore(&isp->lock, flags); 465 return IRQ_HANDLED; 466 } 467 err = atomisp_css_irq_translate(isp, &irq_infos); 468 if (err) { 469 spin_unlock_irqrestore(&isp->lock, flags); 470 return IRQ_NONE; 471 } 472 473 clear_irq_reg(isp); 474 475 if (!atomisp_streaming_count(isp)) 476 goto out_nowake; 477 478 if (isp->asd.streaming == ATOMISP_DEVICE_STREAMING_ENABLED) { 479 if (irq_infos & IA_CSS_IRQ_INFO_CSS_RECEIVER_SOF) { 480 atomic_inc(&isp->asd.sof_count); 481 atomisp_sof_event(&isp->asd); 482 483 /* If sequence_temp and sequence are the same 484 * there where no frames lost so we can increase 485 * sequence_temp. 486 * If not then processing of frame is still in progress 487 * and driver needs to keep old sequence_temp value. 488 * NOTE: There is assumption here that ISP will not 489 * start processing next frame from sensor before old 490 * one is completely done. */ 491 if (atomic_read(&isp->asd.sequence) == 492 atomic_read(&isp->asd.sequence_temp)) 493 atomic_set(&isp->asd.sequence_temp, 494 atomic_read(&isp->asd.sof_count)); 495 } 496 if (irq_infos & IA_CSS_IRQ_INFO_EVENTS_READY) 497 atomic_set(&isp->asd.sequence, 498 atomic_read(&isp->asd.sequence_temp)); 499 } 500 501 if (irq_infos & IA_CSS_IRQ_INFO_CSS_RECEIVER_SOF) { 502 dev_dbg_ratelimited(isp->dev, 503 "irq:0x%x (SOF)\n", 504 irq_infos); 505 irq_infos &= ~IA_CSS_IRQ_INFO_CSS_RECEIVER_SOF; 506 } 507 508 if ((irq_infos & IA_CSS_IRQ_INFO_INPUT_SYSTEM_ERROR) || 509 (irq_infos & IA_CSS_IRQ_INFO_IF_ERROR)) { 510 /* handle mipi receiver error */ 511 u32 rx_infos; 512 enum mipi_port_id port; 513 514 for (port = MIPI_PORT0_ID; port <= MIPI_PORT2_ID; 515 port++) { 516 print_csi_rx_errors(port, isp); 517 atomisp_css_rx_get_irq_info(port, &rx_infos); 518 atomisp_css_rx_clear_irq_info(port, rx_infos); 519 } 520 } 521 522 if (irq_infos & IA_CSS_IRQ_INFO_ISYS_EVENTS_READY) { 523 while (ia_css_dequeue_isys_event(&eof_event.event) == 0) { 524 atomisp_eof_event(&isp->asd, eof_event.event.exp_id); 525 dev_dbg_ratelimited(isp->dev, "ISYS event: EOF exp_id %d\n", 526 eof_event.event.exp_id); 527 } 528 529 irq_infos &= ~IA_CSS_IRQ_INFO_ISYS_EVENTS_READY; 530 if (irq_infos == 0) 531 goto out_nowake; 532 } 533 534 spin_unlock_irqrestore(&isp->lock, flags); 535 536 dev_dbg_ratelimited(isp->dev, "irq:0x%x (unhandled)\n", irq_infos); 537 538 return IRQ_WAKE_THREAD; 539 540 out_nowake: 541 spin_unlock_irqrestore(&isp->lock, flags); 542 543 if (irq_infos) 544 dev_dbg_ratelimited(isp->dev, "irq:0x%x (ignored, as not streaming anymore)\n", 545 irq_infos); 546 547 return IRQ_HANDLED; 548 } 549 550 void atomisp_clear_css_buffer_counters(struct atomisp_sub_device *asd) 551 { 552 int i; 553 554 memset(asd->s3a_bufs_in_css, 0, sizeof(asd->s3a_bufs_in_css)); 555 for (i = 0; i < ATOMISP_INPUT_STREAM_NUM; i++) 556 memset(asd->metadata_bufs_in_css[i], 0, 557 sizeof(asd->metadata_bufs_in_css[i])); 558 asd->dis_bufs_in_css = 0; 559 } 560 561 /* 0x100000 is the start of dmem inside SP */ 562 #define SP_DMEM_BASE 0x100000 563 564 void dump_sp_dmem(struct atomisp_device *isp, unsigned int addr, 565 unsigned int size) 566 { 567 unsigned int data = 0; 568 unsigned int size32 = DIV_ROUND_UP(size, sizeof(u32)); 569 570 dev_dbg(isp->dev, "atomisp mmio base: %p\n", isp->base); 571 dev_dbg(isp->dev, "%s, addr:0x%x, size: %d, size32: %d\n", __func__, 572 addr, size, size32); 573 if (size32 * 4 + addr > 0x4000) { 574 dev_err(isp->dev, "illegal size (%d) or addr (0x%x)\n", 575 size32, addr); 576 return; 577 } 578 addr += SP_DMEM_BASE; 579 addr &= 0x003FFFFF; 580 do { 581 data = readl(isp->base + addr); 582 dev_dbg(isp->dev, "%s, \t [0x%x]:0x%x\n", __func__, addr, data); 583 addr += sizeof(u32); 584 } while (--size32); 585 } 586 587 int atomisp_buffers_in_css(struct atomisp_video_pipe *pipe) 588 { 589 unsigned long irqflags; 590 struct list_head *pos; 591 int buffers_in_css = 0; 592 593 spin_lock_irqsave(&pipe->irq_lock, irqflags); 594 595 list_for_each(pos, &pipe->buffers_in_css) 596 buffers_in_css++; 597 598 spin_unlock_irqrestore(&pipe->irq_lock, irqflags); 599 600 return buffers_in_css; 601 } 602 603 void atomisp_buffer_done(struct ia_css_frame *frame, enum vb2_buffer_state state) 604 { 605 struct atomisp_video_pipe *pipe = vb_to_pipe(&frame->vb.vb2_buf); 606 607 lockdep_assert_held(&pipe->irq_lock); 608 609 frame->vb.vb2_buf.timestamp = ktime_get_ns(); 610 frame->vb.field = pipe->pix.field; 611 frame->vb.sequence = atomic_read(&pipe->asd->sequence); 612 list_del(&frame->queue); 613 if (state == VB2_BUF_STATE_DONE) 614 vb2_set_plane_payload(&frame->vb.vb2_buf, 0, pipe->pix.sizeimage); 615 vb2_buffer_done(&frame->vb.vb2_buf, state); 616 } 617 618 void atomisp_flush_video_pipe(struct atomisp_video_pipe *pipe, enum vb2_buffer_state state, 619 bool warn_on_css_frames) 620 { 621 struct ia_css_frame *frame, *_frame; 622 unsigned long irqflags; 623 624 spin_lock_irqsave(&pipe->irq_lock, irqflags); 625 626 list_for_each_entry_safe(frame, _frame, &pipe->buffers_in_css, queue) { 627 if (warn_on_css_frames) 628 dev_warn(pipe->isp->dev, "Warning: CSS frames queued on flush\n"); 629 atomisp_buffer_done(frame, state); 630 } 631 632 list_for_each_entry_safe(frame, _frame, &pipe->activeq, queue) 633 atomisp_buffer_done(frame, state); 634 635 list_for_each_entry_safe(frame, _frame, &pipe->buffers_waiting_for_param, queue) { 636 pipe->frame_request_config_id[frame->vb.vb2_buf.index] = 0; 637 atomisp_buffer_done(frame, state); 638 } 639 640 spin_unlock_irqrestore(&pipe->irq_lock, irqflags); 641 } 642 643 /* Returns queued buffers back to video-core */ 644 void atomisp_flush_bufs_and_wakeup(struct atomisp_sub_device *asd) 645 { 646 atomisp_flush_video_pipe(&asd->video_out_capture, VB2_BUF_STATE_ERROR, false); 647 atomisp_flush_video_pipe(&asd->video_out_vf, VB2_BUF_STATE_ERROR, false); 648 atomisp_flush_video_pipe(&asd->video_out_preview, VB2_BUF_STATE_ERROR, false); 649 atomisp_flush_video_pipe(&asd->video_out_video_capture, VB2_BUF_STATE_ERROR, false); 650 } 651 652 /* clean out the parameters that did not apply */ 653 void atomisp_flush_params_queue(struct atomisp_video_pipe *pipe) 654 { 655 struct atomisp_css_params_with_list *param; 656 657 while (!list_empty(&pipe->per_frame_params)) { 658 param = list_entry(pipe->per_frame_params.next, 659 struct atomisp_css_params_with_list, list); 660 list_del(¶m->list); 661 atomisp_free_css_parameters(¶m->params); 662 kvfree(param); 663 } 664 } 665 666 /* Re-queue per-frame parameters */ 667 static void atomisp_recover_params_queue(struct atomisp_video_pipe *pipe) 668 { 669 struct atomisp_css_params_with_list *param; 670 int i; 671 672 for (i = 0; i < VIDEO_MAX_FRAME; i++) { 673 param = pipe->frame_params[i]; 674 if (param) 675 list_add_tail(¶m->list, &pipe->per_frame_params); 676 pipe->frame_params[i] = NULL; 677 } 678 atomisp_handle_parameter_and_buffer(pipe); 679 } 680 681 void atomisp_buf_done(struct atomisp_sub_device *asd, int error, 682 enum ia_css_buffer_type buf_type, 683 enum ia_css_pipe_id css_pipe_id, 684 bool q_buffers, enum atomisp_input_stream_id stream_id) 685 { 686 struct atomisp_video_pipe *pipe = NULL; 687 struct atomisp_css_buffer buffer; 688 bool requeue = false; 689 unsigned long irqflags; 690 struct ia_css_frame *frame = NULL; 691 struct atomisp_s3a_buf *s3a_buf = NULL, *_s3a_buf_tmp, *s3a_iter; 692 struct atomisp_dis_buf *dis_buf = NULL, *_dis_buf_tmp, *dis_iter; 693 struct atomisp_metadata_buf *md_buf = NULL, *_md_buf_tmp, *md_iter; 694 enum atomisp_metadata_type md_type; 695 struct atomisp_device *isp = asd->isp; 696 struct v4l2_control ctrl; 697 int i, err; 698 699 lockdep_assert_held(&isp->mutex); 700 701 if ( 702 buf_type != IA_CSS_BUFFER_TYPE_METADATA && 703 buf_type != IA_CSS_BUFFER_TYPE_3A_STATISTICS && 704 buf_type != IA_CSS_BUFFER_TYPE_DIS_STATISTICS && 705 buf_type != IA_CSS_BUFFER_TYPE_OUTPUT_FRAME && 706 buf_type != IA_CSS_BUFFER_TYPE_SEC_OUTPUT_FRAME && 707 buf_type != IA_CSS_BUFFER_TYPE_RAW_OUTPUT_FRAME && 708 buf_type != IA_CSS_BUFFER_TYPE_SEC_VF_OUTPUT_FRAME && 709 buf_type != IA_CSS_BUFFER_TYPE_VF_OUTPUT_FRAME) { 710 dev_err(isp->dev, "%s, unsupported buffer type: %d\n", 711 __func__, buf_type); 712 return; 713 } 714 715 memset(&buffer, 0, sizeof(struct atomisp_css_buffer)); 716 buffer.css_buffer.type = buf_type; 717 err = atomisp_css_dequeue_buffer(asd, stream_id, css_pipe_id, 718 buf_type, &buffer); 719 if (err) { 720 dev_err(isp->dev, 721 "atomisp_css_dequeue_buffer failed: 0x%x\n", err); 722 return; 723 } 724 725 switch (buf_type) { 726 case IA_CSS_BUFFER_TYPE_3A_STATISTICS: 727 list_for_each_entry_safe(s3a_iter, _s3a_buf_tmp, 728 &asd->s3a_stats_in_css, list) { 729 if (s3a_iter->s3a_data == 730 buffer.css_buffer.data.stats_3a) { 731 list_del_init(&s3a_iter->list); 732 list_add_tail(&s3a_iter->list, 733 &asd->s3a_stats_ready); 734 s3a_buf = s3a_iter; 735 break; 736 } 737 } 738 739 asd->s3a_bufs_in_css[css_pipe_id]--; 740 atomisp_3a_stats_ready_event(asd, buffer.css_buffer.exp_id); 741 if (s3a_buf) 742 dev_dbg(isp->dev, "%s: s3a stat with exp_id %d is ready\n", 743 __func__, s3a_buf->s3a_data->exp_id); 744 else 745 dev_dbg(isp->dev, "%s: s3a stat is ready with no exp_id found\n", 746 __func__); 747 break; 748 case IA_CSS_BUFFER_TYPE_METADATA: 749 if (error) 750 break; 751 752 md_type = ATOMISP_MAIN_METADATA; 753 list_for_each_entry_safe(md_iter, _md_buf_tmp, 754 &asd->metadata_in_css[md_type], list) { 755 if (md_iter->metadata == 756 buffer.css_buffer.data.metadata) { 757 list_del_init(&md_iter->list); 758 list_add_tail(&md_iter->list, 759 &asd->metadata_ready[md_type]); 760 md_buf = md_iter; 761 break; 762 } 763 } 764 asd->metadata_bufs_in_css[stream_id][css_pipe_id]--; 765 atomisp_metadata_ready_event(asd, md_type); 766 if (md_buf) 767 dev_dbg(isp->dev, "%s: metadata with exp_id %d is ready\n", 768 __func__, md_buf->metadata->exp_id); 769 else 770 dev_dbg(isp->dev, "%s: metadata is ready with no exp_id found\n", 771 __func__); 772 break; 773 case IA_CSS_BUFFER_TYPE_DIS_STATISTICS: 774 list_for_each_entry_safe(dis_iter, _dis_buf_tmp, 775 &asd->dis_stats_in_css, list) { 776 if (dis_iter->dis_data == 777 buffer.css_buffer.data.stats_dvs) { 778 spin_lock_irqsave(&asd->dis_stats_lock, 779 irqflags); 780 list_del_init(&dis_iter->list); 781 list_add(&dis_iter->list, &asd->dis_stats); 782 asd->params.dis_proj_data_valid = true; 783 spin_unlock_irqrestore(&asd->dis_stats_lock, 784 irqflags); 785 dis_buf = dis_iter; 786 break; 787 } 788 } 789 asd->dis_bufs_in_css--; 790 if (dis_buf) 791 dev_dbg(isp->dev, "%s: dis stat with exp_id %d is ready\n", 792 __func__, dis_buf->dis_data->exp_id); 793 else 794 dev_dbg(isp->dev, "%s: dis stat is ready with no exp_id found\n", 795 __func__); 796 break; 797 case IA_CSS_BUFFER_TYPE_VF_OUTPUT_FRAME: 798 case IA_CSS_BUFFER_TYPE_SEC_VF_OUTPUT_FRAME: 799 frame = buffer.css_buffer.data.frame; 800 if (!frame) { 801 WARN_ON(1); 802 break; 803 } 804 if (!frame->valid) 805 error = true; 806 807 pipe = vb_to_pipe(&frame->vb.vb2_buf); 808 809 dev_dbg(isp->dev, "%s: vf frame with exp_id %d is ready\n", 810 __func__, frame->exp_id); 811 if (asd->params.flash_state == ATOMISP_FLASH_ONGOING) { 812 if (frame->flash_state 813 == IA_CSS_FRAME_FLASH_STATE_PARTIAL) 814 dev_dbg(isp->dev, "%s thumb partially flashed\n", 815 __func__); 816 else if (frame->flash_state 817 == IA_CSS_FRAME_FLASH_STATE_FULL) 818 dev_dbg(isp->dev, "%s thumb completely flashed\n", 819 __func__); 820 else 821 dev_dbg(isp->dev, "%s thumb no flash in this frame\n", 822 __func__); 823 } 824 pipe->frame_config_id[frame->vb.vb2_buf.index] = frame->isp_config_id; 825 break; 826 case IA_CSS_BUFFER_TYPE_OUTPUT_FRAME: 827 case IA_CSS_BUFFER_TYPE_SEC_OUTPUT_FRAME: 828 frame = buffer.css_buffer.data.frame; 829 if (!frame) { 830 WARN_ON(1); 831 break; 832 } 833 834 if (!frame->valid) 835 error = true; 836 837 pipe = vb_to_pipe(&frame->vb.vb2_buf); 838 839 dev_dbg(isp->dev, "%s: main frame with exp_id %d is ready\n", 840 __func__, frame->exp_id); 841 842 i = frame->vb.vb2_buf.index; 843 844 /* free the parameters */ 845 if (pipe->frame_params[i]) { 846 if (asd->params.dvs_6axis == pipe->frame_params[i]->params.dvs_6axis) 847 asd->params.dvs_6axis = NULL; 848 atomisp_free_css_parameters(&pipe->frame_params[i]->params); 849 kvfree(pipe->frame_params[i]); 850 pipe->frame_params[i] = NULL; 851 } 852 853 pipe->frame_config_id[i] = frame->isp_config_id; 854 ctrl.id = V4L2_CID_FLASH_MODE; 855 if (asd->params.flash_state == ATOMISP_FLASH_ONGOING) { 856 if (frame->flash_state == IA_CSS_FRAME_FLASH_STATE_PARTIAL) { 857 asd->frame_status[i] = ATOMISP_FRAME_STATUS_FLASH_PARTIAL; 858 dev_dbg(isp->dev, "%s partially flashed\n", __func__); 859 } else if (frame->flash_state == IA_CSS_FRAME_FLASH_STATE_FULL) { 860 asd->frame_status[i] = ATOMISP_FRAME_STATUS_FLASH_EXPOSED; 861 asd->params.num_flash_frames--; 862 dev_dbg(isp->dev, "%s completely flashed\n", __func__); 863 } else { 864 asd->frame_status[i] = ATOMISP_FRAME_STATUS_OK; 865 dev_dbg(isp->dev, "%s no flash in this frame\n", __func__); 866 } 867 868 /* Check if flashing sequence is done */ 869 if (asd->frame_status[i] == ATOMISP_FRAME_STATUS_FLASH_EXPOSED) 870 asd->params.flash_state = ATOMISP_FLASH_DONE; 871 } else if (isp->flash) { 872 if (v4l2_g_ctrl(isp->flash->ctrl_handler, &ctrl) == 0 && 873 ctrl.value == ATOMISP_FLASH_MODE_TORCH) { 874 ctrl.id = V4L2_CID_FLASH_TORCH_INTENSITY; 875 if (v4l2_g_ctrl(isp->flash->ctrl_handler, &ctrl) == 0 && 876 ctrl.value > 0) 877 asd->frame_status[i] = ATOMISP_FRAME_STATUS_FLASH_EXPOSED; 878 else 879 asd->frame_status[i] = ATOMISP_FRAME_STATUS_OK; 880 } else { 881 asd->frame_status[i] = ATOMISP_FRAME_STATUS_OK; 882 } 883 } else { 884 asd->frame_status[i] = ATOMISP_FRAME_STATUS_OK; 885 } 886 887 asd->params.last_frame_status = asd->frame_status[i]; 888 889 if (asd->params.css_update_params_needed) { 890 atomisp_apply_css_parameters(asd, 891 &asd->params.css_param); 892 if (asd->params.css_param.update_flag.dz_config) 893 asd->params.config.dz_config = &asd->params.css_param.dz_config; 894 /* New global dvs 6axis config should be blocked 895 * here if there's a buffer with per-frame parameters 896 * pending in CSS frame buffer queue. 897 * This is to aviod zooming vibration since global 898 * parameters take effect immediately while 899 * per-frame parameters are taken after previous 900 * buffers in CSS got processed. 901 */ 902 if (asd->params.dvs_6axis) 903 atomisp_css_set_dvs_6axis(asd, 904 asd->params.dvs_6axis); 905 else 906 asd->params.css_update_params_needed = false; 907 /* The update flag should not be cleaned here 908 * since it is still going to be used to make up 909 * following per-frame parameters. 910 * This will introduce more copy work since each 911 * time when updating global parameters, the whole 912 * parameter set are applied. 913 * FIXME: A new set of parameter copy functions can 914 * be added to make up per-frame parameters based on 915 * solid structures stored in asd->params.css_param 916 * instead of using shadow pointers in update flag. 917 */ 918 atomisp_css_update_isp_params(asd); 919 } 920 break; 921 default: 922 break; 923 } 924 if (frame) { 925 spin_lock_irqsave(&pipe->irq_lock, irqflags); 926 atomisp_buffer_done(frame, error ? VB2_BUF_STATE_ERROR : VB2_BUF_STATE_DONE); 927 spin_unlock_irqrestore(&pipe->irq_lock, irqflags); 928 } 929 930 /* 931 * Requeue should only be done for 3a and dis buffers. 932 * Queue/dequeue order will change if driver recycles image buffers. 933 */ 934 if (requeue) { 935 err = atomisp_css_queue_buffer(asd, 936 stream_id, css_pipe_id, 937 buf_type, &buffer); 938 if (err) 939 dev_err(isp->dev, "%s, q to css fails: %d\n", 940 __func__, err); 941 return; 942 } 943 if (!error && q_buffers) 944 atomisp_qbuffers_to_css(asd); 945 } 946 947 static void __atomisp_css_recover(struct atomisp_device *isp, bool isp_timeout) 948 { 949 struct pci_dev *pdev = to_pci_dev(isp->dev); 950 enum ia_css_pipe_id css_pipe_id; 951 bool stream_restart = false; 952 unsigned long flags; 953 int ret; 954 955 lockdep_assert_held(&isp->mutex); 956 957 if (!atomisp_streaming_count(isp)) 958 return; 959 960 atomisp_css_irq_enable(isp, IA_CSS_IRQ_INFO_CSS_RECEIVER_SOF, false); 961 962 if (isp->asd.streaming == ATOMISP_DEVICE_STREAMING_ENABLED || 963 isp->asd.stream_prepared) { 964 stream_restart = true; 965 966 spin_lock_irqsave(&isp->lock, flags); 967 isp->asd.streaming = ATOMISP_DEVICE_STREAMING_STOPPING; 968 spin_unlock_irqrestore(&isp->lock, flags); 969 970 /* stream off sensor */ 971 ret = v4l2_subdev_call( 972 isp->inputs[isp->asd.input_curr]. 973 camera, video, s_stream, 0); 974 if (ret) 975 dev_warn(isp->dev, 976 "can't stop streaming on sensor!\n"); 977 978 atomisp_clear_css_buffer_counters(&isp->asd); 979 980 css_pipe_id = atomisp_get_css_pipe_id(&isp->asd); 981 atomisp_css_stop(&isp->asd, css_pipe_id, true); 982 983 spin_lock_irqsave(&isp->lock, flags); 984 isp->asd.streaming = ATOMISP_DEVICE_STREAMING_DISABLED; 985 spin_unlock_irqrestore(&isp->lock, flags); 986 987 isp->asd.preview_exp_id = 1; 988 isp->asd.postview_exp_id = 1; 989 /* notify HAL the CSS reset */ 990 dev_dbg(isp->dev, 991 "send reset event to %s\n", isp->asd.subdev.devnode->name); 992 atomisp_reset_event(&isp->asd); 993 } 994 995 /* clear irq */ 996 disable_isp_irq(hrt_isp_css_irq_sp); 997 clear_isp_irq(hrt_isp_css_irq_sp); 998 999 /* Set the SRSE to 3 before resetting */ 1000 pci_write_config_dword(pdev, PCI_I_CONTROL, 1001 isp->saved_regs.i_control | MRFLD_PCI_I_CONTROL_SRSE_RESET_MASK); 1002 1003 /* reset ISP and restore its state */ 1004 isp->isp_timeout = true; 1005 atomisp_reset(isp); 1006 isp->isp_timeout = false; 1007 1008 if (stream_restart) { 1009 atomisp_css_input_set_mode(&isp->asd, IA_CSS_INPUT_MODE_BUFFERED_SENSOR); 1010 1011 css_pipe_id = atomisp_get_css_pipe_id(&isp->asd); 1012 if (atomisp_css_start(&isp->asd, css_pipe_id, true)) { 1013 dev_warn(isp->dev, 1014 "start SP failed, so do not set streaming to be enable!\n"); 1015 } else { 1016 spin_lock_irqsave(&isp->lock, flags); 1017 isp->asd.streaming = ATOMISP_DEVICE_STREAMING_ENABLED; 1018 spin_unlock_irqrestore(&isp->lock, flags); 1019 } 1020 1021 atomisp_csi2_configure(&isp->asd); 1022 } 1023 1024 atomisp_css_irq_enable(isp, IA_CSS_IRQ_INFO_CSS_RECEIVER_SOF, 1025 atomisp_css_valid_sof(isp)); 1026 1027 if (atomisp_freq_scaling(isp, ATOMISP_DFS_MODE_AUTO, true) < 0) 1028 dev_dbg(isp->dev, "DFS auto failed while recovering!\n"); 1029 1030 if (stream_restart) { 1031 /* 1032 * dequeueing buffers is not needed. CSS will recycle 1033 * buffers that it has. 1034 */ 1035 atomisp_flush_bufs_and_wakeup(&isp->asd); 1036 1037 /* Requeue unprocessed per-frame parameters. */ 1038 atomisp_recover_params_queue(&isp->asd.video_out_capture); 1039 atomisp_recover_params_queue(&isp->asd.video_out_preview); 1040 atomisp_recover_params_queue(&isp->asd.video_out_video_capture); 1041 1042 ret = v4l2_subdev_call( 1043 isp->inputs[isp->asd.input_curr].camera, video, 1044 s_stream, 1); 1045 if (ret) 1046 dev_warn(isp->dev, 1047 "can't start streaming on sensor!\n"); 1048 } 1049 } 1050 1051 void atomisp_assert_recovery_work(struct work_struct *work) 1052 { 1053 struct atomisp_device *isp = container_of(work, struct atomisp_device, 1054 assert_recovery_work); 1055 1056 mutex_lock(&isp->mutex); 1057 __atomisp_css_recover(isp, true); 1058 mutex_unlock(&isp->mutex); 1059 } 1060 1061 void atomisp_css_flush(struct atomisp_device *isp) 1062 { 1063 /* Start recover */ 1064 __atomisp_css_recover(isp, false); 1065 1066 dev_dbg(isp->dev, "atomisp css flush done\n"); 1067 } 1068 1069 void atomisp_setup_flash(struct atomisp_sub_device *asd) 1070 { 1071 struct atomisp_device *isp = asd->isp; 1072 struct v4l2_control ctrl; 1073 1074 if (!isp->flash) 1075 return; 1076 1077 if (asd->params.flash_state != ATOMISP_FLASH_REQUESTED && 1078 asd->params.flash_state != ATOMISP_FLASH_DONE) 1079 return; 1080 1081 if (asd->params.num_flash_frames) { 1082 /* make sure the timeout is set before setting flash mode */ 1083 ctrl.id = V4L2_CID_FLASH_TIMEOUT; 1084 ctrl.value = FLASH_TIMEOUT; 1085 1086 if (v4l2_s_ctrl(NULL, isp->flash->ctrl_handler, &ctrl)) { 1087 dev_err(isp->dev, "flash timeout configure failed\n"); 1088 return; 1089 } 1090 1091 ia_css_stream_request_flash(asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream); 1092 1093 asd->params.flash_state = ATOMISP_FLASH_ONGOING; 1094 } else { 1095 asd->params.flash_state = ATOMISP_FLASH_IDLE; 1096 } 1097 } 1098 1099 irqreturn_t atomisp_isr_thread(int irq, void *isp_ptr) 1100 { 1101 struct atomisp_device *isp = isp_ptr; 1102 unsigned long flags; 1103 1104 dev_dbg(isp->dev, ">%s\n", __func__); 1105 1106 spin_lock_irqsave(&isp->lock, flags); 1107 1108 if (!atomisp_streaming_count(isp)) { 1109 spin_unlock_irqrestore(&isp->lock, flags); 1110 return IRQ_HANDLED; 1111 } 1112 1113 spin_unlock_irqrestore(&isp->lock, flags); 1114 1115 /* 1116 * The standard CSS2.0 API tells the following calling sequence of 1117 * dequeue ready buffers: 1118 * while (ia_css_dequeue_psys_event(...)) { 1119 * switch (event.type) { 1120 * ... 1121 * ia_css_pipe_dequeue_buffer() 1122 * } 1123 * } 1124 * That is, dequeue event and buffer are one after another. 1125 * 1126 * But the following implementation is to first deuque all the event 1127 * to a FIFO, then process the event in the FIFO. 1128 * This will not have issue in single stream mode, but it do have some 1129 * issue in multiple stream case. The issue is that 1130 * ia_css_pipe_dequeue_buffer() will not return the corrent buffer in 1131 * a specific pipe. 1132 * 1133 * This is due to ia_css_pipe_dequeue_buffer() does not take the 1134 * ia_css_pipe parameter. 1135 * 1136 * So: 1137 * For CSS2.0: we change the way to not dequeue all the event at one 1138 * time, instead, dequue one and process one, then another 1139 */ 1140 mutex_lock(&isp->mutex); 1141 if (atomisp_css_isr_thread(isp)) 1142 goto out; 1143 1144 if (isp->asd.streaming == ATOMISP_DEVICE_STREAMING_ENABLED) 1145 atomisp_setup_flash(&isp->asd); 1146 out: 1147 mutex_unlock(&isp->mutex); 1148 dev_dbg(isp->dev, "<%s\n", __func__); 1149 1150 return IRQ_HANDLED; 1151 } 1152 1153 /* 1154 * Get internal fmt according to V4L2 fmt 1155 */ 1156 static enum ia_css_frame_format 1157 v4l2_fmt_to_sh_fmt(u32 fmt) 1158 { 1159 switch (fmt) { 1160 case V4L2_PIX_FMT_YUV420: 1161 return IA_CSS_FRAME_FORMAT_YUV420; 1162 case V4L2_PIX_FMT_YVU420: 1163 return IA_CSS_FRAME_FORMAT_YV12; 1164 case V4L2_PIX_FMT_YUV422P: 1165 return IA_CSS_FRAME_FORMAT_YUV422; 1166 case V4L2_PIX_FMT_YUV444: 1167 return IA_CSS_FRAME_FORMAT_YUV444; 1168 case V4L2_PIX_FMT_NV12: 1169 return IA_CSS_FRAME_FORMAT_NV12; 1170 case V4L2_PIX_FMT_NV21: 1171 return IA_CSS_FRAME_FORMAT_NV21; 1172 case V4L2_PIX_FMT_NV16: 1173 return IA_CSS_FRAME_FORMAT_NV16; 1174 case V4L2_PIX_FMT_NV61: 1175 return IA_CSS_FRAME_FORMAT_NV61; 1176 case V4L2_PIX_FMT_UYVY: 1177 return IA_CSS_FRAME_FORMAT_UYVY; 1178 case V4L2_PIX_FMT_YUYV: 1179 return IA_CSS_FRAME_FORMAT_YUYV; 1180 case V4L2_PIX_FMT_RGB24: 1181 return IA_CSS_FRAME_FORMAT_PLANAR_RGB888; 1182 case V4L2_PIX_FMT_RGB32: 1183 return IA_CSS_FRAME_FORMAT_RGBA888; 1184 case V4L2_PIX_FMT_RGB565: 1185 return IA_CSS_FRAME_FORMAT_RGB565; 1186 #if 0 1187 case V4L2_PIX_FMT_JPEG: 1188 case V4L2_PIX_FMT_CUSTOM_M10MO_RAW: 1189 return IA_CSS_FRAME_FORMAT_BINARY_8; 1190 #endif 1191 case V4L2_PIX_FMT_SBGGR16: 1192 case V4L2_PIX_FMT_SBGGR10: 1193 case V4L2_PIX_FMT_SGBRG10: 1194 case V4L2_PIX_FMT_SGRBG10: 1195 case V4L2_PIX_FMT_SRGGB10: 1196 case V4L2_PIX_FMT_SBGGR12: 1197 case V4L2_PIX_FMT_SGBRG12: 1198 case V4L2_PIX_FMT_SGRBG12: 1199 case V4L2_PIX_FMT_SRGGB12: 1200 case V4L2_PIX_FMT_SBGGR8: 1201 case V4L2_PIX_FMT_SGBRG8: 1202 case V4L2_PIX_FMT_SGRBG8: 1203 case V4L2_PIX_FMT_SRGGB8: 1204 return IA_CSS_FRAME_FORMAT_RAW; 1205 default: 1206 return -EINVAL; 1207 } 1208 } 1209 1210 /* 1211 * raw format match between SH format and V4L2 format 1212 */ 1213 static int raw_output_format_match_input(u32 input, u32 output) 1214 { 1215 if ((input == ATOMISP_INPUT_FORMAT_RAW_12) && 1216 ((output == V4L2_PIX_FMT_SRGGB12) || 1217 (output == V4L2_PIX_FMT_SGRBG12) || 1218 (output == V4L2_PIX_FMT_SBGGR12) || 1219 (output == V4L2_PIX_FMT_SGBRG12))) 1220 return 0; 1221 1222 if ((input == ATOMISP_INPUT_FORMAT_RAW_10) && 1223 ((output == V4L2_PIX_FMT_SRGGB10) || 1224 (output == V4L2_PIX_FMT_SGRBG10) || 1225 (output == V4L2_PIX_FMT_SBGGR10) || 1226 (output == V4L2_PIX_FMT_SGBRG10))) 1227 return 0; 1228 1229 if ((input == ATOMISP_INPUT_FORMAT_RAW_8) && 1230 ((output == V4L2_PIX_FMT_SRGGB8) || 1231 (output == V4L2_PIX_FMT_SGRBG8) || 1232 (output == V4L2_PIX_FMT_SBGGR8) || 1233 (output == V4L2_PIX_FMT_SGBRG8))) 1234 return 0; 1235 1236 if ((input == ATOMISP_INPUT_FORMAT_RAW_16) && (output == V4L2_PIX_FMT_SBGGR16)) 1237 return 0; 1238 1239 return -EINVAL; 1240 } 1241 1242 u32 atomisp_get_pixel_depth(u32 pixelformat) 1243 { 1244 switch (pixelformat) { 1245 case V4L2_PIX_FMT_YUV420: 1246 case V4L2_PIX_FMT_NV12: 1247 case V4L2_PIX_FMT_NV21: 1248 case V4L2_PIX_FMT_YVU420: 1249 return 12; 1250 case V4L2_PIX_FMT_YUV422P: 1251 case V4L2_PIX_FMT_YUYV: 1252 case V4L2_PIX_FMT_UYVY: 1253 case V4L2_PIX_FMT_NV16: 1254 case V4L2_PIX_FMT_NV61: 1255 case V4L2_PIX_FMT_RGB565: 1256 case V4L2_PIX_FMT_SBGGR16: 1257 case V4L2_PIX_FMT_SBGGR12: 1258 case V4L2_PIX_FMT_SGBRG12: 1259 case V4L2_PIX_FMT_SGRBG12: 1260 case V4L2_PIX_FMT_SRGGB12: 1261 case V4L2_PIX_FMT_SBGGR10: 1262 case V4L2_PIX_FMT_SGBRG10: 1263 case V4L2_PIX_FMT_SGRBG10: 1264 case V4L2_PIX_FMT_SRGGB10: 1265 return 16; 1266 case V4L2_PIX_FMT_RGB24: 1267 case V4L2_PIX_FMT_YUV444: 1268 return 24; 1269 case V4L2_PIX_FMT_RGB32: 1270 return 32; 1271 case V4L2_PIX_FMT_JPEG: 1272 case V4L2_PIX_FMT_CUSTOM_M10MO_RAW: 1273 case V4L2_PIX_FMT_SBGGR8: 1274 case V4L2_PIX_FMT_SGBRG8: 1275 case V4L2_PIX_FMT_SGRBG8: 1276 case V4L2_PIX_FMT_SRGGB8: 1277 return 8; 1278 default: 1279 return 8 * 2; /* raw type now */ 1280 } 1281 } 1282 1283 bool atomisp_is_mbuscode_raw(uint32_t code) 1284 { 1285 return code >= 0x3000 && code < 0x4000; 1286 } 1287 1288 /* 1289 * ISP features control function 1290 */ 1291 1292 /* 1293 * Set ISP capture mode based on current settings 1294 */ 1295 static void atomisp_update_capture_mode(struct atomisp_sub_device *asd) 1296 { 1297 if (asd->params.gdc_cac_en) 1298 atomisp_css_capture_set_mode(asd, IA_CSS_CAPTURE_MODE_ADVANCED); 1299 else if (asd->params.low_light) 1300 atomisp_css_capture_set_mode(asd, IA_CSS_CAPTURE_MODE_LOW_LIGHT); 1301 else if (asd->video_out_capture.sh_fmt == IA_CSS_FRAME_FORMAT_RAW) 1302 atomisp_css_capture_set_mode(asd, IA_CSS_CAPTURE_MODE_RAW); 1303 else 1304 atomisp_css_capture_set_mode(asd, IA_CSS_CAPTURE_MODE_PRIMARY); 1305 } 1306 1307 /* ISP2401 */ 1308 int atomisp_set_sensor_runmode(struct atomisp_sub_device *asd, 1309 struct atomisp_s_runmode *runmode) 1310 { 1311 struct atomisp_device *isp = asd->isp; 1312 struct v4l2_ctrl *c; 1313 int ret = 0; 1314 1315 if (!(runmode && (runmode->mode & RUNMODE_MASK))) 1316 return -EINVAL; 1317 1318 mutex_lock(asd->ctrl_handler.lock); 1319 c = v4l2_ctrl_find(isp->inputs[asd->input_curr].camera->ctrl_handler, 1320 V4L2_CID_RUN_MODE); 1321 1322 if (c) 1323 ret = v4l2_ctrl_s_ctrl(c, runmode->mode); 1324 1325 mutex_unlock(asd->ctrl_handler.lock); 1326 return ret; 1327 } 1328 1329 /* 1330 * Function to enable/disable lens geometry distortion correction (GDC) and 1331 * chromatic aberration correction (CAC) 1332 */ 1333 int atomisp_gdc_cac(struct atomisp_sub_device *asd, int flag, 1334 __s32 *value) 1335 { 1336 if (flag == 0) { 1337 *value = asd->params.gdc_cac_en; 1338 return 0; 1339 } 1340 1341 asd->params.gdc_cac_en = !!*value; 1342 if (asd->params.gdc_cac_en) { 1343 asd->params.config.morph_table = asd->params.css_param.morph_table; 1344 } else { 1345 asd->params.config.morph_table = NULL; 1346 } 1347 asd->params.css_update_params_needed = true; 1348 atomisp_update_capture_mode(asd); 1349 return 0; 1350 } 1351 1352 /* 1353 * Function to enable/disable low light mode including ANR 1354 */ 1355 int atomisp_low_light(struct atomisp_sub_device *asd, int flag, 1356 __s32 *value) 1357 { 1358 if (flag == 0) { 1359 *value = asd->params.low_light; 1360 return 0; 1361 } 1362 1363 asd->params.low_light = (*value != 0); 1364 atomisp_update_capture_mode(asd); 1365 return 0; 1366 } 1367 1368 /* 1369 * Function to enable/disable extra noise reduction (XNR) in low light 1370 * condition 1371 */ 1372 int atomisp_xnr(struct atomisp_sub_device *asd, int flag, 1373 int *xnr_enable) 1374 { 1375 if (flag == 0) { 1376 *xnr_enable = asd->params.xnr_en; 1377 return 0; 1378 } 1379 1380 atomisp_css_capture_enable_xnr(asd, !!*xnr_enable); 1381 1382 return 0; 1383 } 1384 1385 /* 1386 * Function to configure bayer noise reduction 1387 */ 1388 int atomisp_nr(struct atomisp_sub_device *asd, int flag, 1389 struct atomisp_nr_config *arg) 1390 { 1391 if (flag == 0) { 1392 /* Get nr config from current setup */ 1393 if (atomisp_css_get_nr_config(asd, arg)) 1394 return -EINVAL; 1395 } else { 1396 /* Set nr config to isp parameters */ 1397 memcpy(&asd->params.css_param.nr_config, arg, 1398 sizeof(struct ia_css_nr_config)); 1399 asd->params.config.nr_config = &asd->params.css_param.nr_config; 1400 asd->params.css_update_params_needed = true; 1401 } 1402 return 0; 1403 } 1404 1405 /* 1406 * Function to configure temporal noise reduction (TNR) 1407 */ 1408 int atomisp_tnr(struct atomisp_sub_device *asd, int flag, 1409 struct atomisp_tnr_config *config) 1410 { 1411 /* Get tnr config from current setup */ 1412 if (flag == 0) { 1413 /* Get tnr config from current setup */ 1414 if (atomisp_css_get_tnr_config(asd, config)) 1415 return -EINVAL; 1416 } else { 1417 /* Set tnr config to isp parameters */ 1418 memcpy(&asd->params.css_param.tnr_config, config, 1419 sizeof(struct ia_css_tnr_config)); 1420 asd->params.config.tnr_config = &asd->params.css_param.tnr_config; 1421 asd->params.css_update_params_needed = true; 1422 } 1423 1424 return 0; 1425 } 1426 1427 /* 1428 * Function to configure black level compensation 1429 */ 1430 int atomisp_black_level(struct atomisp_sub_device *asd, int flag, 1431 struct atomisp_ob_config *config) 1432 { 1433 if (flag == 0) { 1434 /* Get ob config from current setup */ 1435 if (atomisp_css_get_ob_config(asd, config)) 1436 return -EINVAL; 1437 } else { 1438 /* Set ob config to isp parameters */ 1439 memcpy(&asd->params.css_param.ob_config, config, 1440 sizeof(struct ia_css_ob_config)); 1441 asd->params.config.ob_config = &asd->params.css_param.ob_config; 1442 asd->params.css_update_params_needed = true; 1443 } 1444 1445 return 0; 1446 } 1447 1448 /* 1449 * Function to configure edge enhancement 1450 */ 1451 int atomisp_ee(struct atomisp_sub_device *asd, int flag, 1452 struct atomisp_ee_config *config) 1453 { 1454 if (flag == 0) { 1455 /* Get ee config from current setup */ 1456 if (atomisp_css_get_ee_config(asd, config)) 1457 return -EINVAL; 1458 } else { 1459 /* Set ee config to isp parameters */ 1460 memcpy(&asd->params.css_param.ee_config, config, 1461 sizeof(asd->params.css_param.ee_config)); 1462 asd->params.config.ee_config = &asd->params.css_param.ee_config; 1463 asd->params.css_update_params_needed = true; 1464 } 1465 1466 return 0; 1467 } 1468 1469 /* 1470 * Function to update Gamma table for gamma, brightness and contrast config 1471 */ 1472 int atomisp_gamma(struct atomisp_sub_device *asd, int flag, 1473 struct atomisp_gamma_table *config) 1474 { 1475 if (flag == 0) { 1476 /* Get gamma table from current setup */ 1477 if (atomisp_css_get_gamma_table(asd, config)) 1478 return -EINVAL; 1479 } else { 1480 /* Set gamma table to isp parameters */ 1481 memcpy(&asd->params.css_param.gamma_table, config, 1482 sizeof(asd->params.css_param.gamma_table)); 1483 asd->params.config.gamma_table = &asd->params.css_param.gamma_table; 1484 } 1485 1486 return 0; 1487 } 1488 1489 /* 1490 * Function to update Ctc table for Chroma Enhancement 1491 */ 1492 int atomisp_ctc(struct atomisp_sub_device *asd, int flag, 1493 struct atomisp_ctc_table *config) 1494 { 1495 if (flag == 0) { 1496 /* Get ctc table from current setup */ 1497 if (atomisp_css_get_ctc_table(asd, config)) 1498 return -EINVAL; 1499 } else { 1500 /* Set ctc table to isp parameters */ 1501 memcpy(&asd->params.css_param.ctc_table, config, 1502 sizeof(asd->params.css_param.ctc_table)); 1503 atomisp_css_set_ctc_table(asd, &asd->params.css_param.ctc_table); 1504 } 1505 1506 return 0; 1507 } 1508 1509 /* 1510 * Function to update gamma correction parameters 1511 */ 1512 int atomisp_gamma_correction(struct atomisp_sub_device *asd, int flag, 1513 struct atomisp_gc_config *config) 1514 { 1515 if (flag == 0) { 1516 /* Get gamma correction params from current setup */ 1517 if (atomisp_css_get_gc_config(asd, config)) 1518 return -EINVAL; 1519 } else { 1520 /* Set gamma correction params to isp parameters */ 1521 memcpy(&asd->params.css_param.gc_config, config, 1522 sizeof(asd->params.css_param.gc_config)); 1523 asd->params.config.gc_config = &asd->params.css_param.gc_config; 1524 asd->params.css_update_params_needed = true; 1525 } 1526 1527 return 0; 1528 } 1529 1530 /* 1531 * Function to update narrow gamma flag 1532 */ 1533 int atomisp_formats(struct atomisp_sub_device *asd, int flag, 1534 struct atomisp_formats_config *config) 1535 { 1536 if (flag == 0) { 1537 /* Get narrow gamma flag from current setup */ 1538 if (atomisp_css_get_formats_config(asd, config)) 1539 return -EINVAL; 1540 } else { 1541 /* Set narrow gamma flag to isp parameters */ 1542 memcpy(&asd->params.css_param.formats_config, config, 1543 sizeof(asd->params.css_param.formats_config)); 1544 asd->params.config.formats_config = &asd->params.css_param.formats_config; 1545 } 1546 1547 return 0; 1548 } 1549 1550 void atomisp_free_internal_buffers(struct atomisp_sub_device *asd) 1551 { 1552 atomisp_free_css_parameters(&asd->params.css_param); 1553 } 1554 1555 static void atomisp_update_grid_info(struct atomisp_sub_device *asd, 1556 enum ia_css_pipe_id pipe_id, 1557 int source_pad) 1558 { 1559 struct atomisp_device *isp = asd->isp; 1560 int err; 1561 1562 if (atomisp_css_get_grid_info(asd, pipe_id, source_pad)) 1563 return; 1564 1565 /* We must free all buffers because they no longer match 1566 the grid size. */ 1567 atomisp_css_free_stat_buffers(asd); 1568 1569 err = atomisp_alloc_css_stat_bufs(asd, ATOMISP_INPUT_STREAM_GENERAL); 1570 if (err) { 1571 dev_err(isp->dev, "stat_buf allocate error\n"); 1572 goto err; 1573 } 1574 1575 if (atomisp_alloc_3a_output_buf(asd)) { 1576 /* Failure for 3A buffers does not influence DIS buffers */ 1577 if (asd->params.s3a_output_bytes != 0) { 1578 /* For SOC sensor happens s3a_output_bytes == 0, 1579 * using if condition to exclude false error log */ 1580 dev_err(isp->dev, "Failed to allocate memory for 3A statistics\n"); 1581 } 1582 goto err; 1583 } 1584 1585 if (atomisp_alloc_dis_coef_buf(asd)) { 1586 dev_err(isp->dev, 1587 "Failed to allocate memory for DIS statistics\n"); 1588 goto err; 1589 } 1590 1591 if (atomisp_alloc_metadata_output_buf(asd)) { 1592 dev_err(isp->dev, "Failed to allocate memory for metadata\n"); 1593 goto err; 1594 } 1595 1596 return; 1597 1598 err: 1599 atomisp_css_free_stat_buffers(asd); 1600 return; 1601 } 1602 1603 static void atomisp_curr_user_grid_info(struct atomisp_sub_device *asd, 1604 struct atomisp_grid_info *info) 1605 { 1606 memcpy(info, &asd->params.curr_grid_info.s3a_grid, 1607 sizeof(struct ia_css_3a_grid_info)); 1608 } 1609 1610 int atomisp_compare_grid(struct atomisp_sub_device *asd, 1611 struct atomisp_grid_info *atomgrid) 1612 { 1613 struct atomisp_grid_info tmp = {0}; 1614 1615 atomisp_curr_user_grid_info(asd, &tmp); 1616 return memcmp(atomgrid, &tmp, sizeof(tmp)); 1617 } 1618 1619 /* 1620 * Function to update Gdc table for gdc 1621 */ 1622 int atomisp_gdc_cac_table(struct atomisp_sub_device *asd, int flag, 1623 struct atomisp_morph_table *config) 1624 { 1625 int ret; 1626 int i; 1627 struct atomisp_device *isp = asd->isp; 1628 1629 if (flag == 0) { 1630 /* Get gdc table from current setup */ 1631 struct ia_css_morph_table tab = {0}; 1632 1633 atomisp_css_get_morph_table(asd, &tab); 1634 1635 config->width = tab.width; 1636 config->height = tab.height; 1637 1638 for (i = 0; i < IA_CSS_MORPH_TABLE_NUM_PLANES; i++) { 1639 ret = copy_to_user(config->coordinates_x[i], 1640 tab.coordinates_x[i], tab.height * 1641 tab.width * sizeof(*tab.coordinates_x[i])); 1642 if (ret) { 1643 dev_err(isp->dev, 1644 "Failed to copy to User for x\n"); 1645 return -EFAULT; 1646 } 1647 ret = copy_to_user(config->coordinates_y[i], 1648 tab.coordinates_y[i], tab.height * 1649 tab.width * sizeof(*tab.coordinates_y[i])); 1650 if (ret) { 1651 dev_err(isp->dev, 1652 "Failed to copy to User for y\n"); 1653 return -EFAULT; 1654 } 1655 } 1656 } else { 1657 struct ia_css_morph_table *tab = 1658 asd->params.css_param.morph_table; 1659 1660 /* free first if we have one */ 1661 if (tab) { 1662 atomisp_css_morph_table_free(tab); 1663 asd->params.css_param.morph_table = NULL; 1664 } 1665 1666 /* allocate new one */ 1667 tab = atomisp_css_morph_table_allocate(config->width, 1668 config->height); 1669 1670 if (!tab) { 1671 dev_err(isp->dev, "out of memory\n"); 1672 return -EINVAL; 1673 } 1674 1675 for (i = 0; i < IA_CSS_MORPH_TABLE_NUM_PLANES; i++) { 1676 ret = copy_from_user(tab->coordinates_x[i], 1677 config->coordinates_x[i], 1678 config->height * config->width * 1679 sizeof(*config->coordinates_x[i])); 1680 if (ret) { 1681 dev_err(isp->dev, 1682 "Failed to copy from User for x, ret %d\n", 1683 ret); 1684 atomisp_css_morph_table_free(tab); 1685 return -EFAULT; 1686 } 1687 ret = copy_from_user(tab->coordinates_y[i], 1688 config->coordinates_y[i], 1689 config->height * config->width * 1690 sizeof(*config->coordinates_y[i])); 1691 if (ret) { 1692 dev_err(isp->dev, 1693 "Failed to copy from User for y, ret is %d\n", 1694 ret); 1695 atomisp_css_morph_table_free(tab); 1696 return -EFAULT; 1697 } 1698 } 1699 asd->params.css_param.morph_table = tab; 1700 if (asd->params.gdc_cac_en) 1701 asd->params.config.morph_table = tab; 1702 } 1703 1704 return 0; 1705 } 1706 1707 int atomisp_macc_table(struct atomisp_sub_device *asd, int flag, 1708 struct atomisp_macc_config *config) 1709 { 1710 struct ia_css_macc_table *macc_table; 1711 1712 switch (config->color_effect) { 1713 case V4L2_COLORFX_NONE: 1714 macc_table = &asd->params.css_param.macc_table; 1715 break; 1716 case V4L2_COLORFX_SKY_BLUE: 1717 macc_table = &blue_macc_table; 1718 break; 1719 case V4L2_COLORFX_GRASS_GREEN: 1720 macc_table = &green_macc_table; 1721 break; 1722 case V4L2_COLORFX_SKIN_WHITEN_LOW: 1723 macc_table = &skin_low_macc_table; 1724 break; 1725 case V4L2_COLORFX_SKIN_WHITEN: 1726 macc_table = &skin_medium_macc_table; 1727 break; 1728 case V4L2_COLORFX_SKIN_WHITEN_HIGH: 1729 macc_table = &skin_high_macc_table; 1730 break; 1731 default: 1732 return -EINVAL; 1733 } 1734 1735 if (flag == 0) { 1736 /* Get macc table from current setup */ 1737 memcpy(&config->table, macc_table, 1738 sizeof(struct ia_css_macc_table)); 1739 } else { 1740 memcpy(macc_table, &config->table, 1741 sizeof(struct ia_css_macc_table)); 1742 if (config->color_effect == asd->params.color_effect) 1743 asd->params.config.macc_table = macc_table; 1744 } 1745 1746 return 0; 1747 } 1748 1749 int atomisp_set_dis_vector(struct atomisp_sub_device *asd, 1750 struct atomisp_dis_vector *vector) 1751 { 1752 atomisp_css_video_set_dis_vector(asd, vector); 1753 1754 asd->params.dis_proj_data_valid = false; 1755 asd->params.css_update_params_needed = true; 1756 return 0; 1757 } 1758 1759 /* 1760 * Function to set/get image stablization statistics 1761 */ 1762 int atomisp_get_dis_stat(struct atomisp_sub_device *asd, 1763 struct atomisp_dis_statistics *stats) 1764 { 1765 return atomisp_css_get_dis_stat(asd, stats); 1766 } 1767 1768 /* 1769 * Function set camrea_prefiles.xml current sensor pixel array size 1770 */ 1771 int atomisp_set_array_res(struct atomisp_sub_device *asd, 1772 struct atomisp_resolution *config) 1773 { 1774 dev_dbg(asd->isp->dev, ">%s start\n", __func__); 1775 if (!config) { 1776 dev_err(asd->isp->dev, "Set sensor array size is not valid\n"); 1777 return -EINVAL; 1778 } 1779 1780 asd->sensor_array_res.width = config->width; 1781 asd->sensor_array_res.height = config->height; 1782 return 0; 1783 } 1784 1785 /* 1786 * Function to get DVS2 BQ resolution settings 1787 */ 1788 int atomisp_get_dvs2_bq_resolutions(struct atomisp_sub_device *asd, 1789 struct atomisp_dvs2_bq_resolutions *bq_res) 1790 { 1791 struct ia_css_pipe_config *pipe_cfg = NULL; 1792 1793 struct ia_css_stream *stream = 1794 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream; 1795 if (!stream) { 1796 dev_warn(asd->isp->dev, "stream is not created"); 1797 return -EAGAIN; 1798 } 1799 1800 pipe_cfg = &asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL] 1801 .pipe_configs[IA_CSS_PIPE_ID_VIDEO]; 1802 1803 if (!bq_res) 1804 return -EINVAL; 1805 1806 /* the GDC output resolution */ 1807 bq_res->output_bq.width_bq = pipe_cfg->output_info[0].res.width / 2; 1808 bq_res->output_bq.height_bq = pipe_cfg->output_info[0].res.height / 2; 1809 1810 bq_res->envelope_bq.width_bq = 0; 1811 bq_res->envelope_bq.height_bq = 0; 1812 /* the GDC input resolution */ 1813 bq_res->source_bq.width_bq = bq_res->output_bq.width_bq + 1814 pipe_cfg->dvs_envelope.width / 2; 1815 bq_res->source_bq.height_bq = bq_res->output_bq.height_bq + 1816 pipe_cfg->dvs_envelope.height / 2; 1817 /* 1818 * Bad pixels caused by spatial filter processing 1819 * ISP filter resolution should be given by CSS/FW, but for now 1820 * there is not such API to query, and it is fixed value, so 1821 * hardcoded here. 1822 */ 1823 bq_res->ispfilter_bq.width_bq = 12 / 2; 1824 bq_res->ispfilter_bq.height_bq = 12 / 2; 1825 /* spatial filter shift, always 4 pixels */ 1826 bq_res->gdc_shift_bq.width_bq = 4 / 2; 1827 bq_res->gdc_shift_bq.height_bq = 4 / 2; 1828 1829 if (asd->params.video_dis_en) { 1830 bq_res->envelope_bq.width_bq = pipe_cfg->dvs_envelope.width / 2 - 1831 bq_res->ispfilter_bq.width_bq; 1832 bq_res->envelope_bq.height_bq = pipe_cfg->dvs_envelope.height / 2 - 1833 bq_res->ispfilter_bq.height_bq; 1834 } 1835 1836 dev_dbg(asd->isp->dev, 1837 "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", 1838 bq_res->source_bq.width_bq, bq_res->source_bq.height_bq, 1839 bq_res->ispfilter_bq.width_bq, bq_res->ispfilter_bq.height_bq, 1840 bq_res->gdc_shift_bq.width_bq, bq_res->gdc_shift_bq.height_bq, 1841 bq_res->envelope_bq.width_bq, bq_res->envelope_bq.height_bq, 1842 bq_res->output_bq.width_bq, bq_res->output_bq.height_bq); 1843 1844 return 0; 1845 } 1846 1847 int atomisp_set_dis_coefs(struct atomisp_sub_device *asd, 1848 struct atomisp_dis_coefficients *coefs) 1849 { 1850 return atomisp_css_set_dis_coefs(asd, coefs); 1851 } 1852 1853 /* 1854 * Function to set/get 3A stat from isp 1855 */ 1856 int atomisp_3a_stat(struct atomisp_sub_device *asd, int flag, 1857 struct atomisp_3a_statistics *config) 1858 { 1859 struct atomisp_device *isp = asd->isp; 1860 struct atomisp_s3a_buf *s3a_buf; 1861 unsigned long ret; 1862 1863 if (flag != 0) 1864 return -EINVAL; 1865 1866 /* sanity check to avoid writing into unallocated memory. */ 1867 if (asd->params.s3a_output_bytes == 0) 1868 return -EINVAL; 1869 1870 if (atomisp_compare_grid(asd, &config->grid_info) != 0) { 1871 /* If the grid info in the argument differs from the current 1872 grid info, we tell the caller to reset the grid size and 1873 try again. */ 1874 return -EAGAIN; 1875 } 1876 1877 if (list_empty(&asd->s3a_stats_ready)) { 1878 dev_err(isp->dev, "3a statistics is not valid.\n"); 1879 return -EAGAIN; 1880 } 1881 1882 s3a_buf = list_entry(asd->s3a_stats_ready.next, 1883 struct atomisp_s3a_buf, list); 1884 if (s3a_buf->s3a_map) 1885 ia_css_translate_3a_statistics( 1886 asd->params.s3a_user_stat, s3a_buf->s3a_map); 1887 else 1888 ia_css_get_3a_statistics(asd->params.s3a_user_stat, 1889 s3a_buf->s3a_data); 1890 1891 config->exp_id = s3a_buf->s3a_data->exp_id; 1892 config->isp_config_id = s3a_buf->s3a_data->isp_config_id; 1893 1894 ret = copy_to_user(config->data, asd->params.s3a_user_stat->data, 1895 asd->params.s3a_output_bytes); 1896 if (ret) { 1897 dev_err(isp->dev, "copy to user failed: copied %lu bytes\n", 1898 ret); 1899 return -EFAULT; 1900 } 1901 1902 /* Move to free buffer list */ 1903 list_del_init(&s3a_buf->list); 1904 list_add_tail(&s3a_buf->list, &asd->s3a_stats); 1905 dev_dbg(isp->dev, "%s: finish getting exp_id %d 3a stat, isp_config_id %d\n", 1906 __func__, 1907 config->exp_id, config->isp_config_id); 1908 return 0; 1909 } 1910 1911 int atomisp_get_metadata(struct atomisp_sub_device *asd, int flag, 1912 struct atomisp_metadata *md) 1913 { 1914 struct atomisp_device *isp = asd->isp; 1915 struct ia_css_stream_info *stream_info; 1916 struct camera_mipi_info *mipi_info; 1917 struct atomisp_metadata_buf *md_buf; 1918 enum atomisp_metadata_type md_type = ATOMISP_MAIN_METADATA; 1919 int ret, i; 1920 1921 if (flag != 0) 1922 return -EINVAL; 1923 1924 stream_info = &asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]. 1925 stream_info; 1926 1927 /* We always return the resolution and stride even if there is 1928 * no valid metadata. This allows the caller to get the information 1929 * needed to allocate user-space buffers. */ 1930 md->width = stream_info->metadata_info.resolution.width; 1931 md->height = stream_info->metadata_info.resolution.height; 1932 md->stride = stream_info->metadata_info.stride; 1933 1934 /* sanity check to avoid writing into unallocated memory. 1935 * This does not return an error because it is a valid way 1936 * for applications to detect that metadata is not enabled. */ 1937 if (md->width == 0 || md->height == 0 || !md->data) 1938 return 0; 1939 1940 /* This is done in the atomisp_buf_done() */ 1941 if (list_empty(&asd->metadata_ready[md_type])) { 1942 dev_warn(isp->dev, "Metadata queue is empty now!\n"); 1943 return -EAGAIN; 1944 } 1945 1946 mipi_info = atomisp_to_sensor_mipi_info( 1947 isp->inputs[asd->input_curr].camera); 1948 if (!mipi_info) 1949 return -EINVAL; 1950 1951 if (mipi_info->metadata_effective_width) { 1952 for (i = 0; i < md->height; i++) 1953 md->effective_width[i] = 1954 mipi_info->metadata_effective_width[i]; 1955 } 1956 1957 md_buf = list_entry(asd->metadata_ready[md_type].next, 1958 struct atomisp_metadata_buf, list); 1959 md->exp_id = md_buf->metadata->exp_id; 1960 if (md_buf->md_vptr) { 1961 ret = copy_to_user(md->data, 1962 md_buf->md_vptr, 1963 stream_info->metadata_info.size); 1964 } else { 1965 hmm_load(md_buf->metadata->address, 1966 asd->params.metadata_user[md_type], 1967 stream_info->metadata_info.size); 1968 1969 ret = copy_to_user(md->data, 1970 asd->params.metadata_user[md_type], 1971 stream_info->metadata_info.size); 1972 } 1973 if (ret) { 1974 dev_err(isp->dev, "copy to user failed: copied %d bytes\n", 1975 ret); 1976 return -EFAULT; 1977 } 1978 1979 list_del_init(&md_buf->list); 1980 list_add_tail(&md_buf->list, &asd->metadata[md_type]); 1981 1982 dev_dbg(isp->dev, "%s: HAL de-queued metadata type %d with exp_id %d\n", 1983 __func__, md_type, md->exp_id); 1984 return 0; 1985 } 1986 1987 int atomisp_get_metadata_by_type(struct atomisp_sub_device *asd, int flag, 1988 struct atomisp_metadata_with_type *md) 1989 { 1990 struct atomisp_device *isp = asd->isp; 1991 struct ia_css_stream_info *stream_info; 1992 struct camera_mipi_info *mipi_info; 1993 struct atomisp_metadata_buf *md_buf; 1994 enum atomisp_metadata_type md_type; 1995 int ret, i; 1996 1997 if (flag != 0) 1998 return -EINVAL; 1999 2000 stream_info = &asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]. 2001 stream_info; 2002 2003 /* We always return the resolution and stride even if there is 2004 * no valid metadata. This allows the caller to get the information 2005 * needed to allocate user-space buffers. */ 2006 md->width = stream_info->metadata_info.resolution.width; 2007 md->height = stream_info->metadata_info.resolution.height; 2008 md->stride = stream_info->metadata_info.stride; 2009 2010 /* sanity check to avoid writing into unallocated memory. 2011 * This does not return an error because it is a valid way 2012 * for applications to detect that metadata is not enabled. */ 2013 if (md->width == 0 || md->height == 0 || !md->data) 2014 return 0; 2015 2016 md_type = md->type; 2017 if (md_type < 0 || md_type >= ATOMISP_METADATA_TYPE_NUM) 2018 return -EINVAL; 2019 2020 /* This is done in the atomisp_buf_done() */ 2021 if (list_empty(&asd->metadata_ready[md_type])) { 2022 dev_warn(isp->dev, "Metadata queue is empty now!\n"); 2023 return -EAGAIN; 2024 } 2025 2026 mipi_info = atomisp_to_sensor_mipi_info( 2027 isp->inputs[asd->input_curr].camera); 2028 if (!mipi_info) 2029 return -EINVAL; 2030 2031 if (mipi_info->metadata_effective_width) { 2032 for (i = 0; i < md->height; i++) 2033 md->effective_width[i] = 2034 mipi_info->metadata_effective_width[i]; 2035 } 2036 2037 md_buf = list_entry(asd->metadata_ready[md_type].next, 2038 struct atomisp_metadata_buf, list); 2039 md->exp_id = md_buf->metadata->exp_id; 2040 if (md_buf->md_vptr) { 2041 ret = copy_to_user(md->data, 2042 md_buf->md_vptr, 2043 stream_info->metadata_info.size); 2044 } else { 2045 hmm_load(md_buf->metadata->address, 2046 asd->params.metadata_user[md_type], 2047 stream_info->metadata_info.size); 2048 2049 ret = copy_to_user(md->data, 2050 asd->params.metadata_user[md_type], 2051 stream_info->metadata_info.size); 2052 } 2053 if (ret) { 2054 dev_err(isp->dev, "copy to user failed: copied %d bytes\n", 2055 ret); 2056 return -EFAULT; 2057 } else { 2058 list_del_init(&md_buf->list); 2059 list_add_tail(&md_buf->list, &asd->metadata[md_type]); 2060 } 2061 dev_dbg(isp->dev, "%s: HAL de-queued metadata type %d with exp_id %d\n", 2062 __func__, md_type, md->exp_id); 2063 return 0; 2064 } 2065 2066 /* 2067 * Function to calculate real zoom region for every pipe 2068 */ 2069 int atomisp_calculate_real_zoom_region(struct atomisp_sub_device *asd, 2070 struct ia_css_dz_config *dz_config, 2071 enum ia_css_pipe_id css_pipe_id) 2072 2073 { 2074 struct atomisp_stream_env *stream_env = 2075 &asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]; 2076 struct atomisp_resolution eff_res, out_res; 2077 int w_offset, h_offset; 2078 2079 memset(&eff_res, 0, sizeof(eff_res)); 2080 memset(&out_res, 0, sizeof(out_res)); 2081 2082 if (dz_config->dx || dz_config->dy) 2083 return 0; 2084 2085 if (css_pipe_id != IA_CSS_PIPE_ID_PREVIEW 2086 && css_pipe_id != IA_CSS_PIPE_ID_CAPTURE) { 2087 dev_err(asd->isp->dev, "%s the set pipe no support crop region" 2088 , __func__); 2089 return -EINVAL; 2090 } 2091 2092 eff_res.width = 2093 stream_env->stream_config.input_config.effective_res.width; 2094 eff_res.height = 2095 stream_env->stream_config.input_config.effective_res.height; 2096 if (eff_res.width == 0 || eff_res.height == 0) { 2097 dev_err(asd->isp->dev, "%s err effective resolution" 2098 , __func__); 2099 return -EINVAL; 2100 } 2101 2102 if (dz_config->zoom_region.resolution.width 2103 == asd->sensor_array_res.width 2104 || dz_config->zoom_region.resolution.height 2105 == asd->sensor_array_res.height) { 2106 /*no need crop region*/ 2107 dz_config->zoom_region.origin.x = 0; 2108 dz_config->zoom_region.origin.y = 0; 2109 dz_config->zoom_region.resolution.width = eff_res.width; 2110 dz_config->zoom_region.resolution.height = eff_res.height; 2111 return 0; 2112 } 2113 2114 /* FIXME: 2115 * This is not the correct implementation with Google's definition, due 2116 * to firmware limitation. 2117 * map real crop region base on above calculating base max crop region. 2118 */ 2119 2120 if (!IS_ISP2401) { 2121 dz_config->zoom_region.origin.x = dz_config->zoom_region.origin.x 2122 * eff_res.width 2123 / asd->sensor_array_res.width; 2124 dz_config->zoom_region.origin.y = dz_config->zoom_region.origin.y 2125 * eff_res.height 2126 / asd->sensor_array_res.height; 2127 dz_config->zoom_region.resolution.width = dz_config->zoom_region.resolution.width 2128 * eff_res.width 2129 / asd->sensor_array_res.width; 2130 dz_config->zoom_region.resolution.height = dz_config->zoom_region.resolution.height 2131 * eff_res.height 2132 / asd->sensor_array_res.height; 2133 /* 2134 * Set same ratio of crop region resolution and current pipe output 2135 * resolution 2136 */ 2137 out_res.width = stream_env->pipe_configs[css_pipe_id].output_info[0].res.width; 2138 out_res.height = stream_env->pipe_configs[css_pipe_id].output_info[0].res.height; 2139 if (out_res.width == 0 || out_res.height == 0) { 2140 dev_err(asd->isp->dev, "%s err current pipe output resolution" 2141 , __func__); 2142 return -EINVAL; 2143 } 2144 } else { 2145 out_res.width = stream_env->pipe_configs[css_pipe_id].output_info[0].res.width; 2146 out_res.height = stream_env->pipe_configs[css_pipe_id].output_info[0].res.height; 2147 if (out_res.width == 0 || out_res.height == 0) { 2148 dev_err(asd->isp->dev, "%s err current pipe output resolution" 2149 , __func__); 2150 return -EINVAL; 2151 } 2152 2153 if (asd->sensor_array_res.width * out_res.height 2154 < out_res.width * asd->sensor_array_res.height) { 2155 h_offset = asd->sensor_array_res.height 2156 - asd->sensor_array_res.width 2157 * out_res.height / out_res.width; 2158 h_offset = h_offset / 2; 2159 if (dz_config->zoom_region.origin.y < h_offset) 2160 dz_config->zoom_region.origin.y = 0; 2161 else 2162 dz_config->zoom_region.origin.y = dz_config->zoom_region.origin.y - h_offset; 2163 w_offset = 0; 2164 } else { 2165 w_offset = asd->sensor_array_res.width 2166 - asd->sensor_array_res.height 2167 * out_res.width / out_res.height; 2168 w_offset = w_offset / 2; 2169 if (dz_config->zoom_region.origin.x < w_offset) 2170 dz_config->zoom_region.origin.x = 0; 2171 else 2172 dz_config->zoom_region.origin.x = dz_config->zoom_region.origin.x - w_offset; 2173 h_offset = 0; 2174 } 2175 dz_config->zoom_region.origin.x = dz_config->zoom_region.origin.x 2176 * eff_res.width 2177 / (asd->sensor_array_res.width - 2 * w_offset); 2178 dz_config->zoom_region.origin.y = dz_config->zoom_region.origin.y 2179 * eff_res.height 2180 / (asd->sensor_array_res.height - 2 * h_offset); 2181 dz_config->zoom_region.resolution.width = dz_config->zoom_region.resolution.width 2182 * eff_res.width 2183 / (asd->sensor_array_res.width - 2 * w_offset); 2184 dz_config->zoom_region.resolution.height = dz_config->zoom_region.resolution.height 2185 * eff_res.height 2186 / (asd->sensor_array_res.height - 2 * h_offset); 2187 } 2188 2189 if (out_res.width * dz_config->zoom_region.resolution.height 2190 > dz_config->zoom_region.resolution.width * out_res.height) { 2191 dz_config->zoom_region.resolution.height = 2192 dz_config->zoom_region.resolution.width 2193 * out_res.height / out_res.width; 2194 } else { 2195 dz_config->zoom_region.resolution.width = 2196 dz_config->zoom_region.resolution.height 2197 * out_res.width / out_res.height; 2198 } 2199 dev_dbg(asd->isp->dev, 2200 "%s crop region:(%d,%d),(%d,%d) eff_res(%d, %d) array_size(%d,%d) out_res(%d, %d)\n", 2201 __func__, dz_config->zoom_region.origin.x, 2202 dz_config->zoom_region.origin.y, 2203 dz_config->zoom_region.resolution.width, 2204 dz_config->zoom_region.resolution.height, 2205 eff_res.width, eff_res.height, 2206 asd->sensor_array_res.width, 2207 asd->sensor_array_res.height, 2208 out_res.width, out_res.height); 2209 2210 if ((dz_config->zoom_region.origin.x + 2211 dz_config->zoom_region.resolution.width 2212 > eff_res.width) || 2213 (dz_config->zoom_region.origin.y + 2214 dz_config->zoom_region.resolution.height 2215 > eff_res.height)) 2216 return -EINVAL; 2217 2218 return 0; 2219 } 2220 2221 /* 2222 * Function to check the zoom region whether is effective 2223 */ 2224 static bool atomisp_check_zoom_region( 2225 struct atomisp_sub_device *asd, 2226 struct ia_css_dz_config *dz_config) 2227 { 2228 struct atomisp_resolution config; 2229 bool flag = false; 2230 unsigned int w, h; 2231 2232 memset(&config, 0, sizeof(struct atomisp_resolution)); 2233 2234 if (dz_config->dx && dz_config->dy) 2235 return true; 2236 2237 config.width = asd->sensor_array_res.width; 2238 config.height = asd->sensor_array_res.height; 2239 w = dz_config->zoom_region.origin.x + 2240 dz_config->zoom_region.resolution.width; 2241 h = dz_config->zoom_region.origin.y + 2242 dz_config->zoom_region.resolution.height; 2243 2244 if ((w <= config.width) && (h <= config.height) && w > 0 && h > 0) 2245 flag = true; 2246 else 2247 /* setting error zoom region */ 2248 dev_err(asd->isp->dev, 2249 "%s zoom region ERROR:dz_config:(%d,%d),(%d,%d)array_res(%d, %d)\n", 2250 __func__, dz_config->zoom_region.origin.x, 2251 dz_config->zoom_region.origin.y, 2252 dz_config->zoom_region.resolution.width, 2253 dz_config->zoom_region.resolution.height, 2254 config.width, config.height); 2255 2256 return flag; 2257 } 2258 2259 void atomisp_apply_css_parameters( 2260 struct atomisp_sub_device *asd, 2261 struct atomisp_css_params *css_param) 2262 { 2263 if (css_param->update_flag.wb_config) 2264 asd->params.config.wb_config = &css_param->wb_config; 2265 2266 if (css_param->update_flag.ob_config) 2267 asd->params.config.ob_config = &css_param->ob_config; 2268 2269 if (css_param->update_flag.dp_config) 2270 asd->params.config.dp_config = &css_param->dp_config; 2271 2272 if (css_param->update_flag.nr_config) 2273 asd->params.config.nr_config = &css_param->nr_config; 2274 2275 if (css_param->update_flag.ee_config) 2276 asd->params.config.ee_config = &css_param->ee_config; 2277 2278 if (css_param->update_flag.tnr_config) 2279 asd->params.config.tnr_config = &css_param->tnr_config; 2280 2281 if (css_param->update_flag.a3a_config) 2282 asd->params.config.s3a_config = &css_param->s3a_config; 2283 2284 if (css_param->update_flag.ctc_config) 2285 asd->params.config.ctc_config = &css_param->ctc_config; 2286 2287 if (css_param->update_flag.cnr_config) 2288 asd->params.config.cnr_config = &css_param->cnr_config; 2289 2290 if (css_param->update_flag.ecd_config) 2291 asd->params.config.ecd_config = &css_param->ecd_config; 2292 2293 if (css_param->update_flag.ynr_config) 2294 asd->params.config.ynr_config = &css_param->ynr_config; 2295 2296 if (css_param->update_flag.fc_config) 2297 asd->params.config.fc_config = &css_param->fc_config; 2298 2299 if (css_param->update_flag.macc_config) 2300 asd->params.config.macc_config = &css_param->macc_config; 2301 2302 if (css_param->update_flag.aa_config) 2303 asd->params.config.aa_config = &css_param->aa_config; 2304 2305 if (css_param->update_flag.anr_config) 2306 asd->params.config.anr_config = &css_param->anr_config; 2307 2308 if (css_param->update_flag.xnr_config) 2309 asd->params.config.xnr_config = &css_param->xnr_config; 2310 2311 if (css_param->update_flag.yuv2rgb_cc_config) 2312 asd->params.config.yuv2rgb_cc_config = &css_param->yuv2rgb_cc_config; 2313 2314 if (css_param->update_flag.rgb2yuv_cc_config) 2315 asd->params.config.rgb2yuv_cc_config = &css_param->rgb2yuv_cc_config; 2316 2317 if (css_param->update_flag.macc_table) 2318 asd->params.config.macc_table = &css_param->macc_table; 2319 2320 if (css_param->update_flag.xnr_table) 2321 asd->params.config.xnr_table = &css_param->xnr_table; 2322 2323 if (css_param->update_flag.r_gamma_table) 2324 asd->params.config.r_gamma_table = &css_param->r_gamma_table; 2325 2326 if (css_param->update_flag.g_gamma_table) 2327 asd->params.config.g_gamma_table = &css_param->g_gamma_table; 2328 2329 if (css_param->update_flag.b_gamma_table) 2330 asd->params.config.b_gamma_table = &css_param->b_gamma_table; 2331 2332 if (css_param->update_flag.anr_thres) 2333 atomisp_css_set_anr_thres(asd, &css_param->anr_thres); 2334 2335 if (css_param->update_flag.shading_table) 2336 asd->params.config.shading_table = css_param->shading_table; 2337 2338 if (css_param->update_flag.morph_table && asd->params.gdc_cac_en) 2339 asd->params.config.morph_table = css_param->morph_table; 2340 2341 if (css_param->update_flag.dvs2_coefs) { 2342 struct ia_css_dvs_grid_info *dvs_grid_info = 2343 atomisp_css_get_dvs_grid_info( 2344 &asd->params.curr_grid_info); 2345 2346 if (dvs_grid_info && dvs_grid_info->enable) 2347 atomisp_css_set_dvs2_coefs(asd, css_param->dvs2_coeff); 2348 } 2349 2350 if (css_param->update_flag.dvs_6axis_config) 2351 atomisp_css_set_dvs_6axis(asd, css_param->dvs_6axis); 2352 2353 atomisp_css_set_isp_config_id(asd, css_param->isp_config_id); 2354 /* 2355 * These configurations are on used by ISP1.x, not for ISP2.x, 2356 * so do not handle them. see comments of ia_css_isp_config. 2357 * 1 cc_config 2358 * 2 ce_config 2359 * 3 de_config 2360 * 4 gc_config 2361 * 5 gamma_table 2362 * 6 ctc_table 2363 * 7 dvs_coefs 2364 */ 2365 } 2366 2367 static unsigned int long copy_from_compatible(void *to, const void *from, 2368 unsigned long n, bool from_user) 2369 { 2370 if (from_user) 2371 return copy_from_user(to, (void __user *)from, n); 2372 else 2373 memcpy(to, from, n); 2374 return 0; 2375 } 2376 2377 int atomisp_cp_general_isp_parameters(struct atomisp_sub_device *asd, 2378 struct atomisp_parameters *arg, 2379 struct atomisp_css_params *css_param, 2380 bool from_user) 2381 { 2382 struct atomisp_parameters *cur_config = &css_param->update_flag; 2383 2384 if (!arg || !asd || !css_param) 2385 return -EINVAL; 2386 2387 if (arg->wb_config && (from_user || !cur_config->wb_config)) { 2388 if (copy_from_compatible(&css_param->wb_config, arg->wb_config, 2389 sizeof(struct ia_css_wb_config), 2390 from_user)) 2391 return -EFAULT; 2392 css_param->update_flag.wb_config = 2393 (struct atomisp_wb_config *)&css_param->wb_config; 2394 } 2395 2396 if (arg->ob_config && (from_user || !cur_config->ob_config)) { 2397 if (copy_from_compatible(&css_param->ob_config, arg->ob_config, 2398 sizeof(struct ia_css_ob_config), 2399 from_user)) 2400 return -EFAULT; 2401 css_param->update_flag.ob_config = 2402 (struct atomisp_ob_config *)&css_param->ob_config; 2403 } 2404 2405 if (arg->dp_config && (from_user || !cur_config->dp_config)) { 2406 if (copy_from_compatible(&css_param->dp_config, arg->dp_config, 2407 sizeof(struct ia_css_dp_config), 2408 from_user)) 2409 return -EFAULT; 2410 css_param->update_flag.dp_config = 2411 (struct atomisp_dp_config *)&css_param->dp_config; 2412 } 2413 2414 if (asd->run_mode->val != ATOMISP_RUN_MODE_VIDEO) { 2415 if (arg->dz_config && (from_user || !cur_config->dz_config)) { 2416 if (copy_from_compatible(&css_param->dz_config, 2417 arg->dz_config, 2418 sizeof(struct ia_css_dz_config), 2419 from_user)) 2420 return -EFAULT; 2421 if (!atomisp_check_zoom_region(asd, 2422 &css_param->dz_config)) { 2423 dev_err(asd->isp->dev, "crop region error!"); 2424 return -EINVAL; 2425 } 2426 css_param->update_flag.dz_config = 2427 (struct atomisp_dz_config *) 2428 &css_param->dz_config; 2429 } 2430 } 2431 2432 if (arg->nr_config && (from_user || !cur_config->nr_config)) { 2433 if (copy_from_compatible(&css_param->nr_config, arg->nr_config, 2434 sizeof(struct ia_css_nr_config), 2435 from_user)) 2436 return -EFAULT; 2437 css_param->update_flag.nr_config = 2438 (struct atomisp_nr_config *)&css_param->nr_config; 2439 } 2440 2441 if (arg->ee_config && (from_user || !cur_config->ee_config)) { 2442 if (copy_from_compatible(&css_param->ee_config, arg->ee_config, 2443 sizeof(struct ia_css_ee_config), 2444 from_user)) 2445 return -EFAULT; 2446 css_param->update_flag.ee_config = 2447 (struct atomisp_ee_config *)&css_param->ee_config; 2448 } 2449 2450 if (arg->tnr_config && (from_user || !cur_config->tnr_config)) { 2451 if (copy_from_compatible(&css_param->tnr_config, 2452 arg->tnr_config, 2453 sizeof(struct ia_css_tnr_config), 2454 from_user)) 2455 return -EFAULT; 2456 css_param->update_flag.tnr_config = 2457 (struct atomisp_tnr_config *) 2458 &css_param->tnr_config; 2459 } 2460 2461 if (arg->a3a_config && (from_user || !cur_config->a3a_config)) { 2462 if (copy_from_compatible(&css_param->s3a_config, 2463 arg->a3a_config, 2464 sizeof(struct ia_css_3a_config), 2465 from_user)) 2466 return -EFAULT; 2467 css_param->update_flag.a3a_config = 2468 (struct atomisp_3a_config *)&css_param->s3a_config; 2469 } 2470 2471 if (arg->ctc_config && (from_user || !cur_config->ctc_config)) { 2472 if (copy_from_compatible(&css_param->ctc_config, 2473 arg->ctc_config, 2474 sizeof(struct ia_css_ctc_config), 2475 from_user)) 2476 return -EFAULT; 2477 css_param->update_flag.ctc_config = 2478 (struct atomisp_ctc_config *) 2479 &css_param->ctc_config; 2480 } 2481 2482 if (arg->cnr_config && (from_user || !cur_config->cnr_config)) { 2483 if (copy_from_compatible(&css_param->cnr_config, 2484 arg->cnr_config, 2485 sizeof(struct ia_css_cnr_config), 2486 from_user)) 2487 return -EFAULT; 2488 css_param->update_flag.cnr_config = 2489 (struct atomisp_cnr_config *) 2490 &css_param->cnr_config; 2491 } 2492 2493 if (arg->ecd_config && (from_user || !cur_config->ecd_config)) { 2494 if (copy_from_compatible(&css_param->ecd_config, 2495 arg->ecd_config, 2496 sizeof(struct ia_css_ecd_config), 2497 from_user)) 2498 return -EFAULT; 2499 css_param->update_flag.ecd_config = 2500 (struct atomisp_ecd_config *) 2501 &css_param->ecd_config; 2502 } 2503 2504 if (arg->ynr_config && (from_user || !cur_config->ynr_config)) { 2505 if (copy_from_compatible(&css_param->ynr_config, 2506 arg->ynr_config, 2507 sizeof(struct ia_css_ynr_config), 2508 from_user)) 2509 return -EFAULT; 2510 css_param->update_flag.ynr_config = 2511 (struct atomisp_ynr_config *) 2512 &css_param->ynr_config; 2513 } 2514 2515 if (arg->fc_config && (from_user || !cur_config->fc_config)) { 2516 if (copy_from_compatible(&css_param->fc_config, 2517 arg->fc_config, 2518 sizeof(struct ia_css_fc_config), 2519 from_user)) 2520 return -EFAULT; 2521 css_param->update_flag.fc_config = 2522 (struct atomisp_fc_config *)&css_param->fc_config; 2523 } 2524 2525 if (arg->macc_config && (from_user || !cur_config->macc_config)) { 2526 if (copy_from_compatible(&css_param->macc_config, 2527 arg->macc_config, 2528 sizeof(struct ia_css_macc_config), 2529 from_user)) 2530 return -EFAULT; 2531 css_param->update_flag.macc_config = 2532 (struct atomisp_macc_config *) 2533 &css_param->macc_config; 2534 } 2535 2536 if (arg->aa_config && (from_user || !cur_config->aa_config)) { 2537 if (copy_from_compatible(&css_param->aa_config, arg->aa_config, 2538 sizeof(struct ia_css_aa_config), 2539 from_user)) 2540 return -EFAULT; 2541 css_param->update_flag.aa_config = 2542 (struct atomisp_aa_config *)&css_param->aa_config; 2543 } 2544 2545 if (arg->anr_config && (from_user || !cur_config->anr_config)) { 2546 if (copy_from_compatible(&css_param->anr_config, 2547 arg->anr_config, 2548 sizeof(struct ia_css_anr_config), 2549 from_user)) 2550 return -EFAULT; 2551 css_param->update_flag.anr_config = 2552 (struct atomisp_anr_config *) 2553 &css_param->anr_config; 2554 } 2555 2556 if (arg->xnr_config && (from_user || !cur_config->xnr_config)) { 2557 if (copy_from_compatible(&css_param->xnr_config, 2558 arg->xnr_config, 2559 sizeof(struct ia_css_xnr_config), 2560 from_user)) 2561 return -EFAULT; 2562 css_param->update_flag.xnr_config = 2563 (struct atomisp_xnr_config *) 2564 &css_param->xnr_config; 2565 } 2566 2567 if (arg->yuv2rgb_cc_config && 2568 (from_user || !cur_config->yuv2rgb_cc_config)) { 2569 if (copy_from_compatible(&css_param->yuv2rgb_cc_config, 2570 arg->yuv2rgb_cc_config, 2571 sizeof(struct ia_css_cc_config), 2572 from_user)) 2573 return -EFAULT; 2574 css_param->update_flag.yuv2rgb_cc_config = 2575 (struct atomisp_cc_config *) 2576 &css_param->yuv2rgb_cc_config; 2577 } 2578 2579 if (arg->rgb2yuv_cc_config && 2580 (from_user || !cur_config->rgb2yuv_cc_config)) { 2581 if (copy_from_compatible(&css_param->rgb2yuv_cc_config, 2582 arg->rgb2yuv_cc_config, 2583 sizeof(struct ia_css_cc_config), 2584 from_user)) 2585 return -EFAULT; 2586 css_param->update_flag.rgb2yuv_cc_config = 2587 (struct atomisp_cc_config *) 2588 &css_param->rgb2yuv_cc_config; 2589 } 2590 2591 if (arg->macc_table && (from_user || !cur_config->macc_table)) { 2592 if (copy_from_compatible(&css_param->macc_table, 2593 arg->macc_table, 2594 sizeof(struct ia_css_macc_table), 2595 from_user)) 2596 return -EFAULT; 2597 css_param->update_flag.macc_table = 2598 (struct atomisp_macc_table *) 2599 &css_param->macc_table; 2600 } 2601 2602 if (arg->xnr_table && (from_user || !cur_config->xnr_table)) { 2603 if (copy_from_compatible(&css_param->xnr_table, 2604 arg->xnr_table, 2605 sizeof(struct ia_css_xnr_table), 2606 from_user)) 2607 return -EFAULT; 2608 css_param->update_flag.xnr_table = 2609 (struct atomisp_xnr_table *)&css_param->xnr_table; 2610 } 2611 2612 if (arg->r_gamma_table && (from_user || !cur_config->r_gamma_table)) { 2613 if (copy_from_compatible(&css_param->r_gamma_table, 2614 arg->r_gamma_table, 2615 sizeof(struct ia_css_rgb_gamma_table), 2616 from_user)) 2617 return -EFAULT; 2618 css_param->update_flag.r_gamma_table = 2619 (struct atomisp_rgb_gamma_table *) 2620 &css_param->r_gamma_table; 2621 } 2622 2623 if (arg->g_gamma_table && (from_user || !cur_config->g_gamma_table)) { 2624 if (copy_from_compatible(&css_param->g_gamma_table, 2625 arg->g_gamma_table, 2626 sizeof(struct ia_css_rgb_gamma_table), 2627 from_user)) 2628 return -EFAULT; 2629 css_param->update_flag.g_gamma_table = 2630 (struct atomisp_rgb_gamma_table *) 2631 &css_param->g_gamma_table; 2632 } 2633 2634 if (arg->b_gamma_table && (from_user || !cur_config->b_gamma_table)) { 2635 if (copy_from_compatible(&css_param->b_gamma_table, 2636 arg->b_gamma_table, 2637 sizeof(struct ia_css_rgb_gamma_table), 2638 from_user)) 2639 return -EFAULT; 2640 css_param->update_flag.b_gamma_table = 2641 (struct atomisp_rgb_gamma_table *) 2642 &css_param->b_gamma_table; 2643 } 2644 2645 if (arg->anr_thres && (from_user || !cur_config->anr_thres)) { 2646 if (copy_from_compatible(&css_param->anr_thres, arg->anr_thres, 2647 sizeof(struct ia_css_anr_thres), 2648 from_user)) 2649 return -EFAULT; 2650 css_param->update_flag.anr_thres = 2651 (struct atomisp_anr_thres *)&css_param->anr_thres; 2652 } 2653 2654 if (from_user) 2655 css_param->isp_config_id = arg->isp_config_id; 2656 /* 2657 * These configurations are on used by ISP1.x, not for ISP2.x, 2658 * so do not handle them. see comments of ia_css_isp_config. 2659 * 1 cc_config 2660 * 2 ce_config 2661 * 3 de_config 2662 * 4 gc_config 2663 * 5 gamma_table 2664 * 6 ctc_table 2665 * 7 dvs_coefs 2666 */ 2667 return 0; 2668 } 2669 2670 int atomisp_cp_lsc_table(struct atomisp_sub_device *asd, 2671 struct atomisp_shading_table *source_st, 2672 struct atomisp_css_params *css_param, 2673 bool from_user) 2674 { 2675 unsigned int i; 2676 unsigned int len_table; 2677 struct ia_css_shading_table *shading_table; 2678 struct ia_css_shading_table *old_table; 2679 struct atomisp_shading_table *st, dest_st; 2680 2681 if (!source_st) 2682 return 0; 2683 2684 if (!css_param) 2685 return -EINVAL; 2686 2687 if (!from_user && css_param->update_flag.shading_table) 2688 return 0; 2689 2690 if (IS_ISP2401) { 2691 if (copy_from_compatible(&dest_st, source_st, 2692 sizeof(struct atomisp_shading_table), 2693 from_user)) { 2694 dev_err(asd->isp->dev, "copy shading table failed!"); 2695 return -EFAULT; 2696 } 2697 st = &dest_st; 2698 } else { 2699 st = source_st; 2700 } 2701 2702 old_table = css_param->shading_table; 2703 2704 /* user config is to disable the shading table. */ 2705 if (!st->enable) { 2706 /* Generate a minimum table with enable = 0. */ 2707 shading_table = atomisp_css_shading_table_alloc(1, 1); 2708 if (!shading_table) 2709 return -ENOMEM; 2710 shading_table->enable = 0; 2711 goto set_lsc; 2712 } 2713 2714 /* Setting a new table. Validate first - all tables must be set */ 2715 for (i = 0; i < ATOMISP_NUM_SC_COLORS; i++) { 2716 if (!st->data[i]) { 2717 dev_err(asd->isp->dev, "shading table validate failed"); 2718 return -EINVAL; 2719 } 2720 } 2721 2722 /* Shading table size per color */ 2723 if (st->width > SH_CSS_MAX_SCTBL_WIDTH_PER_COLOR || 2724 st->height > SH_CSS_MAX_SCTBL_HEIGHT_PER_COLOR) { 2725 dev_err(asd->isp->dev, "shading table w/h validate failed!"); 2726 return -EINVAL; 2727 } 2728 2729 shading_table = atomisp_css_shading_table_alloc(st->width, st->height); 2730 if (!shading_table) 2731 return -ENOMEM; 2732 2733 len_table = st->width * st->height * ATOMISP_SC_TYPE_SIZE; 2734 for (i = 0; i < ATOMISP_NUM_SC_COLORS; i++) { 2735 if (copy_from_compatible(shading_table->data[i], 2736 st->data[i], len_table, from_user)) { 2737 atomisp_css_shading_table_free(shading_table); 2738 return -EFAULT; 2739 } 2740 } 2741 shading_table->sensor_width = st->sensor_width; 2742 shading_table->sensor_height = st->sensor_height; 2743 shading_table->fraction_bits = st->fraction_bits; 2744 shading_table->enable = st->enable; 2745 2746 /* No need to update shading table if it is the same */ 2747 if (old_table && 2748 old_table->sensor_width == shading_table->sensor_width && 2749 old_table->sensor_height == shading_table->sensor_height && 2750 old_table->width == shading_table->width && 2751 old_table->height == shading_table->height && 2752 old_table->fraction_bits == shading_table->fraction_bits && 2753 old_table->enable == shading_table->enable) { 2754 bool data_is_same = true; 2755 2756 for (i = 0; i < ATOMISP_NUM_SC_COLORS; i++) { 2757 if (memcmp(shading_table->data[i], old_table->data[i], 2758 len_table) != 0) { 2759 data_is_same = false; 2760 break; 2761 } 2762 } 2763 2764 if (data_is_same) { 2765 atomisp_css_shading_table_free(shading_table); 2766 return 0; 2767 } 2768 } 2769 2770 set_lsc: 2771 /* set LSC to CSS */ 2772 css_param->shading_table = shading_table; 2773 css_param->update_flag.shading_table = (struct atomisp_shading_table *)shading_table; 2774 asd->params.sc_en = shading_table; 2775 2776 if (old_table) 2777 atomisp_css_shading_table_free(old_table); 2778 2779 return 0; 2780 } 2781 2782 int atomisp_css_cp_dvs2_coefs(struct atomisp_sub_device *asd, 2783 struct ia_css_dvs2_coefficients *coefs, 2784 struct atomisp_css_params *css_param, 2785 bool from_user) 2786 { 2787 struct ia_css_dvs_grid_info *cur = 2788 atomisp_css_get_dvs_grid_info(&asd->params.curr_grid_info); 2789 int dvs_hor_coef_bytes, dvs_ver_coef_bytes; 2790 struct ia_css_dvs2_coefficients dvs2_coefs; 2791 2792 if (!coefs || !cur) 2793 return 0; 2794 2795 if (!from_user && css_param->update_flag.dvs2_coefs) 2796 return 0; 2797 2798 if (!IS_ISP2401) { 2799 if (sizeof(*cur) != sizeof(coefs->grid) || 2800 memcmp(&coefs->grid, cur, sizeof(coefs->grid))) { 2801 dev_err(asd->isp->dev, "dvs grid mismatch!\n"); 2802 /* If the grid info in the argument differs from the current 2803 grid info, we tell the caller to reset the grid size and 2804 try again. */ 2805 return -EAGAIN; 2806 } 2807 2808 if (!coefs->hor_coefs.odd_real || 2809 !coefs->hor_coefs.odd_imag || 2810 !coefs->hor_coefs.even_real || 2811 !coefs->hor_coefs.even_imag || 2812 !coefs->ver_coefs.odd_real || 2813 !coefs->ver_coefs.odd_imag || 2814 !coefs->ver_coefs.even_real || 2815 !coefs->ver_coefs.even_imag) 2816 return -EINVAL; 2817 2818 if (!css_param->dvs2_coeff) { 2819 /* DIS coefficients. */ 2820 css_param->dvs2_coeff = ia_css_dvs2_coefficients_allocate(cur); 2821 if (!css_param->dvs2_coeff) 2822 return -ENOMEM; 2823 } 2824 2825 dvs_hor_coef_bytes = asd->params.dvs_hor_coef_bytes; 2826 dvs_ver_coef_bytes = asd->params.dvs_ver_coef_bytes; 2827 if (copy_from_compatible(css_param->dvs2_coeff->hor_coefs.odd_real, 2828 coefs->hor_coefs.odd_real, dvs_hor_coef_bytes, from_user) || 2829 copy_from_compatible(css_param->dvs2_coeff->hor_coefs.odd_imag, 2830 coefs->hor_coefs.odd_imag, dvs_hor_coef_bytes, from_user) || 2831 copy_from_compatible(css_param->dvs2_coeff->hor_coefs.even_real, 2832 coefs->hor_coefs.even_real, dvs_hor_coef_bytes, from_user) || 2833 copy_from_compatible(css_param->dvs2_coeff->hor_coefs.even_imag, 2834 coefs->hor_coefs.even_imag, dvs_hor_coef_bytes, from_user) || 2835 copy_from_compatible(css_param->dvs2_coeff->ver_coefs.odd_real, 2836 coefs->ver_coefs.odd_real, dvs_ver_coef_bytes, from_user) || 2837 copy_from_compatible(css_param->dvs2_coeff->ver_coefs.odd_imag, 2838 coefs->ver_coefs.odd_imag, dvs_ver_coef_bytes, from_user) || 2839 copy_from_compatible(css_param->dvs2_coeff->ver_coefs.even_real, 2840 coefs->ver_coefs.even_real, dvs_ver_coef_bytes, from_user) || 2841 copy_from_compatible(css_param->dvs2_coeff->ver_coefs.even_imag, 2842 coefs->ver_coefs.even_imag, dvs_ver_coef_bytes, from_user)) { 2843 ia_css_dvs2_coefficients_free(css_param->dvs2_coeff); 2844 css_param->dvs2_coeff = NULL; 2845 return -EFAULT; 2846 } 2847 } else { 2848 if (copy_from_compatible(&dvs2_coefs, coefs, 2849 sizeof(struct ia_css_dvs2_coefficients), 2850 from_user)) { 2851 dev_err(asd->isp->dev, "copy dvs2 coef failed"); 2852 return -EFAULT; 2853 } 2854 2855 if (sizeof(*cur) != sizeof(dvs2_coefs.grid) || 2856 memcmp(&dvs2_coefs.grid, cur, sizeof(dvs2_coefs.grid))) { 2857 dev_err(asd->isp->dev, "dvs grid mismatch!\n"); 2858 /* If the grid info in the argument differs from the current 2859 grid info, we tell the caller to reset the grid size and 2860 try again. */ 2861 return -EAGAIN; 2862 } 2863 2864 if (!dvs2_coefs.hor_coefs.odd_real || 2865 !dvs2_coefs.hor_coefs.odd_imag || 2866 !dvs2_coefs.hor_coefs.even_real || 2867 !dvs2_coefs.hor_coefs.even_imag || 2868 !dvs2_coefs.ver_coefs.odd_real || 2869 !dvs2_coefs.ver_coefs.odd_imag || 2870 !dvs2_coefs.ver_coefs.even_real || 2871 !dvs2_coefs.ver_coefs.even_imag) 2872 return -EINVAL; 2873 2874 if (!css_param->dvs2_coeff) { 2875 /* DIS coefficients. */ 2876 css_param->dvs2_coeff = ia_css_dvs2_coefficients_allocate(cur); 2877 if (!css_param->dvs2_coeff) 2878 return -ENOMEM; 2879 } 2880 2881 dvs_hor_coef_bytes = asd->params.dvs_hor_coef_bytes; 2882 dvs_ver_coef_bytes = asd->params.dvs_ver_coef_bytes; 2883 if (copy_from_compatible(css_param->dvs2_coeff->hor_coefs.odd_real, 2884 dvs2_coefs.hor_coefs.odd_real, dvs_hor_coef_bytes, from_user) || 2885 copy_from_compatible(css_param->dvs2_coeff->hor_coefs.odd_imag, 2886 dvs2_coefs.hor_coefs.odd_imag, dvs_hor_coef_bytes, from_user) || 2887 copy_from_compatible(css_param->dvs2_coeff->hor_coefs.even_real, 2888 dvs2_coefs.hor_coefs.even_real, dvs_hor_coef_bytes, from_user) || 2889 copy_from_compatible(css_param->dvs2_coeff->hor_coefs.even_imag, 2890 dvs2_coefs.hor_coefs.even_imag, dvs_hor_coef_bytes, from_user) || 2891 copy_from_compatible(css_param->dvs2_coeff->ver_coefs.odd_real, 2892 dvs2_coefs.ver_coefs.odd_real, dvs_ver_coef_bytes, from_user) || 2893 copy_from_compatible(css_param->dvs2_coeff->ver_coefs.odd_imag, 2894 dvs2_coefs.ver_coefs.odd_imag, dvs_ver_coef_bytes, from_user) || 2895 copy_from_compatible(css_param->dvs2_coeff->ver_coefs.even_real, 2896 dvs2_coefs.ver_coefs.even_real, dvs_ver_coef_bytes, from_user) || 2897 copy_from_compatible(css_param->dvs2_coeff->ver_coefs.even_imag, 2898 dvs2_coefs.ver_coefs.even_imag, dvs_ver_coef_bytes, from_user)) { 2899 ia_css_dvs2_coefficients_free(css_param->dvs2_coeff); 2900 css_param->dvs2_coeff = NULL; 2901 return -EFAULT; 2902 } 2903 } 2904 2905 css_param->update_flag.dvs2_coefs = 2906 (struct atomisp_dis_coefficients *)css_param->dvs2_coeff; 2907 return 0; 2908 } 2909 2910 int atomisp_cp_dvs_6axis_config(struct atomisp_sub_device *asd, 2911 struct atomisp_dvs_6axis_config *source_6axis_config, 2912 struct atomisp_css_params *css_param, 2913 bool from_user) 2914 { 2915 struct ia_css_dvs_6axis_config *dvs_6axis_config; 2916 struct ia_css_dvs_6axis_config *old_6axis_config; 2917 struct ia_css_stream *stream = 2918 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream; 2919 struct ia_css_dvs_grid_info *dvs_grid_info = 2920 atomisp_css_get_dvs_grid_info(&asd->params.curr_grid_info); 2921 int ret = -EFAULT; 2922 2923 if (!stream) { 2924 dev_err(asd->isp->dev, "%s: internal error!", __func__); 2925 return -EINVAL; 2926 } 2927 2928 if (!source_6axis_config || !dvs_grid_info) 2929 return 0; 2930 2931 if (!dvs_grid_info->enable) 2932 return 0; 2933 2934 if (!from_user && css_param->update_flag.dvs_6axis_config) 2935 return 0; 2936 2937 /* check whether need to reallocate for 6 axis config */ 2938 old_6axis_config = css_param->dvs_6axis; 2939 dvs_6axis_config = old_6axis_config; 2940 2941 if (IS_ISP2401) { 2942 struct ia_css_dvs_6axis_config t_6axis_config; 2943 2944 if (copy_from_compatible(&t_6axis_config, source_6axis_config, 2945 sizeof(struct atomisp_dvs_6axis_config), 2946 from_user)) { 2947 dev_err(asd->isp->dev, "copy morph table failed!"); 2948 return -EFAULT; 2949 } 2950 2951 if (old_6axis_config && 2952 (old_6axis_config->width_y != t_6axis_config.width_y || 2953 old_6axis_config->height_y != t_6axis_config.height_y || 2954 old_6axis_config->width_uv != t_6axis_config.width_uv || 2955 old_6axis_config->height_uv != t_6axis_config.height_uv)) { 2956 ia_css_dvs2_6axis_config_free(css_param->dvs_6axis); 2957 css_param->dvs_6axis = NULL; 2958 2959 dvs_6axis_config = ia_css_dvs2_6axis_config_allocate(stream); 2960 if (!dvs_6axis_config) 2961 return -ENOMEM; 2962 } else if (!dvs_6axis_config) { 2963 dvs_6axis_config = ia_css_dvs2_6axis_config_allocate(stream); 2964 if (!dvs_6axis_config) 2965 return -ENOMEM; 2966 } 2967 2968 dvs_6axis_config->exp_id = t_6axis_config.exp_id; 2969 2970 if (copy_from_compatible(dvs_6axis_config->xcoords_y, 2971 t_6axis_config.xcoords_y, 2972 t_6axis_config.width_y * 2973 t_6axis_config.height_y * 2974 sizeof(*dvs_6axis_config->xcoords_y), 2975 from_user)) 2976 goto error; 2977 if (copy_from_compatible(dvs_6axis_config->ycoords_y, 2978 t_6axis_config.ycoords_y, 2979 t_6axis_config.width_y * 2980 t_6axis_config.height_y * 2981 sizeof(*dvs_6axis_config->ycoords_y), 2982 from_user)) 2983 goto error; 2984 if (copy_from_compatible(dvs_6axis_config->xcoords_uv, 2985 t_6axis_config.xcoords_uv, 2986 t_6axis_config.width_uv * 2987 t_6axis_config.height_uv * 2988 sizeof(*dvs_6axis_config->xcoords_uv), 2989 from_user)) 2990 goto error; 2991 if (copy_from_compatible(dvs_6axis_config->ycoords_uv, 2992 t_6axis_config.ycoords_uv, 2993 t_6axis_config.width_uv * 2994 t_6axis_config.height_uv * 2995 sizeof(*dvs_6axis_config->ycoords_uv), 2996 from_user)) 2997 goto error; 2998 } else { 2999 if (old_6axis_config && 3000 (old_6axis_config->width_y != source_6axis_config->width_y || 3001 old_6axis_config->height_y != source_6axis_config->height_y || 3002 old_6axis_config->width_uv != source_6axis_config->width_uv || 3003 old_6axis_config->height_uv != source_6axis_config->height_uv)) { 3004 ia_css_dvs2_6axis_config_free(css_param->dvs_6axis); 3005 css_param->dvs_6axis = NULL; 3006 3007 dvs_6axis_config = ia_css_dvs2_6axis_config_allocate(stream); 3008 if (!dvs_6axis_config) 3009 return -ENOMEM; 3010 } else if (!dvs_6axis_config) { 3011 dvs_6axis_config = ia_css_dvs2_6axis_config_allocate(stream); 3012 if (!dvs_6axis_config) 3013 return -ENOMEM; 3014 } 3015 3016 dvs_6axis_config->exp_id = source_6axis_config->exp_id; 3017 3018 if (copy_from_compatible(dvs_6axis_config->xcoords_y, 3019 source_6axis_config->xcoords_y, 3020 source_6axis_config->width_y * 3021 source_6axis_config->height_y * 3022 sizeof(*source_6axis_config->xcoords_y), 3023 from_user)) 3024 goto error; 3025 if (copy_from_compatible(dvs_6axis_config->ycoords_y, 3026 source_6axis_config->ycoords_y, 3027 source_6axis_config->width_y * 3028 source_6axis_config->height_y * 3029 sizeof(*source_6axis_config->ycoords_y), 3030 from_user)) 3031 goto error; 3032 if (copy_from_compatible(dvs_6axis_config->xcoords_uv, 3033 source_6axis_config->xcoords_uv, 3034 source_6axis_config->width_uv * 3035 source_6axis_config->height_uv * 3036 sizeof(*source_6axis_config->xcoords_uv), 3037 from_user)) 3038 goto error; 3039 if (copy_from_compatible(dvs_6axis_config->ycoords_uv, 3040 source_6axis_config->ycoords_uv, 3041 source_6axis_config->width_uv * 3042 source_6axis_config->height_uv * 3043 sizeof(*source_6axis_config->ycoords_uv), 3044 from_user)) 3045 goto error; 3046 } 3047 css_param->dvs_6axis = dvs_6axis_config; 3048 css_param->update_flag.dvs_6axis_config = 3049 (struct atomisp_dvs_6axis_config *)dvs_6axis_config; 3050 return 0; 3051 3052 error: 3053 if (dvs_6axis_config) 3054 ia_css_dvs2_6axis_config_free(dvs_6axis_config); 3055 return ret; 3056 } 3057 3058 int atomisp_cp_morph_table(struct atomisp_sub_device *asd, 3059 struct atomisp_morph_table *source_morph_table, 3060 struct atomisp_css_params *css_param, 3061 bool from_user) 3062 { 3063 int ret = -EFAULT; 3064 unsigned int i; 3065 struct ia_css_morph_table *morph_table; 3066 struct ia_css_morph_table *old_morph_table; 3067 3068 if (!source_morph_table) 3069 return 0; 3070 3071 if (!from_user && css_param->update_flag.morph_table) 3072 return 0; 3073 3074 old_morph_table = css_param->morph_table; 3075 3076 if (IS_ISP2401) { 3077 struct ia_css_morph_table mtbl; 3078 3079 if (copy_from_compatible(&mtbl, source_morph_table, 3080 sizeof(struct atomisp_morph_table), 3081 from_user)) { 3082 dev_err(asd->isp->dev, "copy morph table failed!"); 3083 return -EFAULT; 3084 } 3085 3086 morph_table = atomisp_css_morph_table_allocate( 3087 mtbl.width, 3088 mtbl.height); 3089 if (!morph_table) 3090 return -ENOMEM; 3091 3092 for (i = 0; i < IA_CSS_MORPH_TABLE_NUM_PLANES; i++) { 3093 if (copy_from_compatible(morph_table->coordinates_x[i], 3094 (__force void *)source_morph_table->coordinates_x[i], 3095 mtbl.height * mtbl.width * 3096 sizeof(*morph_table->coordinates_x[i]), 3097 from_user)) 3098 goto error; 3099 3100 if (copy_from_compatible(morph_table->coordinates_y[i], 3101 (__force void *)source_morph_table->coordinates_y[i], 3102 mtbl.height * mtbl.width * 3103 sizeof(*morph_table->coordinates_y[i]), 3104 from_user)) 3105 goto error; 3106 } 3107 } else { 3108 morph_table = atomisp_css_morph_table_allocate( 3109 source_morph_table->width, 3110 source_morph_table->height); 3111 if (!morph_table) 3112 return -ENOMEM; 3113 3114 for (i = 0; i < IA_CSS_MORPH_TABLE_NUM_PLANES; i++) { 3115 if (copy_from_compatible(morph_table->coordinates_x[i], 3116 (__force void *)source_morph_table->coordinates_x[i], 3117 source_morph_table->height * source_morph_table->width * 3118 sizeof(*source_morph_table->coordinates_x[i]), 3119 from_user)) 3120 goto error; 3121 3122 if (copy_from_compatible(morph_table->coordinates_y[i], 3123 (__force void *)source_morph_table->coordinates_y[i], 3124 source_morph_table->height * source_morph_table->width * 3125 sizeof(*source_morph_table->coordinates_y[i]), 3126 from_user)) 3127 goto error; 3128 } 3129 } 3130 3131 css_param->morph_table = morph_table; 3132 if (old_morph_table) 3133 atomisp_css_morph_table_free(old_morph_table); 3134 css_param->update_flag.morph_table = 3135 (struct atomisp_morph_table *)morph_table; 3136 return 0; 3137 3138 error: 3139 if (morph_table) 3140 atomisp_css_morph_table_free(morph_table); 3141 return ret; 3142 } 3143 3144 int atomisp_makeup_css_parameters(struct atomisp_sub_device *asd, 3145 struct atomisp_parameters *arg, 3146 struct atomisp_css_params *css_param) 3147 { 3148 int ret; 3149 3150 ret = atomisp_cp_general_isp_parameters(asd, arg, css_param, false); 3151 if (ret) 3152 return ret; 3153 ret = atomisp_cp_lsc_table(asd, arg->shading_table, css_param, false); 3154 if (ret) 3155 return ret; 3156 ret = atomisp_cp_morph_table(asd, arg->morph_table, css_param, false); 3157 if (ret) 3158 return ret; 3159 ret = atomisp_css_cp_dvs2_coefs(asd, 3160 (struct ia_css_dvs2_coefficients *)arg->dvs2_coefs, 3161 css_param, false); 3162 if (ret) 3163 return ret; 3164 ret = atomisp_cp_dvs_6axis_config(asd, arg->dvs_6axis_config, 3165 css_param, false); 3166 return ret; 3167 } 3168 3169 void atomisp_free_css_parameters(struct atomisp_css_params *css_param) 3170 { 3171 if (css_param->dvs_6axis) { 3172 ia_css_dvs2_6axis_config_free(css_param->dvs_6axis); 3173 css_param->dvs_6axis = NULL; 3174 } 3175 if (css_param->dvs2_coeff) { 3176 ia_css_dvs2_coefficients_free(css_param->dvs2_coeff); 3177 css_param->dvs2_coeff = NULL; 3178 } 3179 if (css_param->shading_table) { 3180 ia_css_shading_table_free(css_param->shading_table); 3181 css_param->shading_table = NULL; 3182 } 3183 if (css_param->morph_table) { 3184 ia_css_morph_table_free(css_param->morph_table); 3185 css_param->morph_table = NULL; 3186 } 3187 } 3188 3189 static void atomisp_move_frame_to_activeq(struct ia_css_frame *frame, 3190 struct atomisp_css_params_with_list *param) 3191 { 3192 struct atomisp_video_pipe *pipe = vb_to_pipe(&frame->vb.vb2_buf); 3193 unsigned long irqflags; 3194 3195 pipe->frame_params[frame->vb.vb2_buf.index] = param; 3196 spin_lock_irqsave(&pipe->irq_lock, irqflags); 3197 list_move_tail(&frame->queue, &pipe->activeq); 3198 spin_unlock_irqrestore(&pipe->irq_lock, irqflags); 3199 } 3200 3201 /* 3202 * Check parameter queue list and buffer queue list to find out if matched items 3203 * and then set parameter to CSS and enqueue buffer to CSS. 3204 * Of course, if the buffer in buffer waiting list is not bound to a per-frame 3205 * parameter, it will be enqueued into CSS as long as the per-frame setting 3206 * buffers before it get enqueued. 3207 */ 3208 void atomisp_handle_parameter_and_buffer(struct atomisp_video_pipe *pipe) 3209 { 3210 struct atomisp_sub_device *asd = pipe->asd; 3211 struct ia_css_frame *frame = NULL, *frame_tmp; 3212 struct atomisp_css_params_with_list *param = NULL, *param_tmp; 3213 bool need_to_enqueue_buffer = false; 3214 int i; 3215 3216 if (!asd) { 3217 dev_err(pipe->isp->dev, "%s(): asd is NULL, device is %s\n", 3218 __func__, pipe->vdev.name); 3219 return; 3220 } 3221 3222 lockdep_assert_held(&asd->isp->mutex); 3223 3224 if (atomisp_is_vf_pipe(pipe)) 3225 return; 3226 3227 /* 3228 * CSS/FW requires set parameter and enqueue buffer happen after ISP 3229 * is streamon. 3230 */ 3231 if (asd->streaming != ATOMISP_DEVICE_STREAMING_ENABLED) 3232 return; 3233 3234 if (list_empty(&pipe->per_frame_params) || 3235 list_empty(&pipe->buffers_waiting_for_param)) 3236 return; 3237 3238 list_for_each_entry_safe(frame, frame_tmp, 3239 &pipe->buffers_waiting_for_param, queue) { 3240 i = frame->vb.vb2_buf.index; 3241 if (pipe->frame_request_config_id[i]) { 3242 list_for_each_entry_safe(param, param_tmp, 3243 &pipe->per_frame_params, list) { 3244 if (pipe->frame_request_config_id[i] != param->params.isp_config_id) 3245 continue; 3246 3247 list_del(¶m->list); 3248 3249 /* 3250 * clear the request config id as the buffer 3251 * will be handled and enqueued into CSS soon 3252 */ 3253 pipe->frame_request_config_id[i] = 0; 3254 atomisp_move_frame_to_activeq(frame, param); 3255 need_to_enqueue_buffer = true; 3256 break; 3257 } 3258 3259 /* If this is the end, stop further loop */ 3260 if (list_entry_is_head(param, &pipe->per_frame_params, list)) 3261 break; 3262 } else { 3263 atomisp_move_frame_to_activeq(frame, NULL); 3264 need_to_enqueue_buffer = true; 3265 } 3266 } 3267 3268 if (!need_to_enqueue_buffer) 3269 return; 3270 3271 atomisp_qbuffers_to_css(asd); 3272 } 3273 3274 /* 3275 * Function to configure ISP parameters 3276 */ 3277 int atomisp_set_parameters(struct video_device *vdev, 3278 struct atomisp_parameters *arg) 3279 { 3280 struct atomisp_video_pipe *pipe = atomisp_to_video_pipe(vdev); 3281 struct atomisp_sub_device *asd = pipe->asd; 3282 struct atomisp_css_params_with_list *param = NULL; 3283 struct atomisp_css_params *css_param = &asd->params.css_param; 3284 int ret; 3285 3286 if (!asd) { 3287 dev_err(pipe->isp->dev, "%s(): asd is NULL, device is %s\n", 3288 __func__, vdev->name); 3289 return -EINVAL; 3290 } 3291 3292 lockdep_assert_held(&asd->isp->mutex); 3293 3294 if (!asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream) { 3295 dev_err(asd->isp->dev, "%s: internal error!\n", __func__); 3296 return -EINVAL; 3297 } 3298 3299 dev_dbg(asd->isp->dev, "set parameter(per_frame_setting %d) isp_config_id %d of %s\n", 3300 arg->per_frame_setting, arg->isp_config_id, vdev->name); 3301 3302 if (IS_ISP2401) { 3303 if (atomisp_is_vf_pipe(pipe) && arg->per_frame_setting) { 3304 dev_err(asd->isp->dev, "%s: vf pipe not support per_frame_setting", 3305 __func__); 3306 return -EINVAL; 3307 } 3308 } 3309 3310 if (arg->per_frame_setting && !atomisp_is_vf_pipe(pipe)) { 3311 /* 3312 * Per-frame setting enabled, we allocate a new parameter 3313 * buffer to cache the parameters and only when frame buffers 3314 * are ready, the parameters will be set to CSS. 3315 * per-frame setting only works for the main output frame. 3316 */ 3317 param = kvzalloc(sizeof(*param), GFP_KERNEL); 3318 if (!param) { 3319 dev_err(asd->isp->dev, "%s: failed to alloc params buffer\n", 3320 __func__); 3321 return -ENOMEM; 3322 } 3323 css_param = ¶m->params; 3324 } 3325 3326 ret = atomisp_cp_general_isp_parameters(asd, arg, css_param, true); 3327 if (ret) 3328 goto apply_parameter_failed; 3329 3330 ret = atomisp_cp_lsc_table(asd, arg->shading_table, css_param, true); 3331 if (ret) 3332 goto apply_parameter_failed; 3333 3334 ret = atomisp_cp_morph_table(asd, arg->morph_table, css_param, true); 3335 if (ret) 3336 goto apply_parameter_failed; 3337 3338 ret = atomisp_css_cp_dvs2_coefs(asd, 3339 (struct ia_css_dvs2_coefficients *)arg->dvs2_coefs, 3340 css_param, true); 3341 if (ret) 3342 goto apply_parameter_failed; 3343 3344 ret = atomisp_cp_dvs_6axis_config(asd, arg->dvs_6axis_config, 3345 css_param, true); 3346 if (ret) 3347 goto apply_parameter_failed; 3348 3349 if (!(arg->per_frame_setting && !atomisp_is_vf_pipe(pipe))) { 3350 /* indicate to CSS that we have parameters to be updated */ 3351 asd->params.css_update_params_needed = true; 3352 } else { 3353 list_add_tail(¶m->list, &pipe->per_frame_params); 3354 atomisp_handle_parameter_and_buffer(pipe); 3355 } 3356 3357 return 0; 3358 3359 apply_parameter_failed: 3360 if (css_param) 3361 atomisp_free_css_parameters(css_param); 3362 kvfree(param); 3363 3364 return ret; 3365 } 3366 3367 /* 3368 * Function to set/get isp parameters to isp 3369 */ 3370 int atomisp_param(struct atomisp_sub_device *asd, int flag, 3371 struct atomisp_parm *config) 3372 { 3373 struct ia_css_pipe_config *vp_cfg = 3374 &asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]. 3375 pipe_configs[IA_CSS_PIPE_ID_VIDEO]; 3376 3377 /* Read parameter for 3A binary info */ 3378 if (flag == 0) { 3379 struct ia_css_dvs_grid_info *dvs_grid_info = 3380 atomisp_css_get_dvs_grid_info( 3381 &asd->params.curr_grid_info); 3382 3383 atomisp_curr_user_grid_info(asd, &config->info); 3384 3385 /* We always return the resolution and stride even if there is 3386 * no valid metadata. This allows the caller to get the 3387 * information needed to allocate user-space buffers. */ 3388 config->metadata_config.metadata_height = asd-> 3389 stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream_info. 3390 metadata_info.resolution.height; 3391 config->metadata_config.metadata_stride = asd-> 3392 stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream_info. 3393 metadata_info.stride; 3394 3395 /* update dvs grid info */ 3396 if (dvs_grid_info) 3397 memcpy(&config->dvs_grid, 3398 dvs_grid_info, 3399 sizeof(struct ia_css_dvs_grid_info)); 3400 3401 if (asd->run_mode->val != ATOMISP_RUN_MODE_VIDEO) { 3402 config->dvs_envelop.width = 0; 3403 config->dvs_envelop.height = 0; 3404 return 0; 3405 } 3406 3407 /* update dvs envelop info */ 3408 config->dvs_envelop.width = vp_cfg->dvs_envelope.width; 3409 config->dvs_envelop.height = vp_cfg->dvs_envelope.height; 3410 return 0; 3411 } 3412 3413 memcpy(&asd->params.css_param.wb_config, &config->wb_config, 3414 sizeof(struct ia_css_wb_config)); 3415 memcpy(&asd->params.css_param.ob_config, &config->ob_config, 3416 sizeof(struct ia_css_ob_config)); 3417 memcpy(&asd->params.css_param.dp_config, &config->dp_config, 3418 sizeof(struct ia_css_dp_config)); 3419 memcpy(&asd->params.css_param.de_config, &config->de_config, 3420 sizeof(struct ia_css_de_config)); 3421 memcpy(&asd->params.css_param.dz_config, &config->dz_config, 3422 sizeof(struct ia_css_dz_config)); 3423 memcpy(&asd->params.css_param.ce_config, &config->ce_config, 3424 sizeof(struct ia_css_ce_config)); 3425 memcpy(&asd->params.css_param.nr_config, &config->nr_config, 3426 sizeof(struct ia_css_nr_config)); 3427 memcpy(&asd->params.css_param.ee_config, &config->ee_config, 3428 sizeof(struct ia_css_ee_config)); 3429 memcpy(&asd->params.css_param.tnr_config, &config->tnr_config, 3430 sizeof(struct ia_css_tnr_config)); 3431 3432 if (asd->params.color_effect == V4L2_COLORFX_NEGATIVE) { 3433 asd->params.css_param.cc_config.matrix[3] = -config->cc_config.matrix[3]; 3434 asd->params.css_param.cc_config.matrix[4] = -config->cc_config.matrix[4]; 3435 asd->params.css_param.cc_config.matrix[5] = -config->cc_config.matrix[5]; 3436 asd->params.css_param.cc_config.matrix[6] = -config->cc_config.matrix[6]; 3437 asd->params.css_param.cc_config.matrix[7] = -config->cc_config.matrix[7]; 3438 asd->params.css_param.cc_config.matrix[8] = -config->cc_config.matrix[8]; 3439 } 3440 3441 if (asd->params.color_effect != V4L2_COLORFX_SEPIA && 3442 asd->params.color_effect != V4L2_COLORFX_BW) { 3443 memcpy(&asd->params.css_param.cc_config, &config->cc_config, 3444 sizeof(struct ia_css_cc_config)); 3445 asd->params.config.cc_config = &asd->params.css_param.cc_config; 3446 } 3447 3448 asd->params.config.wb_config = &asd->params.css_param.wb_config; 3449 asd->params.config.ob_config = &asd->params.css_param.ob_config; 3450 asd->params.config.de_config = &asd->params.css_param.de_config; 3451 asd->params.config.dz_config = &asd->params.css_param.dz_config; 3452 asd->params.config.ce_config = &asd->params.css_param.ce_config; 3453 asd->params.config.dp_config = &asd->params.css_param.dp_config; 3454 asd->params.config.nr_config = &asd->params.css_param.nr_config; 3455 asd->params.config.ee_config = &asd->params.css_param.ee_config; 3456 asd->params.config.tnr_config = &asd->params.css_param.tnr_config; 3457 asd->params.css_update_params_needed = true; 3458 3459 return 0; 3460 } 3461 3462 /* 3463 * Function to configure color effect of the image 3464 */ 3465 int atomisp_color_effect(struct atomisp_sub_device *asd, int flag, 3466 __s32 *effect) 3467 { 3468 struct ia_css_cc_config *cc_config = NULL; 3469 struct ia_css_macc_table *macc_table = NULL; 3470 struct ia_css_ctc_table *ctc_table = NULL; 3471 int ret = 0; 3472 struct v4l2_control control; 3473 struct atomisp_device *isp = asd->isp; 3474 3475 if (flag == 0) { 3476 *effect = asd->params.color_effect; 3477 return 0; 3478 } 3479 3480 control.id = V4L2_CID_COLORFX; 3481 control.value = *effect; 3482 ret = 3483 v4l2_s_ctrl(NULL, isp->inputs[asd->input_curr].camera->ctrl_handler, 3484 &control); 3485 /* 3486 * if set color effect to sensor successfully, return 3487 * 0 directly. 3488 */ 3489 if (!ret) { 3490 asd->params.color_effect = (u32)*effect; 3491 return 0; 3492 } 3493 3494 if (*effect == asd->params.color_effect) 3495 return 0; 3496 3497 /* 3498 * isp_subdev->params.macc_en should be set to false. 3499 */ 3500 asd->params.macc_en = false; 3501 3502 switch (*effect) { 3503 case V4L2_COLORFX_NONE: 3504 macc_table = &asd->params.css_param.macc_table; 3505 asd->params.macc_en = true; 3506 break; 3507 case V4L2_COLORFX_SEPIA: 3508 cc_config = &sepia_cc_config; 3509 break; 3510 case V4L2_COLORFX_NEGATIVE: 3511 cc_config = &nega_cc_config; 3512 break; 3513 case V4L2_COLORFX_BW: 3514 cc_config = &mono_cc_config; 3515 break; 3516 case V4L2_COLORFX_SKY_BLUE: 3517 macc_table = &blue_macc_table; 3518 asd->params.macc_en = true; 3519 break; 3520 case V4L2_COLORFX_GRASS_GREEN: 3521 macc_table = &green_macc_table; 3522 asd->params.macc_en = true; 3523 break; 3524 case V4L2_COLORFX_SKIN_WHITEN_LOW: 3525 macc_table = &skin_low_macc_table; 3526 asd->params.macc_en = true; 3527 break; 3528 case V4L2_COLORFX_SKIN_WHITEN: 3529 macc_table = &skin_medium_macc_table; 3530 asd->params.macc_en = true; 3531 break; 3532 case V4L2_COLORFX_SKIN_WHITEN_HIGH: 3533 macc_table = &skin_high_macc_table; 3534 asd->params.macc_en = true; 3535 break; 3536 case V4L2_COLORFX_VIVID: 3537 ctc_table = &vivid_ctc_table; 3538 break; 3539 default: 3540 return -EINVAL; 3541 } 3542 atomisp_update_capture_mode(asd); 3543 3544 if (cc_config) 3545 asd->params.config.cc_config = cc_config; 3546 if (macc_table) 3547 asd->params.config.macc_table = macc_table; 3548 if (ctc_table) 3549 atomisp_css_set_ctc_table(asd, ctc_table); 3550 asd->params.color_effect = (u32)*effect; 3551 asd->params.css_update_params_needed = true; 3552 return 0; 3553 } 3554 3555 /* 3556 * Function to configure bad pixel correction 3557 */ 3558 int atomisp_bad_pixel(struct atomisp_sub_device *asd, int flag, 3559 __s32 *value) 3560 { 3561 if (flag == 0) { 3562 *value = asd->params.bad_pixel_en; 3563 return 0; 3564 } 3565 asd->params.bad_pixel_en = !!*value; 3566 3567 return 0; 3568 } 3569 3570 /* 3571 * Function to configure bad pixel correction params 3572 */ 3573 int atomisp_bad_pixel_param(struct atomisp_sub_device *asd, int flag, 3574 struct atomisp_dp_config *config) 3575 { 3576 if (flag == 0) { 3577 /* Get bad pixel from current setup */ 3578 if (atomisp_css_get_dp_config(asd, config)) 3579 return -EINVAL; 3580 } else { 3581 /* Set bad pixel to isp parameters */ 3582 memcpy(&asd->params.css_param.dp_config, config, 3583 sizeof(asd->params.css_param.dp_config)); 3584 asd->params.config.dp_config = &asd->params.css_param.dp_config; 3585 asd->params.css_update_params_needed = true; 3586 } 3587 3588 return 0; 3589 } 3590 3591 /* 3592 * Function to enable/disable video image stablization 3593 */ 3594 int atomisp_video_stable(struct atomisp_sub_device *asd, int flag, 3595 __s32 *value) 3596 { 3597 if (flag == 0) 3598 *value = asd->params.video_dis_en; 3599 else 3600 asd->params.video_dis_en = !!*value; 3601 3602 return 0; 3603 } 3604 3605 /* 3606 * Function to configure fixed pattern noise 3607 */ 3608 int atomisp_fixed_pattern(struct atomisp_sub_device *asd, int flag, 3609 __s32 *value) 3610 { 3611 if (flag == 0) { 3612 *value = asd->params.fpn_en; 3613 return 0; 3614 } 3615 3616 if (*value == 0) { 3617 asd->params.fpn_en = false; 3618 return 0; 3619 } 3620 3621 /* Add function to get black from from sensor with shutter off */ 3622 return 0; 3623 } 3624 3625 static unsigned int 3626 atomisp_bytesperline_to_padded_width(unsigned int bytesperline, 3627 enum ia_css_frame_format format) 3628 { 3629 switch (format) { 3630 case IA_CSS_FRAME_FORMAT_UYVY: 3631 case IA_CSS_FRAME_FORMAT_YUYV: 3632 case IA_CSS_FRAME_FORMAT_RAW: 3633 case IA_CSS_FRAME_FORMAT_RGB565: 3634 return bytesperline / 2; 3635 case IA_CSS_FRAME_FORMAT_RGBA888: 3636 return bytesperline / 4; 3637 /* The following cases could be removed, but we leave them 3638 in to document the formats that are included. */ 3639 case IA_CSS_FRAME_FORMAT_NV11: 3640 case IA_CSS_FRAME_FORMAT_NV12: 3641 case IA_CSS_FRAME_FORMAT_NV16: 3642 case IA_CSS_FRAME_FORMAT_NV21: 3643 case IA_CSS_FRAME_FORMAT_NV61: 3644 case IA_CSS_FRAME_FORMAT_YV12: 3645 case IA_CSS_FRAME_FORMAT_YV16: 3646 case IA_CSS_FRAME_FORMAT_YUV420: 3647 case IA_CSS_FRAME_FORMAT_YUV420_16: 3648 case IA_CSS_FRAME_FORMAT_YUV422: 3649 case IA_CSS_FRAME_FORMAT_YUV422_16: 3650 case IA_CSS_FRAME_FORMAT_YUV444: 3651 case IA_CSS_FRAME_FORMAT_YUV_LINE: 3652 case IA_CSS_FRAME_FORMAT_PLANAR_RGB888: 3653 case IA_CSS_FRAME_FORMAT_QPLANE6: 3654 case IA_CSS_FRAME_FORMAT_BINARY_8: 3655 default: 3656 return bytesperline; 3657 } 3658 } 3659 3660 static int 3661 atomisp_v4l2_framebuffer_to_css_frame(const struct v4l2_framebuffer *arg, 3662 struct ia_css_frame **result) 3663 { 3664 struct ia_css_frame *res = NULL; 3665 unsigned int padded_width; 3666 enum ia_css_frame_format sh_format; 3667 char *tmp_buf = NULL; 3668 int ret = 0; 3669 3670 sh_format = v4l2_fmt_to_sh_fmt(arg->fmt.pixelformat); 3671 padded_width = atomisp_bytesperline_to_padded_width( 3672 arg->fmt.bytesperline, sh_format); 3673 3674 /* Note: the padded width on an ia_css_frame is in elements, not in 3675 bytes. The RAW frame we use here should always be a 16bit RAW 3676 frame. This is why we bytesperline/2 is equal to the padded with */ 3677 if (ia_css_frame_allocate(&res, arg->fmt.width, arg->fmt.height, 3678 sh_format, padded_width, 0)) { 3679 ret = -ENOMEM; 3680 goto err; 3681 } 3682 3683 tmp_buf = vmalloc(arg->fmt.sizeimage); 3684 if (!tmp_buf) { 3685 ret = -ENOMEM; 3686 goto err; 3687 } 3688 if (copy_from_user(tmp_buf, (void __user __force *)arg->base, 3689 arg->fmt.sizeimage)) { 3690 ret = -EFAULT; 3691 goto err; 3692 } 3693 3694 if (hmm_store(res->data, tmp_buf, arg->fmt.sizeimage)) { 3695 ret = -EINVAL; 3696 goto err; 3697 } 3698 3699 err: 3700 if (ret && res) 3701 ia_css_frame_free(res); 3702 vfree(tmp_buf); 3703 if (ret == 0) 3704 *result = res; 3705 return ret; 3706 } 3707 3708 /* 3709 * Function to configure fixed pattern noise table 3710 */ 3711 int atomisp_fixed_pattern_table(struct atomisp_sub_device *asd, 3712 struct v4l2_framebuffer *arg) 3713 { 3714 struct ia_css_frame *raw_black_frame = NULL; 3715 int ret; 3716 3717 if (!arg) 3718 return -EINVAL; 3719 3720 ret = atomisp_v4l2_framebuffer_to_css_frame(arg, &raw_black_frame); 3721 if (ret) 3722 return ret; 3723 3724 if (sh_css_set_black_frame(asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream, 3725 raw_black_frame) != 0) 3726 return -ENOMEM; 3727 3728 ia_css_frame_free(raw_black_frame); 3729 return ret; 3730 } 3731 3732 /* 3733 * Function to configure false color correction 3734 */ 3735 int atomisp_false_color(struct atomisp_sub_device *asd, int flag, 3736 __s32 *value) 3737 { 3738 /* Get nr config from current setup */ 3739 if (flag == 0) { 3740 *value = asd->params.false_color; 3741 return 0; 3742 } 3743 3744 /* Set nr config to isp parameters */ 3745 if (*value) { 3746 asd->params.config.de_config = NULL; 3747 } else { 3748 asd->params.css_param.de_config.pixelnoise = 0; 3749 asd->params.config.de_config = &asd->params.css_param.de_config; 3750 } 3751 asd->params.css_update_params_needed = true; 3752 asd->params.false_color = *value; 3753 return 0; 3754 } 3755 3756 /* 3757 * Function to configure bad pixel correction params 3758 */ 3759 int atomisp_false_color_param(struct atomisp_sub_device *asd, int flag, 3760 struct atomisp_de_config *config) 3761 { 3762 if (flag == 0) { 3763 /* Get false color from current setup */ 3764 if (atomisp_css_get_de_config(asd, config)) 3765 return -EINVAL; 3766 } else { 3767 /* Set false color to isp parameters */ 3768 memcpy(&asd->params.css_param.de_config, config, 3769 sizeof(asd->params.css_param.de_config)); 3770 asd->params.config.de_config = &asd->params.css_param.de_config; 3771 asd->params.css_update_params_needed = true; 3772 } 3773 3774 return 0; 3775 } 3776 3777 /* 3778 * Function to configure white balance params 3779 */ 3780 int atomisp_white_balance_param(struct atomisp_sub_device *asd, int flag, 3781 struct atomisp_wb_config *config) 3782 { 3783 if (flag == 0) { 3784 /* Get white balance from current setup */ 3785 if (atomisp_css_get_wb_config(asd, config)) 3786 return -EINVAL; 3787 } else { 3788 /* Set white balance to isp parameters */ 3789 memcpy(&asd->params.css_param.wb_config, config, 3790 sizeof(asd->params.css_param.wb_config)); 3791 asd->params.config.wb_config = &asd->params.css_param.wb_config; 3792 asd->params.css_update_params_needed = true; 3793 } 3794 3795 return 0; 3796 } 3797 3798 int atomisp_3a_config_param(struct atomisp_sub_device *asd, int flag, 3799 struct atomisp_3a_config *config) 3800 { 3801 struct atomisp_device *isp = asd->isp; 3802 3803 dev_dbg(isp->dev, ">%s %d\n", __func__, flag); 3804 3805 if (flag == 0) { 3806 /* Get white balance from current setup */ 3807 if (atomisp_css_get_3a_config(asd, config)) 3808 return -EINVAL; 3809 } else { 3810 /* Set white balance to isp parameters */ 3811 memcpy(&asd->params.css_param.s3a_config, config, 3812 sizeof(asd->params.css_param.s3a_config)); 3813 asd->params.config.s3a_config = &asd->params.css_param.s3a_config; 3814 asd->params.css_update_params_needed = true; 3815 } 3816 3817 dev_dbg(isp->dev, "<%s %d\n", __func__, flag); 3818 return 0; 3819 } 3820 3821 /* 3822 * Function to setup digital zoom 3823 */ 3824 int atomisp_digital_zoom(struct atomisp_sub_device *asd, int flag, 3825 __s32 *value) 3826 { 3827 u32 zoom; 3828 struct atomisp_device *isp = asd->isp; 3829 3830 unsigned int max_zoom = MRFLD_MAX_ZOOM_FACTOR; 3831 3832 if (flag == 0) { 3833 atomisp_css_get_zoom_factor(asd, &zoom); 3834 *value = max_zoom - zoom; 3835 } else { 3836 if (*value < 0) 3837 return -EINVAL; 3838 3839 zoom = max_zoom - min_t(u32, max_zoom - 1, *value); 3840 atomisp_css_set_zoom_factor(asd, zoom); 3841 3842 dev_dbg(isp->dev, "%s, zoom: %d\n", __func__, zoom); 3843 asd->params.css_update_params_needed = true; 3844 } 3845 3846 return 0; 3847 } 3848 3849 static void __atomisp_update_stream_env(struct atomisp_sub_device *asd, 3850 u16 stream_index, struct atomisp_input_stream_info *stream_info) 3851 { 3852 int i; 3853 3854 /* assign virtual channel id return from sensor driver query */ 3855 asd->stream_env[stream_index].ch_id = stream_info->ch_id; 3856 asd->stream_env[stream_index].isys_configs = stream_info->isys_configs; 3857 for (i = 0; i < stream_info->isys_configs; i++) { 3858 asd->stream_env[stream_index].isys_info[i].input_format = 3859 stream_info->isys_info[i].input_format; 3860 asd->stream_env[stream_index].isys_info[i].width = 3861 stream_info->isys_info[i].width; 3862 asd->stream_env[stream_index].isys_info[i].height = 3863 stream_info->isys_info[i].height; 3864 } 3865 } 3866 3867 static void __atomisp_init_stream_info(u16 stream_index, 3868 struct atomisp_input_stream_info *stream_info) 3869 { 3870 int i; 3871 3872 stream_info->enable = 1; 3873 stream_info->stream = stream_index; 3874 stream_info->ch_id = 0; 3875 stream_info->isys_configs = 0; 3876 for (i = 0; i < MAX_STREAMS_PER_CHANNEL; i++) { 3877 stream_info->isys_info[i].input_format = 0; 3878 stream_info->isys_info[i].width = 0; 3879 stream_info->isys_info[i].height = 0; 3880 } 3881 } 3882 3883 /* This function looks up the closest available resolution. */ 3884 int atomisp_try_fmt(struct video_device *vdev, struct v4l2_pix_format *f, 3885 bool *res_overflow) 3886 { 3887 struct atomisp_device *isp = video_get_drvdata(vdev); 3888 struct atomisp_sub_device *asd = atomisp_to_video_pipe(vdev)->asd; 3889 struct v4l2_subdev_pad_config pad_cfg; 3890 struct v4l2_subdev_state pad_state = { 3891 .pads = &pad_cfg, 3892 }; 3893 struct v4l2_subdev_format format = { 3894 .which = V4L2_SUBDEV_FORMAT_TRY, 3895 }; 3896 const struct atomisp_format_bridge *fmt; 3897 int ret; 3898 3899 if (!asd) { 3900 dev_err(isp->dev, "%s(): asd is NULL, device is %s\n", 3901 __func__, vdev->name); 3902 return -EINVAL; 3903 } 3904 3905 if (!isp->inputs[asd->input_curr].camera) 3906 return -EINVAL; 3907 3908 fmt = atomisp_get_format_bridge(f->pixelformat); 3909 if (!fmt) { 3910 dev_err(isp->dev, "unsupported pixelformat!\n"); 3911 fmt = atomisp_output_fmts; 3912 } 3913 3914 if (f->width <= 0 || f->height <= 0) 3915 return -EINVAL; 3916 3917 format.format.code = fmt->mbus_code; 3918 format.format.width = f->width; 3919 format.format.height = f->height; 3920 3921 __atomisp_init_stream_info(ATOMISP_INPUT_STREAM_GENERAL, 3922 (struct atomisp_input_stream_info *)format.format.reserved); 3923 3924 dev_dbg(isp->dev, "try_mbus_fmt: asking for %ux%u\n", 3925 format.format.width, format.format.height); 3926 3927 ret = v4l2_subdev_call(isp->inputs[asd->input_curr].camera, 3928 pad, set_fmt, &pad_state, &format); 3929 if (ret) 3930 return ret; 3931 3932 dev_dbg(isp->dev, "try_mbus_fmt: got %ux%u\n", 3933 format.format.width, format.format.height); 3934 3935 fmt = atomisp_get_format_bridge_from_mbus(format.format.code); 3936 if (!fmt) { 3937 dev_err(isp->dev, "unknown sensor format 0x%8.8x\n", 3938 format.format.code); 3939 return -EINVAL; 3940 } 3941 3942 f->pixelformat = fmt->pixelformat; 3943 3944 /* 3945 * If the format is jpeg or custom RAW, then the width and height will 3946 * not satisfy the normal atomisp requirements and no need to check 3947 * the below conditions. So just assign to what is being returned from 3948 * the sensor driver. 3949 */ 3950 if (f->pixelformat == V4L2_PIX_FMT_JPEG || 3951 f->pixelformat == V4L2_PIX_FMT_CUSTOM_M10MO_RAW) { 3952 f->width = format.format.width; 3953 f->height = format.format.height; 3954 return 0; 3955 } 3956 3957 if (!res_overflow || (format.format.width < f->width && 3958 format.format.height < f->height)) { 3959 f->width = format.format.width; 3960 f->height = format.format.height; 3961 /* Set the flag when resolution requested is 3962 * beyond the max value supported by sensor 3963 */ 3964 if (res_overflow) 3965 *res_overflow = true; 3966 } 3967 3968 /* app vs isp */ 3969 f->width = rounddown(clamp_t(u32, f->width, ATOM_ISP_MIN_WIDTH, 3970 ATOM_ISP_MAX_WIDTH), ATOM_ISP_STEP_WIDTH); 3971 f->height = rounddown(clamp_t(u32, f->height, ATOM_ISP_MIN_HEIGHT, 3972 ATOM_ISP_MAX_HEIGHT), ATOM_ISP_STEP_HEIGHT); 3973 3974 return 0; 3975 } 3976 3977 enum mipi_port_id __get_mipi_port(struct atomisp_device *isp, 3978 enum atomisp_camera_port port) 3979 { 3980 switch (port) { 3981 case ATOMISP_CAMERA_PORT_PRIMARY: 3982 return MIPI_PORT0_ID; 3983 case ATOMISP_CAMERA_PORT_SECONDARY: 3984 return MIPI_PORT1_ID; 3985 case ATOMISP_CAMERA_PORT_TERTIARY: 3986 if (MIPI_PORT1_ID + 1 != N_MIPI_PORT_ID) 3987 return MIPI_PORT1_ID + 1; 3988 fallthrough; 3989 default: 3990 dev_err(isp->dev, "unsupported port: %d\n", port); 3991 return MIPI_PORT0_ID; 3992 } 3993 } 3994 3995 static inline int atomisp_set_sensor_mipi_to_isp( 3996 struct atomisp_sub_device *asd, 3997 enum atomisp_input_stream_id stream_id, 3998 struct camera_mipi_info *mipi_info) 3999 { 4000 struct v4l2_control ctrl; 4001 struct atomisp_device *isp = asd->isp; 4002 const struct atomisp_in_fmt_conv *fc; 4003 int mipi_freq = 0; 4004 unsigned int input_format, bayer_order; 4005 4006 ctrl.id = V4L2_CID_LINK_FREQ; 4007 if (v4l2_g_ctrl 4008 (isp->inputs[asd->input_curr].camera->ctrl_handler, &ctrl) == 0) 4009 mipi_freq = ctrl.value; 4010 4011 if (asd->stream_env[stream_id].isys_configs == 1) { 4012 input_format = 4013 asd->stream_env[stream_id].isys_info[0].input_format; 4014 atomisp_css_isys_set_format(asd, stream_id, 4015 input_format, IA_CSS_STREAM_DEFAULT_ISYS_STREAM_IDX); 4016 } else if (asd->stream_env[stream_id].isys_configs == 2) { 4017 atomisp_css_isys_two_stream_cfg_update_stream1( 4018 asd, stream_id, 4019 asd->stream_env[stream_id].isys_info[0].input_format, 4020 asd->stream_env[stream_id].isys_info[0].width, 4021 asd->stream_env[stream_id].isys_info[0].height); 4022 4023 atomisp_css_isys_two_stream_cfg_update_stream2( 4024 asd, stream_id, 4025 asd->stream_env[stream_id].isys_info[1].input_format, 4026 asd->stream_env[stream_id].isys_info[1].width, 4027 asd->stream_env[stream_id].isys_info[1].height); 4028 } 4029 4030 /* Compatibility for sensors which provide no media bus code 4031 * in s_mbus_framefmt() nor support pad formats. */ 4032 if (mipi_info->input_format != -1) { 4033 bayer_order = mipi_info->raw_bayer_order; 4034 4035 /* Input stream config is still needs configured */ 4036 /* TODO: Check if this is necessary */ 4037 fc = atomisp_find_in_fmt_conv_by_atomisp_in_fmt( 4038 mipi_info->input_format); 4039 if (!fc) 4040 return -EINVAL; 4041 input_format = fc->atomisp_in_fmt; 4042 } else { 4043 struct v4l2_mbus_framefmt *sink; 4044 4045 sink = atomisp_subdev_get_ffmt(&asd->subdev, NULL, 4046 V4L2_SUBDEV_FORMAT_ACTIVE, 4047 ATOMISP_SUBDEV_PAD_SINK); 4048 fc = atomisp_find_in_fmt_conv(sink->code); 4049 if (!fc) 4050 return -EINVAL; 4051 input_format = fc->atomisp_in_fmt; 4052 bayer_order = fc->bayer_order; 4053 } 4054 4055 atomisp_css_input_set_format(asd, stream_id, input_format); 4056 atomisp_css_input_set_bayer_order(asd, stream_id, bayer_order); 4057 4058 fc = atomisp_find_in_fmt_conv_by_atomisp_in_fmt( 4059 mipi_info->metadata_format); 4060 if (!fc) 4061 return -EINVAL; 4062 input_format = fc->atomisp_in_fmt; 4063 atomisp_css_input_configure_port(asd, 4064 __get_mipi_port(asd->isp, mipi_info->port), 4065 mipi_info->num_lanes, 4066 0xffff4, mipi_freq, 4067 input_format, 4068 mipi_info->metadata_width, 4069 mipi_info->metadata_height); 4070 return 0; 4071 } 4072 4073 static int configure_pp_input_nop(struct atomisp_sub_device *asd, 4074 unsigned int width, unsigned int height) 4075 { 4076 return 0; 4077 } 4078 4079 static int configure_output_nop(struct atomisp_sub_device *asd, 4080 unsigned int width, unsigned int height, 4081 unsigned int min_width, 4082 enum ia_css_frame_format sh_fmt) 4083 { 4084 return 0; 4085 } 4086 4087 static int get_frame_info_nop(struct atomisp_sub_device *asd, 4088 struct ia_css_frame_info *finfo) 4089 { 4090 return 0; 4091 } 4092 4093 /* 4094 * Resets CSS parameters that depend on input resolution. 4095 * 4096 * Update params like CSS RAW binning, 2ppc mode and pp_input 4097 * which depend on input size, but are not automatically 4098 * handled in CSS when the input resolution is changed. 4099 */ 4100 static int css_input_resolution_changed(struct atomisp_sub_device *asd, 4101 struct v4l2_mbus_framefmt *ffmt) 4102 { 4103 struct atomisp_metadata_buf *md_buf = NULL, *_md_buf; 4104 unsigned int i; 4105 4106 dev_dbg(asd->isp->dev, "css_input_resolution_changed to %ux%u\n", 4107 ffmt->width, ffmt->height); 4108 4109 if (IS_ISP2401) 4110 atomisp_css_input_set_two_pixels_per_clock(asd, false); 4111 else 4112 atomisp_css_input_set_two_pixels_per_clock(asd, true); 4113 4114 /* 4115 * If sensor input changed, which means metadata resolution changed 4116 * together. Release all metadata buffers here to let it re-allocated 4117 * next time in reqbufs. 4118 */ 4119 for (i = 0; i < ATOMISP_METADATA_TYPE_NUM; i++) { 4120 list_for_each_entry_safe(md_buf, _md_buf, &asd->metadata[i], 4121 list) { 4122 atomisp_css_free_metadata_buffer(md_buf); 4123 list_del(&md_buf->list); 4124 kfree(md_buf); 4125 } 4126 } 4127 return 0; 4128 4129 /* 4130 * TODO: atomisp_css_preview_configure_pp_input() not 4131 * reset due to CSS bug tracked as PSI BZ 115124 4132 */ 4133 } 4134 4135 static int atomisp_set_fmt_to_isp(struct video_device *vdev, 4136 struct ia_css_frame_info *output_info, 4137 struct v4l2_pix_format *pix, 4138 unsigned int source_pad) 4139 { 4140 struct camera_mipi_info *mipi_info; 4141 struct atomisp_device *isp = video_get_drvdata(vdev); 4142 struct atomisp_sub_device *asd = atomisp_to_video_pipe(vdev)->asd; 4143 const struct atomisp_format_bridge *format; 4144 struct v4l2_rect *isp_sink_crop; 4145 enum ia_css_pipe_id pipe_id; 4146 struct v4l2_subdev_fh fh; 4147 int (*configure_output)(struct atomisp_sub_device *asd, 4148 unsigned int width, unsigned int height, 4149 unsigned int min_width, 4150 enum ia_css_frame_format sh_fmt) = 4151 configure_output_nop; 4152 int (*get_frame_info)(struct atomisp_sub_device *asd, 4153 struct ia_css_frame_info *finfo) = 4154 get_frame_info_nop; 4155 int (*configure_pp_input)(struct atomisp_sub_device *asd, 4156 unsigned int width, unsigned int height) = 4157 configure_pp_input_nop; 4158 const struct atomisp_in_fmt_conv *fc; 4159 int ret, i; 4160 4161 if (!asd) { 4162 dev_err(isp->dev, "%s(): asd is NULL, device is %s\n", 4163 __func__, vdev->name); 4164 return -EINVAL; 4165 } 4166 4167 v4l2_fh_init(&fh.vfh, vdev); 4168 4169 isp_sink_crop = atomisp_subdev_get_rect( 4170 &asd->subdev, NULL, V4L2_SUBDEV_FORMAT_ACTIVE, 4171 ATOMISP_SUBDEV_PAD_SINK, V4L2_SEL_TGT_CROP); 4172 4173 format = atomisp_get_format_bridge(pix->pixelformat); 4174 if (!format) 4175 return -EINVAL; 4176 4177 if (isp->inputs[asd->input_curr].type != TEST_PATTERN) { 4178 mipi_info = atomisp_to_sensor_mipi_info( 4179 isp->inputs[asd->input_curr].camera); 4180 if (!mipi_info) { 4181 dev_err(isp->dev, "mipi_info is NULL\n"); 4182 return -EINVAL; 4183 } 4184 if (atomisp_set_sensor_mipi_to_isp(asd, ATOMISP_INPUT_STREAM_GENERAL, 4185 mipi_info)) 4186 return -EINVAL; 4187 fc = atomisp_find_in_fmt_conv_by_atomisp_in_fmt( 4188 mipi_info->input_format); 4189 if (!fc) 4190 fc = atomisp_find_in_fmt_conv( 4191 atomisp_subdev_get_ffmt(&asd->subdev, 4192 NULL, V4L2_SUBDEV_FORMAT_ACTIVE, 4193 ATOMISP_SUBDEV_PAD_SINK)->code); 4194 if (!fc) 4195 return -EINVAL; 4196 if (format->sh_fmt == IA_CSS_FRAME_FORMAT_RAW && 4197 raw_output_format_match_input(fc->atomisp_in_fmt, 4198 pix->pixelformat)) 4199 return -EINVAL; 4200 } 4201 4202 /* 4203 * Configure viewfinder also when vfpp is disabled: the 4204 * CSS still requires viewfinder configuration. 4205 */ 4206 { 4207 struct v4l2_rect vf_size = {0}; 4208 struct v4l2_mbus_framefmt vf_ffmt = {0}; 4209 4210 if (pix->width < 640 || pix->height < 480) { 4211 vf_size.width = pix->width; 4212 vf_size.height = pix->height; 4213 } else { 4214 vf_size.width = 640; 4215 vf_size.height = 480; 4216 } 4217 4218 /* FIXME: proper format name for this one. See 4219 atomisp_output_fmts[] in atomisp_v4l2.c */ 4220 vf_ffmt.code = V4L2_MBUS_FMT_CUSTOM_YUV420; 4221 4222 atomisp_subdev_set_selection(&asd->subdev, fh.state, 4223 V4L2_SUBDEV_FORMAT_ACTIVE, 4224 ATOMISP_SUBDEV_PAD_SOURCE_VF, 4225 V4L2_SEL_TGT_COMPOSE, 0, &vf_size); 4226 atomisp_subdev_set_ffmt(&asd->subdev, fh.state, 4227 V4L2_SUBDEV_FORMAT_ACTIVE, 4228 ATOMISP_SUBDEV_PAD_SOURCE_VF, &vf_ffmt); 4229 asd->video_out_vf.sh_fmt = IA_CSS_FRAME_FORMAT_NV12; 4230 4231 if (asd->vfpp->val == ATOMISP_VFPP_DISABLE_SCALER) { 4232 atomisp_css_video_configure_viewfinder(asd, 4233 vf_size.width, vf_size.height, 0, 4234 asd->video_out_vf.sh_fmt); 4235 } else if (asd->run_mode->val == ATOMISP_RUN_MODE_VIDEO) { 4236 if (source_pad == ATOMISP_SUBDEV_PAD_SOURCE_PREVIEW || 4237 source_pad == ATOMISP_SUBDEV_PAD_SOURCE_VIDEO) 4238 atomisp_css_video_configure_viewfinder(asd, 4239 vf_size.width, vf_size.height, 0, 4240 asd->video_out_vf.sh_fmt); 4241 else 4242 atomisp_css_capture_configure_viewfinder(asd, 4243 vf_size.width, vf_size.height, 0, 4244 asd->video_out_vf.sh_fmt); 4245 } else if (source_pad != ATOMISP_SUBDEV_PAD_SOURCE_PREVIEW || 4246 asd->vfpp->val == ATOMISP_VFPP_DISABLE_LOWLAT) { 4247 atomisp_css_capture_configure_viewfinder(asd, 4248 vf_size.width, vf_size.height, 0, 4249 asd->video_out_vf.sh_fmt); 4250 } 4251 } 4252 4253 atomisp_css_input_set_mode(asd, IA_CSS_INPUT_MODE_BUFFERED_SENSOR); 4254 4255 for (i = 0; i < IA_CSS_PIPE_ID_NUM; i++) 4256 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].pipe_extra_configs[i].disable_vf_pp = asd->vfpp->val != ATOMISP_VFPP_ENABLE; 4257 4258 /* ISP2401 new input system need to use copy pipe */ 4259 if (asd->copy_mode) { 4260 pipe_id = IA_CSS_PIPE_ID_COPY; 4261 atomisp_css_capture_enable_online(asd, ATOMISP_INPUT_STREAM_GENERAL, false); 4262 } else if (asd->vfpp->val == ATOMISP_VFPP_DISABLE_SCALER) { 4263 /* video same in continuouscapture and online modes */ 4264 configure_output = atomisp_css_video_configure_output; 4265 get_frame_info = atomisp_css_video_get_output_frame_info; 4266 pipe_id = IA_CSS_PIPE_ID_VIDEO; 4267 } else if (asd->run_mode->val == ATOMISP_RUN_MODE_VIDEO) { 4268 configure_output = atomisp_css_video_configure_output; 4269 get_frame_info = atomisp_css_video_get_output_frame_info; 4270 pipe_id = IA_CSS_PIPE_ID_VIDEO; 4271 } else if (source_pad == ATOMISP_SUBDEV_PAD_SOURCE_PREVIEW) { 4272 configure_output = atomisp_css_preview_configure_output; 4273 get_frame_info = atomisp_css_preview_get_output_frame_info; 4274 configure_pp_input = atomisp_css_preview_configure_pp_input; 4275 pipe_id = IA_CSS_PIPE_ID_PREVIEW; 4276 } else { 4277 if (format->sh_fmt == IA_CSS_FRAME_FORMAT_RAW) { 4278 atomisp_css_capture_set_mode(asd, IA_CSS_CAPTURE_MODE_RAW); 4279 atomisp_css_enable_dz(asd, false); 4280 } else { 4281 atomisp_update_capture_mode(asd); 4282 } 4283 4284 /* in case of ANR, force capture pipe to offline mode */ 4285 atomisp_css_capture_enable_online(asd, ATOMISP_INPUT_STREAM_GENERAL, 4286 !asd->params.low_light); 4287 4288 configure_output = atomisp_css_capture_configure_output; 4289 get_frame_info = atomisp_css_capture_get_output_frame_info; 4290 configure_pp_input = atomisp_css_capture_configure_pp_input; 4291 pipe_id = IA_CSS_PIPE_ID_CAPTURE; 4292 4293 if (asd->run_mode->val != ATOMISP_RUN_MODE_STILL_CAPTURE) { 4294 dev_err(isp->dev, 4295 "Need to set the running mode first\n"); 4296 asd->run_mode->val = ATOMISP_RUN_MODE_STILL_CAPTURE; 4297 } 4298 } 4299 4300 if (asd->copy_mode) 4301 ret = atomisp_css_copy_configure_output(asd, ATOMISP_INPUT_STREAM_GENERAL, 4302 pix->width, pix->height, 4303 format->planar ? pix->bytesperline : 4304 pix->bytesperline * 8 / format->depth, 4305 format->sh_fmt); 4306 else 4307 ret = configure_output(asd, pix->width, pix->height, 4308 format->planar ? pix->bytesperline : 4309 pix->bytesperline * 8 / format->depth, 4310 format->sh_fmt); 4311 if (ret) { 4312 dev_err(isp->dev, "configure_output %ux%u, format %8.8x\n", 4313 pix->width, pix->height, format->sh_fmt); 4314 return -EINVAL; 4315 } 4316 4317 ret = configure_pp_input(asd, isp_sink_crop->width, isp_sink_crop->height); 4318 if (ret) { 4319 dev_err(isp->dev, "configure_pp_input %ux%u\n", 4320 isp_sink_crop->width, 4321 isp_sink_crop->height); 4322 return -EINVAL; 4323 } 4324 if (asd->copy_mode) 4325 ret = atomisp_css_copy_get_output_frame_info(asd, 4326 ATOMISP_INPUT_STREAM_GENERAL, 4327 output_info); 4328 else 4329 ret = get_frame_info(asd, output_info); 4330 if (ret) { 4331 dev_err(isp->dev, "__get_frame_info %ux%u (padded to %u) returned %d\n", 4332 pix->width, pix->height, pix->bytesperline, ret); 4333 return ret; 4334 } 4335 4336 atomisp_update_grid_info(asd, pipe_id, source_pad); 4337 return 0; 4338 } 4339 4340 static void atomisp_get_dis_envelop(struct atomisp_sub_device *asd, 4341 unsigned int width, unsigned int height, 4342 unsigned int *dvs_env_w, unsigned int *dvs_env_h) 4343 { 4344 if (asd->params.video_dis_en && 4345 asd->run_mode->val == ATOMISP_RUN_MODE_VIDEO) { 4346 /* envelope is 20% of the output resolution */ 4347 /* 4348 * dvs envelope cannot be round up. 4349 * it would cause ISP timeout and color switch issue 4350 */ 4351 *dvs_env_w = rounddown(width / 5, ATOM_ISP_STEP_WIDTH); 4352 *dvs_env_h = rounddown(height / 5, ATOM_ISP_STEP_HEIGHT); 4353 } 4354 4355 asd->params.dis_proj_data_valid = false; 4356 asd->params.css_update_params_needed = true; 4357 } 4358 4359 static void atomisp_check_copy_mode(struct atomisp_sub_device *asd, 4360 int source_pad, const struct v4l2_pix_format *f) 4361 { 4362 struct v4l2_mbus_framefmt *sink, *src; 4363 4364 if (!IS_ISP2401) { 4365 /* Only used for the new input system */ 4366 asd->copy_mode = false; 4367 return; 4368 } 4369 4370 sink = atomisp_subdev_get_ffmt(&asd->subdev, NULL, 4371 V4L2_SUBDEV_FORMAT_ACTIVE, ATOMISP_SUBDEV_PAD_SINK); 4372 src = atomisp_subdev_get_ffmt(&asd->subdev, NULL, 4373 V4L2_SUBDEV_FORMAT_ACTIVE, source_pad); 4374 4375 if (sink->code == src->code && sink->width == f->width && sink->height == f->height) 4376 asd->copy_mode = true; 4377 else 4378 asd->copy_mode = false; 4379 4380 dev_dbg(asd->isp->dev, "copy_mode: %d\n", asd->copy_mode); 4381 } 4382 4383 static int atomisp_set_fmt_to_snr(struct video_device *vdev, const struct v4l2_pix_format *f, 4384 unsigned int padding_w, unsigned int padding_h, 4385 unsigned int dvs_env_w, unsigned int dvs_env_h) 4386 { 4387 struct atomisp_video_pipe *pipe = atomisp_to_video_pipe(vdev); 4388 struct atomisp_sub_device *asd = pipe->asd; 4389 const struct atomisp_format_bridge *format; 4390 struct v4l2_subdev_pad_config pad_cfg; 4391 struct v4l2_subdev_state pad_state = { 4392 .pads = &pad_cfg, 4393 }; 4394 struct v4l2_subdev_format vformat = { 4395 .which = V4L2_SUBDEV_FORMAT_TRY, 4396 }; 4397 struct v4l2_mbus_framefmt *ffmt = &vformat.format; 4398 struct v4l2_mbus_framefmt *req_ffmt; 4399 struct atomisp_device *isp; 4400 struct atomisp_input_stream_info *stream_info = 4401 (struct atomisp_input_stream_info *)ffmt->reserved; 4402 int source_pad = atomisp_subdev_source_pad(vdev); 4403 struct v4l2_subdev_fh fh; 4404 int ret; 4405 4406 if (!asd) { 4407 dev_err(pipe->isp->dev, "%s(): asd is NULL, device is %s\n", 4408 __func__, vdev->name); 4409 return -EINVAL; 4410 } 4411 4412 isp = asd->isp; 4413 4414 v4l2_fh_init(&fh.vfh, vdev); 4415 4416 format = atomisp_get_format_bridge(f->pixelformat); 4417 if (!format) 4418 return -EINVAL; 4419 4420 v4l2_fill_mbus_format(ffmt, f, format->mbus_code); 4421 ffmt->height += padding_h + dvs_env_h; 4422 ffmt->width += padding_w + dvs_env_w; 4423 4424 dev_dbg(isp->dev, "s_mbus_fmt: ask %ux%u (padding %ux%u, dvs %ux%u)\n", 4425 ffmt->width, ffmt->height, padding_w, padding_h, 4426 dvs_env_w, dvs_env_h); 4427 4428 __atomisp_init_stream_info(ATOMISP_INPUT_STREAM_GENERAL, stream_info); 4429 4430 req_ffmt = ffmt; 4431 4432 /* Disable dvs if resolution can't be supported by sensor */ 4433 if (asd->params.video_dis_en && 4434 source_pad == ATOMISP_SUBDEV_PAD_SOURCE_VIDEO) { 4435 vformat.which = V4L2_SUBDEV_FORMAT_TRY; 4436 ret = v4l2_subdev_call(isp->inputs[asd->input_curr].camera, 4437 pad, set_fmt, &pad_state, &vformat); 4438 if (ret) 4439 return ret; 4440 4441 dev_dbg(isp->dev, "video dis: sensor width: %d, height: %d\n", 4442 ffmt->width, ffmt->height); 4443 4444 if (ffmt->width < req_ffmt->width || 4445 ffmt->height < req_ffmt->height) { 4446 req_ffmt->height -= dvs_env_h; 4447 req_ffmt->width -= dvs_env_w; 4448 ffmt = req_ffmt; 4449 dev_warn(isp->dev, 4450 "can not enable video dis due to sensor limitation."); 4451 asd->params.video_dis_en = false; 4452 } 4453 } 4454 vformat.which = V4L2_SUBDEV_FORMAT_ACTIVE; 4455 ret = v4l2_subdev_call(isp->inputs[asd->input_curr].camera, pad, 4456 set_fmt, NULL, &vformat); 4457 if (ret) 4458 return ret; 4459 4460 __atomisp_update_stream_env(asd, ATOMISP_INPUT_STREAM_GENERAL, stream_info); 4461 4462 dev_dbg(isp->dev, "sensor width: %d, height: %d\n", 4463 ffmt->width, ffmt->height); 4464 4465 if (ffmt->width < ATOM_ISP_STEP_WIDTH || 4466 ffmt->height < ATOM_ISP_STEP_HEIGHT) 4467 return -EINVAL; 4468 4469 if (asd->params.video_dis_en && 4470 source_pad == ATOMISP_SUBDEV_PAD_SOURCE_VIDEO && 4471 (ffmt->width < req_ffmt->width || ffmt->height < req_ffmt->height)) { 4472 dev_warn(isp->dev, 4473 "can not enable video dis due to sensor limitation."); 4474 asd->params.video_dis_en = false; 4475 } 4476 4477 atomisp_subdev_set_ffmt(&asd->subdev, fh.state, 4478 V4L2_SUBDEV_FORMAT_ACTIVE, 4479 ATOMISP_SUBDEV_PAD_SINK, ffmt); 4480 4481 return css_input_resolution_changed(asd, ffmt); 4482 } 4483 4484 int atomisp_set_fmt(struct video_device *vdev, struct v4l2_format *f) 4485 { 4486 struct atomisp_device *isp = video_get_drvdata(vdev); 4487 struct atomisp_video_pipe *pipe = atomisp_to_video_pipe(vdev); 4488 struct atomisp_sub_device *asd = pipe->asd; 4489 const struct atomisp_format_bridge *format_bridge; 4490 const struct atomisp_format_bridge *snr_format_bridge; 4491 struct ia_css_frame_info output_info; 4492 unsigned int dvs_env_w = 0, dvs_env_h = 0; 4493 unsigned int padding_w = pad_w, padding_h = pad_h; 4494 struct v4l2_mbus_framefmt isp_source_fmt = {0}; 4495 struct v4l2_subdev_format vformat = { 4496 .which = V4L2_SUBDEV_FORMAT_ACTIVE, 4497 }; 4498 struct v4l2_rect isp_sink_crop; 4499 u16 source_pad = atomisp_subdev_source_pad(vdev); 4500 struct v4l2_subdev_fh fh; 4501 int ret; 4502 4503 ret = atomisp_pipe_check(pipe, true); 4504 if (ret) 4505 return ret; 4506 4507 if (source_pad >= ATOMISP_SUBDEV_PADS_NUM) 4508 return -EINVAL; 4509 4510 dev_dbg(isp->dev, 4511 "setting resolution %ux%u on pad %u bytesperline %u\n", 4512 f->fmt.pix.width, f->fmt.pix.height, source_pad, f->fmt.pix.bytesperline); 4513 4514 v4l2_fh_init(&fh.vfh, vdev); 4515 4516 format_bridge = atomisp_get_format_bridge(f->fmt.pix.pixelformat); 4517 if (!format_bridge) 4518 return -EINVAL; 4519 4520 /* Currently, raw formats are broken!!! */ 4521 4522 if (format_bridge->sh_fmt == IA_CSS_FRAME_FORMAT_RAW) { 4523 f->fmt.pix.pixelformat = V4L2_PIX_FMT_YUV420; 4524 4525 format_bridge = atomisp_get_format_bridge(f->fmt.pix.pixelformat); 4526 if (!format_bridge) 4527 return -EINVAL; 4528 } 4529 pipe->sh_fmt = format_bridge->sh_fmt; 4530 pipe->pix.pixelformat = f->fmt.pix.pixelformat; 4531 4532 /* Ensure that the resolution is equal or below the maximum supported */ 4533 4534 vformat.which = V4L2_SUBDEV_FORMAT_ACTIVE; 4535 v4l2_fill_mbus_format(&vformat.format, &f->fmt.pix, format_bridge->mbus_code); 4536 vformat.format.height += padding_h; 4537 vformat.format.width += padding_w; 4538 4539 ret = v4l2_subdev_call(isp->inputs[asd->input_curr].camera, pad, 4540 set_fmt, NULL, &vformat); 4541 if (ret) 4542 return ret; 4543 4544 f->fmt.pix.width = vformat.format.width - padding_w; 4545 f->fmt.pix.height = vformat.format.height - padding_h; 4546 4547 snr_format_bridge = atomisp_get_format_bridge_from_mbus(vformat.format.code); 4548 if (!snr_format_bridge) { 4549 dev_warn(isp->dev, "Can't find bridge format\n"); 4550 return -EINVAL; 4551 } 4552 4553 atomisp_subdev_get_ffmt(&asd->subdev, NULL, 4554 V4L2_SUBDEV_FORMAT_ACTIVE, 4555 ATOMISP_SUBDEV_PAD_SINK)->code = 4556 snr_format_bridge->mbus_code; 4557 4558 isp_source_fmt.code = format_bridge->mbus_code; 4559 atomisp_subdev_set_ffmt(&asd->subdev, fh.state, 4560 V4L2_SUBDEV_FORMAT_ACTIVE, 4561 source_pad, &isp_source_fmt); 4562 4563 if (!atomisp_subdev_format_conversion(asd, source_pad)) { 4564 padding_w = 0; 4565 padding_h = 0; 4566 } 4567 4568 atomisp_get_dis_envelop(asd, f->fmt.pix.width, f->fmt.pix.height, 4569 &dvs_env_w, &dvs_env_h); 4570 4571 asd->capture_pad = source_pad; 4572 4573 ret = atomisp_set_fmt_to_snr(vdev, &f->fmt.pix, 4574 padding_w, padding_h, dvs_env_w, dvs_env_h); 4575 if (ret) { 4576 dev_warn(isp->dev, 4577 "Set format to sensor failed with %d\n", ret); 4578 return -EINVAL; 4579 } 4580 4581 atomisp_csi_lane_config(isp); 4582 4583 atomisp_check_copy_mode(asd, source_pad, &f->fmt.pix); 4584 4585 isp_sink_crop = *atomisp_subdev_get_rect(&asd->subdev, NULL, 4586 V4L2_SUBDEV_FORMAT_ACTIVE, 4587 ATOMISP_SUBDEV_PAD_SINK, 4588 V4L2_SEL_TGT_CROP); 4589 4590 /* Try to enable YUV downscaling if ISP input is 10 % (either 4591 * width or height) bigger than the desired result. */ 4592 if (isp_sink_crop.width * 9 / 10 < f->fmt.pix.width || 4593 isp_sink_crop.height * 9 / 10 < f->fmt.pix.height || 4594 (atomisp_subdev_format_conversion(asd, source_pad) && 4595 (asd->run_mode->val == ATOMISP_RUN_MODE_VIDEO || 4596 asd->vfpp->val == ATOMISP_VFPP_DISABLE_SCALER))) { 4597 isp_sink_crop.width = f->fmt.pix.width; 4598 isp_sink_crop.height = f->fmt.pix.height; 4599 4600 atomisp_subdev_set_selection(&asd->subdev, fh.state, 4601 V4L2_SUBDEV_FORMAT_ACTIVE, 4602 ATOMISP_SUBDEV_PAD_SINK, 4603 V4L2_SEL_TGT_CROP, 4604 V4L2_SEL_FLAG_KEEP_CONFIG, 4605 &isp_sink_crop); 4606 atomisp_subdev_set_selection(&asd->subdev, fh.state, 4607 V4L2_SUBDEV_FORMAT_ACTIVE, 4608 source_pad, V4L2_SEL_TGT_COMPOSE, 4609 0, &isp_sink_crop); 4610 } else if (IS_MOFD) { 4611 struct v4l2_rect main_compose = {0}; 4612 4613 main_compose.width = isp_sink_crop.width; 4614 main_compose.height = 4615 DIV_ROUND_UP(main_compose.width * f->fmt.pix.height, 4616 f->fmt.pix.width); 4617 if (main_compose.height > isp_sink_crop.height) { 4618 main_compose.height = isp_sink_crop.height; 4619 main_compose.width = 4620 DIV_ROUND_UP(main_compose.height * 4621 f->fmt.pix.width, 4622 f->fmt.pix.height); 4623 } 4624 4625 atomisp_subdev_set_selection(&asd->subdev, fh.state, 4626 V4L2_SUBDEV_FORMAT_ACTIVE, 4627 source_pad, 4628 V4L2_SEL_TGT_COMPOSE, 0, 4629 &main_compose); 4630 } else { 4631 struct v4l2_rect sink_crop = {0}; 4632 struct v4l2_rect main_compose = {0}; 4633 4634 main_compose.width = f->fmt.pix.width; 4635 main_compose.height = f->fmt.pix.height; 4636 4637 /* WORKAROUND: this override is universally enabled in 4638 * GMIN to work around a CTS failures (GMINL-539) 4639 * which appears to be related by a hardware 4640 * performance limitation. It's unclear why this 4641 * particular code triggers the issue. */ 4642 if (isp_sink_crop.width * main_compose.height > 4643 isp_sink_crop.height * main_compose.width) { 4644 sink_crop.height = isp_sink_crop.height; 4645 sink_crop.width = 4646 DIV_NEAREST_STEP(sink_crop.height * f->fmt.pix.width, 4647 f->fmt.pix.height, 4648 ATOM_ISP_STEP_WIDTH); 4649 } else { 4650 sink_crop.width = isp_sink_crop.width; 4651 sink_crop.height = 4652 DIV_NEAREST_STEP(sink_crop.width * f->fmt.pix.height, 4653 f->fmt.pix.width, 4654 ATOM_ISP_STEP_HEIGHT); 4655 } 4656 atomisp_subdev_set_selection(&asd->subdev, fh.state, 4657 V4L2_SUBDEV_FORMAT_ACTIVE, 4658 ATOMISP_SUBDEV_PAD_SINK, 4659 V4L2_SEL_TGT_CROP, 4660 V4L2_SEL_FLAG_KEEP_CONFIG, 4661 &sink_crop); 4662 4663 atomisp_subdev_set_selection(&asd->subdev, fh.state, 4664 V4L2_SUBDEV_FORMAT_ACTIVE, 4665 source_pad, 4666 V4L2_SEL_TGT_COMPOSE, 0, 4667 &main_compose); 4668 } 4669 4670 ret = atomisp_set_fmt_to_isp(vdev, &output_info, &f->fmt.pix, source_pad); 4671 if (ret) { 4672 dev_warn(isp->dev, "Can't set format on ISP. Error %d\n", ret); 4673 return -EINVAL; 4674 } 4675 4676 pipe->pix.width = f->fmt.pix.width; 4677 pipe->pix.height = f->fmt.pix.height; 4678 pipe->pix.pixelformat = f->fmt.pix.pixelformat; 4679 /* 4680 * FIXME: do we need to setup this differently, depending on the 4681 * sensor or the pipeline? 4682 */ 4683 pipe->pix.colorspace = V4L2_COLORSPACE_REC709; 4684 pipe->pix.ycbcr_enc = V4L2_YCBCR_ENC_709; 4685 pipe->pix.xfer_func = V4L2_XFER_FUNC_709; 4686 4687 if (format_bridge->planar) { 4688 pipe->pix.bytesperline = output_info.padded_width; 4689 pipe->pix.sizeimage = PAGE_ALIGN(f->fmt.pix.height * 4690 DIV_ROUND_UP(format_bridge->depth * 4691 output_info.padded_width, 8)); 4692 } else { 4693 pipe->pix.bytesperline = 4694 DIV_ROUND_UP(format_bridge->depth * 4695 output_info.padded_width, 8); 4696 pipe->pix.sizeimage = 4697 PAGE_ALIGN(f->fmt.pix.height * pipe->pix.bytesperline); 4698 } 4699 dev_dbg(isp->dev, "%s: image size: %d, %d bytes per line\n", 4700 __func__, pipe->pix.sizeimage, pipe->pix.bytesperline); 4701 4702 if (f->fmt.pix.field == V4L2_FIELD_ANY) 4703 f->fmt.pix.field = V4L2_FIELD_NONE; 4704 pipe->pix.field = f->fmt.pix.field; 4705 4706 f->fmt.pix = pipe->pix; 4707 f->fmt.pix.priv = PAGE_ALIGN(pipe->pix.width * 4708 pipe->pix.height * 2); 4709 4710 /* 4711 * If in video 480P case, no GFX throttle 4712 */ 4713 if (asd->run_mode->val == ATOMISP_SUBDEV_PAD_SOURCE_VIDEO && 4714 f->fmt.pix.width == 720 && f->fmt.pix.height == 480) 4715 isp->need_gfx_throttle = false; 4716 else 4717 isp->need_gfx_throttle = true; 4718 4719 /* Report the needed sizes */ 4720 f->fmt.pix.sizeimage = pipe->pix.sizeimage; 4721 f->fmt.pix.bytesperline = pipe->pix.bytesperline; 4722 4723 dev_dbg(isp->dev, "%s: %dx%d, image size: %d, %d bytes per line\n", 4724 __func__, 4725 f->fmt.pix.width, f->fmt.pix.height, 4726 f->fmt.pix.sizeimage, f->fmt.pix.bytesperline); 4727 4728 return 0; 4729 } 4730 4731 int atomisp_set_shading_table(struct atomisp_sub_device *asd, 4732 struct atomisp_shading_table *user_shading_table) 4733 { 4734 struct ia_css_shading_table *shading_table; 4735 struct ia_css_shading_table *free_table; 4736 unsigned int len_table; 4737 int i; 4738 int ret = 0; 4739 4740 if (!user_shading_table) 4741 return -EINVAL; 4742 4743 if (!user_shading_table->enable) { 4744 asd->params.config.shading_table = NULL; 4745 asd->params.sc_en = false; 4746 return 0; 4747 } 4748 4749 /* If enabling, all tables must be set */ 4750 for (i = 0; i < ATOMISP_NUM_SC_COLORS; i++) { 4751 if (!user_shading_table->data[i]) 4752 return -EINVAL; 4753 } 4754 4755 /* Shading table size per color */ 4756 if (user_shading_table->width > SH_CSS_MAX_SCTBL_WIDTH_PER_COLOR || 4757 user_shading_table->height > SH_CSS_MAX_SCTBL_HEIGHT_PER_COLOR) 4758 return -EINVAL; 4759 4760 shading_table = atomisp_css_shading_table_alloc( 4761 user_shading_table->width, user_shading_table->height); 4762 if (!shading_table) 4763 return -ENOMEM; 4764 4765 len_table = user_shading_table->width * user_shading_table->height * 4766 ATOMISP_SC_TYPE_SIZE; 4767 for (i = 0; i < ATOMISP_NUM_SC_COLORS; i++) { 4768 ret = copy_from_user(shading_table->data[i], 4769 (void __user *)user_shading_table->data[i], 4770 len_table); 4771 if (ret) { 4772 free_table = shading_table; 4773 ret = -EFAULT; 4774 goto out; 4775 } 4776 } 4777 shading_table->sensor_width = user_shading_table->sensor_width; 4778 shading_table->sensor_height = user_shading_table->sensor_height; 4779 shading_table->fraction_bits = user_shading_table->fraction_bits; 4780 4781 free_table = asd->params.css_param.shading_table; 4782 asd->params.css_param.shading_table = shading_table; 4783 asd->params.config.shading_table = shading_table; 4784 asd->params.sc_en = true; 4785 4786 out: 4787 if (free_table) 4788 atomisp_css_shading_table_free(free_table); 4789 4790 return ret; 4791 } 4792 4793 /* 4794 * set auto exposure metering window to camera sensor 4795 */ 4796 int atomisp_s_ae_window(struct atomisp_sub_device *asd, 4797 struct atomisp_ae_window *arg) 4798 { 4799 struct atomisp_device *isp = asd->isp; 4800 /* Coverity CID 298071 - initialzize struct */ 4801 struct v4l2_subdev_selection sel = { 0 }; 4802 4803 sel.r.left = arg->x_left; 4804 sel.r.top = arg->y_top; 4805 sel.r.width = arg->x_right - arg->x_left + 1; 4806 sel.r.height = arg->y_bottom - arg->y_top + 1; 4807 4808 if (v4l2_subdev_call(isp->inputs[asd->input_curr].camera, 4809 pad, set_selection, NULL, &sel)) { 4810 dev_err(isp->dev, "failed to call sensor set_selection.\n"); 4811 return -EINVAL; 4812 } 4813 4814 return 0; 4815 } 4816 4817 int atomisp_flash_enable(struct atomisp_sub_device *asd, int num_frames) 4818 { 4819 struct atomisp_device *isp = asd->isp; 4820 4821 if (num_frames < 0) { 4822 dev_dbg(isp->dev, "%s ERROR: num_frames: %d\n", __func__, 4823 num_frames); 4824 return -EINVAL; 4825 } 4826 /* a requested flash is still in progress. */ 4827 if (num_frames && asd->params.flash_state != ATOMISP_FLASH_IDLE) { 4828 dev_dbg(isp->dev, "%s flash busy: %d frames left: %d\n", 4829 __func__, asd->params.flash_state, 4830 asd->params.num_flash_frames); 4831 return -EBUSY; 4832 } 4833 4834 asd->params.num_flash_frames = num_frames; 4835 asd->params.flash_state = ATOMISP_FLASH_REQUESTED; 4836 return 0; 4837 } 4838 4839 bool atomisp_is_vf_pipe(struct atomisp_video_pipe *pipe) 4840 { 4841 struct atomisp_sub_device *asd = pipe->asd; 4842 4843 if (!asd) { 4844 dev_err(pipe->isp->dev, "%s(): asd is NULL, device is %s\n", 4845 __func__, pipe->vdev.name); 4846 return false; 4847 } 4848 4849 if (pipe == &asd->video_out_vf) 4850 return true; 4851 4852 if (asd->run_mode->val == ATOMISP_RUN_MODE_VIDEO && 4853 pipe == &asd->video_out_preview) 4854 return true; 4855 4856 return false; 4857 } 4858 4859 static int __checking_exp_id(struct atomisp_sub_device *asd, int exp_id) 4860 { 4861 struct atomisp_device *isp = asd->isp; 4862 4863 if (!asd->enable_raw_buffer_lock->val) { 4864 dev_warn(isp->dev, "%s Raw Buffer Lock is disable.\n", __func__); 4865 return -EINVAL; 4866 } 4867 if (asd->streaming != ATOMISP_DEVICE_STREAMING_ENABLED) { 4868 dev_err(isp->dev, "%s streaming %d invalid exp_id %d.\n", 4869 __func__, exp_id, asd->streaming); 4870 return -EINVAL; 4871 } 4872 if ((exp_id > ATOMISP_MAX_EXP_ID) || (exp_id <= 0)) { 4873 dev_err(isp->dev, "%s exp_id %d invalid.\n", __func__, exp_id); 4874 return -EINVAL; 4875 } 4876 return 0; 4877 } 4878 4879 void atomisp_init_raw_buffer_bitmap(struct atomisp_sub_device *asd) 4880 { 4881 unsigned long flags; 4882 4883 spin_lock_irqsave(&asd->raw_buffer_bitmap_lock, flags); 4884 memset(asd->raw_buffer_bitmap, 0, sizeof(asd->raw_buffer_bitmap)); 4885 asd->raw_buffer_locked_count = 0; 4886 spin_unlock_irqrestore(&asd->raw_buffer_bitmap_lock, flags); 4887 } 4888 4889 static int __is_raw_buffer_locked(struct atomisp_sub_device *asd, int exp_id) 4890 { 4891 int *bitmap, bit; 4892 unsigned long flags; 4893 int ret; 4894 4895 if (__checking_exp_id(asd, exp_id)) 4896 return -EINVAL; 4897 4898 bitmap = asd->raw_buffer_bitmap + exp_id / 32; 4899 bit = exp_id % 32; 4900 spin_lock_irqsave(&asd->raw_buffer_bitmap_lock, flags); 4901 ret = ((*bitmap) & (1 << bit)); 4902 spin_unlock_irqrestore(&asd->raw_buffer_bitmap_lock, flags); 4903 return !ret; 4904 } 4905 4906 static int __clear_raw_buffer_bitmap(struct atomisp_sub_device *asd, int exp_id) 4907 { 4908 int *bitmap, bit; 4909 unsigned long flags; 4910 4911 if (__is_raw_buffer_locked(asd, exp_id)) 4912 return -EINVAL; 4913 4914 bitmap = asd->raw_buffer_bitmap + exp_id / 32; 4915 bit = exp_id % 32; 4916 spin_lock_irqsave(&asd->raw_buffer_bitmap_lock, flags); 4917 (*bitmap) &= ~(1 << bit); 4918 asd->raw_buffer_locked_count--; 4919 spin_unlock_irqrestore(&asd->raw_buffer_bitmap_lock, flags); 4920 4921 dev_dbg(asd->isp->dev, "%s: exp_id %d, raw_buffer_locked_count %d\n", 4922 __func__, exp_id, asd->raw_buffer_locked_count); 4923 return 0; 4924 } 4925 4926 int atomisp_exp_id_capture(struct atomisp_sub_device *asd, int *exp_id) 4927 { 4928 struct atomisp_device *isp = asd->isp; 4929 int value = *exp_id; 4930 int ret; 4931 4932 lockdep_assert_held(&isp->mutex); 4933 4934 ret = __is_raw_buffer_locked(asd, value); 4935 if (ret) { 4936 dev_err(isp->dev, "%s exp_id %d invalid %d.\n", __func__, value, ret); 4937 return -EINVAL; 4938 } 4939 4940 dev_dbg(isp->dev, "%s exp_id %d\n", __func__, value); 4941 ret = atomisp_css_exp_id_capture(asd, value); 4942 if (ret) { 4943 dev_err(isp->dev, "%s exp_id %d failed.\n", __func__, value); 4944 return -EIO; 4945 } 4946 return 0; 4947 } 4948 4949 int atomisp_exp_id_unlock(struct atomisp_sub_device *asd, int *exp_id) 4950 { 4951 struct atomisp_device *isp = asd->isp; 4952 int value = *exp_id; 4953 int ret; 4954 4955 lockdep_assert_held(&isp->mutex); 4956 4957 ret = __clear_raw_buffer_bitmap(asd, value); 4958 if (ret) { 4959 dev_err(isp->dev, "%s exp_id %d invalid %d.\n", __func__, value, ret); 4960 return -EINVAL; 4961 } 4962 4963 dev_dbg(isp->dev, "%s exp_id %d\n", __func__, value); 4964 ret = atomisp_css_exp_id_unlock(asd, value); 4965 if (ret) 4966 dev_err(isp->dev, "%s exp_id %d failed, err %d.\n", 4967 __func__, value, ret); 4968 4969 return ret; 4970 } 4971 4972 int atomisp_enable_dz_capt_pipe(struct atomisp_sub_device *asd, 4973 unsigned int *enable) 4974 { 4975 bool value; 4976 4977 if (!enable) 4978 return -EINVAL; 4979 4980 value = *enable > 0; 4981 4982 atomisp_en_dz_capt_pipe(asd, value); 4983 4984 return 0; 4985 } 4986 4987 int atomisp_inject_a_fake_event(struct atomisp_sub_device *asd, int *event) 4988 { 4989 if (!event || asd->streaming != ATOMISP_DEVICE_STREAMING_ENABLED) 4990 return -EINVAL; 4991 4992 lockdep_assert_held(&asd->isp->mutex); 4993 4994 dev_dbg(asd->isp->dev, "%s: trying to inject a fake event 0x%x\n", 4995 __func__, *event); 4996 4997 switch (*event) { 4998 case V4L2_EVENT_FRAME_SYNC: 4999 atomisp_sof_event(asd); 5000 break; 5001 case V4L2_EVENT_FRAME_END: 5002 atomisp_eof_event(asd, 0); 5003 break; 5004 case V4L2_EVENT_ATOMISP_3A_STATS_READY: 5005 atomisp_3a_stats_ready_event(asd, 0); 5006 break; 5007 case V4L2_EVENT_ATOMISP_METADATA_READY: 5008 atomisp_metadata_ready_event(asd, 0); 5009 break; 5010 default: 5011 return -EINVAL; 5012 } 5013 5014 return 0; 5015 } 5016 5017 static int atomisp_get_pipe_id(struct atomisp_video_pipe *pipe) 5018 { 5019 struct atomisp_sub_device *asd = pipe->asd; 5020 5021 if (!asd) { 5022 dev_err(pipe->isp->dev, "%s(): asd is NULL, device is %s\n", 5023 __func__, pipe->vdev.name); 5024 return -EINVAL; 5025 } 5026 5027 if (asd->vfpp->val == ATOMISP_VFPP_DISABLE_SCALER) { 5028 return IA_CSS_PIPE_ID_VIDEO; 5029 } else if (asd->vfpp->val == ATOMISP_VFPP_DISABLE_LOWLAT) { 5030 return IA_CSS_PIPE_ID_CAPTURE; 5031 } else if (pipe == &asd->video_out_video_capture) { 5032 return IA_CSS_PIPE_ID_VIDEO; 5033 } else if (pipe == &asd->video_out_vf) { 5034 return IA_CSS_PIPE_ID_CAPTURE; 5035 } else if (pipe == &asd->video_out_preview) { 5036 if (asd->run_mode->val == ATOMISP_RUN_MODE_VIDEO) 5037 return IA_CSS_PIPE_ID_VIDEO; 5038 else 5039 return IA_CSS_PIPE_ID_PREVIEW; 5040 } else if (pipe == &asd->video_out_capture) { 5041 if (asd->copy_mode) 5042 return IA_CSS_PIPE_ID_COPY; 5043 else 5044 return IA_CSS_PIPE_ID_CAPTURE; 5045 } 5046 5047 /* fail through */ 5048 dev_warn(asd->isp->dev, "%s failed to find proper pipe\n", 5049 __func__); 5050 return IA_CSS_PIPE_ID_CAPTURE; 5051 } 5052 5053 int atomisp_get_invalid_frame_num(struct video_device *vdev, 5054 int *invalid_frame_num) 5055 { 5056 struct atomisp_video_pipe *pipe = atomisp_to_video_pipe(vdev); 5057 struct atomisp_sub_device *asd = pipe->asd; 5058 enum ia_css_pipe_id pipe_id; 5059 struct ia_css_pipe_info p_info; 5060 int ret; 5061 5062 pipe_id = atomisp_get_pipe_id(pipe); 5063 if (!asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].pipes[pipe_id]) { 5064 dev_warn(asd->isp->dev, 5065 "%s pipe %d has not been created yet, do SET_FMT first!\n", 5066 __func__, pipe_id); 5067 return -EINVAL; 5068 } 5069 5070 ret = ia_css_pipe_get_info( 5071 asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL] 5072 .pipes[pipe_id], &p_info); 5073 if (!ret) { 5074 *invalid_frame_num = p_info.num_invalid_frames; 5075 return 0; 5076 } else { 5077 dev_warn(asd->isp->dev, "%s get pipe infor failed %d\n", 5078 __func__, ret); 5079 return -EINVAL; 5080 } 5081 } 5082