msm: camera: isp: Add support for QCFA CSID binning
Add support to configure CSID binning for QCFA. Change-Id: I9e2673d89f521a4b4fddc41ad1217ffe229d8b01 Signed-off-by: Tejas Prajapati <tpraja@codeaurora.org> Signed-off-by: Trishansh Bhardwaj <tbhardwa@codeaurora.org> Signed-off-by: Jigarkumar Zala <jzala@codeaurora.org>
This commit is contained in:
parent
a89607a875
commit
f458d1d231
@ -12,9 +12,11 @@
|
||||
#include <media/v4l2-subdev.h>
|
||||
#include <cam_cpas.h>
|
||||
#include <cam_req_mgr.h>
|
||||
#include <dt-bindings/msm/msm-camera.h>
|
||||
|
||||
#include "cam_subdev.h"
|
||||
#include "cam_cpas_hw_intf.h"
|
||||
#include "cam_cpas_soc.h"
|
||||
|
||||
#define CAM_CPAS_DEV_NAME "cam-cpas"
|
||||
#define CAM_CPAS_INTF_INITIALIZED() (g_cpas_intf && g_cpas_intf->probe_done)
|
||||
@ -104,6 +106,31 @@ const char *cam_cpas_axi_util_trans_type_to_string(
|
||||
}
|
||||
EXPORT_SYMBOL(cam_cpas_axi_util_trans_type_to_string);
|
||||
|
||||
int cam_cpas_is_feature_supported(uint32_t flag)
|
||||
{
|
||||
struct cam_hw_info *cpas_hw = NULL;
|
||||
struct cam_cpas_private_soc *soc_private = NULL;
|
||||
uint32_t feature_mask;
|
||||
|
||||
if (!CAM_CPAS_INTF_INITIALIZED()) {
|
||||
CAM_ERR(CAM_CPAS, "cpas intf not initialized");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
cpas_hw = (struct cam_hw_info *) g_cpas_intf->hw_intf->hw_priv;
|
||||
soc_private =
|
||||
(struct cam_cpas_private_soc *)cpas_hw->soc_info.soc_private;
|
||||
feature_mask = soc_private->feature_mask;
|
||||
|
||||
if (flag >= CAM_CPAS_FUSE_FEATURE_MAX) {
|
||||
CAM_ERR(CAM_CPAS, "Unknown feature flag %x", flag);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return feature_mask & flag ? 1 : 0;
|
||||
}
|
||||
EXPORT_SYMBOL(cam_cpas_is_feature_supported);
|
||||
|
||||
int cam_cpas_get_cpas_hw_version(uint32_t *hw_version)
|
||||
{
|
||||
struct cam_hw_info *cpas_hw = NULL;
|
||||
|
@ -349,6 +349,45 @@ static int cam_cpas_parse_node_tree(struct cam_cpas *cpas_core,
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int cam_cpas_get_hw_features(struct platform_device *pdev,
|
||||
struct cam_cpas_private_soc *soc_private)
|
||||
{
|
||||
struct device_node *of_node;
|
||||
void *fuse;
|
||||
uint32_t fuse_addr, fuse_bit;
|
||||
uint32_t fuse_val = 0, feature_bit_pos;
|
||||
int count = 0, i = 0;
|
||||
|
||||
of_node = pdev->dev.of_node;
|
||||
count = of_property_count_u32_elems(of_node, "cam_hw_fuse");
|
||||
|
||||
for (i = 0; (i + 3) <= count; i = i + 3) {
|
||||
of_property_read_u32_index(of_node, "cam_hw_fuse", i,
|
||||
&feature_bit_pos);
|
||||
of_property_read_u32_index(of_node, "cam_hw_fuse", i + 1,
|
||||
&fuse_addr);
|
||||
of_property_read_u32_index(of_node, "cam_hw_fuse", i + 2,
|
||||
&fuse_bit);
|
||||
CAM_INFO(CAM_CPAS, "feature_bit 0x%x addr 0x%x, bit %d",
|
||||
feature_bit_pos, fuse_addr, fuse_bit);
|
||||
|
||||
fuse = ioremap(fuse_addr, 4);
|
||||
if (fuse) {
|
||||
fuse_val = cam_io_r(fuse);
|
||||
if (fuse_val & BIT(fuse_bit))
|
||||
soc_private->feature_mask |= feature_bit_pos;
|
||||
else
|
||||
soc_private->feature_mask &= ~feature_bit_pos;
|
||||
}
|
||||
CAM_INFO(CAM_CPAS, "fuse %pK, fuse_val %x, feature_mask %x",
|
||||
fuse, fuse_val, soc_private->feature_mask);
|
||||
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int cam_cpas_get_custom_dt_info(struct cam_hw_info *cpas_hw,
|
||||
struct platform_device *pdev, struct cam_cpas_private_soc *soc_private)
|
||||
{
|
||||
@ -363,6 +402,7 @@ int cam_cpas_get_custom_dt_info(struct cam_hw_info *cpas_hw,
|
||||
}
|
||||
|
||||
of_node = pdev->dev.of_node;
|
||||
soc_private->feature_mask = 0xFFFFFFFF;
|
||||
|
||||
rc = of_property_read_string(of_node, "arch-compat",
|
||||
&soc_private->arch_compat);
|
||||
@ -372,6 +412,8 @@ int cam_cpas_get_custom_dt_info(struct cam_hw_info *cpas_hw,
|
||||
return rc;
|
||||
}
|
||||
|
||||
cam_cpas_get_hw_features(pdev, soc_private);
|
||||
|
||||
soc_private->camnoc_axi_min_ib_bw = 0;
|
||||
rc = of_property_read_u64(of_node,
|
||||
"camnoc-axi-min-ib-bw",
|
||||
|
@ -87,6 +87,7 @@ struct cam_cpas_tree_node {
|
||||
* @camnoc_axi_clk_bw_margin : BW Margin in percentage to add while calculating
|
||||
* camnoc axi clock
|
||||
* @camnoc_axi_min_ib_bw: Min camnoc BW which varies based on target
|
||||
* @feature_mask: feature mask value for hw supported features
|
||||
*
|
||||
*/
|
||||
struct cam_cpas_private_soc {
|
||||
@ -103,6 +104,7 @@ struct cam_cpas_private_soc {
|
||||
uint32_t camnoc_bus_width;
|
||||
uint32_t camnoc_axi_clk_bw_margin;
|
||||
uint64_t camnoc_axi_min_ib_bw;
|
||||
uint32_t feature_mask;
|
||||
};
|
||||
|
||||
void cam_cpas_util_debug_parse_data(struct cam_cpas_private_soc *soc_private);
|
||||
|
@ -525,6 +525,19 @@ int cam_cpas_get_hw_info(
|
||||
int cam_cpas_get_cpas_hw_version(
|
||||
uint32_t *hw_version);
|
||||
|
||||
/**
|
||||
* cam_cpas_is_feature_supported()
|
||||
*
|
||||
* @brief: API to get camera features
|
||||
*
|
||||
* @flag : Camera hw features to check
|
||||
*
|
||||
* @return 1 if feature is supported
|
||||
*
|
||||
*/
|
||||
int cam_cpas_is_feature_supported(
|
||||
uint32_t flag);
|
||||
|
||||
/**
|
||||
* cam_cpas_axi_util_path_type_to_string()
|
||||
*
|
||||
|
@ -4236,6 +4236,54 @@ static int cam_isp_blob_csid_clock_update(
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int cam_isp_blob_csid_qcfa_update(
|
||||
uint32_t blob_type,
|
||||
struct cam_isp_generic_blob_info *blob_info,
|
||||
struct cam_isp_csid_qcfa_config *qcfa_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_csid_qcfa_update_args csid_qcfa_upd_args;
|
||||
int rc = -EINVAL;
|
||||
uint32_t i;
|
||||
|
||||
ctx = prepare->ctxt_to_hw_map;
|
||||
|
||||
CAM_DBG(CAM_ISP,
|
||||
"csid binning=%d", qcfa_config->csid_binning);
|
||||
|
||||
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] ||
|
||||
hw_mgr_res->res_id != CAM_IFE_PIX_PATH_RES_IPP)
|
||||
continue;
|
||||
|
||||
hw_intf = hw_mgr_res->hw_res[i]->hw_intf;
|
||||
if (hw_intf && hw_intf->hw_ops.process_cmd) {
|
||||
csid_qcfa_upd_args.qcfa_binning =
|
||||
qcfa_config->csid_binning;
|
||||
CAM_DBG(CAM_ISP, "i= %d QCFA binning=%d\n",
|
||||
i, csid_qcfa_upd_args.qcfa_binning);
|
||||
|
||||
rc = hw_intf->hw_ops.process_cmd(
|
||||
hw_intf->hw_priv,
|
||||
CAM_ISP_HW_CMD_CSID_QCFA_SUPPORTED,
|
||||
&csid_qcfa_upd_args,
|
||||
sizeof(
|
||||
struct cam_ife_csid_qcfa_update_args));
|
||||
if (rc)
|
||||
CAM_ERR(CAM_ISP, "QCFA Update failed");
|
||||
} else
|
||||
CAM_ERR(CAM_ISP, "NULL hw_intf!");
|
||||
}
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int cam_isp_blob_core_cfg_update(
|
||||
uint32_t blob_type,
|
||||
struct cam_isp_generic_blob_info *blob_info,
|
||||
@ -4848,6 +4896,26 @@ static int cam_isp_packet_generic_blob_handler(void *user_data,
|
||||
clock_config, prepare);
|
||||
if (rc)
|
||||
CAM_ERR(CAM_ISP, "Clock Update Failed");
|
||||
}
|
||||
break;
|
||||
case CAM_ISP_GENERIC_BLOB_TYPE_CSID_QCFA_CONFIG: {
|
||||
struct cam_isp_csid_qcfa_config *qcfa_config;
|
||||
|
||||
if (blob_size < sizeof(struct cam_isp_csid_qcfa_config)) {
|
||||
CAM_ERR(CAM_ISP,
|
||||
"Invalid qcfa blob size %u expected %u",
|
||||
blob_size,
|
||||
sizeof(struct cam_isp_csid_qcfa_config));
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
qcfa_config = (struct cam_isp_csid_qcfa_config *)blob_data;
|
||||
|
||||
rc = cam_isp_blob_csid_qcfa_update(blob_type, blob_info,
|
||||
qcfa_config, prepare);
|
||||
if (rc)
|
||||
CAM_ERR(CAM_ISP, "QCFA Update Failed rc: %d", rc);
|
||||
|
||||
}
|
||||
break;
|
||||
case CAM_ISP_GENERIC_BLOB_TYPE_FE_CONFIG: {
|
||||
|
@ -1,6 +1,6 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2018, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2019, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef _CAM_IFE_CSID_175_200_H_
|
||||
@ -47,6 +47,7 @@ static struct cam_ife_csid_pxl_reg_offset
|
||||
/* configurations */
|
||||
.pix_store_en_shift_val = 7,
|
||||
.early_eof_en_shift_val = 29,
|
||||
.quad_cfa_bin_en_shift_val = 30,
|
||||
.ccif_violation_en = 1,
|
||||
};
|
||||
|
||||
|
@ -8,6 +8,8 @@
|
||||
#include <uapi/media/cam_isp.h>
|
||||
#include <uapi/media/cam_defs.h>
|
||||
|
||||
#include <dt-bindings/msm/msm-camera.h>
|
||||
|
||||
#include "cam_ife_csid_core.h"
|
||||
#include "cam_isp_hw.h"
|
||||
#include "cam_soc_util.h"
|
||||
@ -1611,6 +1613,10 @@ static int cam_ife_csid_init_config_pxl_path(
|
||||
val |= (1 << pxl_reg->quad_cfa_bin_en_shift_val);
|
||||
}
|
||||
|
||||
if (is_ipp && csid_hw->binning_supported &&
|
||||
csid_hw->binning_enable)
|
||||
val |= (1 << pxl_reg->quad_cfa_bin_en_shift_val);
|
||||
|
||||
val |= (1 << pxl_reg->pix_store_en_shift_val);
|
||||
cam_io_w_mb(val, soc_info->reg_map[0].mem_base +
|
||||
pxl_reg->csid_pxl_cfg0_addr);
|
||||
@ -3124,6 +3130,23 @@ static int cam_ife_csid_set_csid_clock(
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cam_ife_csid_set_csid_qcfa(
|
||||
struct cam_ife_csid_hw *csid_hw, void *cmd_args)
|
||||
{
|
||||
struct cam_ife_csid_qcfa_update_args *qcfa_update = NULL;
|
||||
|
||||
if (!csid_hw)
|
||||
return -EINVAL;
|
||||
|
||||
qcfa_update =
|
||||
(struct cam_ife_csid_qcfa_update_args *)cmd_args;
|
||||
|
||||
csid_hw->binning_supported = qcfa_update->qcfa_binning;
|
||||
CAM_DBG(CAM_ISP, "CSID QCFA binning %d", csid_hw->binning_supported);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cam_ife_csid_process_cmd(void *hw_priv,
|
||||
uint32_t cmd_type, void *cmd_args, uint32_t arg_size)
|
||||
{
|
||||
@ -3158,6 +3181,9 @@ static int cam_ife_csid_process_cmd(void *hw_priv,
|
||||
case CAM_ISP_HW_CMD_CSID_CLOCK_UPDATE:
|
||||
rc = cam_ife_csid_set_csid_clock(csid_hw, cmd_args);
|
||||
break;
|
||||
case CAM_ISP_HW_CMD_CSID_QCFA_SUPPORTED:
|
||||
rc = cam_ife_csid_set_csid_qcfa(csid_hw, cmd_args);
|
||||
break;
|
||||
default:
|
||||
CAM_ERR(CAM_ISP, "CSID:%d unsupported cmd:%d",
|
||||
csid_hw->hw_intf->hw_idx, cmd_type);
|
||||
@ -3601,6 +3627,9 @@ int cam_ife_csid_hw_probe_init(struct cam_hw_intf *csid_hw_intf,
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (cam_cpas_is_feature_supported(CAM_CPAS_QCFA_BINNING_ENABLE) == 1)
|
||||
ife_csid_hw->binning_enable = 1;
|
||||
|
||||
ife_csid_hw->hw_intf->hw_ops.get_hw_caps = cam_ife_csid_get_hw_caps;
|
||||
ife_csid_hw->hw_intf->hw_ops.init = cam_ife_csid_init_hw;
|
||||
ife_csid_hw->hw_intf->hw_ops.deinit = cam_ife_csid_deinit_hw;
|
||||
|
@ -482,6 +482,8 @@ struct cam_ife_csid_path_cfg {
|
||||
* @irq_debug_cnt: Counter to track sof irq's when above flag is set.
|
||||
* @error_irq_count Error IRQ count, if continuous error irq comes
|
||||
* need to stop the CSID and mask interrupts.
|
||||
* @binning_enable Flag is set if hardware supports QCFA binning
|
||||
* @binning_supported Flag is set if sensor supports QCFA binning
|
||||
*
|
||||
*/
|
||||
struct cam_ife_csid_hw {
|
||||
@ -510,6 +512,8 @@ struct cam_ife_csid_hw {
|
||||
uint32_t error_irq_count;
|
||||
uint32_t device_enabled;
|
||||
spinlock_t lock_state;
|
||||
uint32_t binning_enable;
|
||||
uint32_t binning_supported;
|
||||
};
|
||||
|
||||
int cam_ife_csid_hw_probe_init(struct cam_hw_intf *csid_hw_intf,
|
||||
|
@ -222,5 +222,14 @@ struct cam_ife_csid_clock_update_args {
|
||||
uint64_t clk_rate;
|
||||
};
|
||||
|
||||
/*
|
||||
* struct cam_ife_csid_qcfa_update_args:
|
||||
*
|
||||
* @qcfa_binning: QCFA binning supported
|
||||
*/
|
||||
struct cam_ife_csid_qcfa_update_args {
|
||||
uint32_t qcfa_binning;
|
||||
};
|
||||
|
||||
|
||||
#endif /* _CAM_CSID_HW_INTF_H_ */
|
||||
|
@ -100,6 +100,7 @@ enum cam_isp_hw_cmd_type {
|
||||
CAM_ISP_HW_CMD_UBWC_UPDATE_V2,
|
||||
CAM_ISP_HW_CMD_CORE_CONFIG,
|
||||
CAM_ISP_HW_CMD_WM_CONFIG_UPDATE,
|
||||
CAM_ISP_HW_CMD_CSID_QCFA_SUPPORTED,
|
||||
CAM_ISP_HW_CMD_MAX,
|
||||
};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user