.. | .. |
---|
35 | 35 | * rkisp_hw |
---|
36 | 36 | */ |
---|
37 | 37 | |
---|
| 38 | +struct backup_reg { |
---|
| 39 | + const u32 base; |
---|
| 40 | + const u32 shd; |
---|
| 41 | + u32 val; |
---|
| 42 | +}; |
---|
| 43 | + |
---|
38 | 44 | struct isp_irqs_data { |
---|
39 | 45 | const char *name; |
---|
40 | 46 | irqreturn_t (*irq_hdl)(int irq, void *ctx); |
---|
.. | .. |
---|
346 | 352 | } |
---|
347 | 353 | |
---|
348 | 354 | return 0; |
---|
| 355 | +} |
---|
| 356 | + |
---|
| 357 | +void rkisp_hw_reg_save(struct rkisp_hw_dev *dev) |
---|
| 358 | +{ |
---|
| 359 | + void *buf = dev->sw_reg; |
---|
| 360 | + |
---|
| 361 | + memcpy_fromio(buf, dev->base_addr, RKISP_ISP_SW_REG_SIZE); |
---|
| 362 | + if (dev->unite == ISP_UNITE_TWO) { |
---|
| 363 | + buf += RKISP_ISP_SW_REG_SIZE; |
---|
| 364 | + memcpy_fromio(buf, dev->base_next_addr, RKISP_ISP_SW_REG_SIZE); |
---|
| 365 | + } |
---|
| 366 | +} |
---|
| 367 | + |
---|
| 368 | +void rkisp_hw_reg_restore(struct rkisp_hw_dev *dev) |
---|
| 369 | +{ |
---|
| 370 | + struct rkisp_device *isp = dev->isp[dev->cur_dev_id]; |
---|
| 371 | + void __iomem *base = dev->base_addr; |
---|
| 372 | + void *reg_buf = dev->sw_reg; |
---|
| 373 | + u32 val, *reg, *reg1, i, j; |
---|
| 374 | + u32 self_upd_reg[] = { |
---|
| 375 | + ISP21_BAY3D_BASE, ISP21_DRC_BASE, ISP3X_BAY3D_CTRL, |
---|
| 376 | + ISP_DHAZ_CTRL, ISP3X_3DLUT_BASE, ISP_RAWAE_LITE_BASE, |
---|
| 377 | + RAWAE_BIG1_BASE, RAWAE_BIG2_BASE, RAWAE_BIG3_BASE, |
---|
| 378 | + ISP_RAWHIST_LITE_BASE, ISP_RAWHIST_BIG1_BASE, |
---|
| 379 | + ISP_RAWHIST_BIG2_BASE, ISP_RAWHIST_BIG3_BASE, |
---|
| 380 | + ISP_RAWAF_BASE, ISP_RAWAWB_BASE, ISP_LDCH_BASE, |
---|
| 381 | + ISP3X_CAC_BASE, |
---|
| 382 | + }; |
---|
| 383 | + struct backup_reg backup[] = { |
---|
| 384 | + { |
---|
| 385 | + .base = MI_MP_WR_Y_BASE, |
---|
| 386 | + .shd = MI_MP_WR_Y_BASE_SHD, |
---|
| 387 | + }, { |
---|
| 388 | + .base = MI_MP_WR_CB_BASE, |
---|
| 389 | + .shd = MI_MP_WR_CB_BASE_SHD, |
---|
| 390 | + }, { |
---|
| 391 | + .base = MI_MP_WR_CR_BASE, |
---|
| 392 | + .shd = MI_MP_WR_CR_BASE_SHD, |
---|
| 393 | + }, { |
---|
| 394 | + .base = MI_SP_WR_Y_BASE, |
---|
| 395 | + .shd = MI_SP_WR_Y_BASE_SHD, |
---|
| 396 | + }, { |
---|
| 397 | + .base = MI_SP_WR_CB_BASE, |
---|
| 398 | + .shd = MI_SP_WR_CB_BASE_AD_SHD, |
---|
| 399 | + }, { |
---|
| 400 | + .base = MI_SP_WR_CR_BASE, |
---|
| 401 | + .shd = MI_SP_WR_CR_BASE_AD_SHD, |
---|
| 402 | + }, { |
---|
| 403 | + .base = ISP3X_MI_BP_WR_Y_BASE, |
---|
| 404 | + .shd = ISP3X_MI_BP_WR_Y_BASE_SHD, |
---|
| 405 | + }, { |
---|
| 406 | + .base = ISP3X_MI_BP_WR_CB_BASE, |
---|
| 407 | + .shd = ISP3X_MI_BP_WR_CB_BASE_SHD, |
---|
| 408 | + }, { |
---|
| 409 | + .base = ISP32_MI_MPDS_WR_Y_BASE, |
---|
| 410 | + .shd = ISP32_MI_MPDS_WR_Y_BASE_SHD, |
---|
| 411 | + }, { |
---|
| 412 | + .base = ISP32_MI_MPDS_WR_CB_BASE, |
---|
| 413 | + .shd = ISP32_MI_MPDS_WR_CB_BASE_SHD, |
---|
| 414 | + }, { |
---|
| 415 | + .base = ISP32_MI_BPDS_WR_Y_BASE, |
---|
| 416 | + .shd = ISP32_MI_BPDS_WR_Y_BASE_SHD, |
---|
| 417 | + }, { |
---|
| 418 | + .base = ISP32_MI_BPDS_WR_CB_BASE, |
---|
| 419 | + .shd = ISP32_MI_BPDS_WR_CB_BASE_SHD, |
---|
| 420 | + }, { |
---|
| 421 | + .base = MI_RAW0_WR_BASE, |
---|
| 422 | + .shd = MI_RAW0_WR_BASE_SHD, |
---|
| 423 | + }, { |
---|
| 424 | + .base = MI_RAW1_WR_BASE, |
---|
| 425 | + .shd = MI_RAW1_WR_BASE_SHD, |
---|
| 426 | + }, { |
---|
| 427 | + .base = MI_RAW2_WR_BASE, |
---|
| 428 | + .shd = MI_RAW2_WR_BASE_SHD, |
---|
| 429 | + }, { |
---|
| 430 | + .base = MI_RAW3_WR_BASE, |
---|
| 431 | + .shd = MI_RAW3_WR_BASE_SHD, |
---|
| 432 | + }, { |
---|
| 433 | + .base = MI_RAW0_RD_BASE, |
---|
| 434 | + .shd = MI_RAW0_RD_BASE_SHD, |
---|
| 435 | + }, { |
---|
| 436 | + .base = MI_RAW1_RD_BASE, |
---|
| 437 | + .shd = MI_RAW1_RD_BASE_SHD, |
---|
| 438 | + }, { |
---|
| 439 | + .base = MI_RAW2_RD_BASE, |
---|
| 440 | + .shd = MI_RAW2_RD_BASE_SHD, |
---|
| 441 | + }, { |
---|
| 442 | + .base = MI_GAIN_WR_BASE, |
---|
| 443 | + .shd = MI_GAIN_WR_BASE_SHD, |
---|
| 444 | + } |
---|
| 445 | + }; |
---|
| 446 | + |
---|
| 447 | + for (i = 0; i <= !!dev->unite; i++) { |
---|
| 448 | + if (dev->unite != ISP_UNITE_TWO && i) |
---|
| 449 | + break; |
---|
| 450 | + |
---|
| 451 | + if (i) { |
---|
| 452 | + reg_buf += RKISP_ISP_SW_REG_SIZE; |
---|
| 453 | + base = dev->base_next_addr; |
---|
| 454 | + } |
---|
| 455 | + |
---|
| 456 | + /* process special reg */ |
---|
| 457 | + for (j = 0; j < ARRAY_SIZE(self_upd_reg); j++) { |
---|
| 458 | + reg = reg_buf + self_upd_reg[j]; |
---|
| 459 | + *reg &= ~ISP21_SELF_FORCE_UPD; |
---|
| 460 | + if (self_upd_reg[j] == ISP3X_3DLUT_BASE && *reg & ISP_3DLUT_EN) { |
---|
| 461 | + reg = reg_buf + ISP3X_3DLUT_UPDATE; |
---|
| 462 | + *reg = 1; |
---|
| 463 | + } |
---|
| 464 | + } |
---|
| 465 | + reg = reg_buf + ISP_CTRL; |
---|
| 466 | + *reg &= ~(CIF_ISP_CTRL_ISP_ENABLE | |
---|
| 467 | + CIF_ISP_CTRL_ISP_INFORM_ENABLE | |
---|
| 468 | + CIF_ISP_CTRL_ISP_CFG_UPD); |
---|
| 469 | + reg = reg_buf + MI_WR_INIT; |
---|
| 470 | + *reg = 0; |
---|
| 471 | + reg = reg_buf + CSI2RX_CTRL0; |
---|
| 472 | + *reg &= ~SW_CSI2RX_EN; |
---|
| 473 | + for (j = 0; j < RKISP_ISP_SW_REG_SIZE; j += 4) { |
---|
| 474 | + /* skip table RAM */ |
---|
| 475 | + if ((j > ISP3X_LSC_CTRL && j < ISP3X_LSC_XGRAD_01) || |
---|
| 476 | + (j > ISP32_CAC_OFFSET && j < ISP3X_CAC_RO_CNT) || |
---|
| 477 | + (j > ISP3X_3DLUT_UPDATE && j < ISP3X_GAIN_BASE) || |
---|
| 478 | + (j == 0x4840 || j == 0x4a80 || j == 0x4b40 || j == 0x5660)) |
---|
| 479 | + continue; |
---|
| 480 | + /* skip mmu range */ |
---|
| 481 | + if (dev->isp_ver < ISP_V30 && |
---|
| 482 | + j > ISP21_MI_BAY3D_RD_BASE_SHD && j < CSI2RX_CTRL0) |
---|
| 483 | + continue; |
---|
| 484 | + /* reg value of read diff to write */ |
---|
| 485 | + if (j == ISP_MPFBC_CTRL || |
---|
| 486 | + j == ISP32_ISP_AWB1_GAIN_G || j == ISP32_ISP_AWB1_GAIN_RB) |
---|
| 487 | + reg = isp->sw_base_addr + j; |
---|
| 488 | + else |
---|
| 489 | + reg = reg_buf + j; |
---|
| 490 | + writel(*reg, base + j); |
---|
| 491 | + } |
---|
| 492 | + |
---|
| 493 | + /* config shd_reg to base_reg */ |
---|
| 494 | + for (j = 0; j < ARRAY_SIZE(backup); j++) { |
---|
| 495 | + reg = reg_buf + backup[j].base; |
---|
| 496 | + reg1 = reg_buf + backup[j].shd; |
---|
| 497 | + backup[j].val = *reg; |
---|
| 498 | + writel(*reg1, base + backup[j].base); |
---|
| 499 | + } |
---|
| 500 | + |
---|
| 501 | + /* update module */ |
---|
| 502 | + reg = reg_buf + DUAL_CROP_CTRL; |
---|
| 503 | + if (*reg & 0xf) |
---|
| 504 | + writel(*reg | CIF_DUAL_CROP_CFG_UPD, base + DUAL_CROP_CTRL); |
---|
| 505 | + reg = reg_buf + SELF_RESIZE_CTRL; |
---|
| 506 | + if (*reg & 0xf) { |
---|
| 507 | + if (dev->isp_ver == ISP_V32_L) |
---|
| 508 | + writel(*reg | ISP32_SCALE_FORCE_UPD, base + ISP32_SELF_SCALE_UPDATE); |
---|
| 509 | + else |
---|
| 510 | + writel(*reg | CIF_RSZ_CTRL_CFG_UPD, base + SELF_RESIZE_CTRL); |
---|
| 511 | + } |
---|
| 512 | + reg = reg_buf + MAIN_RESIZE_CTRL; |
---|
| 513 | + if (*reg & 0xf) |
---|
| 514 | + writel(*reg | CIF_RSZ_CTRL_CFG_UPD, base + MAIN_RESIZE_CTRL); |
---|
| 515 | + reg = reg_buf + ISP32_BP_RESIZE_CTRL; |
---|
| 516 | + if (*reg & 0xf) |
---|
| 517 | + writel(*reg | CIF_RSZ_CTRL_CFG_UPD, base + ISP32_BP_RESIZE_CTRL); |
---|
| 518 | + |
---|
| 519 | + /* update mi and isp, base_reg will update to shd_reg */ |
---|
| 520 | + writel(CIF_MI_INIT_SOFT_UPD, base + MI_WR_INIT); |
---|
| 521 | + |
---|
| 522 | + /* config base_reg */ |
---|
| 523 | + for (j = 0; j < ARRAY_SIZE(backup); j++) |
---|
| 524 | + writel(backup[j].val, base + backup[j].base); |
---|
| 525 | + /* base_reg = shd_reg, write is base but read is shd */ |
---|
| 526 | + val = rkisp_read_reg_cache(isp, ISP_MPFBC_HEAD_PTR); |
---|
| 527 | + writel(val, base + ISP_MPFBC_HEAD_PTR); |
---|
| 528 | + val = rkisp_read_reg_cache(isp, MI_SWS_3A_WR_BASE); |
---|
| 529 | + writel(val, base + MI_SWS_3A_WR_BASE); |
---|
| 530 | + } |
---|
| 531 | + |
---|
| 532 | + rkisp_params_cfgsram(&isp->params_vdev, false); |
---|
| 533 | + |
---|
| 534 | + reg = reg_buf + ISP_CTRL; |
---|
| 535 | + *reg |= CIF_ISP_CTRL_ISP_ENABLE | |
---|
| 536 | + CIF_ISP_CTRL_ISP_CFG_UPD | |
---|
| 537 | + CIF_ISP_CTRL_ISP_INFORM_ENABLE; |
---|
| 538 | + writel(*reg, dev->base_addr + ISP_CTRL); |
---|
| 539 | + if (dev->unite == ISP_UNITE_TWO) |
---|
| 540 | + writel(*reg, dev->base_next_addr + ISP_CTRL); |
---|
349 | 541 | } |
---|
350 | 542 | |
---|
351 | 543 | static const char * const rk3562_isp_clks[] = { |
---|
.. | .. |
---|
779 | 971 | static int enable_sys_clk(struct rkisp_hw_dev *dev) |
---|
780 | 972 | { |
---|
781 | 973 | int i, ret = -EINVAL; |
---|
782 | | - unsigned long rate; |
---|
783 | 974 | |
---|
784 | 975 | for (i = 0; i < dev->num_clks; i++) { |
---|
785 | 976 | if (!IS_ERR(dev->clks[i])) { |
---|
.. | .. |
---|
789 | 980 | } |
---|
790 | 981 | } |
---|
791 | 982 | |
---|
792 | | - if (!dev->is_assigned_clk) { |
---|
793 | | - rate = dev->clk_rate_tbl[0].clk_rate * 1000000UL; |
---|
794 | | - rkisp_set_clk_rate(dev->clks[0], rate); |
---|
795 | | - if (dev->unite == ISP_UNITE_TWO) |
---|
796 | | - rkisp_set_clk_rate(dev->clks[5], rate); |
---|
797 | | - } |
---|
798 | 983 | rkisp_soft_reset(dev, false); |
---|
799 | 984 | isp_config_clk(dev, true); |
---|
800 | 985 | return 0; |
---|
.. | .. |
---|
851 | 1036 | struct device *dev = &pdev->dev; |
---|
852 | 1037 | struct rkisp_hw_dev *hw_dev; |
---|
853 | 1038 | struct resource *res; |
---|
854 | | - int i, ret; |
---|
| 1039 | + int i, ret, mult = 1; |
---|
855 | 1040 | bool is_mem_reserved = true; |
---|
856 | 1041 | u32 clk_rate = 0; |
---|
857 | 1042 | |
---|
858 | 1043 | match = of_match_node(rkisp_hw_of_match, node); |
---|
859 | 1044 | if (IS_ERR(match)) |
---|
860 | 1045 | return PTR_ERR(match); |
---|
| 1046 | + match_data = match->data; |
---|
861 | 1047 | |
---|
862 | 1048 | hw_dev = devm_kzalloc(dev, sizeof(*hw_dev), GFP_KERNEL); |
---|
863 | 1049 | if (!hw_dev) |
---|
864 | 1050 | return -ENOMEM; |
---|
865 | 1051 | |
---|
866 | | - match_data = match->data; |
---|
| 1052 | + if (match_data->unite) |
---|
| 1053 | + mult = 2; |
---|
| 1054 | + hw_dev->sw_reg = devm_kzalloc(dev, RKISP_ISP_SW_REG_SIZE * mult, GFP_KERNEL); |
---|
| 1055 | + if (!hw_dev->sw_reg) |
---|
| 1056 | + return -ENOMEM; |
---|
867 | 1057 | dev_set_drvdata(dev, hw_dev); |
---|
868 | 1058 | hw_dev->dev = dev; |
---|
869 | 1059 | hw_dev->is_thunderboot = IS_ENABLED(CONFIG_VIDEO_ROCKCHIP_THUNDER_BOOT_ISP); |
---|
.. | .. |
---|
1041 | 1231 | static int __maybe_unused rkisp_runtime_suspend(struct device *dev) |
---|
1042 | 1232 | { |
---|
1043 | 1233 | struct rkisp_hw_dev *hw_dev = dev_get_drvdata(dev); |
---|
| 1234 | + int i; |
---|
1044 | 1235 | |
---|
1045 | | - hw_dev->dev_link_num = 0; |
---|
1046 | | - hw_dev->is_single = true; |
---|
1047 | | - hw_dev->is_multi_overflow = false; |
---|
1048 | | - hw_dev->is_frm_buf = false; |
---|
| 1236 | + hw_dev->is_idle = true; |
---|
| 1237 | + if (dev->power.runtime_status) { |
---|
| 1238 | + hw_dev->dev_link_num = 0; |
---|
| 1239 | + hw_dev->is_single = true; |
---|
| 1240 | + hw_dev->is_multi_overflow = false; |
---|
| 1241 | + hw_dev->is_frm_buf = false; |
---|
| 1242 | + } else { |
---|
| 1243 | + /* system suspend */ |
---|
| 1244 | + for (i = 0; i < hw_dev->dev_num; i++) { |
---|
| 1245 | + if (hw_dev->isp_size[i].is_on) { |
---|
| 1246 | + rkisp_hw_reg_save(hw_dev); |
---|
| 1247 | + break; |
---|
| 1248 | + } |
---|
| 1249 | + } |
---|
| 1250 | + } |
---|
1049 | 1251 | disable_sys_clk(hw_dev); |
---|
1050 | 1252 | return pinctrl_pm_select_sleep_state(dev); |
---|
1051 | 1253 | } |
---|
.. | .. |
---|
1055 | 1257 | struct rkisp_device *isp; |
---|
1056 | 1258 | u32 w, h, i; |
---|
1057 | 1259 | |
---|
1058 | | - memset(hw_dev->isp_size, 0, sizeof(hw_dev->isp_size)); |
---|
1059 | 1260 | if (!hw_dev->max_in.is_fix) { |
---|
1060 | 1261 | hw_dev->max_in.w = 0; |
---|
1061 | 1262 | hw_dev->max_in.h = 0; |
---|
.. | .. |
---|
1108 | 1309 | return ret; |
---|
1109 | 1310 | |
---|
1110 | 1311 | enable_sys_clk(hw_dev); |
---|
1111 | | - for (i = 0; i < hw_dev->dev_num; i++) { |
---|
1112 | | - isp = hw_dev->isp[i]; |
---|
1113 | | - if (!isp || !isp->sw_base_addr) |
---|
1114 | | - continue; |
---|
1115 | | - buf = isp->sw_base_addr; |
---|
1116 | | - memset(buf, 0, RKISP_ISP_SW_MAX_SIZE * mult); |
---|
1117 | | - memcpy_fromio(buf, base, RKISP_ISP_SW_REG_SIZE); |
---|
1118 | | - if (hw_dev->unite) { |
---|
1119 | | - buf += RKISP_ISP_SW_MAX_SIZE; |
---|
1120 | | - base = hw_dev->base_next_addr; |
---|
1121 | | - memcpy_fromio(buf, base, RKISP_ISP_SW_REG_SIZE); |
---|
| 1312 | + if (dev->power.runtime_status) { |
---|
| 1313 | + if (!hw_dev->is_assigned_clk) { |
---|
| 1314 | + unsigned long rate = hw_dev->clk_rate_tbl[0].clk_rate * 1000000UL; |
---|
| 1315 | + |
---|
| 1316 | + rkisp_set_clk_rate(hw_dev->clks[0], rate); |
---|
| 1317 | + if (hw_dev->unite == ISP_UNITE_TWO) |
---|
| 1318 | + rkisp_set_clk_rate(hw_dev->clks[5], rate); |
---|
1122 | 1319 | } |
---|
1123 | | - default_sw_reg_flag(hw_dev->isp[i]); |
---|
| 1320 | + for (i = 0; i < hw_dev->dev_num; i++) { |
---|
| 1321 | + isp = hw_dev->isp[i]; |
---|
| 1322 | + if (!isp || !isp->sw_base_addr) |
---|
| 1323 | + continue; |
---|
| 1324 | + buf = isp->sw_base_addr; |
---|
| 1325 | + memset(buf, 0, RKISP_ISP_SW_MAX_SIZE * mult); |
---|
| 1326 | + memcpy_fromio(buf, base, RKISP_ISP_SW_REG_SIZE); |
---|
| 1327 | + if (hw_dev->unite) { |
---|
| 1328 | + buf += RKISP_ISP_SW_MAX_SIZE; |
---|
| 1329 | + base = hw_dev->base_next_addr; |
---|
| 1330 | + memcpy_fromio(buf, base, RKISP_ISP_SW_REG_SIZE); |
---|
| 1331 | + } |
---|
| 1332 | + default_sw_reg_flag(hw_dev->isp[i]); |
---|
| 1333 | + } |
---|
| 1334 | + rkisp_hw_enum_isp_size(hw_dev); |
---|
| 1335 | + hw_dev->monitor.is_en = rkisp_monitor; |
---|
| 1336 | + } else { |
---|
| 1337 | + /* system resume */ |
---|
| 1338 | + for (i = 0; i < hw_dev->dev_num; i++) { |
---|
| 1339 | + if (hw_dev->isp_size[i].is_on) { |
---|
| 1340 | + rkisp_hw_reg_restore(hw_dev); |
---|
| 1341 | + break; |
---|
| 1342 | + } |
---|
| 1343 | + } |
---|
1124 | 1344 | } |
---|
1125 | | - rkisp_hw_enum_isp_size(hw_dev); |
---|
1126 | | - hw_dev->monitor.is_en = rkisp_monitor; |
---|
1127 | 1345 | return 0; |
---|
1128 | 1346 | } |
---|
1129 | 1347 | |
---|
1130 | 1348 | static const struct dev_pm_ops rkisp_hw_pm_ops = { |
---|
1131 | | - SET_RUNTIME_PM_OPS(rkisp_runtime_suspend, |
---|
1132 | | - rkisp_runtime_resume, NULL) |
---|
| 1349 | + SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, pm_runtime_force_resume) |
---|
| 1350 | + SET_RUNTIME_PM_OPS(rkisp_runtime_suspend, rkisp_runtime_resume, NULL) |
---|
1133 | 1351 | }; |
---|
1134 | 1352 | |
---|
1135 | 1353 | static struct platform_driver rkisp_hw_drv = { |
---|