diff options
author | subrahmanya srinivasamurthy <subrs@codeaurora.org> | 2019-10-22 16:27:30 +0530 |
---|---|---|
committer | subrahmanya srinivasamurthy <subrs@codeaurora.org> | 2019-10-22 16:34:59 +0530 |
commit | 35460096d53a3194d2ebd6b3477383e853ed466a (patch) | |
tree | 353cb1e847f7407a05f037299dbad84da618f67d | |
parent | 36314f42649aba49a7225384190bf0a5f23bbec0 (diff) |
Updating kernel ais in sync with 010.r1LA.AU.0.1.1.r1-01000-gen3meta.0
Change-Id: I92996ec1b0def47eedcf2732608eccb194f128fa
Signed-off-by: subrahmanya srinivasamurthy <subrs@codeaurora.org>
29 files changed, 2308 insertions, 179 deletions
diff --git a/drivers/media/platform/msm/ais/cam_core/cam_hw_mgr_intf.h b/drivers/media/platform/msm/ais/cam_core/cam_hw_mgr_intf.h index 50c38e712f36..d5822e17530f 100644 --- a/drivers/media/platform/msm/ais/cam_core/cam_hw_mgr_intf.h +++ b/drivers/media/platform/msm/ais/cam_core/cam_hw_mgr_intf.h @@ -262,6 +262,16 @@ struct cam_hw_dump_pf_args { bool *mem_found; }; +/** + * struct cam_hw_reset_args -hw reset arguments + * + * @ctxt_to_hw_map: HW context from the acquire + * + */ +struct cam_hw_reset_args { + void *ctxt_to_hw_map; +}; + /* enum cam_hw_mgr_command - Hardware manager command type */ enum cam_hw_mgr_command { CAM_HW_MGR_CMD_INTERNAL, @@ -313,6 +323,7 @@ struct cam_hw_cmd_args { * @hw_open: Function pointer for HW init * @hw_close: Function pointer for HW deinit * @hw_flush: Function pointer for HW flush + * @hw_reset: Function pointer for HW reset * */ struct cam_hw_mgr_intf { @@ -333,6 +344,7 @@ struct cam_hw_mgr_intf { int (*hw_open)(void *hw_priv, void *fw_download_args); int (*hw_close)(void *hw_priv, void *hw_close_args); int (*hw_flush)(void *hw_priv, void *hw_flush_args); + int (*hw_reset)(void *hw_priv, void *hw_reset_args); }; #endif /* _CAM_HW_MGR_INTF_H_ */ diff --git a/drivers/media/platform/msm/ais/cam_cpas/cpas_top/cam_cpastop_hw.c b/drivers/media/platform/msm/ais/cam_cpas/cpas_top/cam_cpastop_hw.c index a21803ee5945..547b93a0f346 100644 --- a/drivers/media/platform/msm/ais/cam_cpas/cpas_top/cam_cpastop_hw.c +++ b/drivers/media/platform/msm/ais/cam_cpas/cpas_top/cam_cpastop_hw.c @@ -21,6 +21,7 @@ #include "cam_cpas_soc.h" #include "cpastop100.h" #include "cpastop_v150_100.h" +#include "cpastop_v150_110.h" #include "cpastop_v170_110.h" #include "cpastop_v175_100.h" #include "cpastop_v175_101.h" @@ -107,6 +108,10 @@ static int cam_cpastop_get_hw_info(struct cam_hw_info *cpas_hw, (hw_caps->cpas_version.incr == 1)) soc_info->hw_version = CAM_CPAS_TITAN_175_V101; else if ((hw_caps->cpas_version.major == 1) && + (hw_caps->cpas_version.minor == 1) && + (hw_caps->cpas_version.incr == 1)) + soc_info->hw_version = CAM_CPAS_TITAN_175_V101; + else if ((hw_caps->cpas_version.major == 1) && (hw_caps->cpas_version.minor == 2) && (hw_caps->cpas_version.incr == 0)) soc_info->hw_version = CAM_CPAS_TITAN_175_V120; @@ -117,6 +122,10 @@ static int cam_cpastop_get_hw_info(struct cam_hw_info *cpas_hw, (hw_caps->cpas_version.minor == 0) && (hw_caps->cpas_version.incr == 0)) soc_info->hw_version = CAM_CPAS_TITAN_150_V100; + else if ((hw_caps->cpas_version.major == 1) && + (hw_caps->cpas_version.minor == 1) && + (hw_caps->cpas_version.incr == 0)) + soc_info->hw_version = CAM_CPAS_TITAN_150_V110; } CAM_DBG(CAM_CPAS, "CPAS HW VERSION %x", soc_info->hw_version); @@ -603,6 +612,9 @@ static int cam_cpastop_init_hw_version(struct cam_hw_info *cpas_hw, case CAM_CPAS_TITAN_150_V100: camnoc_info = &cam150_cpas100_camnoc_info; break; + case CAM_CPAS_TITAN_150_V110: + camnoc_info = &cam150_cpas110_camnoc_info; + break; default: CAM_ERR(CAM_CPAS, "Camera Version not supported %d.%d.%d", hw_caps->camera_version.major, diff --git a/drivers/media/platform/msm/ais/cam_cpas/cpas_top/cpastop_v150_110.h b/drivers/media/platform/msm/ais/cam_cpas/cpas_top/cpastop_v150_110.h new file mode 100644 index 000000000000..734f3784ef6c --- /dev/null +++ b/drivers/media/platform/msm/ais/cam_cpas/cpas_top/cpastop_v150_110.h @@ -0,0 +1,537 @@ +/* Copyright (c) 2019, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#ifndef _CPASTOP_V150_110_H_ +#define _CPASTOP_V150_110_H_ + +#define TEST_IRQ_ENABLE 0 + +static struct cam_camnoc_irq_sbm cam_cpas_v150_110_irq_sbm = { + .sbm_enable = { + .access_type = CAM_REG_TYPE_READ_WRITE, + .enable = true, + .offset = 0x2040, /* SBM_FAULTINEN0_LOW */ + .value = 0x1 | /* SBM_FAULTINEN0_LOW_PORT0_MASK*/ + 0x2 | /* SBM_FAULTINEN0_LOW_PORT1_MASK */ + 0x4 | /* SBM_FAULTINEN0_LOW_PORT2_MASK */ + 0x8 | /* SBM_FAULTINEN0_LOW_PORT3_MASK */ + 0x10 | /* SBM_FAULTINEN0_LOW_PORT4_MASK */ + 0x20 | /* SBM_FAULTINEN0_LOW_PORT5_MASK */ + (TEST_IRQ_ENABLE ? + 0x100 : /* SBM_FAULTINEN0_LOW_PORT8_MASK */ + 0x0), + }, + .sbm_status = { + .access_type = CAM_REG_TYPE_READ, + .enable = true, + .offset = 0x2048, /* SBM_FAULTINSTATUS0_LOW */ + }, + .sbm_clear = { + .access_type = CAM_REG_TYPE_WRITE, + .enable = true, + .offset = 0x2080, /* SBM_FLAGOUTCLR0_LOW */ + .value = TEST_IRQ_ENABLE ? 0x6 : 0x2, + } +}; + +static struct cam_camnoc_irq_err + cam_cpas_v150_110_irq_err[] = { + { + .irq_type = CAM_CAMNOC_HW_IRQ_SLAVE_ERROR, + .enable = true, + .sbm_port = 0x1, /* SBM_FAULTINSTATUS0_LOW_PORT0_MASK */ + .err_enable = { + .access_type = CAM_REG_TYPE_READ_WRITE, + .enable = true, + .offset = 0x2708, /* ERRLOGGER_MAINCTL_LOW */ + .value = 1, + }, + .err_status = { + .access_type = CAM_REG_TYPE_READ, + .enable = true, + .offset = 0x2710, /* ERRLOGGER_ERRVLD_LOW */ + }, + .err_clear = { + .access_type = CAM_REG_TYPE_WRITE, + .enable = true, + .offset = 0x2718, /* ERRLOGGER_ERRCLR_LOW */ + .value = 1, + }, + }, + { + .irq_type = CAM_CAMNOC_HW_IRQ_IFE02_UBWC_ENCODE_ERROR, + .enable = true, + .sbm_port = 0x2, /* SBM_FAULTINSTATUS0_LOW_PORT1_MASK */ + .err_enable = { + .access_type = CAM_REG_TYPE_READ_WRITE, + .enable = true, + .offset = 0x5a0, /* SPECIFIC_IFE02_ENCERREN_LOW */ + .value = 1, + }, + .err_status = { + .access_type = CAM_REG_TYPE_READ, + .enable = true, + .offset = 0x590, /* SPECIFIC_IFE02_ENCERRSTATUS_LOW */ + }, + .err_clear = { + .access_type = CAM_REG_TYPE_WRITE, + .enable = true, + .offset = 0x598, /* SPECIFIC_IFE02_ENCERRCLR_LOW */ + .value = 1, + }, + }, + { + .irq_type = CAM_CAMNOC_HW_IRQ_IFE13_UBWC_ENCODE_ERROR, + .enable = true, + .sbm_port = 0x4, /* SBM_FAULTINSTATUS0_LOW_PORT2_MASK */ + .err_enable = { + .access_type = CAM_REG_TYPE_READ_WRITE, + .enable = true, + .offset = 0x9a0, /* SPECIFIC_IFE13_ENCERREN_LOW */ + .value = 1, + }, + .err_status = { + .access_type = CAM_REG_TYPE_READ, + .enable = true, + .offset = 0x990, /* SPECIFIC_IFE13_ENCERRSTATUS_LOW */ + }, + .err_clear = { + .access_type = CAM_REG_TYPE_WRITE, + .enable = true, + .offset = 0x998, /* SPECIFIC_IFE13_ENCERRCLR_LOW */ + .value = 1, + }, + }, + { + .irq_type = CAM_CAMNOC_HW_IRQ_IPE_BPS_UBWC_DECODE_ERROR, + .enable = true, + .sbm_port = 0x8, /* SBM_FAULTINSTATUS0_LOW_PORT3_MASK */ + .err_enable = { + .access_type = CAM_REG_TYPE_READ_WRITE, + .enable = true, + .offset = 0xd20, /* SPECIFIC_IBL_RD_DECERREN_LOW */ + .value = 1, + }, + .err_status = { + .access_type = CAM_REG_TYPE_READ, + .enable = true, + .offset = 0xd10, /* SPECIFIC_IBL_RD_DECERRSTATUS_LOW */ + }, + .err_clear = { + .access_type = CAM_REG_TYPE_WRITE, + .enable = true, + .offset = 0xd18, /* SPECIFIC_IBL_RD_DECERRCLR_LOW */ + .value = 1, + }, + }, + { + .irq_type = CAM_CAMNOC_HW_IRQ_IPE_BPS_UBWC_ENCODE_ERROR, + .enable = true, + .sbm_port = 0x10, /* SBM_FAULTINSTATUS0_LOW_PORT4_MASK */ + .err_enable = { + .access_type = CAM_REG_TYPE_READ_WRITE, + .enable = true, + .offset = 0x11a0, /* SPECIFIC_IBL_WR_ENCERREN_LOW */ + .value = 1, + }, + .err_status = { + .access_type = CAM_REG_TYPE_READ, + .enable = true, + .offset = 0x1190, + /* SPECIFIC_IBL_WR_ENCERRSTATUS_LOW */ + }, + .err_clear = { + .access_type = CAM_REG_TYPE_WRITE, + .enable = true, + .offset = 0x1198, /* SPECIFIC_IBL_WR_ENCERRCLR_LOW */ + .value = 1, + }, + }, + { + .irq_type = CAM_CAMNOC_HW_IRQ_AHB_TIMEOUT, + .enable = true, + .sbm_port = 0x20, /* SBM_FAULTINSTATUS0_LOW_PORT5_MASK */ + .err_enable = { + .access_type = CAM_REG_TYPE_READ_WRITE, + .enable = true, + .offset = 0x2088, /* SBM_FLAGOUTSET0_LOW */ + .value = 0x1, + }, + .err_status = { + .access_type = CAM_REG_TYPE_READ, + .enable = true, + .offset = 0x2090, /* SBM_FLAGOUTSTATUS0_LOW */ + }, + .err_clear = { + .enable = false, + }, + }, + { + .irq_type = CAM_CAMNOC_HW_IRQ_RESERVED1, + .enable = false, + }, + { + .irq_type = CAM_CAMNOC_HW_IRQ_RESERVED2, + .enable = false, + }, + { + .irq_type = CAM_CAMNOC_HW_IRQ_CAMNOC_TEST, + .enable = TEST_IRQ_ENABLE ? true : false, + .sbm_port = 0x100, /* SBM_FAULTINSTATUS0_LOW_PORT8_MASK */ + .err_enable = { + .access_type = CAM_REG_TYPE_READ_WRITE, + .enable = true, + .offset = 0x2088, /* SBM_FLAGOUTSET0_LOW */ + .value = 0x5, + }, + .err_status = { + .access_type = CAM_REG_TYPE_READ, + .enable = true, + .offset = 0x2090, /* SBM_FLAGOUTSTATUS0_LOW */ + }, + .err_clear = { + .enable = false, + }, + }, +}; + +static struct cam_camnoc_specific + cam_cpas_v150_110_camnoc_specific[] = { + { + .port_type = CAM_CAMNOC_CDM, + .enable = true, + .priority_lut_low = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x30, /* SPECIFIC_CDM_PRIORITYLUT_LOW */ + .value = 0x22222222, + }, + .priority_lut_high = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x34, /* SPECIFIC_CDM_PRIORITYLUT_HIGH */ + .value = 0x22222222, + }, + .urgency = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 1, + .offset = 0x38, /* SPECIFIC_CDM_URGENCY_LOW */ + .mask = 0x7, /* SPECIFIC_CDM_URGENCY_LOW_READ_MASK */ + .shift = 0x0, /* SPECIFIC_CDM_URGENCY_LOW_READ_SHIFT */ + .value = 0x2, + }, + .danger_lut = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x40, /* SPECIFIC_CDM_DANGERLUT_LOW */ + .value = 0x0, + }, + .safe_lut = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x48, /* SPECIFIC_CDM_SAFELUT_LOW */ + .value = 0x0, + }, + .ubwc_ctl = { + .enable = false, + }, + }, + { + .port_type = CAM_CAMNOC_IFE02, + .enable = true, + .priority_lut_low = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x430, /* SPECIFIC_IFE02_PRIORITYLUT_LOW */ + .value = 0x66665433, + }, + .priority_lut_high = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x434, /* SPECIFIC_IFE02_PRIORITYLUT_HIGH */ + .value = 0x66666666, + }, + .urgency = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 1, + .offset = 0x438, /* SPECIFIC_IFE02_URGENCY_LOW */ + /* SPECIFIC_IFE02_URGENCY_LOW_WRITE_MASK */ + .mask = 0x70, + /* SPECIFIC_IFE02_URGENCY_LOW_WRITE_SHIFT */ + .shift = 0x4, + .value = 0x30, + }, + .danger_lut = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .offset = 0x440, /* SPECIFIC_IFE02_DANGERLUT_LOW */ + .value = 0xFFFFFF00, + }, + .safe_lut = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .offset = 0x448, /* SPECIFIC_IFE02_SAFELUT_LOW */ + .value = 0x1, + }, + .ubwc_ctl = { + .enable = false, + }, + }, + { + .port_type = CAM_CAMNOC_IFE13, + .enable = true, + .priority_lut_low = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x830, /* SPECIFIC_IFE13_PRIORITYLUT_LOW */ + .value = 0x66665433, + }, + .priority_lut_high = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x834, /* SPECIFIC_IFE13_PRIORITYLUT_HIGH */ + .value = 0x66666666, + }, + .urgency = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 1, + .offset = 0x838, /* SPECIFIC_IFE13_URGENCY_LOW */ + /* SPECIFIC_IFE13_URGENCY_LOW_WRITE_MASK */ + .mask = 0x70, + /* SPECIFIC_IFE13_URGENCY_LOW_WRITE_SHIFT */ + .shift = 0x4, + .value = 0x30, + }, + .danger_lut = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .offset = 0x840, /* SPECIFIC_IFE13_DANGERLUT_LOW */ + .value = 0xFFFFFF00, + }, + .safe_lut = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .offset = 0x848, /* SPECIFIC_IFE13_SAFELUT_LOW */ + .value = 0x1, + }, + .ubwc_ctl = { + .enable = false, + }, + }, + { + .port_type = CAM_CAMNOC_IPE_BPS_LRME_READ, + .enable = true, + .priority_lut_low = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0xc30, /* SPECIFIC_IBL_RD_PRIORITYLUT_LOW */ + .value = 0x33333333, + }, + .priority_lut_high = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0xc34, /* SPECIFIC_IBL_RD_PRIORITYLUT_HIGH */ + .value = 0x33333333, + }, + .urgency = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 1, + .offset = 0xc38, /* SPECIFIC_IBL_RD_URGENCY_LOW */ + /* SPECIFIC_IBL_RD_URGENCY_LOW_READ_MASK */ + .mask = 0x7, + /* SPECIFIC_IBL_RD_URGENCY_LOW_READ_SHIFT */ + .shift = 0x0, + .value = 3, + }, + .danger_lut = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0xc40, /* SPECIFIC_IBL_RD_DANGERLUT_LOW */ + .value = 0x0, + }, + .safe_lut = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0xc48, /* SPECIFIC_IBL_RD_SAFELUT_LOW */ + .value = 0x0, + }, + .ubwc_ctl = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0xd08, /* SPECIFIC_IBL_RD_DECCTL_LOW */ + .value = 1, + }, + }, + { + .port_type = CAM_CAMNOC_IPE_BPS_LRME_WRITE, + .enable = true, + .priority_lut_low = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x1030, /* SPECIFIC_IBL_WR_PRIORITYLUT_LOW */ + .value = 0x33333333, + }, + .priority_lut_high = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x1034, /* SPECIFIC_IBL_WR_PRIORITYLUT_HIGH */ + .value = 0x33333333, + }, + .urgency = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 1, + .offset = 0x1038, /* SPECIFIC_IBL_WR_URGENCY_LOW */ + /* SPECIFIC_IBL_WR_URGENCY_LOW_WRITE_MASK */ + .mask = 0x70, + /* SPECIFIC_IBL_WR_URGENCY_LOW_WRITE_SHIFT */ + .shift = 0x4, + .value = 0x30, + }, + .danger_lut = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x1040, /* SPECIFIC_IBL_WR_DANGERLUT_LOW */ + .value = 0x0, + }, + .safe_lut = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x1048, /* SPECIFIC_IBL_WR_SAFELUT_LOW */ + .value = 0x0, + }, + .ubwc_ctl = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x1188, /* SPECIFIC_IBL_WR_ENCCTL_LOW */ + .value = 0x5, + }, + }, + { + .port_type = CAM_CAMNOC_JPEG, + .enable = true, + .priority_lut_low = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x1430, /* SPECIFIC_JPEG_PRIORITYLUT_LOW */ + .value = 0x22222222, + }, + .priority_lut_high = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x1434, /* SPECIFIC_JPEG_PRIORITYLUT_HIGH */ + .value = 0x22222222, + }, + .urgency = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x1438, /* SPECIFIC_JPEG_URGENCY_LOW */ + .value = 0x22, + }, + .danger_lut = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x1440, /* SPECIFIC_JPEG_DANGERLUT_LOW */ + .value = 0x0, + }, + .safe_lut = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x1448, /* SPECIFIC_JPEG_SAFELUT_LOW */ + .value = 0x0, + }, + .ubwc_ctl = { + .enable = false, + }, + }, + { + .port_type = CAM_CAMNOC_FD, + .enable = false, + }, + { + .port_type = CAM_CAMNOC_ICP, + .enable = true, + .flag_out_set0_low = { + .enable = true, + .access_type = CAM_REG_TYPE_WRITE, + .masked_value = 0, + .offset = 0x2088, + .value = 0x100000, + }, + }, +}; + +static struct cam_camnoc_err_logger_info cam150_cpas110_err_logger_offsets = { + .mainctrl = 0x2708, /* ERRLOGGER_MAINCTL_LOW */ + .errvld = 0x2710, /* ERRLOGGER_ERRVLD_LOW */ + .errlog0_low = 0x2720, /* ERRLOGGER_ERRLOG0_LOW */ + .errlog0_high = 0x2724, /* ERRLOGGER_ERRLOG0_HIGH */ + .errlog1_low = 0x2728, /* ERRLOGGER_ERRLOG1_LOW */ + .errlog1_high = 0x272c, /* ERRLOGGER_ERRLOG1_HIGH */ + .errlog2_low = 0x2730, /* ERRLOGGER_ERRLOG2_LOW */ + .errlog2_high = 0x2734, /* ERRLOGGER_ERRLOG2_HIGH */ + .errlog3_low = 0x2738, /* ERRLOGGER_ERRLOG3_LOW */ + .errlog3_high = 0x273c, /* ERRLOGGER_ERRLOG3_HIGH */ +}; + +static struct cam_cpas_hw_errata_wa_list cam150_cpas110_errata_wa_list = { + .camnoc_flush_slave_pending_trans = { + .enable = false, + .data.reg_info = { + .access_type = CAM_REG_TYPE_READ, + .offset = 0x2100, /* SidebandManager_SenseIn0_Low */ + .mask = 0xE0000, /* Bits 17, 18, 19 */ + .value = 0, /* expected to be 0 */ + }, + }, +}; + +static struct cam_camnoc_info cam150_cpas110_camnoc_info = { + .specific = &cam_cpas_v150_110_camnoc_specific[0], + .specific_size = sizeof(cam_cpas_v150_110_camnoc_specific) / + sizeof(cam_cpas_v150_110_camnoc_specific[0]), + .irq_sbm = &cam_cpas_v150_110_irq_sbm, + .irq_err = &cam_cpas_v150_110_irq_err[0], + .irq_err_size = sizeof(cam_cpas_v150_110_irq_err) / + sizeof(cam_cpas_v150_110_irq_err[0]), + .err_logger = &cam150_cpas110_err_logger_offsets, + .errata_wa_list = &cam150_cpas110_errata_wa_list, +}; + +#endif /* _CPASTOP_V150_110_H_ */ diff --git a/drivers/media/platform/msm/ais/cam_cpas/include/cam_cpas_api.h b/drivers/media/platform/msm/ais/cam_cpas/include/cam_cpas_api.h index 868591636c09..9486deeaa992 100644 --- a/drivers/media/platform/msm/ais/cam_cpas/include/cam_cpas_api.h +++ b/drivers/media/platform/msm/ais/cam_cpas/include/cam_cpas_api.h @@ -42,6 +42,7 @@ enum cam_cpas_reg_base { enum cam_cpas_hw_version { CAM_CPAS_TITAN_NONE = 0, CAM_CPAS_TITAN_150_V100 = 0x150100, + CAM_CPAS_TITAN_150_V110 = 0x150110, CAM_CPAS_TITAN_170_V100 = 0x170100, CAM_CPAS_TITAN_170_V110 = 0x170110, CAM_CPAS_TITAN_170_V120 = 0x170120, diff --git a/drivers/media/platform/msm/ais/cam_isp/cam_isp_context.c b/drivers/media/platform/msm/ais/cam_isp/cam_isp_context.c index 54b0d57117a1..03a5e4416da8 100644 --- a/drivers/media/platform/msm/ais/cam_isp/cam_isp_context.c +++ b/drivers/media/platform/msm/ais/cam_isp/cam_isp_context.c @@ -62,104 +62,6 @@ static void __cam_isp_ctx_update_state_monitor_array( jiffies_to_msecs(jiffies); } -static const char *__cam_isp_ctx_substate_val_to_type( - uint32_t type) -{ - switch (type) { - case CAM_ISP_CTX_ACTIVATED_SOF: - return "SOF"; - case CAM_ISP_CTX_ACTIVATED_APPLIED: - return "APPLIED"; - case CAM_ISP_CTX_ACTIVATED_EPOCH: - return "EPOCH"; - case CAM_ISP_CTX_ACTIVATED_BUBBLE: - return "BUBBLE"; - case CAM_ISP_CTX_ACTIVATED_BUBBLE_APPLIED: - return "BUBBLE_APPLIED"; - case CAM_ISP_CTX_ACTIVATED_HALT: - return "HALT"; - default: - return "CAM_ISP_CTX_INVALID_STATE"; - } -} - -static const char *__cam_isp_hw_evt_val_to_type( - uint32_t evt_id) -{ - switch (evt_id) { - case CAM_ISP_HW_EVENT_ERROR: - return "ERROR"; - case CAM_ISP_HW_EVENT_SOF: - return "SOF"; - case CAM_ISP_HW_EVENT_REG_UPDATE: - return "REG_UPDATE"; - case CAM_ISP_HW_EVENT_EPOCH: - return "EPOCH"; - case CAM_ISP_HW_EVENT_EOF: - return "EOF"; - case CAM_ISP_HW_EVENT_DONE: - return "DONE"; - default: - return "CAM_ISP_EVENT_INVALID"; - } -} - -static void __cam_isp_ctx_dump_state_monitor_array( - struct cam_isp_context *ctx_isp, bool log_rate_limit) -{ - int i = 0; - uint64_t state_head = 0; - uint64_t index; - struct cam_isp_context_state_monitor *ctx_monitor; - - state_head = atomic64_read(&ctx_isp->state_monitor_head); - - ctx_monitor = ctx_isp->cam_isp_ctx_state_monitor; - - if (log_rate_limit) - CAM_INFO_RATE_LIMIT_CUSTOM(CAM_ISP, 5, 20, - "Dumping state information for preceding requests"); - else - CAM_INFO(CAM_ISP, - "Dumping state information for preceding requests"); - - for (i = CAM_ISP_CTX_STATE_MONITOR_MAX_ENTRIES - 1; i >= 0; - i--) { - index = (((state_head - i) + - CAM_ISP_CTX_STATE_MONITOR_MAX_ENTRIES) % - CAM_ISP_CTX_STATE_MONITOR_MAX_ENTRIES); - - if (log_rate_limit) { - CAM_INFO_RATE_LIMIT_CUSTOM(CAM_ISP, 5, 20, - "time[%lld] last reported req_id[%u] frame id[%lld] applied id[%lld] current state[%s] next state[%s] hw_event[%s]", - ctx_monitor[index].evt_time_stamp, - ctx_monitor[index].last_reported_id, - ctx_monitor[index].frame_id, - ctx_monitor[index].last_applied_req_id, - __cam_isp_ctx_substate_val_to_type( - ctx_monitor[index].curr_state), - __cam_isp_ctx_substate_val_to_type( - ctx_monitor[index].next_state), - __cam_isp_hw_evt_val_to_type( - ctx_monitor[index].hw_event)); - - } else { - CAM_INFO(CAM_ISP, - "time[%lld] last reported req_id[%u] frame id[%lld] applied id[%lld] current state[%s] next state[%s] hw_event[%s]", - ctx_monitor[index].evt_time_stamp, - ctx_monitor[index].last_reported_id, - ctx_monitor[index].frame_id, - ctx_monitor[index].last_applied_req_id, - __cam_isp_ctx_substate_val_to_type( - ctx_monitor[index].curr_state), - __cam_isp_ctx_substate_val_to_type( - ctx_monitor[index].next_state), - __cam_isp_hw_evt_val_to_type( - ctx_monitor[index].hw_event)); - } - } -} - static void cam_isp_ctx_dump_req(struct cam_isp_ctx_req *req_isp) { int i = 0, rc = 0; @@ -453,6 +355,14 @@ static int __cam_isp_ctx_handle_buf_done_in_activated_state( trace_cam_buf_done("ISP", ctx, req); req_isp = (struct cam_isp_ctx_req *) req->req_priv; + if (ctx_isp->frame_id == 1) + ctx_isp->irq_timestamps = done->irq_mono_boot_time; + else if (ctx_isp->fps && ((done->irq_mono_boot_time - + ctx_isp->irq_timestamps) > ((1000*1000)/ctx_isp->fps))) + ctx_isp->irq_delay_detect = true; + + ctx_isp->irq_timestamps = done->irq_mono_boot_time; + for (i = 0; i < done->num_handles; i++) { for (j = 0; j < req_isp->num_fence_map_out; j++) { if (done->resource_handle[i] == @@ -566,6 +476,26 @@ static int __cam_isp_ctx_handle_buf_done_in_activated_state( ctx_isp->substate_activated); } + if (ctx_isp->active_req_cnt && ctx_isp->irq_delay_detect) { + CAM_ERR(CAM_ISP, "isp req[%lld] IRQ buf done got delayed", + req->request_id); + req = list_first_entry(&ctx->active_req_list, + struct cam_ctx_request, list); + req_isp = (struct cam_isp_ctx_req *) req->req_priv; + + for (j = 0; j < req_isp->num_fence_map_out; j++) { + rc = cam_sync_signal(req_isp->fence_map_out[j].sync_id, + CAM_SYNC_STATE_SIGNALED_ERROR); + if (rc) + CAM_DBG(CAM_ISP, "Sync failed with rc = %d", + rc); + req_isp->fence_map_out[j].sync_id = -1; + } + list_del_init(&req->list); + list_add_tail(&req->list, &ctx->free_req_list); + ctx_isp->active_req_cnt--; + } + ctx_isp->irq_delay_detect = false; end: return rc; } @@ -644,12 +574,47 @@ static void __cam_isp_ctx_send_sof_timestamp( static int __cam_isp_ctx_reg_upd_in_epoch_state( struct cam_isp_context *ctx_isp, void *evt_data) { - if (ctx_isp->frame_id == 1) + struct cam_isp_hw_reg_update_event_data *rup_event_data = evt_data; + + struct cam_context *ctx = ctx_isp->base; + struct cam_ctx_request *req = NULL; + struct cam_isp_ctx_req *req_isp = NULL; + + if (ctx_isp->frame_id == 1) { CAM_DBG(CAM_ISP, "Reg update for early PCR"); - else + if (!list_empty(&ctx->active_req_list)) { + req = list_first_entry(&ctx->active_req_list, + struct cam_ctx_request, list); + req_isp = (struct cam_isp_ctx_req *) req->req_priv; + } else if (!list_empty(&ctx->wait_req_list)) { + req = list_first_entry(&ctx->active_req_list, + struct cam_ctx_request, list); + req_isp = (struct cam_isp_ctx_req *) req->req_priv; + } + } else { + if (!list_empty(&ctx->wait_req_list)) { + req = list_first_entry(&ctx->active_req_list, + struct cam_ctx_request, list); + req_isp = (struct cam_isp_ctx_req *) req->req_priv; + } CAM_WARN(CAM_ISP, "Unexpected reg update in activated substate:%d for frame_id:%lld", ctx_isp->substate_activated, ctx_isp->frame_id); + } + + if (req_isp && req_isp->hw_update_data.fps) { + ctx_isp->fps = req_isp->hw_update_data.fps; + CAM_DBG(CAM_ISP, "req_isp %pK, Upadting ctx_isp->fps %d", + req_isp, ctx_isp->fps); + } + + if (ctx_isp->frame_id == 1) + ctx_isp->irq_timestamps = rup_event_data->irq_mono_boot_time; + else if (ctx_isp->fps && ((rup_event_data->irq_mono_boot_time - + ctx_isp->irq_timestamps) > ((1000*1000)/ctx_isp->fps))) + ctx_isp->irq_delay_detect = true; + + ctx_isp->irq_timestamps = rup_event_data->irq_mono_boot_time; return 0; } @@ -659,7 +624,8 @@ static int __cam_isp_ctx_reg_upd_in_activated_state( int rc = 0; struct cam_ctx_request *req; struct cam_context *ctx = ctx_isp->base; - struct cam_isp_ctx_req *req_isp; + struct cam_isp_ctx_req *req_isp = NULL; + struct cam_isp_hw_reg_update_event_data *rup_event_data = evt_data; if (list_empty(&ctx->wait_req_list)) { CAM_ERR(CAM_ISP, "Reg upd ack with no waiting request"); @@ -684,13 +650,22 @@ static int __cam_isp_ctx_reg_upd_in_activated_state( req->request_id, ctx_isp->active_req_cnt, ctx->ctx_id); } + if (req_isp && req_isp->hw_update_data.fps) + ctx_isp->fps = req_isp->hw_update_data.fps; + /* * This function only called directly from applied and bubble applied * state so change substate here. */ ctx_isp->substate_activated = CAM_ISP_CTX_ACTIVATED_EPOCH; CAM_DBG(CAM_ISP, "next substate %d", ctx_isp->substate_activated); + if (ctx_isp->frame_id == 1) + ctx_isp->irq_timestamps = rup_event_data->irq_mono_boot_time; + else if (ctx_isp->fps && ((rup_event_data->irq_mono_boot_time - + ctx_isp->irq_timestamps) > ((1000*1000)/ctx_isp->fps))) + ctx_isp->irq_delay_detect = true; + ctx_isp->irq_timestamps = rup_event_data->irq_mono_boot_time; end: return rc; } @@ -747,7 +722,6 @@ static int __cam_isp_ctx_notify_sof_in_activated_state( ctx->ctx_id, request_id, ctx_isp->req_info.reported_req_id); - __cam_isp_ctx_dump_state_monitor_array(ctx_isp, true); } __cam_isp_ctx_send_sof_timestamp(ctx_isp, request_id, @@ -818,6 +792,14 @@ static int __cam_isp_ctx_sof_in_activated_state( ctx_isp->sof_timestamp_val = sof_event_data->timestamp; ctx_isp->boot_timestamp = sof_event_data->boot_time; + if (ctx_isp->frame_id == 1) + ctx_isp->irq_timestamps = sof_event_data->irq_mono_boot_time; + else if (ctx_isp->fps && ((sof_event_data->irq_mono_boot_time - + ctx_isp->irq_timestamps) > ((1000*1000)/ctx_isp->fps))) + ctx_isp->irq_delay_detect = true; + + ctx_isp->irq_timestamps = sof_event_data->irq_mono_boot_time; + CAM_DBG(CAM_ISP, "frame id: %lld time stamp:0x%llx, ctx %u", ctx_isp->frame_id, ctx_isp->sof_timestamp_val, ctx->ctx_id); @@ -829,8 +811,9 @@ static int __cam_isp_ctx_reg_upd_in_sof(struct cam_isp_context *ctx_isp, { int rc = 0; struct cam_ctx_request *req = NULL; - struct cam_isp_ctx_req *req_isp; + struct cam_isp_ctx_req *req_isp = NULL; struct cam_context *ctx = ctx_isp->base; + struct cam_isp_hw_reg_update_event_data *rup_event_data = evt_data; if (ctx->state != CAM_CTX_ACTIVATED && ctx_isp->frame_id > 1) { CAM_DBG(CAM_ISP, "invalid RUP"); @@ -853,6 +836,16 @@ static int __cam_isp_ctx_reg_upd_in_sof(struct cam_isp_context *ctx_isp, "receive rup in unexpected state"); } + if (req_isp && req_isp->hw_update_data.fps) + ctx_isp->fps = req_isp->hw_update_data.fps; + + if (ctx_isp->frame_id == 1) + ctx_isp->irq_timestamps = rup_event_data->irq_mono_boot_time; + else if (ctx_isp->fps && ((rup_event_data->irq_mono_boot_time - + ctx_isp->irq_timestamps) > ((1000*1000)/ctx_isp->fps))) + ctx_isp->irq_delay_detect = true; + + ctx_isp->irq_timestamps = rup_event_data->irq_mono_boot_time; end: return rc; } @@ -861,9 +854,10 @@ static int __cam_isp_ctx_epoch_in_applied(struct cam_isp_context *ctx_isp, void *evt_data) { struct cam_ctx_request *req; - struct cam_isp_ctx_req *req_isp; + struct cam_isp_ctx_req *req_isp = NULL; struct cam_context *ctx = ctx_isp->base; uint64_t request_id = 0; + struct cam_isp_hw_epoch_event_data *epoch_hw_event_data = evt_data; if (list_empty(&ctx->wait_req_list)) { /* @@ -871,7 +865,6 @@ static int __cam_isp_ctx_epoch_in_applied(struct cam_isp_context *ctx_isp, * The recovery is to go back to sof state */ CAM_ERR(CAM_ISP, "Ctx:%d No wait request", ctx->ctx_id); - __cam_isp_ctx_dump_state_monitor_array(ctx_isp, true); ctx_isp->substate_activated = CAM_ISP_CTX_ACTIVATED_SOF; /* Send SOF event as empty frame*/ @@ -888,7 +881,6 @@ static int __cam_isp_ctx_epoch_in_applied(struct cam_isp_context *ctx_isp, CAM_INFO(CAM_ISP, "ctx:%d Report Bubble flag %d req id:%lld", ctx->ctx_id, req_isp->bubble_report, req->request_id); - __cam_isp_ctx_dump_state_monitor_array(ctx_isp, true); if (req_isp->bubble_report && ctx->ctx_crm_intf && ctx->ctx_crm_intf->notify_err) { struct cam_req_mgr_error_notify notify; @@ -929,6 +921,15 @@ static int __cam_isp_ctx_epoch_in_applied(struct cam_isp_context *ctx_isp, ctx_isp->substate_activated); end: + if (ctx_isp->frame_id == 1) + ctx_isp->irq_timestamps = + epoch_hw_event_data->irq_mono_boot_time; + else if (ctx_isp->fps && ((epoch_hw_event_data->irq_mono_boot_time - + ctx_isp->irq_timestamps) > ((1000*1000)/ctx_isp->fps))) + ctx_isp->irq_delay_detect = true; + + ctx_isp->irq_timestamps = epoch_hw_event_data->irq_mono_boot_time; + return 0; } @@ -961,6 +962,14 @@ static int __cam_isp_ctx_sof_in_epoch(struct cam_isp_context *ctx_isp, ctx_isp->sof_timestamp_val = sof_event_data->timestamp; ctx_isp->boot_timestamp = sof_event_data->boot_time; + if (ctx_isp->frame_id == 1) + ctx_isp->irq_timestamps = sof_event_data->irq_mono_boot_time; + else if (ctx_isp->fps && ((sof_event_data->irq_mono_boot_time - + ctx_isp->irq_timestamps) > ((1000*1000)/ctx_isp->fps))) + ctx_isp->irq_delay_detect = true; + + ctx_isp->irq_timestamps = sof_event_data->irq_mono_boot_time; + if (list_empty(&ctx->active_req_list)) ctx_isp->substate_activated = CAM_ISP_CTX_ACTIVATED_SOF; else @@ -1013,7 +1022,6 @@ static int __cam_isp_ctx_epoch_in_bubble_applied( * Just go back to the bubble state. */ CAM_ERR(CAM_ISP, "ctx:%d No pending request.", ctx->ctx_id); - __cam_isp_ctx_dump_state_monitor_array(ctx_isp, true); __cam_isp_ctx_send_sof_timestamp(ctx_isp, request_id, CAM_REQ_MGR_SOF_EVENT_SUCCESS); @@ -1027,7 +1035,6 @@ static int __cam_isp_ctx_epoch_in_bubble_applied( req_isp->bubble_detected = true; CAM_INFO(CAM_ISP, "Ctx:%d Report Bubble flag %d req id:%lld", ctx->ctx_id, req_isp->bubble_report, req->request_id); - __cam_isp_ctx_dump_state_monitor_array(ctx_isp, true); if (req_isp->bubble_report && ctx->ctx_crm_intf && ctx->ctx_crm_intf->notify_err) { @@ -1102,7 +1109,7 @@ static int __cam_isp_ctx_handle_error(struct cam_isp_context *ctx_isp, struct cam_isp_ctx_req *req_isp = NULL; struct cam_isp_ctx_req *req_isp_to_report = NULL; struct cam_req_mgr_error_notify notify; - uint64_t error_request_id; + uint64_t error_request_id = 0; struct cam_hw_fence_map_entry *fence_map_out = NULL; struct cam_req_mgr_message req_msg; @@ -1443,7 +1450,7 @@ static int __cam_isp_ctx_fs2_reg_upd_in_sof(struct cam_isp_context *ctx_isp, { int rc = 0; struct cam_ctx_request *req = NULL; - struct cam_isp_ctx_req *req_isp; + struct cam_isp_ctx_req *req_isp = NULL; struct cam_context *ctx = ctx_isp->base; if (ctx->state != CAM_CTX_ACTIVATED && ctx_isp->frame_id > 1) { @@ -1467,6 +1474,9 @@ static int __cam_isp_ctx_fs2_reg_upd_in_sof(struct cam_isp_context *ctx_isp, "receive rup in unexpected state"); } + if (req_isp && req_isp->hw_update_data.fps) + ctx_isp->fps = req_isp->hw_update_data.fps; + end: return rc; } @@ -1477,7 +1487,7 @@ static int __cam_isp_ctx_fs2_reg_upd_in_applied_state( int rc = 0; struct cam_ctx_request *req = NULL; struct cam_context *ctx = ctx_isp->base; - struct cam_isp_ctx_req *req_isp; + struct cam_isp_ctx_req *req_isp = NULL; struct cam_req_mgr_trigger_notify notify; uint64_t request_id = 0; @@ -1500,6 +1510,9 @@ static int __cam_isp_ctx_fs2_reg_upd_in_applied_state( list_add_tail(&req->list, &ctx->free_req_list); } + if (req_isp && req_isp->hw_update_data.fps) + ctx_isp->fps = req_isp->hw_update_data.fps; + /* * This function only called directly from applied and bubble applied * state so change substate here. @@ -1902,16 +1915,19 @@ static int __cam_isp_ctx_flush_req_in_top_state( struct cam_req_mgr_flush_request *flush_req) { int rc = 0; - struct cam_isp_context *ctx_isp; - - ctx_isp = (struct cam_isp_context *) ctx->ctx_priv; + struct cam_isp_context *ctx_isp = + (struct cam_isp_context *) ctx->ctx_priv; + struct cam_isp_stop_args stop_isp; + struct cam_hw_stop_args stop_args; + struct cam_isp_start_args start_isp; + struct cam_hw_reset_args reset_args; if (flush_req->type == CAM_REQ_MGR_FLUSH_TYPE_ALL) { - CAM_INFO(CAM_ISP, "Last request id to flush is %lld", - flush_req->req_id); + CAM_INFO(CAM_ISP, "ctx id:%d Last request id to flush is %lld", + ctx->ctx_id, flush_req->req_id); ctx->last_flush_req = flush_req->req_id; } - CAM_DBG(CAM_ISP, "try to flush pending list"); + CAM_DBG(CAM_ISP, "ctx id:%d try to flush pending list", ctx->ctx_id); spin_lock_bh(&ctx->lock); rc = __cam_isp_ctx_flush_req(ctx, &ctx->pending_req_list, flush_req); @@ -1929,11 +1945,61 @@ static int __cam_isp_ctx_flush_req_in_top_state( ctx_isp->req_info.last_reported_id_time_stamp, ctx_isp->req_info.last_bufdone_time_stamp); - __cam_isp_ctx_dump_state_monitor_array(ctx_isp, true); } spin_unlock_bh(&ctx->lock); atomic_set(&ctx_isp->process_bubble, 0); + if (flush_req->type == CAM_REQ_MGR_FLUSH_TYPE_ALL) { + /* if active and wait list are empty, return */ + spin_lock_bh(&ctx->lock); + if ((list_empty(&ctx->wait_req_list)) && + (list_empty(&ctx->active_req_list))) { + spin_unlock_bh(&ctx->lock); + CAM_DBG(CAM_ISP, "ctx id:%d active,wait list are empty", + ctx->ctx_id); + goto end; + } + spin_unlock_bh(&ctx->lock); + + /* Stop hw first before active list flush */ + CAM_DBG(CAM_ISP, "ctx id:%d try to stop hw", ctx->ctx_id); + stop_args.ctxt_to_hw_map = ctx_isp->hw_ctx; + stop_isp.hw_stop_cmd = CAM_ISP_HW_STOP_AT_FRAME_BOUNDARY; + stop_isp.stop_only = true; + stop_args.args = (void *)&stop_isp; + ctx->hw_mgr_intf->hw_stop(ctx->hw_mgr_intf->hw_mgr_priv, + &stop_args); + + spin_lock_bh(&ctx->lock); + CAM_DBG(CAM_ISP, "try to flush wait list"); + rc = __cam_isp_ctx_flush_req(ctx, &ctx->wait_req_list, + flush_req); + CAM_DBG(CAM_ISP, "try to flush active list"); + rc = __cam_isp_ctx_flush_req(ctx, &ctx->active_req_list, + flush_req); + ctx_isp->active_req_cnt = 0; + spin_unlock_bh(&ctx->lock); + + CAM_DBG(CAM_ISP, "try to reset hw"); + /* Reset hw */ + reset_args.ctxt_to_hw_map = ctx_isp->hw_ctx; + rc = ctx->hw_mgr_intf->hw_reset(ctx->hw_mgr_intf->hw_mgr_priv, + &reset_args); + if (rc) + goto end; + + CAM_DBG(CAM_ISP, "ctx id%d try to start hw", ctx->ctx_id); + /* Start hw */ + start_isp.hw_config.ctxt_to_hw_map = ctx_isp->hw_ctx; + start_isp.start_only = true; + start_isp.hw_config.priv = NULL; + + rc = ctx->hw_mgr_intf->hw_start(ctx->hw_mgr_intf->hw_mgr_priv, + &start_isp); + } + +end: + ctx_isp->substate_activated = CAM_ISP_CTX_ACTIVATED_SOF; return rc; } @@ -2188,7 +2254,6 @@ static int __cam_isp_ctx_rdi_only_sof_in_bubble_applied( req_isp->bubble_detected = true; CAM_INFO(CAM_ISP, "Ctx:%d Report Bubble flag %d req id:%lld", ctx->ctx_id, req_isp->bubble_report, req->request_id); - __cam_isp_ctx_dump_state_monitor_array(ctx_isp, true); if (req_isp->bubble_report && ctx->ctx_crm_intf && ctx->ctx_crm_intf->notify_err) { @@ -2315,7 +2380,7 @@ static int __cam_isp_ctx_rdi_only_reg_upd_in_bubble_applied_state( { struct cam_ctx_request *req; struct cam_context *ctx = ctx_isp->base; - struct cam_isp_ctx_req *req_isp; + struct cam_isp_ctx_req *req_isp = NULL; struct cam_req_mgr_trigger_notify notify; uint64_t request_id = 0; @@ -2370,6 +2435,9 @@ static int __cam_isp_ctx_rdi_only_reg_upd_in_bubble_applied_state( jiffies_to_msecs(jiffies); } + if (req_isp && req_isp->hw_update_data.fps) + ctx_isp->fps = req_isp->hw_update_data.fps; + __cam_isp_ctx_send_sof_timestamp(ctx_isp, request_id, CAM_REQ_MGR_SOF_EVENT_SUCCESS); CAM_DBG(CAM_ISP, "next substate %d", ctx_isp->substate_activated); @@ -2645,7 +2713,7 @@ static int __cam_isp_ctx_config_dev_in_top_state( { int rc = 0, i; struct cam_ctx_request *req = NULL; - struct cam_isp_ctx_req *req_isp; + struct cam_isp_ctx_req *req_isp = NULL; uintptr_t packet_addr; struct cam_packet *packet; size_t len = 0; @@ -2734,6 +2802,7 @@ static int __cam_isp_ctx_config_dev_in_top_state( rc = -EFAULT; goto free_cpu_buf; } + req_isp->num_cfg = cfg.num_hw_update_entries; req_isp->num_fence_map_out = cfg.num_out_map_entries; req_isp->num_fence_map_in = cfg.num_in_map_entries; @@ -2790,6 +2859,7 @@ static int __cam_isp_ctx_config_dev_in_top_state( CAM_ERR(CAM_ISP, "Recevied Update in wrong state"); } } + if (rc) goto put_ref; @@ -3560,7 +3630,6 @@ static int __cam_isp_ctx_apply_req(struct cam_context *ctx, CAM_ERR_RATE_LIMIT(CAM_ISP, "Ctx:%d No handle function in activated substate %d", ctx->ctx_id, ctx_isp->substate_activated); - __cam_isp_ctx_dump_state_monitor_array(ctx_isp, true); rc = -EFAULT; } @@ -3571,8 +3640,6 @@ static int __cam_isp_ctx_apply_req(struct cam_context *ctx, return rc; } - - static int __cam_isp_ctx_handle_irq_in_activated(void *context, uint32_t evt_id, void *evt_data) { @@ -3597,7 +3664,6 @@ static int __cam_isp_ctx_handle_irq_in_activated(void *context, } else { CAM_INFO(CAM_ISP, "Ctx:%d No handle function for substate %d", ctx->ctx_id, ctx_isp->substate_activated); - __cam_isp_ctx_dump_state_monitor_array(ctx_isp, true); } if (evt_id != CAM_ISP_HW_EVENT_DONE) __cam_isp_ctx_update_state_monitor_array(ctx_isp, evt_id, diff --git a/drivers/media/platform/msm/ais/cam_isp/cam_isp_context.h b/drivers/media/platform/msm/ais/cam_isp/cam_isp_context.h index a4f4e5ae0ee9..cb73252363db 100644 --- a/drivers/media/platform/msm/ais/cam_isp/cam_isp_context.h +++ b/drivers/media/platform/msm/ais/cam_isp/cam_isp_context.h @@ -35,6 +35,11 @@ #define CAM_ISP_CTX_CFG_MAX 22 /* + * Defalut fps value set to 30 + */ +#define CAM_ISP_CTX_DEFAULT_FPS 30 + +/* * Maximum entries in state monitoring array for error logging */ #define CAM_ISP_CTX_STATE_MONITOR_MAX_ENTRIES 20 @@ -180,6 +185,9 @@ struct cam_isp_context_req_id_info { * @hw_acquired: Indicate whether HW resources are acquired * @init_received: Indicate whether init config packet is received * @split_acquire: Indicate whether a separate acquire is expected + * @irq_delay_detect: Indicate whether a irq delay has detected or not + * @irq_timestamps: Timestamp from last handled IRQ + * @fps: Current FPS for the activated state. * */ struct cam_isp_context { @@ -209,6 +217,9 @@ struct cam_isp_context { bool hw_acquired; bool init_received; bool split_acquire; + bool irq_delay_detect; + uint64_t irq_timestamps; + uint32_t fps; }; /** diff --git a/drivers/media/platform/msm/ais/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c b/drivers/media/platform/msm/ais/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c index 4bb272ec6329..ca8f26884f41 100644 --- a/drivers/media/platform/msm/ais/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c +++ b/drivers/media/platform/msm/ais/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c @@ -146,6 +146,74 @@ static int cam_ife_hw_mgr_is_rdi_res(uint32_t res_id) return rc; } +static const char *cam_ife_hw_mgr_get_res_id( + enum cam_ife_pix_path_res_id csid_res_id) +{ + char *res_name = NULL; + + switch (csid_res_id) { + case CAM_IFE_PIX_PATH_RES_RDI_0: + res_name = "RDI_0"; + break; + case CAM_IFE_PIX_PATH_RES_RDI_1: + res_name = "RDI_1"; + break; + case CAM_IFE_PIX_PATH_RES_RDI_2: + res_name = "RDI_2"; + break; + case CAM_IFE_PIX_PATH_RES_RDI_3: + res_name = "RDI_3"; + break; + case CAM_IFE_PIX_PATH_RES_IPP: + res_name = "IPP"; + break; + case CAM_IFE_PIX_PATH_RES_PPP: + res_name = "PPP"; + break; + case CAM_IFE_PIX_PATH_RES_MAX: + res_name = "Invalid Max res"; + break; + default: + res_name = "Invalid"; + break; + } + return res_name; +} + +static const char *cam_ife_hw_mgr_get_res_type( + enum cam_isp_resource_type csid_res_type) +{ + char *res_type = NULL; + + switch (csid_res_type) { + case CAM_ISP_RESOURCE_UNINT: + res_type = "Unint"; + break; + case CAM_ISP_RESOURCE_SRC: + res_type = "Src"; + break; + case CAM_ISP_RESOURCE_CID: + res_type = "Cid"; + break; + case CAM_ISP_RESOURCE_PIX_PATH: + res_type = "Pix Path"; + break; + case CAM_ISP_RESOURCE_VFE_IN: + res_type = "Vfe In"; + break; + case CAM_ISP_RESOURCE_VFE_OUT: + res_type = "Vfe Out"; + break; + case CAM_ISP_RESOURCE_MAX: + res_type = "Invalid Max res"; + break; + default: + res_type = "Invalid"; + break; + } + return res_type; +} + static int cam_ife_hw_mgr_reset_csid_res( struct cam_ife_hw_mgr_res *isp_hw_res) { @@ -599,6 +667,61 @@ static int cam_ife_hw_mgr_get_ctx( return rc; } +static void cam_ife_hw_mgr_dump_all_ctx( + struct cam_ife_hw_mgr_ctx *ife_ctx) +{ + uint32_t i; + struct cam_ife_hw_mgr_ctx *ctx; + struct cam_ife_hw_mgr_res *hw_mgr; + + mutex_lock(&g_ife_hw_mgr.ctx_mutex); + list_for_each_entry(ctx, &g_ife_hw_mgr.used_ctx_list, list) { + CAM_ERR_RATE_LIMIT(CAM_ISP, + "ctx id:%d dual:%d in src:%d num_base:%d rdi only:%d", + ctx->ctx_index, + ctx->res_list_ife_in.is_dual_vfe, + ctx->res_list_ife_in.res_id, + ctx->num_base, ctx->is_rdi_only_context); + list_for_each_entry(hw_mgr, &ctx->res_list_ife_csid, + list) { + for (i = 0; i < CAM_ISP_HW_SPLIT_MAX; i++) { + if (!hw_mgr->hw_res[i]) + continue; + CAM_ERR_RATE_LIMIT(CAM_ISP, + "csid:%d res_type:%s id:%s state:%d", + hw_mgr->hw_res[i]->hw_intf->hw_idx, + cam_ife_hw_mgr_get_res_type( + hw_mgr->hw_res[i]->res_type), + cam_ife_hw_mgr_get_res_id( + hw_mgr->hw_res[i]->res_id), + hw_mgr->hw_res[i]->res_state); + } + } + list_for_each_entry(hw_mgr, &ctx->res_list_ife_src, + list) { + for (i = 0; i < CAM_ISP_HW_SPLIT_MAX; i++) { + if (!hw_mgr->hw_res[i]) + continue; + CAM_ERR_RATE_LIMIT(CAM_ISP, + "Src IFE:%d res_type:%s id:%s state:%d", + hw_mgr->hw_res[i]->hw_intf->hw_idx, + cam_ife_hw_mgr_get_res_type( + hw_mgr->hw_res[i]->res_type), + cam_ife_hw_mgr_get_res_id( + hw_mgr->hw_res[i]->res_id), + hw_mgr->hw_res[i]->res_state); + } + } + } + CAM_ERR_RATE_LIMIT(CAM_ISP, + "Current ctx id:%d dual:%d in src:%d num_base:%d rdi only:%d", + ife_ctx->ctx_index, + ife_ctx->res_list_ife_in.is_dual_vfe, + ife_ctx->res_list_ife_in.res_id, + ife_ctx->num_base, ife_ctx->is_rdi_only_context); + mutex_unlock(&g_ife_hw_mgr.ctx_mutex); +} + static void cam_ife_mgr_add_base_info( struct cam_ife_hw_mgr_ctx *ctx, enum cam_isp_hw_split_id split_id, @@ -1493,8 +1616,9 @@ static int cam_ife_hw_mgr_acquire_res_ife_csid_pxl( &csid_acquire, sizeof(csid_acquire)); if (rc) { CAM_ERR(CAM_ISP, - "Cannot acquire ife csid pxl path rsrc %s", - (is_ipp) ? "IPP" : "PPP"); + "Cannot acquire ife csid pxl path rsrc %s, hw=%d rc=%d", + (is_ipp) ? "IPP" : "PPP", + hw_intf->hw_idx, rc); goto put_res; } @@ -1606,7 +1730,6 @@ static int cam_ife_hw_mgr_acquire_res_ife_csid_rdi( "CSID Path reserve failed hw=%d rc=%d cid=%d", hw_intf->hw_idx, rc, cid_res->hw_res[0]->res_id); - goto put_res; } @@ -2002,6 +2125,8 @@ static int cam_ife_mgr_acquire_hw(void *hw_mgr_priv, void *acquire_hw_args) return 0; free_res: + /*Dump all the current acquired resources */ + cam_ife_hw_mgr_dump_all_ctx(ife_ctx); cam_ife_hw_mgr_release_hw_for_ctx(ife_ctx); free_cdm: cam_cdm_release(ife_ctx->cdm_handle); @@ -2156,11 +2281,13 @@ static int cam_ife_mgr_acquire_dev(void *hw_mgr_priv, void *acquire_hw_args) ife_ctx->ctx_in_use = 1; cam_ife_hw_mgr_put_ctx(&ife_hw_mgr->used_ctx_list, &ife_ctx); - CAM_DBG(CAM_ISP, "Exit...(success)"); return 0; + free_res: + /*Dump all the current acquired resources */ + cam_ife_hw_mgr_dump_all_ctx(ife_ctx); cam_ife_hw_mgr_release_hw_for_ctx(ife_ctx); cam_cdm_release(ife_ctx->cdm_handle); free_ctx: @@ -2406,7 +2533,7 @@ static int cam_ife_mgr_config_hw(void *hw_mgr_priv, if (cfg->init_packet) { rc = wait_for_completion_timeout( &ctx->config_done_complete, - msecs_to_jiffies(30)); + msecs_to_jiffies(50)); if (rc <= 0) { CAM_ERR(CAM_ISP, "config done completion timeout for req_id=%llu rc=%d ctx_index %d", @@ -2556,6 +2683,11 @@ static int cam_ife_mgr_pause_hw(struct cam_ife_hw_mgr_ctx *ctx) return cam_ife_mgr_bw_control(ctx, CAM_VFE_BW_CONTROL_EXCLUDE); } +static int cam_ife_mgr_resume_hw(struct cam_ife_hw_mgr_ctx *ctx) +{ + return cam_ife_mgr_bw_control(ctx, CAM_VFE_BW_CONTROL_INCLUDE); +} + /* entry function: stop_hw */ static int cam_ife_mgr_stop_hw(void *hw_mgr_priv, void *stop_hw_args) { @@ -2909,6 +3041,9 @@ start_only: CAM_DBG(CAM_ISP, "START IFE OUT ... in ctx id:%d", ctx->ctx_index); + if (start_isp->start_only) + cam_ife_mgr_resume_hw(ctx); + /* start the IFE out devices */ for (i = 0; i < CAM_IFE_HW_OUT_RES_MAX; i++) { rc = cam_ife_hw_mgr_start_hw_res( @@ -3009,6 +3144,44 @@ static int cam_ife_mgr_write(void *hw_mgr_priv, void *write_args) return -EPERM; } +static int cam_ife_mgr_reset(void *hw_mgr_priv, void *hw_reset_args) +{ + struct cam_ife_hw_mgr *hw_mgr = hw_mgr_priv; + struct cam_hw_reset_args *reset_args = hw_reset_args; + struct cam_ife_hw_mgr_ctx *ctx; + struct cam_ife_hw_mgr_res *hw_mgr_res; + uint32_t i; + int rc = 0; + + if (!hw_mgr_priv || !hw_reset_args) { + CAM_ERR(CAM_ISP, "Invalid arguments"); + return -EINVAL; + } + + ctx = (struct cam_ife_hw_mgr_ctx *)reset_args->ctxt_to_hw_map; + if (!ctx || !ctx->ctx_in_use) { + CAM_ERR(CAM_ISP, "Invalid context is used"); + return -EPERM; + } + + CAM_DBG(CAM_ISP, "reset csid and vfe hw"); + list_for_each_entry(hw_mgr_res, &ctx->res_list_ife_csid, + list) { + rc = cam_ife_hw_mgr_reset_csid_res(hw_mgr_res); + if (rc) { + CAM_ERR(CAM_ISP, "Failed RESET (%d) rc:%d", + hw_mgr_res->res_id, rc); + goto end; + } + } + + for (i = 0; i < ctx->num_base; i++) + rc = cam_ife_mgr_reset_vfe_hw(hw_mgr, ctx->base[i].idx); + +end: + return rc; +} + static int cam_ife_mgr_release_hw(void *hw_mgr_priv, void *release_hw_args) { @@ -3136,6 +3309,54 @@ static int cam_isp_blob_fe_update( return rc; } +static int cam_isp_blob_fps_config( + uint32_t blob_type, + struct cam_isp_generic_blob_info *blob_info, + struct cam_fps_config *fps_config, + struct cam_hw_prepare_update_args *prepare) +{ + struct cam_ife_hw_mgr_ctx *ctx = NULL; + struct cam_ife_hw_mgr_res *hw_mgr_res; + struct cam_hw_intf *hw_intf; + struct cam_vfe_fps_config_args fps_config_args; + int rc = -EINVAL; + uint32_t i; + + ctx = prepare->ctxt_to_hw_map; + + list_for_each_entry(hw_mgr_res, &ctx->res_list_ife_src, list) { + for (i = 0; i < CAM_ISP_HW_SPLIT_MAX; i++) { + if (!hw_mgr_res->hw_res[i]) + continue; + + if (hw_mgr_res->res_id == CAM_ISP_HW_VFE_IN_CAMIF) { + hw_intf = hw_mgr_res->hw_res[i]->hw_intf; + if (hw_intf && hw_intf->hw_ops.process_cmd) { + fps_config_args.fps = + fps_config->fps; + fps_config_args.node_res = + hw_mgr_res->hw_res[i]; + + rc = hw_intf->hw_ops.process_cmd( + hw_intf->hw_priv, + CAM_ISP_HW_CMD_FPS_CONFIG, + &fps_config_args, + sizeof( + struct cam_vfe_fps_config_args) + ); + if (rc) + CAM_ERR(CAM_ISP, + "Failed fps config:%d", + fps_config->fps); + } else + CAM_WARN(CAM_ISP, "NULL hw_intf!"); + } + } + } + + return rc; +} + static int cam_isp_blob_ubwc_update( uint32_t blob_type, struct cam_isp_generic_blob_info *blob_info, @@ -3512,6 +3733,75 @@ static int cam_isp_blob_clock_update( return rc; } +static int cam_isp_blob_sensor_config( + uint32_t blob_type, + struct cam_isp_generic_blob_info *blob_info, + struct cam_isp_sensor_config *dim_config, + struct cam_hw_prepare_update_args *prepare) +{ + struct cam_ife_hw_mgr_ctx *ctx = NULL; + struct cam_ife_hw_mgr_res *hw_mgr_res; + struct cam_hw_intf *hw_intf; + struct cam_ife_sensor_dimension_update_args update_args; + int rc = -EINVAL, found = 0; + uint32_t i, j; + struct cam_isp_sensor_dimension *path_config; + + ctx = prepare->ctxt_to_hw_map; + + list_for_each_entry(hw_mgr_res, &ctx->res_list_ife_csid, list) { + for (i = 0; i < CAM_ISP_HW_SPLIT_MAX; i++) { + if (!hw_mgr_res->hw_res[i]) + continue; + found = 1; + hw_intf = hw_mgr_res->hw_res[i]->hw_intf; + if (hw_intf && hw_intf->hw_ops.process_cmd) { + path_config = &(dim_config->ipp_path); + update_args.ipp_path.width = + path_config->width; + update_args.ipp_path.height = + path_config->height; + update_args.ipp_path.measure_enabled = + path_config->measure_enabled; + path_config = &(dim_config->ppp_path); + update_args.ppp_path.width = + path_config->width; + update_args.ppp_path.height = + path_config->height; + update_args.ppp_path.measure_enabled = + path_config->measure_enabled; + for (j = 0; j < CAM_IFE_RDI_NUM_MAX; j++) { + path_config = + &(dim_config->rdi_path[j]); + update_args.rdi_path[j].width = + path_config->width; + update_args.rdi_path[j].height = + path_config->height; + update_args.rdi_path[j].measure_enabled = + path_config->measure_enabled; + } + rc = hw_intf->hw_ops.process_cmd( + hw_intf->hw_priv, + CAM_IFE_CSID_SET_SENSOR_DIMENSION_CFG, + &update_args, + sizeof( + struct + cam_ife_sensor_dimension_update_args) + ); + if (rc) + CAM_ERR(CAM_ISP, + "Dimension Update failed"); + } else + CAM_ERR(CAM_ISP, "hw_intf is NULL"); + } + if (found) + break; + } + + return rc; +} + + static void fill_res_bitmap(uint32_t resource_type, unsigned long *res_bitmap) { @@ -3852,6 +4142,49 @@ static int cam_isp_packet_generic_blob_handler(void *user_data, CAM_ERR(CAM_ISP, "Init Frame drop Update Failed"); } break; + case CAM_ISP_GENERIC_BLOB_TYPE_SENSOR_DIMENSION_CONFIG: { + struct cam_isp_sensor_config *csid_dim_config; + + if (blob_size < sizeof(struct cam_isp_sensor_config)) { + CAM_ERR(CAM_ISP, "Invalid blob size %u expected %u", + blob_size, + sizeof(struct cam_isp_sensor_config)); + return -EINVAL; + } + + csid_dim_config = + (struct cam_isp_sensor_config *)blob_data; + + rc = cam_isp_blob_sensor_config(blob_type, blob_info, + csid_dim_config, prepare); + if (rc) + CAM_ERR(CAM_ISP, + "Sensor Dimension Update Failed rc: %d", rc); + } + break; + case CAM_ISP_GENERIC_BLOB_TYPE_FPS_CONFIG: { + struct cam_fps_config *fps_config; + struct cam_isp_prepare_hw_update_data *prepare_hw_data; + + if (blob_size < sizeof(struct cam_fps_config)) { + CAM_ERR(CAM_ISP, "Invalid fps blob size %u expected %u", + blob_size, sizeof(struct cam_fps_config)); + return -EINVAL; + } + + fps_config = (struct cam_fps_config *)blob_data; + prepare_hw_data = (struct cam_isp_prepare_hw_update_data *) + prepare->priv; + + prepare_hw_data->fps = fps_config->fps; + + rc = cam_isp_blob_fps_config(blob_type, blob_info, + fps_config, prepare); + if (rc) + CAM_ERR(CAM_ISP, "FPS Update Failed rc: %d", rc); + + } + break; default: CAM_WARN(CAM_ISP, "Invalid blob type %d", blob_type); break; @@ -4009,10 +4342,6 @@ end: return rc; } -static int cam_ife_mgr_resume_hw(struct cam_ife_hw_mgr_ctx *ctx) -{ - return cam_ife_mgr_bw_control(ctx, CAM_VFE_BW_CONTROL_INCLUDE); -} static int cam_ife_mgr_sof_irq_debug( struct cam_ife_hw_mgr_ctx *ctx, @@ -4750,6 +5079,8 @@ static int cam_ife_hw_mgr_handle_reg_update( break; if (!rup_status) { + rup_event_data.irq_mono_boot_time = + evt_payload->ts.time_usecs; ife_hwr_irq_rup_cb( ife_hwr_mgr_ctx->common.cb_priv, CAM_ISP_HW_EVENT_REG_UPDATE, @@ -4779,6 +5110,8 @@ static int cam_ife_hw_mgr_handle_reg_update( if (atomic_read(&ife_hwr_mgr_ctx->overflow_pending)) break; if (!rup_status) { + rup_event_data.irq_mono_boot_time = + evt_payload->ts.time_usecs; /* Send the Reg update hw event */ ife_hwr_irq_rup_cb( ife_hwr_mgr_ctx->common.cb_priv, @@ -5138,6 +5471,8 @@ static int cam_ife_hw_mgr_handle_sof( ife_hw_mgr_ctx, &sof_done_event_data.timestamp, &sof_done_event_data.boot_time); + sof_done_event_data.irq_mono_boot_time = + evt_payload->ts.time_usecs; ife_hw_irq_sof_cb( ife_hw_mgr_ctx->common.cb_priv, @@ -5161,6 +5496,8 @@ static int cam_ife_hw_mgr_handle_sof( ife_hw_mgr_ctx, &sof_done_event_data.timestamp, &sof_done_event_data.boot_time); + sof_done_event_data.irq_mono_boot_time = + evt_payload->ts.time_usecs; ife_hw_irq_sof_cb( ife_hw_mgr_ctx->common.cb_priv, @@ -5246,13 +5583,15 @@ static int cam_ife_hw_mgr_handle_eof_for_camif_hw_res( if (atomic_read( &ife_hwr_mgr_ctx->overflow_pending)) break; - if (!eof_status) + if (!eof_status) { + eof_done_event_data.irq_mono_boot_time = + evt_payload->ts.time_usecs; ife_hwr_irq_eof_cb( ife_hwr_mgr_ctx->common.cb_priv, CAM_ISP_HW_EVENT_EOF, &eof_done_event_data); + } } - break; /* Handling dual VFE Scenario */ case 1: @@ -5293,11 +5632,14 @@ static int cam_ife_hw_mgr_handle_eof_for_camif_hw_res( if (atomic_read(&ife_hwr_mgr_ctx->overflow_pending)) break; - if (!rc) + if (!rc) { + eof_done_event_data.irq_mono_boot_time = + evt_payload->ts.time_usecs; ife_hwr_irq_eof_cb( ife_hwr_mgr_ctx->common.cb_priv, CAM_ISP_HW_EVENT_EOF, &eof_done_event_data); + } break; @@ -5397,6 +5739,8 @@ static int cam_ife_hw_mgr_handle_buf_done_for_hw_res( if (atomic_read(&ife_hwr_mgr_ctx->overflow_pending)) break; + buf_done_event_data.irq_mono_boot_time = + evt_payload->ts.time_usecs; /* Report for Successful buf_done event if any */ if (buf_done_event_data.num_handles > 0 && ife_hwr_irq_wm_done_cb) { @@ -5836,6 +6180,7 @@ int cam_ife_hw_mgr_init(struct cam_hw_mgr_intf *hw_mgr_intf, int *iommu_hdl) hw_mgr_intf->hw_prepare_update = cam_ife_mgr_prepare_hw_update; hw_mgr_intf->hw_config = cam_ife_mgr_config_hw; hw_mgr_intf->hw_cmd = cam_ife_mgr_cmd; + hw_mgr_intf->hw_reset = cam_ife_mgr_reset; if (iommu_hdl) *iommu_hdl = g_ife_hw_mgr.mgr_common.img_iommu_hdl; diff --git a/drivers/media/platform/msm/ais/cam_isp/isp_hw_mgr/include/cam_isp_hw_mgr_intf.h b/drivers/media/platform/msm/ais/cam_isp/isp_hw_mgr/include/cam_isp_hw_mgr_intf.h index 096e0f186bbf..1ab9361af1d1 100644 --- a/drivers/media/platform/msm/ais/cam_isp/isp_hw_mgr/include/cam_isp_hw_mgr_intf.h +++ b/drivers/media/platform/msm/ais/cam_isp/isp_hw_mgr/include/cam_isp_hw_mgr_intf.h @@ -130,6 +130,7 @@ struct cam_isp_bw_config_internal { * @bw_config: BW config information * @bw_config_valid: Flag indicating whether the bw_config at the index * is valid or not + * @fps: fps vaue which has been updated in hw * */ struct cam_isp_prepare_hw_update_data { @@ -137,40 +138,47 @@ struct cam_isp_prepare_hw_update_data { struct cam_isp_bw_config_internal bw_config[CAM_IFE_HW_NUM_MAX]; struct cam_isp_bw_config_internal_ab bw_config_ab[CAM_IFE_HW_NUM_MAX]; bool bw_config_valid[CAM_IFE_HW_NUM_MAX]; + uint32_t fps; }; /** * struct cam_isp_hw_sof_event_data - Event payload for CAM_HW_EVENT_SOF * - * @timestamp: Time stamp for the sof event - * @boot_time: Boot time stamp for the sof event + * @timestamp: Time stamp for the sof event + * @boot_time: Boot time stamp for the sof event + * @irq_mono_boot_time: Time stamp till the execution of IRQ wrt event started * */ struct cam_isp_hw_sof_event_data { uint64_t timestamp; uint64_t boot_time; + uint64_t irq_mono_boot_time; }; /** * struct cam_isp_hw_reg_update_event_data - Event payload for * CAM_HW_EVENT_REG_UPDATE * - * @timestamp: Time stamp for the reg update event + * @timestamp: Time stamp for the reg update event + * @irq_mono_boot_time: Time stamp till the execution of IRQ wrt event started * */ struct cam_isp_hw_reg_update_event_data { uint64_t timestamp; + uint64_t irq_mono_boot_time; }; /** * struct cam_isp_hw_epoch_event_data - Event payload for CAM_HW_EVENT_EPOCH * - * @timestamp: Time stamp for the epoch event + * @timestamp: Time stamp for the epoch event + * @irq_mono_boot_time: Time stamp till the execution of this event started * */ struct cam_isp_hw_epoch_event_data { uint64_t timestamp; + uint64_t irq_mono_boot_time; }; /** @@ -179,6 +187,7 @@ struct cam_isp_hw_epoch_event_data { * @num_handles: Number of resource handeles * @resource_handle: Resource handle array * @timestamp: Timestamp for the buf done event + * @irq_mono_boot_time: Time stamp till the execution of this event started * */ struct cam_isp_hw_done_event_data { @@ -186,16 +195,19 @@ struct cam_isp_hw_done_event_data { uint32_t resource_handle[ CAM_NUM_OUT_PER_COMP_IRQ_MAX]; uint64_t timestamp; + uint64_t irq_mono_boot_time; }; /** * struct cam_isp_hw_eof_event_data - Event payload for CAM_HW_EVENT_EOF * * @timestamp: Timestamp for the eof event + * @irq_mono_boot_time: Time stamp till the execution of this event started * */ struct cam_isp_hw_eof_event_data { uint64_t timestamp; + uint64_t irq_mono_boot_time; }; /** diff --git a/drivers/media/platform/msm/ais/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/Makefile b/drivers/media/platform/msm/ais/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/Makefile index 027d8d4b11eb..bac27015691c 100644 --- a/drivers/media/platform/msm/ais/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/Makefile +++ b/drivers/media/platform/msm/ais/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/Makefile @@ -8,5 +8,6 @@ ccflags-y += -Idrivers/media/platform/msm/ais/cam_isp/isp_hw_mgr/isp_hw/include ccflags-y += -Idrivers/media/platform/msm/ais/cam_smmu/ ccflags-y += -Idrivers/media/platform/msm/ais/cam_req_mgr/ +obj-$(CONFIG_MSM_AIS) += cam_csid_ppi_dev.o cam_csid_ppi_core.o cam_csid_ppi170.o obj-$(CONFIG_MSM_AIS) += cam_ife_csid_dev.o cam_ife_csid_soc.o cam_ife_csid_core.o obj-$(CONFIG_MSM_AIS) += cam_ife_csid17x.o cam_ife_csid_lite17x.o diff --git a/drivers/media/platform/msm/ais/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_csid_ppi170.c b/drivers/media/platform/msm/ais/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_csid_ppi170.c new file mode 100644 index 000000000000..2051292be5be --- /dev/null +++ b/drivers/media/platform/msm/ais/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_csid_ppi170.c @@ -0,0 +1,58 @@ +/* Copyright (c) 2019, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include <linux/module.h> +#include "cam_csid_ppi_core.h" +#include "cam_csid_ppi170.h" +#include "cam_csid_ppi_dev.h" + +#define CAM_PPI_DRV_NAME "ppi_170" +#define CAM_PPI_VERSION_V170 0x10070000 + +static struct cam_csid_ppi_hw_info cam_csid_ppi170_hw_info = { + .ppi_reg = &cam_csid_ppi_170_reg_offset, +}; + +static const struct of_device_id cam_csid_ppi170_dt_match[] = { + { + .compatible = "qcom,ppi170", + .data = &cam_csid_ppi170_hw_info, + }, + {} +}; + +MODULE_DEVICE_TABLE(of, cam_csid_ppi170_dt_match); + +static struct platform_driver cam_csid_ppi170_driver = { + .probe = cam_csid_ppi_probe, + .remove = cam_csid_ppi_remove, + .driver = { + .name = CAM_PPI_DRV_NAME, + .owner = THIS_MODULE, + .of_match_table = cam_csid_ppi170_dt_match, + .suppress_bind_attrs = true, + }, +}; + +static int __init cam_csid_ppi170_init_module(void) +{ + return platform_driver_register(&cam_csid_ppi170_driver); +} + +static void __exit cam_csid_ppi170_exit_module(void) +{ + platform_driver_unregister(&cam_csid_ppi170_driver); +} + +module_init(cam_csid_ppi170_init_module); +MODULE_DESCRIPTION("CAM CSID_PPI170 driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/media/platform/msm/ais/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_csid_ppi170.h b/drivers/media/platform/msm/ais/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_csid_ppi170.h new file mode 100644 index 000000000000..0ec767204914 --- /dev/null +++ b/drivers/media/platform/msm/ais/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_csid_ppi170.h @@ -0,0 +1,32 @@ +/* Copyright (c) 2019, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#ifndef _CAM_CSID_PPI_170_H_ +#define _CAM_CSID_PPI_170_H_ + +#include "cam_csid_ppi_core.h" + +static struct cam_csid_ppi_reg_offset cam_csid_ppi_170_reg_offset = { + .ppi_hw_version_addr = 0, + .ppi_module_cfg_addr = 0x60, + .ppi_irq_status_addr = 0x68, + .ppi_irq_mask_addr = 0x6c, + .ppi_irq_set_addr = 0x70, + .ppi_irq_clear_addr = 0x74, + .ppi_irq_cmd_addr = 0x78, + .ppi_rst_cmd_addr = 0x7c, + .ppi_test_bus_ctrl_addr = 0x1f4, + .ppi_debug_addr = 0x1f8, + .ppi_spare_addr = 0x1fc, +}; + +#endif /*_CAM_CSID_PPI_170_H_ */ diff --git a/drivers/media/platform/msm/ais/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_csid_ppi_core.c b/drivers/media/platform/msm/ais/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_csid_ppi_core.c new file mode 100644 index 000000000000..3d521b747e96 --- /dev/null +++ b/drivers/media/platform/msm/ais/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_csid_ppi_core.c @@ -0,0 +1,395 @@ +/* Copyright (c) 2019, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ +#include <linux/iopoll.h> +#include <linux/slab.h> +#include <uapi/media/cam_defs.h> + +#include "cam_csid_ppi_core.h" +#include "cam_csid_ppi_dev.h" +#include "cam_soc_util.h" +#include "cam_debug_util.h" +#include "cam_io_util.h" + +static int cam_csid_ppi_reset(struct cam_csid_ppi_hw *ppi_hw) +{ + struct cam_hw_soc_info *soc_info; + const struct cam_csid_ppi_reg_offset *ppi_reg; + int rc = 0; + uint32_t status; + + soc_info = &ppi_hw->hw_info->soc_info; + ppi_reg = ppi_hw->ppi_info->ppi_reg; + + CAM_DBG(CAM_ISP, "PPI:%d reset", ppi_hw->hw_intf->hw_idx); + + /* Mask all interrupts */ + cam_io_w_mb(0, soc_info->reg_map[0].mem_base + + ppi_reg->ppi_irq_mask_addr); + cam_io_w_mb(PPI_RST_CONTROL, soc_info->reg_map[0].mem_base + + ppi_reg->ppi_irq_set_addr); + cam_io_w_mb(PPI_RST_CONTROL, soc_info->reg_map[0].mem_base + + ppi_reg->ppi_rst_cmd_addr); + cam_io_w_mb(PPI_IRQ_CMD_SET, soc_info->reg_map[0].mem_base + + ppi_reg->ppi_irq_cmd_addr); + + rc = readl_poll_timeout(soc_info->reg_map[0].mem_base + + ppi_reg->ppi_irq_status_addr, status, + (status & 0x1) == 0x1, 1000, 500000); + CAM_DBG(CAM_ISP, "PPI:%d reset status %d", ppi_hw->hw_intf->hw_idx, + status); + if (rc < 0) { + CAM_ERR(CAM_ISP, "PPI:%d ppi_reset fail rc = %d status = %d", + ppi_hw->hw_intf->hw_idx, rc, status); + return rc; + } + cam_io_w_mb(PPI_RST_CONTROL, soc_info->reg_map[0].mem_base + + ppi_reg->ppi_irq_clear_addr); + cam_io_w_mb(PPI_IRQ_CMD_CLEAR, soc_info->reg_map[0].mem_base + + ppi_reg->ppi_irq_cmd_addr); + + return 0; +} + +static int cam_csid_ppi_enable_hw(struct cam_csid_ppi_hw *ppi_hw) +{ + int rc = 0; + uint32_t i; + uint64_t val; + const struct cam_csid_ppi_reg_offset *ppi_reg; + struct cam_hw_soc_info *soc_info; + uint32_t err_irq_mask; + + ppi_reg = ppi_hw->ppi_info->ppi_reg; + soc_info = &ppi_hw->hw_info->soc_info; + + CAM_DBG(CAM_ISP, "PPI:%d init PPI HW", ppi_hw->hw_intf->hw_idx); + + for (i = 0; i < soc_info->num_clk; i++) { + /* Passing zero in clk_rate results in setting no clk_rate */ + rc = cam_soc_util_clk_enable(soc_info->clk[i], + soc_info->clk_name[i], 0); + if (rc) + goto clk_disable; + } + + /* Reset PPI */ + rc = cam_csid_ppi_reset(ppi_hw); + if (rc) + goto clk_disable; + + err_irq_mask = PPI_IRQ_FIFO0_OVERFLOW | PPI_IRQ_FIFO1_OVERFLOW | + PPI_IRQ_FIFO2_OVERFLOW; + cam_io_w_mb(err_irq_mask, soc_info->reg_map[0].mem_base + + ppi_reg->ppi_irq_mask_addr); + rc = cam_soc_util_irq_enable(soc_info); + if (rc) + goto clk_disable; + /* Clear the RST done IRQ */ + cam_io_w_mb(PPI_RST_CONTROL, soc_info->reg_map[0].mem_base + + ppi_reg->ppi_irq_clear_addr); + cam_io_w_mb(PPI_IRQ_CMD_CLEAR, soc_info->reg_map[0].mem_base + + ppi_reg->ppi_irq_cmd_addr); + val = cam_io_r_mb(soc_info->reg_map[0].mem_base + + ppi_reg->ppi_hw_version_addr); + CAM_DBG(CAM_ISP, "PPI:%d PPI HW version: 0x%x", + ppi_hw->hw_intf->hw_idx, val); + ppi_hw->device_enabled = 1; + + return 0; +clk_disable: + for (--i; i >= 0; i--) + cam_soc_util_clk_disable(soc_info->clk[i], + soc_info->clk_name[i]); + return rc; +} + +static int cam_csid_ppi_disable_hw(struct cam_csid_ppi_hw *ppi_hw) +{ + int rc = 0; + int i; + struct cam_hw_soc_info *soc_info; + const struct cam_csid_ppi_reg_offset *ppi_reg; + uint64_t ppi_cfg_val = 0; + + CAM_DBG(CAM_ISP, "PPI:%d De-init PPI HW", + ppi_hw->hw_intf->hw_idx); + + soc_info = &ppi_hw->hw_info->soc_info; + ppi_reg = ppi_hw->ppi_info->ppi_reg; + + CAM_DBG(CAM_ISP, "%s:Calling PPI Reset\n", __func__); + cam_csid_ppi_reset(ppi_hw); + CAM_DBG(CAM_ISP, "%s:PPI Reset Done\n", __func__); + + /* disable the clocks */ + for (i = 0; i < soc_info->num_clk; i++) + cam_soc_util_clk_disable(soc_info->clk[i], + soc_info->clk_name[i]); + + /* disable the interrupt */ + cam_io_w_mb(0, soc_info->reg_map[0].mem_base + + ppi_reg->ppi_irq_mask_addr); + cam_soc_util_irq_disable(soc_info); + + /* disable lanes */ + for (i = 0; i < CAM_CSID_PPI_LANES_MAX; i++) + ppi_cfg_val &= ~PPI_CFG_CPHY_DLX_EN(i); + + cam_io_w_mb(ppi_cfg_val, soc_info->reg_map[0].mem_base + + ppi_reg->ppi_module_cfg_addr); + + ppi_hw->device_enabled = 0; + + return rc; +} + +static int cam_csid_ppi_init_hw(void *hw_priv, void *init_args, + uint32_t arg_size) +{ + int i, rc = 0; + uint32_t num_lanes; + uint32_t lanes[CAM_CSID_PPI_HW_MAX] = {0, 0, 0, 0}; + uint32_t cphy; + bool dl0, dl1; + uint32_t ppi_cfg_val = 0; + struct cam_csid_ppi_hw *ppi_hw; + struct cam_hw_info *ppi_hw_info; + const struct cam_csid_ppi_reg_offset *ppi_reg; + struct cam_hw_soc_info *soc_info; + struct cam_csid_ppi_cfg ppi_cfg; + + if (!hw_priv || !init_args || + (arg_size != sizeof(struct cam_csid_ppi_cfg))) { + CAM_ERR(CAM_ISP, "PPI: Invalid args"); + rc = -EINVAL; + goto end; + } + + dl0 = dl1 = false; + ppi_hw_info = (struct cam_hw_info *)hw_priv; + ppi_hw = (struct cam_csid_ppi_hw *)ppi_hw_info->core_info; + ppi_reg = ppi_hw->ppi_info->ppi_reg; + ppi_cfg = *((struct cam_csid_ppi_cfg *)init_args); + + /* Initialize the ppi hardware */ + rc = cam_csid_ppi_enable_hw(ppi_hw); + if (rc) + goto end; + + /* Do lane configuration here*/ + num_lanes = ppi_cfg.lane_num; + /* lane_type = 1 refers to cphy */ + cphy = ppi_cfg.lane_type; + CAM_DBG(CAM_ISP, "lane_cfg 0x%x | num_lanes 0x%x | lane_type 0x%x", + ppi_cfg.lane_cfg, num_lanes, cphy); + + for (i = 0; i < num_lanes; i++) { + lanes[i] = (ppi_cfg.lane_cfg & (0x3 << (4 * i))) >> (4*i); + (lanes[i] < 2) ? (dl0 = true) : (dl1 = true); + CAM_DBG(CAM_ISP, "lanes[%d] %d", i, lanes[i]); + } + + if (num_lanes) { + if (cphy) { + for (i = 0; i < num_lanes; i++) { + /* Select Cphy */ + ppi_cfg_val |= PPI_CFG_CPHY_DLX_SEL(lanes[i]); + /* Enable lane Cphy */ + ppi_cfg_val |= PPI_CFG_CPHY_DLX_EN(lanes[i]); + } + } else { + if (dl0) + /* Enable lane 0 */ + ppi_cfg_val |= PPI_CFG_CPHY_DLX_EN(0); + if (dl1) + /* Enable lane 1 */ + ppi_cfg_val |= PPI_CFG_CPHY_DLX_EN(1); + } + } else { + CAM_ERR(CAM_ISP, + "Number of lanes to enable is cannot be zero"); + rc = -1; + goto end; + } + + CAM_DBG(CAM_ISP, "ppi_cfg_val 0x%x", ppi_cfg_val); + soc_info = &ppi_hw->hw_info->soc_info; + cam_io_w_mb(ppi_cfg_val, soc_info->reg_map[0].mem_base + + ppi_reg->ppi_module_cfg_addr); + + CAM_DBG(CAM_ISP, "ppi cfg 0x%x", + cam_io_r_mb(soc_info->reg_map[0].mem_base + + ppi_reg->ppi_module_cfg_addr)); +end: + return rc; +} + +static int cam_csid_ppi_deinit_hw(void *hw_priv, void *deinit_args, + uint32_t arg_size) +{ + int rc = 0; + struct cam_csid_ppi_hw *ppi_hw; + struct cam_hw_info *ppi_hw_info; + + CAM_DBG(CAM_ISP, "Enter"); + + if (!hw_priv) { + CAM_ERR(CAM_ISP, "PPI:Invalid arguments"); + rc = -EINVAL; + goto end; + } + + ppi_hw_info = (struct cam_hw_info *)hw_priv; + ppi_hw = (struct cam_csid_ppi_hw *)ppi_hw_info->core_info; + + CAM_DBG(CAM_ISP, "Disabling PPI Hw\n"); + rc = cam_csid_ppi_disable_hw(ppi_hw); + if (rc < 0) + CAM_DBG(CAM_ISP, "%s: Exit with %d\n", __func__, rc); +end: + return rc; +} + +int cam_csid_ppi_hw_probe_init(struct cam_hw_intf *ppi_hw_intf, + uint32_t ppi_idx) +{ + int rc = -EINVAL; + struct cam_hw_info *ppi_hw_info; + struct cam_csid_ppi_hw *csid_ppi_hw = NULL; + + if (ppi_idx >= CAM_CSID_PPI_HW_MAX) { + CAM_ERR(CAM_ISP, "Invalid ppi index:%d", ppi_idx); + goto err; + } + + ppi_hw_info = (struct cam_hw_info *) ppi_hw_intf->hw_priv; + csid_ppi_hw = (struct cam_csid_ppi_hw *) ppi_hw_info->core_info; + + csid_ppi_hw->hw_intf = ppi_hw_intf; + csid_ppi_hw->hw_info = ppi_hw_info; + + CAM_DBG(CAM_ISP, "type %d index %d", + csid_ppi_hw->hw_intf->hw_type, ppi_idx); + + rc = cam_csid_ppi_init_soc_resources(&csid_ppi_hw->hw_info->soc_info, + cam_csid_ppi_irq, csid_ppi_hw); + if (rc < 0) { + CAM_ERR(CAM_ISP, "PPI:%d Failed to init_soc", ppi_idx); + goto err; + } + + csid_ppi_hw->hw_intf->hw_ops.init = cam_csid_ppi_init_hw; + csid_ppi_hw->hw_intf->hw_ops.deinit = cam_csid_ppi_deinit_hw; + return 0; +err: + return rc; +} + +int cam_csid_ppi_init_soc_resources(struct cam_hw_soc_info *soc_info, + irq_handler_t ppi_irq_handler, void *irq_data) +{ + int rc = 0; + + rc = cam_soc_util_get_dt_properties(soc_info); + if (rc) { + CAM_ERR(CAM_ISP, "PPI: Failed to get dt properties"); + goto end; + } + + rc = cam_soc_util_request_platform_resource(soc_info, ppi_irq_handler, + irq_data); + if (rc) { + CAM_ERR(CAM_ISP, + "PPI: Error Request platform resources failed rc=%d", + rc); + goto err; + } +end: + return rc; +err: + cam_soc_util_release_platform_resource(soc_info); + return rc; +} + +irqreturn_t cam_csid_ppi_irq(int irq_num, void *data) +{ + uint32_t irq_status = 0; + uint32_t i, ppi_cfg_val = 0; + bool fatal_err_detected = false; + + struct cam_csid_ppi_hw *ppi_hw; + struct cam_hw_soc_info *soc_info; + const struct cam_csid_ppi_reg_offset *ppi_reg; + + if (!data) { + CAM_ERR(CAM_ISP, "PPI: Invalid arguments"); + return IRQ_HANDLED; + } + + ppi_hw = (struct cam_csid_ppi_hw *)data; + ppi_reg = ppi_hw->ppi_info->ppi_reg; + soc_info = &ppi_hw->hw_info->soc_info; + + /* read */ + irq_status = cam_io_r_mb(soc_info->reg_map[0].mem_base + + ppi_reg->ppi_irq_status_addr); + + /* clear */ + cam_io_w_mb(irq_status, soc_info->reg_map[0].mem_base + + ppi_reg->ppi_irq_clear_addr); + + cam_io_w_mb(PPI_IRQ_CMD_CLEAR, soc_info->reg_map[0].mem_base + + ppi_reg->ppi_irq_cmd_addr); + + CAM_DBG(CAM_ISP, "PPI %d irq status 0x%x", ppi_hw->hw_intf->hw_idx, + irq_status); + + if (ppi_hw->device_enabled == 1) { + if (irq_status & PPI_IRQ_RST_DONE) { + CAM_DBG(CAM_ISP, "PPI Reset Done"); + goto ret; + } + if ((irq_status & PPI_IRQ_FIFO0_OVERFLOW) || + (irq_status & PPI_IRQ_FIFO1_OVERFLOW) || + (irq_status & PPI_IRQ_FIFO2_OVERFLOW)) { + fatal_err_detected = true; + goto handle_fatal_error; + } + } + +handle_fatal_error: + if (fatal_err_detected) { + CAM_ERR(CAM_ISP, "PPI: %d irq_status:0x%x", + ppi_hw->hw_intf->hw_idx, irq_status); + /* disable lanes */ + for (i = 0; i < CAM_CSID_PPI_LANES_MAX; i++) + ppi_cfg_val &= ~PPI_CFG_CPHY_DLX_EN(i); + + cam_io_w_mb(ppi_cfg_val, soc_info->reg_map[0].mem_base + + ppi_reg->ppi_module_cfg_addr); + } +ret: + CAM_DBG(CAM_ISP, "IRQ Handling exit"); + return IRQ_HANDLED; +} + +int cam_csid_ppi_hw_deinit(struct cam_csid_ppi_hw *csid_ppi_hw) +{ + if (!csid_ppi_hw) { + CAM_ERR(CAM_ISP, "Invalid param"); + return -EINVAL; + } + /* release the privdate data memory from resources */ + return cam_soc_util_release_platform_resource( + &csid_ppi_hw->hw_info->soc_info); +} + diff --git a/drivers/media/platform/msm/ais/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_csid_ppi_core.h b/drivers/media/platform/msm/ais/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_csid_ppi_core.h new file mode 100644 index 000000000000..720ac4cd9a6b --- /dev/null +++ b/drivers/media/platform/msm/ais/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_csid_ppi_core.h @@ -0,0 +1,103 @@ +/* Copyright (c) 2019, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#ifndef _CAM_CSID_PPI_HW_H_ +#define _CAM_CSID_PPI_HW_H_ + +#include "cam_hw.h" +#include "cam_hw_intf.h" + +#define CAM_CSID_PPI_HW_MAX 4 +#define CAM_CSID_PPI_LANES_MAX 3 + +#define PPI_IRQ_RST_DONE BIT(0) +#define PPI_IRQ_FIFO0_OVERFLOW BIT(1) +#define PPI_IRQ_FIFO1_OVERFLOW BIT(2) +#define PPI_IRQ_FIFO2_OVERFLOW BIT(3) + +#define PPI_IRQ_CMD_SET BIT(1) + +#define PPI_IRQ_CMD_CLEAR BIT(0) + +#define PPI_RST_CONTROL BIT(0) +/* + * Select the PHY (CPHY set '1' or DPHY set '0') + */ +#define PPI_CFG_CPHY_DLX_SEL(X) ((X < 2) ? BIT(X) : 0) + +#define PPI_CFG_CPHY_DLX_EN(X) BIT(4+X) + +struct cam_csid_ppi_reg_offset { + uint32_t ppi_hw_version_addr; + uint32_t ppi_module_cfg_addr; + + uint32_t ppi_irq_status_addr; + uint32_t ppi_irq_mask_addr; + uint32_t ppi_irq_set_addr; + uint32_t ppi_irq_clear_addr; + uint32_t ppi_irq_cmd_addr; + uint32_t ppi_rst_cmd_addr; + uint32_t ppi_test_bus_ctrl_addr; + uint32_t ppi_debug_addr; + uint32_t ppi_spare_addr; +}; + +/** + * struct cam_csid_ppi_hw_info- ppi HW info + * + * @ppi_reg: ppi register offsets + * + */ +struct cam_csid_ppi_hw_info { + const struct cam_csid_ppi_reg_offset *ppi_reg; +}; + +/** + * struct cam_csid_ppi_hw- ppi hw device resources data + * + * @hw_intf: contain the ppi hw interface information + * @hw_info: ppi hw device information + * @ppi_info: ppi hw specific information + * @device_enabled Device enabled will set once ppi powered on and + * initial configuration are done. + * @lock_state ppi spin lock + * + */ +struct cam_csid_ppi_hw { + struct cam_hw_intf *hw_intf; + struct cam_hw_info *hw_info; + struct cam_csid_ppi_hw_info *ppi_info; + uint32_t device_enabled; +}; + +/** + * struct cam_csid_ppi_cfg - ppi lane configuration data + * @lane_type: lane type: c-phy or d-phy + * @lane_num : active lane number + * @lane_cfg: lane configurations: 4 bits per lane + * + */ +struct cam_csid_ppi_cfg { + uint32_t lane_type; + uint32_t lane_num; + uint32_t lane_cfg; +}; + +int cam_csid_ppi_hw_probe_init(struct cam_hw_intf *ppi_hw_intf, + uint32_t ppi_idx); +int cam_csid_ppi_hw_deinit(struct cam_csid_ppi_hw *csid_ppi_hw); +int cam_csid_ppi_init_soc_resources(struct cam_hw_soc_info *soc_info, + irq_handler_t ppi_irq_handler, void *irq_data); +int cam_csid_ppi_deinit_soc_resources(struct cam_hw_soc_info *soc_info); +int cam_csid_ppi_hw_init(struct cam_hw_intf **csid_ppi_hw, + uint32_t hw_idx); +#endif /* _CAM_CSID_PPI_HW_H_ */ diff --git a/drivers/media/platform/msm/ais/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_csid_ppi_dev.c b/drivers/media/platform/msm/ais/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_csid_ppi_dev.c new file mode 100644 index 000000000000..9bdfc5ff61b3 --- /dev/null +++ b/drivers/media/platform/msm/ais/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_csid_ppi_dev.c @@ -0,0 +1,147 @@ +/* Copyright (c) 2019, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include <linux/slab.h> +#include <linux/mod_devicetable.h> +#include <linux/of_device.h> + +#include "cam_isp_hw.h" +#include "cam_hw_intf.h" +#include "cam_csid_ppi_core.h" +#include "cam_csid_ppi_dev.h" +#include "cam_debug_util.h" + +static struct cam_hw_intf *cam_csid_ppi_hw_list[CAM_CSID_PPI_HW_MAX] = { + NULL, NULL, NULL, NULL}; +static char ppi_dev_name[8]; + +int cam_csid_ppi_probe(struct platform_device *pdev) +{ + struct cam_hw_intf *ppi_hw_intf; + struct cam_hw_info *ppi_hw_info; + struct cam_csid_ppi_hw *ppi_dev = NULL; + const struct of_device_id *match_dev = NULL; + struct cam_csid_ppi_hw_info *ppi_hw_data = NULL; + uint32_t ppi_dev_idx; + int rc = 0; + + CAM_DBG(CAM_ISP, "PPI probe called"); + + ppi_hw_intf = kzalloc(sizeof(struct cam_hw_intf), GFP_KERNEL); + if (!ppi_hw_intf) { + rc = -ENOMEM; + goto err; + } + + ppi_hw_info = kzalloc(sizeof(struct cam_hw_info), GFP_KERNEL); + if (!ppi_hw_info) { + rc = -ENOMEM; + goto free_hw_intf; + } + + ppi_dev = kzalloc(sizeof(struct cam_csid_ppi_hw), GFP_KERNEL); + if (!ppi_dev) { + rc = -ENOMEM; + goto free_hw_info; + } + + /* get csid ppi hw index */ + of_property_read_u32(pdev->dev.of_node, "cell-index", &ppi_dev_idx); + + /* get csid ppi hw information */ + match_dev = of_match_device(pdev->dev.driver->of_match_table, + &pdev->dev); + if (!match_dev) { + CAM_ERR(CAM_ISP, "No matching table for the CSID PPI HW!"); + rc = -EINVAL; + goto free_dev; + } + + memset(ppi_dev_name, 0, sizeof(ppi_dev_name)); + snprintf(ppi_dev_name, sizeof(ppi_dev_name), "ppi%1u", ppi_dev_idx); + + ppi_hw_intf->hw_idx = ppi_dev_idx; + ppi_hw_intf->hw_priv = ppi_hw_info; + + ppi_hw_info->core_info = ppi_dev; + ppi_hw_info->soc_info.pdev = pdev; + ppi_hw_info->soc_info.dev = &pdev->dev; + ppi_hw_info->soc_info.dev_name = ppi_dev_name; + ppi_hw_info->soc_info.index = ppi_dev_idx; + + ppi_hw_data = (struct cam_csid_ppi_hw_info *)match_dev->data; + /* need to setup the pdev before call the csid ppi hw probe init */ + ppi_dev->ppi_info = ppi_hw_data; + + rc = cam_csid_ppi_hw_probe_init(ppi_hw_intf, ppi_dev_idx); + if (rc) { + CAM_ERR(CAM_ISP, "PPI: Probe init failed!"); + goto free_dev; + } + + platform_set_drvdata(pdev, ppi_dev); + CAM_DBG(CAM_ISP, "PPI:%d probe successful", + ppi_hw_intf->hw_idx); + + if (ppi_hw_intf->hw_idx < CAM_CSID_PPI_HW_MAX) + cam_csid_ppi_hw_list[ppi_hw_intf->hw_idx] = ppi_hw_intf; + else + goto free_dev; + + return 0; +free_dev: + kfree(ppi_dev); +free_hw_info: + kfree(ppi_hw_info); +free_hw_intf: + kfree(ppi_hw_intf); +err: + return rc; +} + +int cam_csid_ppi_remove(struct platform_device *pdev) +{ + struct cam_csid_ppi_hw *ppi_dev = NULL; + struct cam_hw_intf *ppi_hw_intf; + struct cam_hw_info *ppi_hw_info; + + ppi_dev = (struct cam_csid_ppi_hw *)platform_get_drvdata(pdev); + ppi_hw_intf = ppi_dev->hw_intf; + ppi_hw_info = ppi_dev->hw_info; + + CAM_DBG(CAM_ISP, "PPI:%d remove", ppi_dev->hw_intf->hw_idx); + + cam_csid_ppi_hw_deinit(ppi_dev); + + /* release the ppi device memory */ + kfree(ppi_dev); + kfree(ppi_hw_info); + kfree(ppi_hw_intf); + return 0; +} + +int cam_csid_ppi_hw_init(struct cam_hw_intf **csid_ppi_hw, + uint32_t hw_idx) +{ + int rc = 0; + + if (cam_csid_ppi_hw_list[hw_idx]) { + *csid_ppi_hw = cam_csid_ppi_hw_list[hw_idx]; + } else { + *csid_ppi_hw = NULL; + rc = -1; + } + + return rc; +} +EXPORT_SYMBOL(cam_csid_ppi_hw_init); + diff --git a/drivers/media/platform/msm/ais/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_csid_ppi_dev.h b/drivers/media/platform/msm/ais/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_csid_ppi_dev.h new file mode 100644 index 000000000000..b2ebeaf92947 --- /dev/null +++ b/drivers/media/platform/msm/ais/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_csid_ppi_dev.h @@ -0,0 +1,22 @@ +/* Copyright (c) 2019, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#ifndef _CAM_CSID_PPI_DEV_H_ +#define _CAM_CSID_PPI_DEV_H_ + +#include "cam_isp_hw.h" + +irqreturn_t cam_csid_ppi_irq(int irq_num, void *data); +int cam_csid_ppi_probe(struct platform_device *pdev); +int cam_csid_ppi_remove(struct platform_device *pdev); + +#endif /*_CAM_CSID_PPI_DEV_H_ */ diff --git a/drivers/media/platform/msm/ais/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid170.h b/drivers/media/platform/msm/ais/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid170.h index 576e8cb8d3b8..6254b97c436a 100644 --- a/drivers/media/platform/msm/ais/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid170.h +++ b/drivers/media/platform/msm/ais/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid170.h @@ -293,6 +293,10 @@ static struct cam_ife_csid_common_reg_offset .ppp_irq_mask_all = 0x0, .measure_en_hbi_vbi_cnt_mask = 0xC, .format_measure_en_val = 1, + .format_measure_height_mask_val = 0xFFFF, + .format_measure_height_shift_val = 0x10, + .format_measure_width_mask_val = 0xFFFF, + .format_measure_width_shift_val = 0x0, }; static struct cam_ife_csid_reg_offset cam_ife_csid_170_reg_offset = { diff --git a/drivers/media/platform/msm/ais/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid175.h b/drivers/media/platform/msm/ais/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid175.h index 8116cb452b35..680b641038cf 100644 --- a/drivers/media/platform/msm/ais/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid175.h +++ b/drivers/media/platform/msm/ais/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid175.h @@ -334,6 +334,10 @@ static struct cam_ife_csid_common_reg_offset .ppp_irq_mask_all = 0xFFFF, .measure_en_hbi_vbi_cnt_mask = 0xC, .format_measure_en_val = 1, + .format_measure_height_mask_val = 0xFFFF, + .format_measure_height_shift_val = 0x10, + .format_measure_width_mask_val = 0xFFFF, + .format_measure_width_shift_val = 0x0, }; static struct cam_ife_csid_reg_offset cam_ife_csid_175_reg_offset = { diff --git a/drivers/media/platform/msm/ais/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid175_200.h b/drivers/media/platform/msm/ais/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid175_200.h index bc162b6b0a87..48570dad5f37 100644 --- a/drivers/media/platform/msm/ais/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid175_200.h +++ b/drivers/media/platform/msm/ais/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid175_200.h @@ -350,6 +350,10 @@ static struct cam_ife_csid_common_reg_offset .ppp_irq_mask_all = 0xFFFF, .measure_en_hbi_vbi_cnt_mask = 0xC, .format_measure_en_val = 1, + .format_measure_height_mask_val = 0xFFFF, + .format_measure_height_shift_val = 0x10, + .format_measure_width_mask_val = 0xFFFF, + .format_measure_width_shift_val = 0x0, }; static struct cam_ife_csid_reg_offset cam_ife_csid_175_200_reg_offset = { diff --git a/drivers/media/platform/msm/ais/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c b/drivers/media/platform/msm/ais/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c index a15879f9d0d9..860b02b472e8 100644 --- a/drivers/media/platform/msm/ais/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c +++ b/drivers/media/platform/msm/ais/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c @@ -16,6 +16,7 @@ #include <uapi/media/cam_defs.h> #include "cam_ife_csid_core.h" +#include "cam_csid_ppi_core.h" #include "cam_isp_hw.h" #include "cam_soc_util.h" #include "cam_io_util.h" @@ -78,7 +79,7 @@ static int cam_ife_csid_is_ipp_ppp_format_supported( static int cam_ife_csid_get_format_rdi( uint32_t in_format, uint32_t out_format, - uint32_t *decode_fmt, uint32_t *plain_fmt) + uint32_t *decode_fmt, uint32_t *plain_fmt, uint32_t *in_bpp) { int rc = 0; @@ -96,6 +97,7 @@ static int cam_ife_csid_get_format_rdi( rc = -EINVAL; break; } + *in_bpp = 6; break; case CAM_FORMAT_MIPI_RAW_8: switch (out_format) { @@ -111,6 +113,7 @@ static int cam_ife_csid_get_format_rdi( rc = -EINVAL; break; } + *in_bpp = 8; break; case CAM_FORMAT_MIPI_RAW_10: switch (out_format) { @@ -126,6 +129,7 @@ static int cam_ife_csid_get_format_rdi( rc = -EINVAL; break; } + *in_bpp = 10; break; case CAM_FORMAT_MIPI_RAW_12: switch (out_format) { @@ -140,6 +144,7 @@ static int cam_ife_csid_get_format_rdi( rc = -EINVAL; break; } + *in_bpp = 12; break; case CAM_FORMAT_MIPI_RAW_14: switch (out_format) { @@ -154,6 +159,7 @@ static int cam_ife_csid_get_format_rdi( rc = -EINVAL; break; } + *in_bpp = 14; break; case CAM_FORMAT_MIPI_RAW_16: switch (out_format) { @@ -168,6 +174,7 @@ static int cam_ife_csid_get_format_rdi( rc = -EINVAL; break; } + *in_bpp = 16; break; case CAM_FORMAT_MIPI_RAW_20: switch (out_format) { @@ -182,6 +189,7 @@ static int cam_ife_csid_get_format_rdi( rc = -EINVAL; break; } + *in_bpp = 20; break; case CAM_FORMAT_DPCM_10_6_10: *decode_fmt = 0x7; @@ -566,10 +574,6 @@ static int cam_ife_csid_path_reset(struct cam_ife_csid_hw *csid_hw, init_completion(complete); reset_strb_val = csid_reg->cmn_reg->path_rst_stb_all; - /* Enable the Test gen before reset */ - cam_io_w_mb(1, csid_hw->hw_info->soc_info.reg_map[0].mem_base + - csid_reg->tpg_reg->csid_tpg_ctrl_addr); - /* Reset the corresponding ife csid path */ cam_io_w_mb(reset_strb_val, soc_info->reg_map[0].mem_base + reset_strb_addr); @@ -584,10 +588,6 @@ static int cam_ife_csid_path_reset(struct cam_ife_csid_hw *csid_hw, rc = -ETIMEDOUT; } - /* Disable Test Gen after reset*/ - cam_io_w_mb(0, soc_info->reg_map[0].mem_base + - csid_reg->tpg_reg->csid_tpg_ctrl_addr); - end: return rc; @@ -1166,6 +1166,11 @@ static int cam_ife_csid_disable_hw(struct cam_ife_csid_hw *csid_hw) for (i = 0; i < CAM_IFE_PIX_PATH_RES_MAX; i++) csid_hw->res_sof_cnt[i] = 0; + csid_hw->ipp_path_config.measure_enabled = 0; + csid_hw->ppp_path_config.measure_enabled = 0; + for (i = 0; i <= CAM_IFE_PIX_PATH_RES_RDI_3; i++) + csid_hw->rdi_path_config[i].measure_enabled = 0; + csid_hw->hw_info->hw_state = CAM_HW_STATE_POWER_DOWN; csid_hw->error_irq_count = 0; csid_hw->first_sof_ts = 0; @@ -1422,10 +1427,12 @@ static int cam_ife_csid_enable_csi2( struct cam_isp_resource_node *res) { int rc = 0; - const struct cam_ife_csid_reg_offset *csid_reg; - struct cam_hw_soc_info *soc_info; - struct cam_ife_csid_cid_data *cid_data; + const struct cam_ife_csid_reg_offset *csid_reg; + struct cam_hw_soc_info *soc_info; + struct cam_ife_csid_cid_data *cid_data; + struct cam_csid_ppi_cfg ppi_lane_cfg; uint32_t val = 0; + uint32_t ppi_index = 0; csid_reg = csid_hw->csid_info->csid_reg; soc_info = &csid_hw->hw_info->soc_info; @@ -1515,6 +1522,24 @@ static int cam_ife_csid_enable_csi2( cam_io_w_mb(val, soc_info->reg_map[0].mem_base + csid_reg->csi2_reg->csid_csi2_rx_irq_mask_addr); + ppi_index = csid_hw->csi2_rx_cfg.phy_sel; + if (csid_hw->ppi_hw_intf[ppi_index] && csid_hw->ppi_enable) { + ppi_lane_cfg.lane_type = csid_hw->csi2_rx_cfg.lane_type; + ppi_lane_cfg.lane_num = csid_hw->csi2_rx_cfg.lane_num; + ppi_lane_cfg.lane_cfg = csid_hw->csi2_rx_cfg.lane_cfg; + + CAM_DBG(CAM_ISP, "ppi_index to init %d", ppi_index); + rc = csid_hw->ppi_hw_intf[ppi_index]->hw_ops.init( + csid_hw->ppi_hw_intf[ppi_index]->hw_priv, + &ppi_lane_cfg, + sizeof(struct cam_csid_ppi_cfg)); + if (rc < 0) { + CAM_ERR(CAM_ISP, "PPI:%d Init Failed", + ppi_index); + return rc; + } + } + return 0; } @@ -1522,8 +1547,10 @@ static int cam_ife_csid_disable_csi2( struct cam_ife_csid_hw *csid_hw, struct cam_isp_resource_node *res) { - const struct cam_ife_csid_reg_offset *csid_reg; - struct cam_hw_soc_info *soc_info; + int rc = 0; + const struct cam_ife_csid_reg_offset *csid_reg; + struct cam_hw_soc_info *soc_info; + uint32_t ppi_index = 0; if (res->res_id >= CAM_IFE_CSID_CID_MAX) { CAM_ERR(CAM_ISP, "CSID:%d Invalid res id :%d", @@ -1554,6 +1581,19 @@ static int cam_ife_csid_disable_csi2( res->res_state = CAM_ISP_RESOURCE_STATE_RESERVED; + ppi_index = csid_hw->csi2_rx_cfg.phy_sel; + if (csid_hw->ppi_hw_intf[ppi_index] && csid_hw->ppi_enable) { + /* De-Initialize the PPI bridge */ + CAM_DBG(CAM_ISP, "ppi_index to de-init %d\n", ppi_index); + rc = csid_hw->ppi_hw_intf[ppi_index]->hw_ops.deinit( + csid_hw->ppi_hw_intf[ppi_index]->hw_priv, + NULL, 0); + if (rc < 0) { + CAM_ERR(CAM_ISP, "PPI:%d De-Init Failed", ppi_index); + return rc; + } + } + return 0; } @@ -1588,6 +1628,7 @@ static int cam_ife_csid_init_config_pxl_path( const struct cam_ife_csid_pxl_reg_offset *pxl_reg = NULL; bool is_ipp; uint32_t decode_format = 0, plain_format = 0, val = 0; + struct cam_isp_sensor_dimension *path_config; path_data = (struct cam_ife_csid_path_cfg *) res->res_priv; csid_reg = csid_hw->csid_info->csid_reg; @@ -1596,9 +1637,11 @@ static int cam_ife_csid_init_config_pxl_path( if (res->res_id == CAM_IFE_PIX_PATH_RES_IPP) { is_ipp = true; pxl_reg = csid_reg->ipp_reg; + path_config = &(csid_hw->ipp_path_config); } else { is_ipp = false; pxl_reg = csid_reg->ppp_reg; + path_config = &(csid_hw->ppp_path_config); } if (!pxl_reg) { @@ -1667,6 +1710,24 @@ static int cam_ife_csid_init_config_pxl_path( } } + /* configure pixel format measure */ + if (path_config->measure_enabled) { + val = (((path_config->height & + csid_reg->cmn_reg->format_measure_height_mask_val) << + csid_reg->cmn_reg->format_measure_height_shift_val) | + (path_config->width & + csid_reg->cmn_reg->format_measure_width_mask_val)); + CAM_DBG(CAM_ISP, "CSID:%d format measure cfg1 value : 0x%x", + csid_hw->hw_intf->hw_idx, val); + + cam_io_w_mb(val, soc_info->reg_map[0].mem_base + + pxl_reg->csid_pxl_format_measure_cfg1_addr); + + /* enable pixel and line counter */ + cam_io_w_mb(3, soc_info->reg_map[0].mem_base + + pxl_reg->csid_pxl_format_measure_cfg0_addr); + } + /* set frame drop pattern to 0 and period to 1 */ cam_io_w_mb(1, soc_info->reg_map[0].mem_base + pxl_reg->csid_pxl_frm_drop_period_addr); @@ -1812,6 +1873,7 @@ static int cam_ife_csid_enable_pxl_path( const struct cam_ife_csid_pxl_reg_offset *pxl_reg = NULL; bool is_ipp; uint32_t val = 0, path_status; + struct cam_isp_sensor_dimension *path_config; path_data = (struct cam_ife_csid_path_cfg *) res->res_priv; csid_reg = csid_hw->csid_info->csid_reg; @@ -1820,9 +1882,11 @@ static int cam_ife_csid_enable_pxl_path( if (res->res_id == CAM_IFE_PIX_PATH_RES_IPP) { is_ipp = true; pxl_reg = csid_reg->ipp_reg; + path_config = &(csid_hw->ipp_path_config); } else { is_ipp = false; pxl_reg = csid_reg->ppp_reg; + path_config = &(csid_hw->ppp_path_config); } if (res->res_state != CAM_ISP_RESOURCE_STATE_INIT_HW) { @@ -1883,6 +1947,10 @@ static int cam_ife_csid_enable_pxl_path( if (csid_hw->csid_debug & CSID_DEBUG_ENABLE_EOF_IRQ) val |= CSID_PATH_INFO_INPUT_EOF; + if (path_config->measure_enabled) + val |= (CSID_PATH_ERROR_PIX_COUNT | + CSID_PATH_ERROR_LINE_COUNT); + cam_io_w_mb(val, soc_info->reg_map[0].mem_base + pxl_reg->csid_pxl_irq_mask_addr); @@ -1983,7 +2051,7 @@ static int cam_ife_csid_init_config_rdi_path( struct cam_ife_csid_path_cfg *path_data; const struct cam_ife_csid_reg_offset *csid_reg; struct cam_hw_soc_info *soc_info; - uint32_t path_format = 0, plain_fmt = 0, val = 0, id; + uint32_t path_format = 0, plain_fmt = 0, val = 0, id, in_bpp = 0; uint32_t format_measure_addr; path_data = (struct cam_ife_csid_path_cfg *) res->res_priv; @@ -1998,7 +2066,7 @@ static int cam_ife_csid_init_config_rdi_path( } rc = cam_ife_csid_get_format_rdi(path_data->in_format, - path_data->out_format, &path_format, &plain_fmt); + path_data->out_format, &path_format, &plain_fmt, &in_bpp); if (rc) return rc; @@ -2047,6 +2115,32 @@ static int cam_ife_csid_init_config_rdi_path( CAM_DBG(CAM_ISP, "CSID:%d Vertical Crop config val: 0x%x", csid_hw->hw_intf->hw_idx, val); } + + /* configure pixel format measure */ + if (csid_hw->rdi_path_config[id].measure_enabled) { + val = ((csid_hw->rdi_path_config[id].height & + csid_reg->cmn_reg->format_measure_height_mask_val) << + csid_reg->cmn_reg->format_measure_height_shift_val); + + if (path_format == 0xF) + val |= (((csid_hw->rdi_path_config[id].width * + in_bpp) / 8) & + csid_reg->cmn_reg->format_measure_width_mask_val); + else + val |= (csid_hw->rdi_path_config[id].width & + csid_reg->cmn_reg->format_measure_width_mask_val); + + CAM_DBG(CAM_ISP, "CSID:%d format measure cfg1 value : 0x%x", + csid_hw->hw_intf->hw_idx, val); + + cam_io_w_mb(val, soc_info->reg_map[0].mem_base + + csid_reg->rdi_reg[id]->csid_rdi_format_measure_cfg1_addr); + + /* enable pixel and line counter */ + cam_io_w_mb(3, soc_info->reg_map[0].mem_base + + csid_reg->rdi_reg[id]->csid_rdi_format_measure_cfg0_addr); + } + /* set frame drop pattern to 0 and period to 1 */ cam_io_w_mb(1, soc_info->reg_map[0].mem_base + csid_reg->rdi_reg[id]->csid_rdi_frm_drop_period_addr); @@ -2219,6 +2313,10 @@ static int cam_ife_csid_enable_rdi_path( if (csid_hw->csid_debug & CSID_DEBUG_ENABLE_EOF_IRQ) val |= CSID_PATH_INFO_INPUT_EOF; + if (csid_hw->rdi_path_config[id].measure_enabled) + val |= (CSID_PATH_ERROR_PIX_COUNT | + CSID_PATH_ERROR_LINE_COUNT); + cam_io_w_mb(val, soc_info->reg_map[0].mem_base + csid_reg->rdi_reg[id]->csid_rdi_irq_mask_addr); @@ -2672,6 +2770,13 @@ static int cam_ife_csid_release(void *hw_priv, case CAM_ISP_RESOURCE_PIX_PATH: res->res_state = CAM_ISP_RESOURCE_STATE_AVAILABLE; cam_ife_csid_reset_init_frame_drop(csid_hw); + if (res->res_id == CAM_IFE_PIX_PATH_RES_IPP) + csid_hw->ipp_path_config.measure_enabled = 0; + else if (res->res_id == CAM_IFE_PIX_PATH_RES_PPP) + csid_hw->ppp_path_config.measure_enabled = 0; + else + csid_hw->rdi_path_config[res->res_id].measure_enabled + = 0; break; default: CAM_ERR(CAM_ISP, "CSID:%d Invalid res type:%d res id%d", @@ -2687,7 +2792,6 @@ end: } - static int cam_ife_csid_reset_retain_sw_reg( struct cam_ife_csid_hw *csid_hw) { @@ -2704,6 +2808,8 @@ static int cam_ife_csid_reset_retain_sw_reg( cam_io_w_mb(1, soc_info->reg_map[0].mem_base + csid_reg->cmn_reg->csid_irq_cmd_addr); + usleep_range(3000, 3010); + cam_io_w_mb(csid_reg->cmn_reg->csid_rst_stb, soc_info->reg_map[0].mem_base + csid_reg->cmn_reg->csid_rst_strobes_addr); @@ -3107,6 +3213,57 @@ static int cam_ife_csid_set_csid_clock( return 0; } +static int cam_ife_csid_set_sensor_dimension( + struct cam_ife_csid_hw *csid_hw, void *cmd_args) +{ + struct cam_ife_sensor_dimension_update_args *dimension_update = NULL; + uint32_t i; + + if (!csid_hw) + return -EINVAL; + + dimension_update = + (struct cam_ife_sensor_dimension_update_args *)cmd_args; + csid_hw->ipp_path_config.measure_enabled = + dimension_update->ipp_path.measure_enabled; + if (dimension_update->ipp_path.measure_enabled) { + csid_hw->ipp_path_config.width = + dimension_update->ipp_path.width; + csid_hw->ipp_path_config.height = + dimension_update->ipp_path.height; + CAM_DBG(CAM_ISP, "CSID ipp path width %d height %d", + csid_hw->ipp_path_config.width, + csid_hw->ipp_path_config.height); + } + csid_hw->ppp_path_config.measure_enabled = + dimension_update->ppp_path.measure_enabled; + if (dimension_update->ppp_path.measure_enabled) { + csid_hw->ppp_path_config.width = + dimension_update->ppp_path.width; + csid_hw->ppp_path_config.height = + dimension_update->ppp_path.height; + CAM_DBG(CAM_ISP, "CSID ppp path width %d height %d", + csid_hw->ppp_path_config.width, + csid_hw->ppp_path_config.height); + } + for (i = 0; i <= CAM_IFE_PIX_PATH_RES_RDI_3; i++) { + csid_hw->rdi_path_config[i].measure_enabled + = dimension_update->rdi_path[i].measure_enabled; + if (csid_hw->rdi_path_config[i].measure_enabled) { + csid_hw->rdi_path_config[i].width = + dimension_update->rdi_path[i].width; + csid_hw->rdi_path_config[i].height = + dimension_update->rdi_path[i].height; + CAM_DBG(CAM_ISP, + "CSID rdi path[%d] width %d height %d", + i, csid_hw->rdi_path_config[i].width, + csid_hw->rdi_path_config[i].height); + } + } + + return 0; +} + static int cam_ife_csid_process_cmd(void *hw_priv, uint32_t cmd_type, void *cmd_args, uint32_t arg_size) { @@ -3144,6 +3301,9 @@ static int cam_ife_csid_process_cmd(void *hw_priv, case CAM_IFE_CSID_SET_INIT_FRAME_DROP: rc = cam_ife_csid_set_init_frame_drop(csid_hw, cmd_args); break; + case CAM_IFE_CSID_SET_SENSOR_DIMENSION_CFG: + rc = cam_ife_csid_set_sensor_dimension(csid_hw, cmd_args); + break; default: CAM_ERR(CAM_ISP, "CSID:%d unsupported cmd:%d", csid_hw->hw_intf->hw_idx, cmd_type); @@ -3166,20 +3326,19 @@ irqreturn_t cam_ife_csid_irq(int irq_num, void *data) const struct cam_ife_csid_rdi_reg_offset *rdi_reg; uint32_t i, irq_status_top, irq_status_rx, irq_status_ipp = 0; uint32_t irq_status_rdi[4] = {0, 0, 0, 0}; - uint32_t val, irq_status_ppp = 0; + uint32_t val, val2, irq_status_ppp = 0; bool fatal_err_detected = false; uint32_t sof_irq_debug_en = 0; unsigned long flags; - csid_hw = (struct cam_ife_csid_hw *)data; - - CAM_DBG(CAM_ISP, "CSID %d IRQ Handling", csid_hw->hw_intf->hw_idx); - if (!data) { CAM_ERR(CAM_ISP, "CSID: Invalid arguments"); return IRQ_HANDLED; } + csid_hw = (struct cam_ife_csid_hw *)data; + CAM_DBG(CAM_ISP, "CSID %d IRQ Handling", csid_hw->hw_intf->hw_idx); + csid_reg = csid_hw->csid_info->csid_reg; soc_info = &csid_hw->hw_info->soc_info; csi2_reg = csid_reg->csi2_reg; @@ -3222,7 +3381,7 @@ irqreturn_t cam_ife_csid_irq(int irq_num, void *data) cam_io_w_mb(1, soc_info->reg_map[0].mem_base + csid_reg->cmn_reg->csid_irq_cmd_addr); - CAM_DBG(CAM_ISP, + CAM_ERR_RATE_LIMIT(CAM_ISP, "CSID %d irq status 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x", csid_hw->hw_intf->hw_idx, irq_status_top, irq_status_rx, irq_status_ipp, irq_status_ppp, @@ -3459,6 +3618,25 @@ handle_fatal_error: csid_reg->ipp_reg->csid_pxl_ctrl_addr); } } + + if ((irq_status_ipp & CSID_PATH_ERROR_PIX_COUNT) || + (irq_status_ipp & CSID_PATH_ERROR_LINE_COUNT)) { + val = cam_io_r_mb(soc_info->reg_map[0].mem_base + + csid_reg->ipp_reg->csid_pxl_format_measure0_addr); + + CAM_ERR(CAM_ISP, + "CSID:%d irq_status_ipp:0x%x", + csid_hw->hw_intf->hw_idx, irq_status_ipp); + CAM_ERR(CAM_ISP, + "Expected sz 0x%x*0x%x actual sz 0x%x*0x%x", + csid_hw->ipp_path_config.height, + csid_hw->ipp_path_config.width, + ((val >> + csid_reg->cmn_reg->format_measure_height_shift_val) & + csid_reg->cmn_reg->format_measure_height_mask_val), + val & + csid_reg->cmn_reg->format_measure_width_mask_val); + } } /*read PPP errors */ @@ -3540,6 +3718,25 @@ handle_fatal_error: csid_reg->ppp_reg->csid_pxl_ctrl_addr); } } + + if ((irq_status_ppp & CSID_PATH_ERROR_PIX_COUNT) || + (irq_status_ppp & CSID_PATH_ERROR_LINE_COUNT)) { + val = cam_io_r_mb(soc_info->reg_map[0].mem_base + + csid_reg->ppp_reg->csid_pxl_format_measure0_addr); + + CAM_ERR(CAM_ISP, + "CSID:%d irq_status_ppp:0x%x", + csid_hw->hw_intf->hw_idx, irq_status_ppp); + CAM_ERR(CAM_ISP, + "Expected sz 0x%x*0x%x actual sz 0x%x*0x%x", + csid_hw->ppp_path_config.height, + csid_hw->ppp_path_config.width, + ((val >> + csid_reg->cmn_reg->format_measure_height_shift_val) & + csid_reg->cmn_reg->format_measure_height_mask_val), + val & + csid_reg->cmn_reg->format_measure_width_mask_val); + } } for (i = 0; i < csid_reg->cmn_reg->num_rdis; i++) { @@ -3606,6 +3803,31 @@ handle_fatal_error: soc_info->reg_map[0].mem_base + csid_reg->rdi_reg[i]->csid_rdi_ctrl_addr); } + + if ((irq_status_rdi[i] & CSID_PATH_ERROR_PIX_COUNT) || + (irq_status_rdi[i] & CSID_PATH_ERROR_LINE_COUNT)) { + val = cam_io_r_mb(soc_info->reg_map[0].mem_base + + csid_reg->rdi_reg[i]->csid_rdi_format_measure0_addr); + val2 = cam_io_r_mb(soc_info->reg_map[0].mem_base + + csid_reg->rdi_reg[i]->csid_rdi_format_measure_cfg1_addr + ); + CAM_ERR(CAM_ISP, + "CSID:%d irq_status_rdi[%d]:0x%x", + csid_hw->hw_intf->hw_idx, i, + irq_status_rdi[i]); + CAM_ERR(CAM_ISP, + "Expected sz 0x%x*0x%x actual sz 0x%x*0x%x", + ((val2 >> + csid_reg->cmn_reg->format_measure_height_shift_val) & + csid_reg->cmn_reg->format_measure_height_mask_val), + val2 & + csid_reg->cmn_reg->format_measure_width_mask_val, + ((val >> + csid_reg->cmn_reg->format_measure_height_shift_val) & + csid_reg->cmn_reg->format_measure_height_mask_val), + val & + csid_reg->cmn_reg->format_measure_width_mask_val); + } } if (csid_hw->irq_debug_cnt >= CAM_CSID_IRQ_SOF_DEBUG_CNT_MAX) { @@ -3642,7 +3864,6 @@ int cam_ife_csid_hw_probe_init(struct cam_hw_intf *csid_hw_intf, CAM_DBG(CAM_ISP, "type %d index %d", ife_csid_hw->hw_intf->hw_type, csid_idx); - ife_csid_hw->device_enabled = 0; ife_csid_hw->hw_info->hw_state = CAM_HW_STATE_POWER_DOWN; mutex_init(&ife_csid_hw->hw_info->hw_mutex); @@ -3657,7 +3878,6 @@ int cam_ife_csid_hw_probe_init(struct cam_hw_intf *csid_hw_intf, for (i = 0; i < CAM_IFE_CSID_RDI_MAX; i++) init_completion(&ife_csid_hw->csid_rdin_complete[i]); - rc = cam_ife_csid_init_soc_resources(&ife_csid_hw->hw_info->soc_info, cam_ife_csid_irq, ife_csid_hw); if (rc < 0) { @@ -3751,8 +3971,27 @@ int cam_ife_csid_hw_probe_init(struct cam_hw_intf *csid_hw_intf, ife_csid_hw->csid_debug = 0; ife_csid_hw->error_irq_count = 0; ife_csid_hw->first_sof_ts = 0; + ife_csid_hw->ipp_path_config.measure_enabled = 0; + ife_csid_hw->ppp_path_config.measure_enabled = 0; + for (i = 0; i <= CAM_IFE_PIX_PATH_RES_RDI_3; i++) + ife_csid_hw->rdi_path_config[i].measure_enabled = 0; - return 0; + /* Check if ppi bridge is present or not? */ + ife_csid_hw->ppi_enable = of_property_read_bool( + csid_hw_info->soc_info.pdev->dev.of_node, + "ppi-enable"); + + if (!ife_csid_hw->ppi_enable) + return 0; + + /* Initialize the PPI bridge */ + for (i = 0; i < CAM_CSID_PPI_HW_MAX; i++) { + rc = cam_csid_ppi_hw_init(&ife_csid_hw->ppi_hw_intf[i], i); + if (rc < 0) { + CAM_ERR(CAM_ISP, "PPI init failed for PPI %d", i); + break; + } + } err: if (rc) { kfree(ife_csid_hw->ipp_res.res_priv); diff --git a/drivers/media/platform/msm/ais/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.h b/drivers/media/platform/msm/ais/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.h index 9b4d5c3d6add..f2173f13f0c4 100644 --- a/drivers/media/platform/msm/ais/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.h +++ b/drivers/media/platform/msm/ais/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.h @@ -16,6 +16,7 @@ #include "cam_hw.h" #include "cam_ife_csid_hw_intf.h" #include "cam_ife_csid_soc.h" +#include "cam_csid_ppi_core.h" #define CAM_IFE_CSID_HW_RES_MAX 4 #define CAM_IFE_CSID_CID_RES_MAX 4 @@ -309,6 +310,10 @@ struct cam_ife_csid_common_reg_offset { uint32_t ppp_irq_mask_all; uint32_t measure_en_hbi_vbi_cnt_mask; uint32_t format_measure_en_val; + uint32_t format_measure_width_shift_val; + uint32_t format_measure_width_mask_val; + uint32_t format_measure_height_shift_val; + uint32_t format_measure_height_mask_val; }; /** @@ -468,6 +473,11 @@ struct cam_ife_csid_path_cfg { * @csid_debug: csid debug information to enable the SOT, EOT, * SOF, EOF, measure etc in the csid hw * @clk_rate Clock rate + * @ipp_path ipp path configuration + * @ppp_path ppp path configuration + * @rdi_path RDI path configuration + * @hbi Horizontal blanking + * @vbi Vertical blanking * @sof_irq_triggered: Flag is set on receiving event to enable sof irq * incase of SOF freeze. * @irq_debug_cnt: Counter to track sof irq's when above flag is set. @@ -481,7 +491,9 @@ struct cam_ife_csid_path_cfg { * @res_sof_cnt path resource sof count value. it used for initial * frame drop * @first_sof_ts flag to mark the first sof has been registered - * + * @ppi_hw_intf interface to ppi hardware + * @ppi_enabled flag to specify if the hardware has ppi bridge + * or not */ struct cam_ife_csid_hw { struct cam_hw_intf *hw_intf; @@ -504,6 +516,11 @@ struct cam_ife_csid_hw { struct completion csid_rdin_complete[CAM_IFE_CSID_RDI_MAX]; uint64_t csid_debug; uint64_t clk_rate; + struct cam_isp_sensor_dimension ipp_path_config; + struct cam_isp_sensor_dimension ppp_path_config; + struct cam_isp_sensor_dimension rdi_path_config[4]; + uint32_t hbi; + uint32_t vbi; bool sof_irq_triggered; uint32_t irq_debug_cnt; uint32_t error_irq_count; @@ -513,6 +530,8 @@ struct cam_ife_csid_hw { uint32_t init_frame_drop; uint32_t res_sof_cnt[CAM_IFE_PIX_PATH_RES_MAX]; uint32_t first_sof_ts; + struct cam_hw_intf *ppi_hw_intf[CAM_CSID_PPI_HW_MAX]; + bool ppi_enable; }; int cam_ife_csid_hw_probe_init(struct cam_hw_intf *csid_hw_intf, diff --git a/drivers/media/platform/msm/ais/cam_isp/isp_hw_mgr/isp_hw/include/cam_ife_csid_hw_intf.h b/drivers/media/platform/msm/ais/cam_isp/isp_hw_mgr/isp_hw/include/cam_ife_csid_hw_intf.h index 0c45bd1268b9..8d340207a0a1 100644 --- a/drivers/media/platform/msm/ais/cam_isp/isp_hw_mgr/isp_hw/include/cam_ife_csid_hw_intf.h +++ b/drivers/media/platform/msm/ais/cam_isp/isp_hw_mgr/isp_hw/include/cam_ife_csid_hw_intf.h @@ -158,6 +158,7 @@ enum cam_ife_csid_cmd_type { CAM_IFE_CSID_SET_CSID_DEBUG, CAM_IFE_CSID_SOF_IRQ_DEBUG, CAM_IFE_CSID_SET_INIT_FRAME_DROP, + CAM_IFE_CSID_SET_SENSOR_DIMENSION_CFG, CAM_IFE_CSID_CMD_MAX, }; @@ -181,5 +182,17 @@ struct cam_ife_csid_clock_update_args { uint64_t clk_rate; }; +/* + * struct cam_ife_sensor_dim_update_args: + * + * @ppp_path: expected ppp path configuration + * @ipp_path: expected ipp path configuration + * @rdi_path: expected rdi path configuration + */ +struct cam_ife_sensor_dimension_update_args { + struct cam_isp_sensor_dimension ppp_path; + struct cam_isp_sensor_dimension ipp_path; + struct cam_isp_sensor_dimension rdi_path[4]; +}; #endif /* _CAM_CSID_HW_INTF_H_ */ diff --git a/drivers/media/platform/msm/ais/cam_isp/isp_hw_mgr/isp_hw/include/cam_isp_hw.h b/drivers/media/platform/msm/ais/cam_isp/isp_hw_mgr/isp_hw/include/cam_isp_hw.h index 185d0f595673..54bdbbe1677f 100644 --- a/drivers/media/platform/msm/ais/cam_isp/isp_hw_mgr/isp_hw/include/cam_isp_hw.h +++ b/drivers/media/platform/msm/ais/cam_isp/isp_hw_mgr/isp_hw/include/cam_isp_hw.h @@ -19,17 +19,21 @@ #include "cam_soc_util.h" #include "cam_irq_controller.h" +#define CAM_ISP_FPS_60 60 + /* * struct cam_isp_timestamp: * * @mono_time: Monotonic boot time * @vt_time: AV Timer time * @ticks: Qtimer ticks + * @time_usecs: time in micro seconds */ struct cam_isp_timestamp { struct timeval mono_time; struct timeval vt_time; uint64_t ticks; + uint64_t time_usecs; }; /* @@ -104,6 +108,7 @@ enum cam_isp_hw_cmd_type { CAM_ISP_HW_CMD_FE_UPDATE_IN_RD, CAM_ISP_HW_CMD_FE_UPDATE_BUS_RD, CAM_ISP_HW_CMD_GET_IRQ_REGISTER_DUMP, + CAM_ISP_HW_CMD_FPS_CONFIG, CAM_ISP_HW_CMD_MAX, }; diff --git a/drivers/media/platform/msm/ais/cam_isp/isp_hw_mgr/isp_hw/include/cam_vfe_hw_intf.h b/drivers/media/platform/msm/ais/cam_isp/isp_hw_mgr/isp_hw/include/cam_vfe_hw_intf.h index 9d6bcb71bb69..3bcedc948a18 100644 --- a/drivers/media/platform/msm/ais/cam_isp/isp_hw_mgr/isp_hw/include/cam_vfe_hw_intf.h +++ b/drivers/media/platform/msm/ais/cam_isp/isp_hw_mgr/isp_hw/include/cam_vfe_hw_intf.h @@ -178,6 +178,17 @@ struct cam_vfe_clock_update_args { }; /* + * struct cam_vfe_fps_config_args: + * + * @node_res: Resource to get the fps value + * @fps: FPS value to configure EPOCH + */ +struct cam_vfe_fps_config_args { + struct cam_isp_resource_node *node_res; + uint32_t fps; +}; + +/* * struct cam_vfe_bw_update_args: * * @node_res: Resource to get the BW diff --git a/drivers/media/platform/msm/ais/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_core.c b/drivers/media/platform/msm/ais/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_core.c index 43531c173f89..6088b9451061 100644 --- a/drivers/media/platform/msm/ais/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_core.c +++ b/drivers/media/platform/msm/ais/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_core.c @@ -465,6 +465,8 @@ void cam_isp_hw_get_timestamp(struct cam_isp_timestamp *time_stamp) get_monotonic_boottime(&ts); time_stamp->mono_time.tv_sec = ts.tv_sec; time_stamp->mono_time.tv_usec = ts.tv_nsec/1000; + time_stamp->time_usecs = ts.tv_sec * 1000000 + + time_stamp->mono_time.tv_usec; } static int cam_vfe_irq_top_half(uint32_t evt_id, @@ -802,6 +804,7 @@ int cam_vfe_process_cmd(void *hw_priv, uint32_t cmd_type, case CAM_ISP_HW_CMD_BW_UPDATE: case CAM_ISP_HW_CMD_BW_CONTROL: case CAM_ISP_HW_CMD_GET_IRQ_REGISTER_DUMP: + case CAM_ISP_HW_CMD_FPS_CONFIG: rc = core_info->vfe_top->hw_ops.process_cmd( core_info->vfe_top->top_priv, cmd_type, cmd_args, arg_size); diff --git a/drivers/media/platform/msm/ais/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.c b/drivers/media/platform/msm/ais/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.c index fc2b3ce5b545..6b764266ecf3 100644 --- a/drivers/media/platform/msm/ais/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.c +++ b/drivers/media/platform/msm/ais/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.c @@ -165,6 +165,7 @@ struct cam_vfe_bus_ver2_wm_resource_data { uint32_t en_cfg; uint32_t is_dual; uint32_t is_lite; + uint32_t is_streaming; }; struct cam_vfe_bus_ver2_comp_grp_data { @@ -1246,6 +1247,7 @@ static int cam_vfe_bus_start_wm(struct cam_isp_resource_node *wm_res) CAM_DBG(CAM_ISP, "enable WM res %d offset 0x%x val 0x%x", rsrc_data->index, (uint32_t) rsrc_data->hw_regs->cfg, rsrc_data->en_cfg); + rsrc_data->is_streaming = CAM_ISP_RESOURCE_STATE_STREAMING; wm_res->res_state = CAM_ISP_RESOURCE_STATE_STREAMING; @@ -1274,6 +1276,7 @@ static int cam_vfe_bus_stop_wm(struct cam_isp_resource_node *wm_res) wm_res->irq_handle); wm_res->res_state = CAM_ISP_RESOURCE_STATE_RESERVED; + rsrc_data->is_streaming = CAM_ISP_RESOURCE_STATE_RESERVED; kfifo_reset( &g_addr_fifo[rsrc_data->common_data->core_index][rsrc_data->index]); @@ -3015,9 +3018,17 @@ static int cam_vfe_bus_update_wm(void *priv, void *cmd_args, &output_image_buf, sizeof(uint32_t)); - cam_io_w_mb(output_image_buf, - bus_priv->common_data.mem_base + - wm_data->hw_regs->image_addr); + if (wm_data->is_streaming == + CAM_ISP_RESOURCE_STATE_STREAMING) + cam_io_w_mb(output_image_buf, + bus_priv->common_data.mem_base + + wm_data->hw_regs->image_addr); + else + CAM_VFE_ADD_REG_VAL_PAIR( + reg_val_pair, + j, + wm_data->hw_regs->image_addr, + output_image_buf); kfifo_in( &bus_priv->addr_fifo[wm_data->index], diff --git a/drivers/media/platform/msm/ais/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver2.c b/drivers/media/platform/msm/ais/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver2.c index 3ed45ee530e8..112a2d680c30 100644 --- a/drivers/media/platform/msm/ais/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver2.c +++ b/drivers/media/platform/msm/ais/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver2.c @@ -44,6 +44,7 @@ struct cam_vfe_mux_camif_data { bool enable_sof_irq_debug; uint32_t irq_debug_cnt; uint32_t camif_debug; + uint32_t fps; }; static int cam_vfe_camif_validate_pix_pattern(uint32_t pattern) @@ -269,9 +270,15 @@ static int cam_vfe_camif_resource_start( rsrc_data->camif_reg->epoch_irq); break; default: - epoch0_irq_mask = ((rsrc_data->last_line - + if (rsrc_data->fps == CAM_ISP_FPS_60) { + epoch0_irq_mask = ((rsrc_data->last_line - rsrc_data->first_line) / 2) + rsrc_data->first_line; + } else { + epoch0_irq_mask = (((rsrc_data->last_line - + rsrc_data->first_line) * 2) / 3) + + rsrc_data->first_line; + } epoch1_irq_mask = rsrc_data->reg_data->epoch_line_cfg & 0xFFFF; computed_epoch_line_cfg = (epoch0_irq_mask << 16) | @@ -515,6 +522,20 @@ static int cam_vfe_camif_sof_irq_debug( return 0; } +static int cam_vfe_camif_set_fps_config( + struct cam_isp_resource_node *rsrc_node, void *cmd_args) +{ + struct cam_vfe_mux_camif_data *camif_priv = NULL; + struct cam_vfe_fps_config_args *fps_args = cmd_args; + + camif_priv = + (struct cam_vfe_mux_camif_data *)rsrc_node->res_priv; + + camif_priv->fps = fps_args->fps; + + return 0; + +} static int cam_vfe_camif_process_cmd(struct cam_isp_resource_node *rsrc_node, uint32_t cmd_type, void *cmd_args, uint32_t arg_size) @@ -546,6 +567,9 @@ static int cam_vfe_camif_process_cmd(struct cam_isp_resource_node *rsrc_node, case CAM_ISP_HW_CMD_GET_IRQ_REGISTER_DUMP: rc = cam_vfe_camif_irq_reg_dump(rsrc_node); break; + case CAM_ISP_HW_CMD_FPS_CONFIG: + rc = cam_vfe_camif_set_fps_config(rsrc_node, cmd_args); + break; default: CAM_ERR(CAM_ISP, "unsupported process command:%d", cmd_type); diff --git a/drivers/media/platform/msm/ais/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver2.c b/drivers/media/platform/msm/ais/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver2.c index d512128b28e5..0461b0820b4f 100644 --- a/drivers/media/platform/msm/ais/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver2.c +++ b/drivers/media/platform/msm/ais/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver2.c @@ -283,6 +283,22 @@ static int cam_vfe_top_fs_update( return 0; } +static int cam_vfe_top_fps_config( + struct cam_vfe_top_ver2_priv *top_priv, + void *cmd_args, uint32_t arg_size) +{ + struct cam_vfe_fps_config_args *cmd_update = NULL; + + cmd_update = + (struct cam_vfe_fps_config_args *)cmd_args; + + if (cmd_update->node_res->process_cmd) + return cmd_update->node_res->process_cmd(cmd_update->node_res, + CAM_ISP_HW_CMD_FPS_CONFIG, cmd_args, arg_size); + + return 0; +} + static int cam_vfe_top_clock_update( struct cam_vfe_top_ver2_priv *top_priv, void *cmd_args, uint32_t arg_size) @@ -740,6 +756,10 @@ int cam_vfe_top_process_cmd(void *device_priv, uint32_t cmd_type, rc = cam_vfe_get_irq_register_dump(top_priv, cmd_args, arg_size); break; + case CAM_ISP_HW_CMD_FPS_CONFIG: + rc = cam_vfe_top_fps_config(top_priv, cmd_args, + arg_size); + break; default: rc = -EINVAL; CAM_ERR(CAM_ISP, "Error! Invalid cmd:%d", cmd_type); diff --git a/drivers/media/platform/msm/ais/cam_sensor_module/cam_csiphy/cam_csiphy_soc.c b/drivers/media/platform/msm/ais/cam_sensor_module/cam_csiphy/cam_csiphy_soc.c index 416cb2a9fa96..9bdb57529d8e 100644 --- a/drivers/media/platform/msm/ais/cam_sensor_module/cam_csiphy/cam_csiphy_soc.c +++ b/drivers/media/platform/msm/ais/cam_sensor_module/cam_csiphy/cam_csiphy_soc.c @@ -274,6 +274,25 @@ int32_t cam_csiphy_parse_dt_info(struct platform_device *pdev, csiphy_dev->ctrl_reg->data_rates_settings_table = &data_rate_delta_table_1_2; } else if (of_device_is_compatible(soc_info->dev->of_node, + "qcom,csiphy-v1.2.2")) { + csiphy_dev->ctrl_reg->csiphy_2ph_reg = csiphy_2ph_v1_2_reg; + csiphy_dev->ctrl_reg->csiphy_2ph_combo_mode_reg = + csiphy_2ph_v1_2_combo_mode_reg; + csiphy_dev->ctrl_reg->csiphy_3ph_reg = csiphy_3ph_v1_2_reg; + csiphy_dev->ctrl_reg->csiphy_2ph_3ph_mode_reg = NULL; + csiphy_dev->ctrl_reg->csiphy_irq_reg = csiphy_irq_reg_1_2; + csiphy_dev->ctrl_reg->csiphy_common_reg = + csiphy_common_reg_1_2; + csiphy_dev->ctrl_reg->csiphy_reset_reg = + csiphy_reset_reg_1_2; + csiphy_dev->ctrl_reg->getclockvoting = get_clk_voting_dynamic; + csiphy_dev->ctrl_reg->csiphy_reg = csiphy_v1_2; + csiphy_dev->is_csiphy_3phase_hw = CSI_3PHASE_HW_12; + csiphy_dev->hw_version = CSIPHY_VERSION_V12; + csiphy_dev->clk_lane = 0; + csiphy_dev->ctrl_reg->data_rates_settings_table = + &data_rate_delta_table_1_2; + } else if (of_device_is_compatible(soc_info->dev->of_node, "qcom,csiphy-v2.0")) { csiphy_dev->ctrl_reg->csiphy_2ph_reg = csiphy_2ph_v2_0_reg; csiphy_dev->ctrl_reg->csiphy_2ph_combo_mode_reg = diff --git a/drivers/media/platform/msm/ais/cam_sensor_module/cam_sensor/cam_sensor_core.c b/drivers/media/platform/msm/ais/cam_sensor_module/cam_sensor/cam_sensor_core.c index 1fa3ced0fb95..81a2f9f657b6 100644 --- a/drivers/media/platform/msm/ais/cam_sensor_module/cam_sensor/cam_sensor_core.c +++ b/drivers/media/platform/msm/ais/cam_sensor_module/cam_sensor/cam_sensor_core.c @@ -926,14 +926,13 @@ free_probe_cmd: s_ctrl->sensor_state = CAM_SENSOR_ACQUIRE; CAM_INFO(CAM_SENSOR, - "CAM_ACQUIRE_DEV Success %d", + "SENSOR_POWER_UP Success %d", s_ctrl->soc_info.index); } break; case AIS_SENSOR_POWER_DOWN: { - if ((s_ctrl->sensor_state == CAM_SENSOR_INIT) || - (s_ctrl->sensor_state == CAM_SENSOR_START)) { + if (s_ctrl->sensor_state == CAM_SENSOR_START) { rc = -EINVAL; CAM_WARN(CAM_SENSOR, "Not in right state to release %d (%d)", @@ -952,7 +951,7 @@ free_probe_cmd: s_ctrl->sensor_state = CAM_SENSOR_INIT; CAM_INFO(CAM_SENSOR, - "CAM_RELEASE_DEV Success %d", + "SENSOR_POWER_DOWN Success %d", s_ctrl->soc_info.index); } break; @@ -1007,7 +1006,7 @@ free_probe_cmd: goto release_mutex; } - CAM_WARN(CAM_SENSOR, "Read 0x%x : 0x%x <- 0x%x", + CAM_DBG(CAM_SENSOR, "Read 0x%x : 0x%x <- 0x%x", i2c_read.i2c_config.slave_addr, i2c_read.reg_addr, i2c_read.reg_data); @@ -1052,7 +1051,7 @@ free_probe_cmd: goto release_mutex; } - CAM_INFO(CAM_SENSOR, + CAM_DBG(CAM_SENSOR, "Write 0x%x, 0x%x <- 0x%x [%d, %d]", i2c_write.i2c_config.slave_addr, i2c_write.wr_payload.reg_addr, @@ -1166,7 +1165,7 @@ free_probe_cmd: goto release_mutex; } - CAM_INFO(CAM_SENSOR, + CAM_DBG(CAM_SENSOR, "Write 0x%x, %d regs [%d, %d]", i2c_write.i2c_config.slave_addr, i2c_write.count, |