| .. | .. |
|---|
| 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 = { |
|---|