msm: camera: common: Partial Camera Support
This change creates a sysfs entry(subparts_info) which has info about number of IFEs, IFE-LITEs, SFEs & CUSTOM, whose values are populated in their respective drivers. Also, validates whether a particular IFE, SFE and CUSTOM is supported or not. Based on this, probe of IFE, SFE and CUSTOM drivers will happen accordingly. CRs-Fixed: 3482745 Change-Id: Iff6e79a7793b14b1f368f215020617f10dbd4bb5 Signed-off-by: Karthik Dillibabu <quic_kard@quicinc.com>
This commit is contained in:

committed by
Camera Software Integration

parent
0aa784b1d9
commit
f910aa0b4f
@@ -34,6 +34,24 @@ static void cam_cpas_dump_monitor_array(
|
|||||||
struct cam_hw_info *cpas_hw);
|
struct cam_hw_info *cpas_hw);
|
||||||
static int cam_cpas_log_vote(struct cam_hw_info *cpas_hw, bool ddr_only);
|
static int cam_cpas_log_vote(struct cam_hw_info *cpas_hw, bool ddr_only);
|
||||||
|
|
||||||
|
static struct cam_cpas_subpart_info g_cam_cpas_camera_subpart_info = {
|
||||||
|
.num_bits = 8,
|
||||||
|
/*
|
||||||
|
* Below fuse indexing is based on software fuse definition which is in SMEM and provided
|
||||||
|
* by XBL team.
|
||||||
|
*/
|
||||||
|
.hw_bitmap_mask = {
|
||||||
|
{CAM_CPAS_CAM_FUSE, BIT(0)},
|
||||||
|
{CAM_CPAS_ISP_FUSE, BIT(0)},
|
||||||
|
{CAM_CPAS_ISP_FUSE, BIT(1)},
|
||||||
|
{CAM_CPAS_ISP_FUSE, BIT(2)},
|
||||||
|
{CAM_CPAS_SFE_FUSE, BIT(0)},
|
||||||
|
{CAM_CPAS_SFE_FUSE, BIT(1)},
|
||||||
|
{CAM_CPAS_SFE_FUSE, BIT(2)},
|
||||||
|
{CAM_CPAS_CUSTOM_FUSE, BIT(0)},
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
static void cam_cpas_process_drv_bw_overrides(
|
static void cam_cpas_process_drv_bw_overrides(
|
||||||
struct cam_cpas_bus_client *bus_client, uint64_t *high_ab, uint64_t *high_ib,
|
struct cam_cpas_bus_client *bus_client, uint64_t *high_ab, uint64_t *high_ib,
|
||||||
uint64_t *low_ab, uint64_t *low_ib, const struct cam_cpas_debug_settings *cpas_settings)
|
uint64_t *low_ab, uint64_t *low_ib, const struct cam_cpas_debug_settings *cpas_settings)
|
||||||
@@ -2912,8 +2930,7 @@ static int cam_cpas_hw_get_hw_info(void *hw_priv,
|
|||||||
cpas_hw->soc_info.soc_private;
|
cpas_hw->soc_info.soc_private;
|
||||||
|
|
||||||
hw_caps->fuse_info = soc_private->fuse_info;
|
hw_caps->fuse_info = soc_private->fuse_info;
|
||||||
CAM_INFO(CAM_CPAS, "fuse info->num_fuses %d",
|
CAM_DBG(CAM_CPAS, "fuse info->num_fuses %d", hw_caps->fuse_info.num_fuses);
|
||||||
hw_caps->fuse_info.num_fuses);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -4445,6 +4462,118 @@ end:
|
|||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static struct cam_hw_info *cam_cpas_kobj_to_cpas_hw(struct kobject *kobj)
|
||||||
|
{
|
||||||
|
return container_of(kobj, struct cam_cpas_kobj_map, base_kobj)->cpas_hw;
|
||||||
|
}
|
||||||
|
|
||||||
|
static ssize_t cam_cpas_sysfs_get_subparts_info(struct kobject *kobj, struct kobj_attribute *attr,
|
||||||
|
char *buf)
|
||||||
|
{
|
||||||
|
int len = 0;
|
||||||
|
struct cam_hw_info *cpas_hw = cam_cpas_kobj_to_cpas_hw(kobj);
|
||||||
|
struct cam_cpas_private_soc *soc_private = NULL;
|
||||||
|
struct cam_cpas_sysfs_info *sysfs_info = NULL;
|
||||||
|
|
||||||
|
mutex_lock(&cpas_hw->hw_mutex);
|
||||||
|
soc_private = (struct cam_cpas_private_soc *) cpas_hw->soc_info.soc_private;
|
||||||
|
sysfs_info = &soc_private->sysfs_info;
|
||||||
|
|
||||||
|
len += scnprintf(buf, PAGE_SIZE, "num_ifes: 0x%x, 0x%x\nnum_ife_lites: 0x%x, 0x%x\n"
|
||||||
|
"num_sfes: 0x%x, 0x%x\nnum_custom: 0x%x, 0x%x\n",
|
||||||
|
sysfs_info->num_ifes[CAM_CPAS_AVAILABLE_NUM_SUBPARTS],
|
||||||
|
sysfs_info->num_ifes[CAM_CPAS_FUNCTIONAL_NUM_SUBPARTS],
|
||||||
|
sysfs_info->num_ife_lites[CAM_CPAS_AVAILABLE_NUM_SUBPARTS],
|
||||||
|
sysfs_info->num_ife_lites[CAM_CPAS_FUNCTIONAL_NUM_SUBPARTS],
|
||||||
|
sysfs_info->num_sfes[CAM_CPAS_AVAILABLE_NUM_SUBPARTS],
|
||||||
|
sysfs_info->num_sfes[CAM_CPAS_FUNCTIONAL_NUM_SUBPARTS],
|
||||||
|
sysfs_info->num_custom[CAM_CPAS_AVAILABLE_NUM_SUBPARTS],
|
||||||
|
sysfs_info->num_custom[CAM_CPAS_FUNCTIONAL_NUM_SUBPARTS]);
|
||||||
|
/*
|
||||||
|
* subparts_info sysfs string looks like below.
|
||||||
|
* num_ifes: 0x3, 0x3 (If all IFEs are available)/0x2 (If 1 IFE is unavailable)
|
||||||
|
* num_ife_lites: 0x2, 0x2
|
||||||
|
* num_sfes: 0x3, 0x3 (If all SFEs are available)/0x2 (If 1 SFE is unavailable)
|
||||||
|
* num_custom: 0x0, 0x0
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (len >= PAGE_SIZE) {
|
||||||
|
CAM_ERR(CAM_CPAS, "camera subparts info sysfs string is truncated, len: %d", len);
|
||||||
|
mutex_unlock(&cpas_hw->hw_mutex);
|
||||||
|
return -EOVERFLOW;
|
||||||
|
}
|
||||||
|
|
||||||
|
mutex_unlock(&cpas_hw->hw_mutex);
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct kobj_attribute cam_subparts_info_attribute = __ATTR(subparts_info, 0444,
|
||||||
|
cam_cpas_sysfs_get_subparts_info, NULL);
|
||||||
|
|
||||||
|
static void cam_cpas_hw_kobj_release(struct kobject *kobj)
|
||||||
|
{
|
||||||
|
CAM_DBG(CAM_CPAS, "Release kobj");
|
||||||
|
kfree(container_of(kobj, struct cam_cpas_kobj_map, base_kobj));
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct kobj_type kobj_cam_cpas_hw_type = {
|
||||||
|
.release = cam_cpas_hw_kobj_release,
|
||||||
|
.sysfs_ops = &kobj_sysfs_ops
|
||||||
|
};
|
||||||
|
|
||||||
|
static void cam_cpas_remove_sysfs(struct cam_hw_info *cpas_hw)
|
||||||
|
{
|
||||||
|
struct cam_cpas_private_soc *soc_private = NULL;
|
||||||
|
|
||||||
|
mutex_lock(&cpas_hw->hw_mutex);
|
||||||
|
soc_private = (struct cam_cpas_private_soc *) cpas_hw->soc_info.soc_private;
|
||||||
|
|
||||||
|
sysfs_remove_file(soc_private->sysfs_info.kobj, &cam_subparts_info_attribute.attr);
|
||||||
|
kobject_put(soc_private->sysfs_info.kobj);
|
||||||
|
mutex_unlock(&cpas_hw->hw_mutex);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int cam_cpas_create_sysfs(struct cam_hw_info *cpas_hw)
|
||||||
|
{
|
||||||
|
int rc = 0;
|
||||||
|
struct cam_cpas_kobj_map *kobj_camera = NULL;
|
||||||
|
struct cam_cpas_private_soc *soc_private = NULL;
|
||||||
|
|
||||||
|
mutex_lock(&cpas_hw->hw_mutex);
|
||||||
|
soc_private = (struct cam_cpas_private_soc *) cpas_hw->soc_info.soc_private;
|
||||||
|
|
||||||
|
kobj_camera = kzalloc(sizeof(*kobj_camera), GFP_KERNEL);
|
||||||
|
if (!kobj_camera) {
|
||||||
|
CAM_ERR(CAM_CPAS, "failed to allocate memory for kobj_camera");
|
||||||
|
mutex_unlock(&cpas_hw->hw_mutex);
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
kobject_init(&kobj_camera->base_kobj, &kobj_cam_cpas_hw_type);
|
||||||
|
kobj_camera->cpas_hw = cpas_hw;
|
||||||
|
soc_private->sysfs_info.kobj = &kobj_camera->base_kobj;
|
||||||
|
|
||||||
|
rc = kobject_add(&kobj_camera->base_kobj, kernel_kobj, "%s", "camera");
|
||||||
|
if (rc) {
|
||||||
|
CAM_ERR(CAM_CPAS, "failed to add camera entry in sysfs");
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* sysfs file is created in /sys/kernel/camera */
|
||||||
|
rc = sysfs_create_file(&kobj_camera->base_kobj, &cam_subparts_info_attribute.attr);
|
||||||
|
if (rc) {
|
||||||
|
CAM_ERR(CAM_CPAS, "failed to create subparts_info file, rc: %d", rc);
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
|
||||||
|
mutex_unlock(&cpas_hw->hw_mutex);
|
||||||
|
return 0;
|
||||||
|
end:
|
||||||
|
kobject_put(&kobj_camera->base_kobj);
|
||||||
|
mutex_unlock(&cpas_hw->hw_mutex);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
int cam_cpas_hw_probe(struct platform_device *pdev,
|
int cam_cpas_hw_probe(struct platform_device *pdev,
|
||||||
struct cam_hw_intf **hw_intf)
|
struct cam_hw_intf **hw_intf)
|
||||||
{
|
{
|
||||||
@@ -4525,6 +4654,13 @@ int cam_cpas_hw_probe(struct platform_device *pdev,
|
|||||||
|
|
||||||
soc_private = (struct cam_cpas_private_soc *)
|
soc_private = (struct cam_cpas_private_soc *)
|
||||||
cpas_hw->soc_info.soc_private;
|
cpas_hw->soc_info.soc_private;
|
||||||
|
|
||||||
|
rc = cam_cpas_create_sysfs(cpas_hw);
|
||||||
|
if (rc) {
|
||||||
|
CAM_ERR(CAM_CPAS, "Failed to create sysfs entries, rc: %d", rc);
|
||||||
|
goto sysfs_fail;
|
||||||
|
}
|
||||||
|
|
||||||
cpas_core->num_clients = soc_private->num_clients;
|
cpas_core->num_clients = soc_private->num_clients;
|
||||||
atomic_set(&cpas_core->soc_access_count, 0);
|
atomic_set(&cpas_core->soc_access_count, 0);
|
||||||
init_waitqueue_head(&cpas_core->soc_access_count_wq);
|
init_waitqueue_head(&cpas_core->soc_access_count_wq);
|
||||||
@@ -4583,6 +4719,14 @@ int cam_cpas_hw_probe(struct platform_device *pdev,
|
|||||||
if (rc)
|
if (rc)
|
||||||
goto disable_soc_res;
|
goto disable_soc_res;
|
||||||
|
|
||||||
|
cpas_core->cam_subpart_info = &g_cam_cpas_camera_subpart_info;
|
||||||
|
|
||||||
|
rc = cam_get_subpart_info(&soc_private->part_info, CAM_CPAS_CAMERA_INSTANCES);
|
||||||
|
if (rc) {
|
||||||
|
CAM_ERR(CAM_CPAS, "Failed to get subpart_info, rc = %d", rc);
|
||||||
|
goto disable_soc_res;
|
||||||
|
}
|
||||||
|
|
||||||
rc = cam_cpas_soc_disable_resources(&cpas_hw->soc_info, true, true);
|
rc = cam_cpas_soc_disable_resources(&cpas_hw->soc_info, true, true);
|
||||||
if (rc) {
|
if (rc) {
|
||||||
CAM_ERR(CAM_CPAS, "failed in soc_disable_resources, rc=%d", rc);
|
CAM_ERR(CAM_CPAS, "failed in soc_disable_resources, rc=%d", rc);
|
||||||
@@ -4612,6 +4756,8 @@ client_cleanup:
|
|||||||
cam_cpas_util_client_cleanup(cpas_hw);
|
cam_cpas_util_client_cleanup(cpas_hw);
|
||||||
cam_cpas_node_tree_cleanup(cpas_core, cpas_hw->soc_info.soc_private);
|
cam_cpas_node_tree_cleanup(cpas_core, cpas_hw->soc_info.soc_private);
|
||||||
deinit_platform_res:
|
deinit_platform_res:
|
||||||
|
cam_cpas_remove_sysfs(cpas_hw);
|
||||||
|
sysfs_fail:
|
||||||
cam_cpas_soc_deinit_resources(&cpas_hw->soc_info);
|
cam_cpas_soc_deinit_resources(&cpas_hw->soc_info);
|
||||||
release_workq:
|
release_workq:
|
||||||
flush_workqueue(cpas_core->work_queue);
|
flush_workqueue(cpas_core->work_queue);
|
||||||
@@ -4643,6 +4789,7 @@ int cam_cpas_hw_remove(struct cam_hw_intf *cpas_hw_intf)
|
|||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cam_cpas_remove_sysfs(cpas_hw);
|
||||||
cam_cpas_util_axi_cleanup(cpas_core, &cpas_hw->soc_info);
|
cam_cpas_util_axi_cleanup(cpas_core, &cpas_hw->soc_info);
|
||||||
cam_cpas_node_tree_cleanup(cpas_core, cpas_hw->soc_info.soc_private);
|
cam_cpas_node_tree_cleanup(cpas_core, cpas_hw->soc_info.soc_private);
|
||||||
cam_cpas_util_unregister_bus_client(&cpas_core->ahb_bus_client);
|
cam_cpas_util_unregister_bus_client(&cpas_core->ahb_bus_client);
|
||||||
|
@@ -27,6 +27,9 @@
|
|||||||
#define CAM_CPAS_MAX_SLOPE_FACTOR 100
|
#define CAM_CPAS_MAX_SLOPE_FACTOR 100
|
||||||
#define CAM_CPAS_MAX_STRESS_INDICATOR 100
|
#define CAM_CPAS_MAX_STRESS_INDICATOR 100
|
||||||
|
|
||||||
|
/* Number of camera (CAM_SS) instances */
|
||||||
|
#define CAM_CPAS_CAMERA_INSTANCES 1
|
||||||
|
|
||||||
#define CAM_CPAS_AXI_MIN_MNOC_AB_BW (2048 * 1024)
|
#define CAM_CPAS_AXI_MIN_MNOC_AB_BW (2048 * 1024)
|
||||||
#define CAM_CPAS_AXI_MIN_MNOC_IB_BW (2048 * 1024)
|
#define CAM_CPAS_AXI_MIN_MNOC_IB_BW (2048 * 1024)
|
||||||
#define CAM_CPAS_AXI_MIN_CAMNOC_AB_BW (2048 * 1024)
|
#define CAM_CPAS_AXI_MIN_CAMNOC_AB_BW (2048 * 1024)
|
||||||
@@ -143,6 +146,17 @@ struct cam_cpas_axi_bw_info {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* struct cam_cpas_kobj_map: wrapper structure for base kobject
|
||||||
|
* and cam cpas private soc info
|
||||||
|
* @base_kobj: kernel object for camera sysfs
|
||||||
|
* @cpas_hw: pointer to cam_hw_info structure
|
||||||
|
*/
|
||||||
|
struct cam_cpas_kobj_map {
|
||||||
|
struct kobject base_kobj;
|
||||||
|
struct cam_hw_info *cpas_hw;
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* struct cam_cpas_internal_ops - CPAS Hardware layer internal ops
|
* struct cam_cpas_internal_ops - CPAS Hardware layer internal ops
|
||||||
*
|
*
|
||||||
@@ -372,6 +386,7 @@ struct cam_cpas_monitor {
|
|||||||
* @ahb_bus_client: AHB Bus client info
|
* @ahb_bus_client: AHB Bus client info
|
||||||
* @axi_port: AXI port info for a specific axi index
|
* @axi_port: AXI port info for a specific axi index
|
||||||
* @camnoc_axi_port: CAMNOC AXI port info for a specific camnoc axi index
|
* @camnoc_axi_port: CAMNOC AXI port info for a specific camnoc axi index
|
||||||
|
* @cam_subpart_info: camera subparts fuse description
|
||||||
* @internal_ops: CPAS HW internal ops
|
* @internal_ops: CPAS HW internal ops
|
||||||
* @work_queue: Work queue handle
|
* @work_queue: Work queue handle
|
||||||
* @soc_access_count: atomic soc_access_count count
|
* @soc_access_count: atomic soc_access_count count
|
||||||
@@ -410,6 +425,7 @@ struct cam_cpas {
|
|||||||
struct cam_cpas_bus_client ahb_bus_client;
|
struct cam_cpas_bus_client ahb_bus_client;
|
||||||
struct cam_cpas_axi_port axi_port[CAM_CPAS_MAX_AXI_PORTS];
|
struct cam_cpas_axi_port axi_port[CAM_CPAS_MAX_AXI_PORTS];
|
||||||
struct cam_cpas_axi_port camnoc_axi_port[CAM_CPAS_MAX_AXI_PORTS];
|
struct cam_cpas_axi_port camnoc_axi_port[CAM_CPAS_MAX_AXI_PORTS];
|
||||||
|
struct cam_cpas_subpart_info *cam_subpart_info;
|
||||||
struct cam_cpas_internal_ops internal_ops;
|
struct cam_cpas_internal_ops internal_ops;
|
||||||
struct workqueue_struct *work_queue;
|
struct workqueue_struct *work_queue;
|
||||||
atomic_t soc_access_count;
|
atomic_t soc_access_count;
|
||||||
|
@@ -20,7 +20,9 @@
|
|||||||
#include "cam_subdev.h"
|
#include "cam_subdev.h"
|
||||||
#include "cam_cpas_hw_intf.h"
|
#include "cam_cpas_hw_intf.h"
|
||||||
#include "cam_cpas_soc.h"
|
#include "cam_cpas_soc.h"
|
||||||
|
#include "cam_cpastop_hw.h"
|
||||||
#include "camera_main.h"
|
#include "camera_main.h"
|
||||||
|
|
||||||
#include <linux/soc/qcom/llcc-qcom.h>
|
#include <linux/soc/qcom/llcc-qcom.h>
|
||||||
#include "cam_req_mgr_interface.h"
|
#include "cam_req_mgr_interface.h"
|
||||||
|
|
||||||
@@ -309,6 +311,37 @@ int cam_cpas_dump_camnoc_buff_fill_info(uint32_t client_handle)
|
|||||||
}
|
}
|
||||||
EXPORT_SYMBOL(cam_cpas_dump_camnoc_buff_fill_info);
|
EXPORT_SYMBOL(cam_cpas_dump_camnoc_buff_fill_info);
|
||||||
|
|
||||||
|
bool cam_cpas_is_part_supported(uint32_t flag, uint32_t hw_map, uint32_t part_info)
|
||||||
|
{
|
||||||
|
int32_t i;
|
||||||
|
struct cam_hw_info *cpas_hw = g_cpas_intf->hw_intf->hw_priv;
|
||||||
|
struct cam_cpas *cpas_core = NULL;
|
||||||
|
struct cam_cpas_subpart_info *cam_subpart_info = NULL;
|
||||||
|
|
||||||
|
mutex_lock(&cpas_hw->hw_mutex);
|
||||||
|
cpas_core = cpas_hw->core_info;
|
||||||
|
cam_subpart_info = cpas_core->cam_subpart_info;
|
||||||
|
|
||||||
|
if (!cam_subpart_info) {
|
||||||
|
CAM_DBG(CAM_CPAS, "Invalid address of cam_subpart_info");
|
||||||
|
mutex_unlock(&cpas_hw->hw_mutex);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < cam_subpart_info->num_bits; i++) {
|
||||||
|
if ((cam_subpart_info->hw_bitmap_mask[i][0] == flag) &&
|
||||||
|
(cam_subpart_info->hw_bitmap_mask[i][1] == hw_map)) {
|
||||||
|
CAM_DBG(CAM_CPAS, "flag: %u hw_map: %u part_info:0x%x",
|
||||||
|
flag, hw_map, part_info);
|
||||||
|
mutex_unlock(&cpas_hw->hw_mutex);
|
||||||
|
return ((part_info & BIT(i)) == 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mutex_unlock(&cpas_hw->hw_mutex);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool cam_cpas_is_feature_supported(uint32_t flag, uint32_t hw_map,
|
bool cam_cpas_is_feature_supported(uint32_t flag, uint32_t hw_map,
|
||||||
uint32_t *fuse_val)
|
uint32_t *fuse_val)
|
||||||
{
|
{
|
||||||
@@ -331,6 +364,8 @@ bool cam_cpas_is_feature_supported(uint32_t flag, uint32_t hw_map,
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
supported = cam_cpas_is_part_supported(flag, hw_map, soc_private->part_info);
|
||||||
|
|
||||||
for (i = 0; i < soc_private->num_feature_info; i++)
|
for (i = 0; i < soc_private->num_feature_info; i++)
|
||||||
if (soc_private->feature_info[i].feature == flag)
|
if (soc_private->feature_info[i].feature == flag)
|
||||||
break;
|
break;
|
||||||
@@ -341,8 +376,10 @@ bool cam_cpas_is_feature_supported(uint32_t flag, uint32_t hw_map,
|
|||||||
if (soc_private->feature_info[i].type == CAM_CPAS_FEATURE_TYPE_DISABLE
|
if (soc_private->feature_info[i].type == CAM_CPAS_FEATURE_TYPE_DISABLE
|
||||||
|| (soc_private->feature_info[i].type ==
|
|| (soc_private->feature_info[i].type ==
|
||||||
CAM_CPAS_FEATURE_TYPE_ENABLE)) {
|
CAM_CPAS_FEATURE_TYPE_ENABLE)) {
|
||||||
if ((soc_private->feature_info[i].hw_map & hw_map) == hw_map)
|
if ((soc_private->feature_info[i].hw_map & hw_map) == hw_map) {
|
||||||
supported = soc_private->feature_info[i].enable;
|
if (!(supported && soc_private->feature_info[i].enable))
|
||||||
|
supported = false;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
if (!fuse_val) {
|
if (!fuse_val) {
|
||||||
CAM_ERR(CAM_CPAS,
|
CAM_ERR(CAM_CPAS,
|
||||||
@@ -836,6 +873,63 @@ int cam_cpas_get_scid(
|
|||||||
}
|
}
|
||||||
EXPORT_SYMBOL(cam_cpas_get_scid);
|
EXPORT_SYMBOL(cam_cpas_get_scid);
|
||||||
|
|
||||||
|
int cam_cpas_prepare_subpart_info(enum cam_subparts_index idx, uint32_t num_subpart_available,
|
||||||
|
uint32_t num_subpart_functional)
|
||||||
|
{
|
||||||
|
struct cam_hw_info *cpas_hw = NULL;
|
||||||
|
struct cam_cpas_private_soc *soc_private = NULL;
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
mutex_lock(&cpas_hw->hw_mutex);
|
||||||
|
soc_private = (struct cam_cpas_private_soc *)cpas_hw->soc_info.soc_private;
|
||||||
|
|
||||||
|
if (!soc_private) {
|
||||||
|
CAM_ERR(CAM_CPAS, "Invalid soc_private: 0x%x", soc_private);
|
||||||
|
mutex_unlock(&cpas_hw->hw_mutex);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (idx) {
|
||||||
|
case CAM_IFE_HW_IDX:
|
||||||
|
soc_private->sysfs_info.num_ifes[CAM_CPAS_AVAILABLE_NUM_SUBPARTS] =
|
||||||
|
num_subpart_available;
|
||||||
|
soc_private->sysfs_info.num_ifes[CAM_CPAS_FUNCTIONAL_NUM_SUBPARTS] =
|
||||||
|
num_subpart_functional;
|
||||||
|
break;
|
||||||
|
case CAM_IFE_LITE_HW_IDX:
|
||||||
|
soc_private->sysfs_info.num_ife_lites[CAM_CPAS_AVAILABLE_NUM_SUBPARTS] =
|
||||||
|
num_subpart_available;
|
||||||
|
soc_private->sysfs_info.num_ife_lites[CAM_CPAS_FUNCTIONAL_NUM_SUBPARTS] =
|
||||||
|
num_subpart_functional;
|
||||||
|
break;
|
||||||
|
case CAM_SFE_HW_IDX:
|
||||||
|
soc_private->sysfs_info.num_sfes[CAM_CPAS_AVAILABLE_NUM_SUBPARTS] =
|
||||||
|
num_subpart_available;
|
||||||
|
soc_private->sysfs_info.num_sfes[CAM_CPAS_FUNCTIONAL_NUM_SUBPARTS] =
|
||||||
|
num_subpart_functional;
|
||||||
|
break;
|
||||||
|
case CAM_CUSTOM_HW_IDX:
|
||||||
|
soc_private->sysfs_info.num_custom[CAM_CPAS_AVAILABLE_NUM_SUBPARTS] =
|
||||||
|
num_subpart_available;
|
||||||
|
soc_private->sysfs_info.num_custom[CAM_CPAS_FUNCTIONAL_NUM_SUBPARTS] =
|
||||||
|
num_subpart_functional;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
CAM_ERR(CAM_CPAS, "Invalid camera subpart index : %d", idx);
|
||||||
|
mutex_unlock(&cpas_hw->hw_mutex);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
mutex_unlock(&cpas_hw->hw_mutex);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(cam_cpas_prepare_subpart_info);
|
||||||
|
|
||||||
int cam_cpas_activate_llcc(
|
int cam_cpas_activate_llcc(
|
||||||
enum cam_sys_cache_config_types type)
|
enum cam_sys_cache_config_types type)
|
||||||
{
|
{
|
||||||
|
@@ -761,8 +761,6 @@ static int cam_cpas_parse_node_tree(struct cam_cpas *cpas_core,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
int cam_cpas_get_hw_features(struct platform_device *pdev,
|
int cam_cpas_get_hw_features(struct platform_device *pdev,
|
||||||
struct cam_cpas_private_soc *soc_private)
|
struct cam_cpas_private_soc *soc_private)
|
||||||
{
|
{
|
||||||
@@ -780,8 +778,6 @@ int cam_cpas_get_hw_features(struct platform_device *pdev,
|
|||||||
CAM_DBG(CAM_CPAS, "fuse info elements count %d", count);
|
CAM_DBG(CAM_CPAS, "fuse info elements count %d", count);
|
||||||
|
|
||||||
if (count <= 0) {
|
if (count <= 0) {
|
||||||
CAM_INFO(CAM_CPAS, "No or invalid fuse entries count: %d",
|
|
||||||
count);
|
|
||||||
goto end;
|
goto end;
|
||||||
} else if (count%5 != 0) {
|
} else if (count%5 != 0) {
|
||||||
CAM_INFO(CAM_CPAS, "fuse entries should be multiple of 5 %d",
|
CAM_INFO(CAM_CPAS, "fuse entries should be multiple of 5 %d",
|
||||||
|
@@ -15,6 +15,15 @@
|
|||||||
#define CAM_CPAS_MAX_TREE_NODES 63
|
#define CAM_CPAS_MAX_TREE_NODES 63
|
||||||
#define CAM_CPAS_MAX_FUSE_FEATURE 10
|
#define CAM_CPAS_MAX_FUSE_FEATURE 10
|
||||||
|
|
||||||
|
/**
|
||||||
|
* enum cam_cpas_num_subparts_types - Enum for types of number of camera subparts
|
||||||
|
*/
|
||||||
|
enum cam_cpas_num_subparts_types {
|
||||||
|
CAM_CPAS_AVAILABLE_NUM_SUBPARTS,
|
||||||
|
CAM_CPAS_FUNCTIONAL_NUM_SUBPARTS,
|
||||||
|
CAM_CPAS_NUM_SUBPARTS_MAX_TYPES,
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* struct cpas_tree_node: Generic cpas tree node for BW voting
|
* struct cpas_tree_node: Generic cpas tree node for BW voting
|
||||||
*
|
*
|
||||||
@@ -215,6 +224,23 @@ struct cam_cpas_soc_irq_data {
|
|||||||
enum cam_camnoc_hw_type camnoc_type;
|
enum cam_camnoc_hw_type camnoc_type;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* struct cam_cpas_sysfs_info - cpas sysfs info
|
||||||
|
*
|
||||||
|
* @kobj: Kobj for camera directory
|
||||||
|
* @num_ifes: Number of available and functional IFEs
|
||||||
|
* @num_ife_lites: Number of available and functional IFE-LITEs
|
||||||
|
* @num_sfes: Number of available and functional SFEs
|
||||||
|
* @num_custom: Number of available and functional CUSTOM
|
||||||
|
*/
|
||||||
|
struct cam_cpas_sysfs_info {
|
||||||
|
struct kobject *kobj;
|
||||||
|
uint32_t num_ifes[CAM_CPAS_NUM_SUBPARTS_MAX_TYPES];
|
||||||
|
uint32_t num_ife_lites[CAM_CPAS_NUM_SUBPARTS_MAX_TYPES];
|
||||||
|
uint32_t num_sfes[CAM_CPAS_NUM_SUBPARTS_MAX_TYPES];
|
||||||
|
uint32_t num_custom[CAM_CPAS_NUM_SUBPARTS_MAX_TYPES];
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* struct cam_cpas_private_soc : CPAS private DT info
|
* struct cam_cpas_private_soc : CPAS private DT info
|
||||||
*
|
*
|
||||||
@@ -235,10 +261,12 @@ struct cam_cpas_soc_irq_data {
|
|||||||
* camnoc axi clock
|
* camnoc axi clock
|
||||||
* @camnoc_axi_min_ib_bw: Min camnoc BW which varies based on target
|
* @camnoc_axi_min_ib_bw: Min camnoc BW which varies based on target
|
||||||
* @fuse_info: fuse information
|
* @fuse_info: fuse information
|
||||||
|
* @sysfs_info: Camera subparts sysfs information
|
||||||
* @rpmh_info: RPMH BCM info
|
* @rpmh_info: RPMH BCM info
|
||||||
* @num_feature_info: number of feature_info entries
|
* @num_feature_info: number of feature_info entries
|
||||||
* @feature_info: Structure for storing feature information
|
* @feature_info: Structure for storing feature information
|
||||||
* @num_caches: Number of last level caches
|
* @num_caches: Number of last level caches
|
||||||
|
* @part_info: Camera Hw subpart info
|
||||||
* @llcc_info: Cache info
|
* @llcc_info: Cache info
|
||||||
* @enable_smart_qos: Whether to enable Smart QoS mechanism on current chipset
|
* @enable_smart_qos: Whether to enable Smart QoS mechanism on current chipset
|
||||||
* @enable_cam_ddr_drv: Whether to enable Camera DDR DRV on current chipset
|
* @enable_cam_ddr_drv: Whether to enable Camera DDR DRV on current chipset
|
||||||
@@ -265,10 +293,12 @@ struct cam_cpas_private_soc {
|
|||||||
uint32_t camnoc_axi_clk_bw_margin;
|
uint32_t camnoc_axi_clk_bw_margin;
|
||||||
uint64_t camnoc_axi_min_ib_bw;
|
uint64_t camnoc_axi_min_ib_bw;
|
||||||
struct cam_cpas_fuse_info fuse_info;
|
struct cam_cpas_fuse_info fuse_info;
|
||||||
|
struct cam_cpas_sysfs_info sysfs_info;
|
||||||
uint32_t rpmh_info[CAM_RPMH_BCM_INFO_MAX];
|
uint32_t rpmh_info[CAM_RPMH_BCM_INFO_MAX];
|
||||||
uint32_t num_feature_info;
|
uint32_t num_feature_info;
|
||||||
struct cam_cpas_feature_info feature_info[CAM_CPAS_MAX_FUSE_FEATURE];
|
struct cam_cpas_feature_info feature_info[CAM_CPAS_MAX_FUSE_FEATURE];
|
||||||
uint32_t num_caches;
|
uint32_t num_caches;
|
||||||
|
uint32_t part_info;
|
||||||
struct cam_sys_cache_info *llcc_info;
|
struct cam_sys_cache_info *llcc_info;
|
||||||
bool enable_smart_qos;
|
bool enable_smart_qos;
|
||||||
bool enable_cam_ddr_drv;
|
bool enable_cam_ddr_drv;
|
||||||
|
@@ -10,6 +10,10 @@
|
|||||||
#include "cam_cpas_api.h"
|
#include "cam_cpas_api.h"
|
||||||
#include "cam_cpas_hw.h"
|
#include "cam_cpas_hw.h"
|
||||||
|
|
||||||
|
/* Camera Hw parts array indices */
|
||||||
|
#define CAM_CPAS_PART_MAX_FUSE_BITS 8
|
||||||
|
#define CAM_CPAS_PART_MAX_FUSE_BIT_INFO 2
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* enum cam_camnoc_hw_irq_type - Enum for camnoc error types
|
* enum cam_camnoc_hw_irq_type - Enum for camnoc error types
|
||||||
*
|
*
|
||||||
@@ -307,6 +311,18 @@ struct cam_cpas_hw_errata_wa {
|
|||||||
} data;
|
} data;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* struct cam_cpas_subpart_info : Struct for camera Hw parts info
|
||||||
|
*
|
||||||
|
* @num_bits: Number of entries in hw_bitmap_mask
|
||||||
|
* @hw_bitmap_mask: Contains Fuse flag and hw_map info
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
struct cam_cpas_subpart_info {
|
||||||
|
uint32_t num_bits;
|
||||||
|
uint32_t hw_bitmap_mask[CAM_CPAS_PART_MAX_FUSE_BITS][CAM_CPAS_PART_MAX_FUSE_BIT_INFO];
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* struct cam_cpas_hw_errata_wa_list : List of HW Errata workaround info
|
* struct cam_cpas_hw_errata_wa_list : List of HW Errata workaround info
|
||||||
*
|
*
|
||||||
|
@@ -296,6 +296,16 @@ enum cam_sys_cache_llcc_staling_op_type {
|
|||||||
CAM_LLCC_NOTIFY_STALING_OPS_MAX
|
CAM_LLCC_NOTIFY_STALING_OPS_MAX
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* enum cam_subparts_index - Enum for camera subparts indices
|
||||||
|
*/
|
||||||
|
enum cam_subparts_index {
|
||||||
|
CAM_IFE_HW_IDX,
|
||||||
|
CAM_IFE_LITE_HW_IDX,
|
||||||
|
CAM_SFE_HW_IDX,
|
||||||
|
CAM_CUSTOM_HW_IDX
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* struct cam_camnoc_irq_slave_err_data : Data for Slave error.
|
* struct cam_camnoc_irq_slave_err_data : Data for Slave error.
|
||||||
*
|
*
|
||||||
@@ -573,6 +583,23 @@ struct cam_axi_vote {
|
|||||||
struct cam_cpas_axi_per_path_bw_vote axi_path[CAM_CPAS_MAX_PATHS_PER_CLIENT];
|
struct cam_cpas_axi_per_path_bw_vote axi_path[CAM_CPAS_MAX_PATHS_PER_CLIENT];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* cam_cpas_prepare_subpart_info()
|
||||||
|
*
|
||||||
|
* @brief: API to update the number of ifes, ife_lites, sfes and custom
|
||||||
|
* in the struct cam_cpas_private_soc.
|
||||||
|
*
|
||||||
|
* @idx : Camera subpart index
|
||||||
|
* @num_subpart_available : Number of available subparts
|
||||||
|
* @num_subpart_functional: Number of functional subparts
|
||||||
|
*
|
||||||
|
* @returns 0 on success & -EINVAL when @subpart_type is invalid.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
int cam_cpas_prepare_subpart_info(
|
||||||
|
enum cam_subparts_index idx, uint32_t num_subpart_available,
|
||||||
|
uint32_t num_subpart_functional);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* cam_cpas_register_client()
|
* cam_cpas_register_client()
|
||||||
*
|
*
|
||||||
|
@@ -1,6 +1,7 @@
|
|||||||
// SPDX-License-Identifier: GPL-2.0-only
|
// SPDX-License-Identifier: GPL-2.0-only
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2019-2021, The Linux Foundation. All rights reserved.
|
* Copyright (c) 2019-2021, The Linux Foundation. All rights reserved.
|
||||||
|
* Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <linux/delay.h>
|
#include <linux/delay.h>
|
||||||
@@ -10,6 +11,7 @@
|
|||||||
#include <linux/iommu.h>
|
#include <linux/iommu.h>
|
||||||
#include <linux/timer.h>
|
#include <linux/timer.h>
|
||||||
#include <linux/kernel.h>
|
#include <linux/kernel.h>
|
||||||
|
#include <dt-bindings/msm-camera.h>
|
||||||
|
|
||||||
#include <media/cam_req_mgr.h>
|
#include <media/cam_req_mgr.h>
|
||||||
|
|
||||||
@@ -23,6 +25,7 @@
|
|||||||
#include "camera_main.h"
|
#include "camera_main.h"
|
||||||
|
|
||||||
static struct cam_custom_dev g_custom_dev;
|
static struct cam_custom_dev g_custom_dev;
|
||||||
|
static uint32_t g_num_custom_hws;
|
||||||
|
|
||||||
static void cam_custom_dev_iommu_fault_handler(
|
static void cam_custom_dev_iommu_fault_handler(
|
||||||
struct cam_smmu_pf_info *pf_info)
|
struct cam_smmu_pf_info *pf_info)
|
||||||
@@ -117,6 +120,11 @@ static int cam_custom_component_bind(struct device *dev,
|
|||||||
g_custom_dev.sd.internal_ops = &cam_custom_subdev_internal_ops;
|
g_custom_dev.sd.internal_ops = &cam_custom_subdev_internal_ops;
|
||||||
g_custom_dev.sd.close_seq_prior = CAM_SD_CLOSE_HIGH_PRIORITY;
|
g_custom_dev.sd.close_seq_prior = CAM_SD_CLOSE_HIGH_PRIORITY;
|
||||||
|
|
||||||
|
if (!cam_cpas_is_feature_supported(CAM_CPAS_CUSTOM_FUSE, BIT(0), NULL)) {
|
||||||
|
CAM_DBG(CAM_CUSTOM, "CUSTOM:0 is not supported");
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
rc = cam_subdev_probe(&g_custom_dev.sd, pdev, CAM_CUSTOM_DEV_NAME,
|
rc = cam_subdev_probe(&g_custom_dev.sd, pdev, CAM_CUSTOM_DEV_NAME,
|
||||||
CAM_CUSTOM_DEVICE_TYPE);
|
CAM_CUSTOM_DEVICE_TYPE);
|
||||||
if (rc) {
|
if (rc) {
|
||||||
@@ -167,6 +175,14 @@ err:
|
|||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void cam_custom_get_num_hws(uint32_t *custom_num)
|
||||||
|
{
|
||||||
|
if (custom_num)
|
||||||
|
*custom_num = g_num_custom_hws;
|
||||||
|
else
|
||||||
|
CAM_ERR(CAM_CUSTOM, "Invalid argument, g_num_custom_hws: %u", g_num_custom_hws);
|
||||||
|
}
|
||||||
|
|
||||||
static void cam_custom_component_unbind(struct device *dev,
|
static void cam_custom_component_unbind(struct device *dev,
|
||||||
struct device *master_dev, void *data)
|
struct device *master_dev, void *data)
|
||||||
{
|
{
|
||||||
@@ -204,6 +220,8 @@ static int cam_custom_dev_probe(struct platform_device *pdev)
|
|||||||
int rc = 0;
|
int rc = 0;
|
||||||
|
|
||||||
CAM_DBG(CAM_CUSTOM, "Adding Custom HW component");
|
CAM_DBG(CAM_CUSTOM, "Adding Custom HW component");
|
||||||
|
g_num_custom_hws++;
|
||||||
|
|
||||||
rc = component_add(&pdev->dev, &cam_custom_component_ops);
|
rc = component_add(&pdev->dev, &cam_custom_component_ops);
|
||||||
if (rc)
|
if (rc)
|
||||||
CAM_ERR(CAM_CUSTOM, "failed to add component rc: %d", rc);
|
CAM_ERR(CAM_CUSTOM, "failed to add component rc: %d", rc);
|
||||||
|
@@ -150,6 +150,16 @@ enum cam_isp_resource_type
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void cam_custom_mgr_count_functional_hws(uint32_t num_custom_functional)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < CAM_CUSTOM_CSID_HW_MAX; i++) {
|
||||||
|
if (g_custom_hw_mgr.custom_hw[i])
|
||||||
|
num_custom_functional++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static int cam_custom_hw_mgr_deinit_hw_res(
|
static int cam_custom_hw_mgr_deinit_hw_res(
|
||||||
struct cam_custom_hw_mgr_res *hw_mgr_res)
|
struct cam_custom_hw_mgr_res *hw_mgr_res)
|
||||||
{
|
{
|
||||||
@@ -1467,6 +1477,7 @@ int cam_custom_hw_mgr_init(struct device_node *of_node,
|
|||||||
{
|
{
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
int i, j;
|
int i, j;
|
||||||
|
uint32_t num_custom_available, num_custom_functional = 0;
|
||||||
|
|
||||||
memset(&g_custom_hw_mgr, 0, sizeof(g_custom_hw_mgr));
|
memset(&g_custom_hw_mgr, 0, sizeof(g_custom_hw_mgr));
|
||||||
mutex_init(&g_custom_hw_mgr.ctx_mutex);
|
mutex_init(&g_custom_hw_mgr.ctx_mutex);
|
||||||
@@ -1545,6 +1556,13 @@ int cam_custom_hw_mgr_init(struct device_node *of_node,
|
|||||||
if (iommu_hdl)
|
if (iommu_hdl)
|
||||||
*iommu_hdl = g_custom_hw_mgr.img_iommu_hdl;
|
*iommu_hdl = g_custom_hw_mgr.img_iommu_hdl;
|
||||||
|
|
||||||
|
cam_custom_get_num_hws(&num_custom_available);
|
||||||
|
cam_custom_mgr_count_functional_hws(&num_custom_functional);
|
||||||
|
rc = cam_cpas_prepare_subpart_info(CAM_CUSTOM_HW_IDX, num_custom_available,
|
||||||
|
num_custom_functional);
|
||||||
|
if (rc)
|
||||||
|
CAM_ERR(CAM_CUSTOM, "Failed to populate num_custom, rc: %d", rc);
|
||||||
|
|
||||||
CAM_DBG(CAM_CUSTOM, "HW manager initialized");
|
CAM_DBG(CAM_CUSTOM, "HW manager initialized");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@@ -1,6 +1,7 @@
|
|||||||
/* SPDX-License-Identifier: GPL-2.0-only
|
/* SPDX-License-Identifier: GPL-2.0-only
|
||||||
*
|
*
|
||||||
* Copyright (c) 2019, The Linux Foundation. All rights reserved.
|
* Copyright (c) 2019, The Linux Foundation. All rights reserved.
|
||||||
|
* Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef _CAM_CUSTOM_HW_MGR_H_
|
#ifndef _CAM_CUSTOM_HW_MGR_H_
|
||||||
@@ -126,6 +127,16 @@ struct cam_custom_hw_mgr {
|
|||||||
struct cam_custom_hw_mgr_ctx ctx_pool[CAM_CTX_MAX];
|
struct cam_custom_hw_mgr_ctx ctx_pool[CAM_CTX_MAX];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* cam_custom_get_num_hws()
|
||||||
|
*
|
||||||
|
* @brief : Populates number of custom.
|
||||||
|
*
|
||||||
|
* @num_custom : Fills number of custom hws in the address passed.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
void cam_custom_get_num_hws(uint32_t *num_custom);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* cam_custom_hw_mgr_init()
|
* cam_custom_hw_mgr_init()
|
||||||
*
|
*
|
||||||
|
@@ -72,7 +72,8 @@ static uint32_t blob_type_hw_cmd_map[CAM_ISP_GENERIC_BLOB_TYPE_MAX] = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
static struct cam_ife_hw_mgr g_ife_hw_mgr;
|
static struct cam_ife_hw_mgr g_ife_hw_mgr;
|
||||||
static uint32_t g_num_ife, g_num_ife_lite, g_num_sfe;
|
static uint32_t g_num_ife_available, g_num_ife_lite_available, g_num_sfe_available;
|
||||||
|
static uint32_t g_num_ife_functional, g_num_ife_lite_functional, g_num_sfe_functional;
|
||||||
static uint32_t max_ife_out_res, max_sfe_out_res;
|
static uint32_t max_ife_out_res, max_sfe_out_res;
|
||||||
|
|
||||||
static int cam_ife_mgr_find_core_idx(int split_id, struct cam_ife_hw_mgr_ctx *ctx,
|
static int cam_ife_mgr_find_core_idx(int split_id, struct cam_ife_hw_mgr_ctx *ctx,
|
||||||
@@ -2535,48 +2536,49 @@ err:
|
|||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void cam_ife_mgr_count_sfe(void)
|
static inline void cam_ife_mgr_count_functional_sfe(void)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
g_num_sfe = 0;
|
g_num_sfe_functional = 0;
|
||||||
|
|
||||||
for (i = 0; i < CAM_SFE_HW_NUM_MAX; i++) {
|
for (i = 0; i < CAM_SFE_HW_NUM_MAX; i++) {
|
||||||
if (g_ife_hw_mgr.sfe_devices[i])
|
if (g_ife_hw_mgr.sfe_devices[i])
|
||||||
g_num_sfe++;
|
g_num_sfe_functional++;
|
||||||
}
|
}
|
||||||
|
|
||||||
CAM_DBG(CAM_ISP, "counted %u SFEs", g_num_sfe);
|
CAM_DBG(CAM_ISP, "counted %u functional SFEs", g_num_sfe_functional);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void cam_ife_mgr_count_ife(void)
|
static inline void cam_ife_mgr_count_functional_ife(void)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
g_num_ife = 0;
|
g_num_ife_functional = 0;
|
||||||
g_num_ife_lite = 0;
|
g_num_ife_lite_functional = 0;
|
||||||
|
|
||||||
for (i = 0; i < CAM_IFE_HW_NUM_MAX; i++) {
|
for (i = 0; i < CAM_IFE_HW_NUM_MAX; i++) {
|
||||||
if (g_ife_hw_mgr.ife_devices[i]) {
|
if (g_ife_hw_mgr.ife_devices[i]) {
|
||||||
if (g_ife_hw_mgr.ife_dev_caps[i].is_lite)
|
if (g_ife_hw_mgr.ife_dev_caps[i].is_lite)
|
||||||
g_num_ife_lite++;
|
g_num_ife_lite_functional++;
|
||||||
else
|
else
|
||||||
g_num_ife++;
|
g_num_ife_functional++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
CAM_DBG(CAM_ISP, "counted %d IFE and %d IFE lite", g_num_ife, g_num_ife_lite);
|
CAM_DBG(CAM_ISP, "counted functional %d IFE and %d IFE lite", g_num_ife_functional,
|
||||||
|
g_num_ife_lite_functional);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int cam_convert_hw_idx_to_sfe_hw_num(int hw_idx)
|
static int cam_convert_hw_idx_to_sfe_hw_num(int hw_idx)
|
||||||
{
|
{
|
||||||
if (hw_idx < g_num_sfe) {
|
if (hw_idx < g_num_sfe_available) {
|
||||||
switch (hw_idx) {
|
switch (hw_idx) {
|
||||||
case 0: return CAM_ISP_SFE0_HW;
|
case 0: return CAM_ISP_SFE0_HW;
|
||||||
case 1: return CAM_ISP_SFE1_HW;
|
case 1: return CAM_ISP_SFE1_HW;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
CAM_ERR(CAM_ISP, "SFE hw idx %d out-of-bounds max %u",
|
CAM_ERR(CAM_ISP, "SFE hw idx %d out-of-bounds max available %u",
|
||||||
hw_idx, g_num_sfe);
|
hw_idx, g_num_sfe_available);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@@ -2584,14 +2586,14 @@ static int cam_convert_hw_idx_to_sfe_hw_num(int hw_idx)
|
|||||||
|
|
||||||
static int cam_convert_hw_idx_to_ife_hw_num(int hw_idx)
|
static int cam_convert_hw_idx_to_ife_hw_num(int hw_idx)
|
||||||
{
|
{
|
||||||
if (hw_idx < g_num_ife) {
|
if (hw_idx < g_num_ife_available) {
|
||||||
switch (hw_idx) {
|
switch (hw_idx) {
|
||||||
case 0: return CAM_ISP_IFE0_HW;
|
case 0: return CAM_ISP_IFE0_HW;
|
||||||
case 1: return CAM_ISP_IFE1_HW;
|
case 1: return CAM_ISP_IFE1_HW;
|
||||||
case 2: return CAM_ISP_IFE2_HW;
|
case 2: return CAM_ISP_IFE2_HW;
|
||||||
}
|
}
|
||||||
} else if (hw_idx < g_num_ife + g_num_ife_lite) {
|
} else if (hw_idx < g_num_ife_available + g_num_ife_lite_available) {
|
||||||
switch (hw_idx - g_num_ife) {
|
switch (hw_idx - g_num_ife_available) {
|
||||||
case 0: return CAM_ISP_IFE0_LITE_HW;
|
case 0: return CAM_ISP_IFE0_LITE_HW;
|
||||||
case 1: return CAM_ISP_IFE1_LITE_HW;
|
case 1: return CAM_ISP_IFE1_LITE_HW;
|
||||||
case 2: return CAM_ISP_IFE2_LITE_HW;
|
case 2: return CAM_ISP_IFE2_LITE_HW;
|
||||||
@@ -16076,8 +16078,27 @@ int cam_ife_hw_mgr_init(struct cam_hw_mgr_intf *hw_mgr_intf, int *iommu_hdl,
|
|||||||
*iommu_hdl = g_ife_hw_mgr.mgr_common.img_iommu_hdl;
|
*iommu_hdl = g_ife_hw_mgr.mgr_common.img_iommu_hdl;
|
||||||
|
|
||||||
cam_ife_hw_mgr_debug_register();
|
cam_ife_hw_mgr_debug_register();
|
||||||
cam_ife_mgr_count_ife();
|
cam_ife_mgr_count_functional_ife();
|
||||||
cam_ife_mgr_count_sfe();
|
cam_ife_mgr_count_functional_sfe();
|
||||||
|
|
||||||
|
cam_vfe_get_num_ifes(&g_num_ife_available);
|
||||||
|
rc = cam_cpas_prepare_subpart_info(CAM_IFE_HW_IDX, g_num_ife_available,
|
||||||
|
g_num_ife_functional);
|
||||||
|
if (rc)
|
||||||
|
CAM_ERR(CAM_ISP, "Failed to populate num_ifes, rc: %d", rc);
|
||||||
|
|
||||||
|
cam_vfe_get_num_ife_lites(&g_num_ife_lite_available);
|
||||||
|
rc = cam_cpas_prepare_subpart_info(CAM_IFE_LITE_HW_IDX, g_num_ife_lite_available,
|
||||||
|
g_num_ife_lite_functional);
|
||||||
|
if (rc)
|
||||||
|
CAM_ERR(CAM_ISP, "Failed to populate num_ife_lites, rc: %d", rc);
|
||||||
|
|
||||||
|
cam_sfe_get_num_hws(&g_num_sfe_available);
|
||||||
|
rc = cam_cpas_prepare_subpart_info(CAM_SFE_HW_IDX, g_num_sfe_available,
|
||||||
|
g_num_sfe_functional);
|
||||||
|
if (rc)
|
||||||
|
CAM_ERR(CAM_ISP, "Failed to populate num_sfes, rc: %d", rc);
|
||||||
|
|
||||||
cam_common_register_mini_dump_cb(cam_ife_hw_mgr_mini_dump_cb,
|
cam_common_register_mini_dump_cb(cam_ife_hw_mgr_mini_dump_cb,
|
||||||
"CAM_ISP", NULL);
|
"CAM_ISP", NULL);
|
||||||
cam_ife_mgr_test_irq_lines_at_probe(&g_ife_hw_mgr);
|
cam_ife_mgr_test_irq_lines_at_probe(&g_ife_hw_mgr);
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
// SPDX-License-Identifier: GPL-2.0-only
|
// SPDX-License-Identifier: GPL-2.0-only
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2017-2021, The Linux Foundation. All rights reserved.
|
* Copyright (c) 2017-2021, The Linux Foundation. All rights reserved.
|
||||||
* Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
|
* Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <linux/slab.h>
|
#include <linux/slab.h>
|
||||||
@@ -31,6 +31,20 @@ static int cam_ife_csid_component_bind(struct device *dev,
|
|||||||
|
|
||||||
CAM_DBG(CAM_ISP, "Binding IFE CSID component");
|
CAM_DBG(CAM_ISP, "Binding IFE CSID component");
|
||||||
|
|
||||||
|
/* get ife csid hw index */
|
||||||
|
rc = of_property_read_u32(pdev->dev.of_node, "cell-index", &csid_dev_idx);
|
||||||
|
if (rc) {
|
||||||
|
CAM_ERR(CAM_ISP, "Failed to read cell-index of IFE CSID HW, rc: %d", rc);
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!cam_cpas_is_feature_supported(CAM_CPAS_ISP_FUSE, BIT(csid_dev_idx), NULL) ||
|
||||||
|
!cam_cpas_is_feature_supported(CAM_CPAS_ISP_LITE_FUSE,
|
||||||
|
BIT(csid_dev_idx), NULL)) {
|
||||||
|
CAM_DBG(CAM_ISP, "CSID[%d] not supported based on fuse", csid_dev_idx);
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
hw_intf = kzalloc(sizeof(*hw_intf), GFP_KERNEL);
|
hw_intf = kzalloc(sizeof(*hw_intf), GFP_KERNEL);
|
||||||
if (!hw_intf) {
|
if (!hw_intf) {
|
||||||
rc = -ENOMEM;
|
rc = -ENOMEM;
|
||||||
@@ -43,8 +57,6 @@ static int cam_ife_csid_component_bind(struct device *dev,
|
|||||||
goto free_hw_intf;
|
goto free_hw_intf;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* get ife csid hw index */
|
|
||||||
of_property_read_u32(pdev->dev.of_node, "cell-index", &csid_dev_idx);
|
|
||||||
/* get ife csid hw information */
|
/* get ife csid hw information */
|
||||||
match_dev = of_match_device(pdev->dev.driver->of_match_table,
|
match_dev = of_match_device(pdev->dev.driver->of_match_table,
|
||||||
&pdev->dev);
|
&pdev->dev);
|
||||||
@@ -65,14 +77,6 @@ static int cam_ife_csid_component_bind(struct device *dev,
|
|||||||
|
|
||||||
csid_core_info = (struct cam_ife_csid_core_info *)match_dev->data;
|
csid_core_info = (struct cam_ife_csid_core_info *)match_dev->data;
|
||||||
|
|
||||||
if (!cam_cpas_is_feature_supported(CAM_CPAS_ISP_FUSE,
|
|
||||||
(1 << hw_intf->hw_idx), NULL) ||
|
|
||||||
!cam_cpas_is_feature_supported(CAM_CPAS_ISP_LITE_FUSE,
|
|
||||||
(1 << hw_intf->hw_idx), NULL)) {
|
|
||||||
CAM_DBG(CAM_ISP, "CSID[%d] not supported based on fuse",
|
|
||||||
csid_dev_idx);
|
|
||||||
goto free_hw_info;
|
|
||||||
}
|
|
||||||
/* call the driver init and fill csid_hw_info->core_info */
|
/* call the driver init and fill csid_hw_info->core_info */
|
||||||
rc = cam_ife_csid_hw_probe_init(hw_intf, csid_core_info, false);
|
rc = cam_ife_csid_hw_probe_init(hw_intf, csid_core_info, false);
|
||||||
|
|
||||||
|
@@ -356,6 +356,15 @@ struct cam_sfe_acquire_args {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* cam_sfe_get_num_hws()
|
||||||
|
*
|
||||||
|
* @brief : Populates number of SFEs.
|
||||||
|
*
|
||||||
|
* @num_sfes : Fills number of SFEs in the address passed.
|
||||||
|
*/
|
||||||
|
void cam_sfe_get_num_hws(uint32_t *num_sfes);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* cam_sfe_hw_init()
|
* cam_sfe_hw_init()
|
||||||
*
|
*
|
||||||
|
@@ -408,6 +408,24 @@ struct cam_vfe_generic_debug_config {
|
|||||||
bool enable_ife_frame_irqs;
|
bool enable_ife_frame_irqs;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* cam_vfe_get_num_ifes()
|
||||||
|
*
|
||||||
|
* @brief: Gets number of IFEs
|
||||||
|
*
|
||||||
|
* @num_ifes: Fills number of IFES in the address passed
|
||||||
|
*/
|
||||||
|
void cam_vfe_get_num_ifes(uint32_t *num_ifes);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* cam_vfe_get_num_ife_lites()
|
||||||
|
*
|
||||||
|
* @brief: Gets number of IFE-LITEs
|
||||||
|
*
|
||||||
|
* @num_ifes: Fills number of IFE-LITES in the address passed
|
||||||
|
*/
|
||||||
|
void cam_vfe_get_num_ife_lites(uint32_t *num_ife_lites);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* cam_vfe_hw_init()
|
* cam_vfe_hw_init()
|
||||||
*
|
*
|
||||||
|
@@ -1,13 +1,14 @@
|
|||||||
// SPDX-License-Identifier: GPL-2.0-only
|
// SPDX-License-Identifier: GPL-2.0-only
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2020-2021, The Linux Foundation. All rights reserved.
|
* Copyright (c) 2020-2021, The Linux Foundation. All rights reserved.
|
||||||
* Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
|
* Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <linux/slab.h>
|
#include <linux/slab.h>
|
||||||
#include <linux/mod_devicetable.h>
|
#include <linux/mod_devicetable.h>
|
||||||
#include <linux/of_device.h>
|
#include <linux/of_device.h>
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
|
#include <dt-bindings/msm-camera.h>
|
||||||
#include "cam_sfe_dev.h"
|
#include "cam_sfe_dev.h"
|
||||||
#include "cam_sfe_core.h"
|
#include "cam_sfe_core.h"
|
||||||
#include "cam_sfe_soc.h"
|
#include "cam_sfe_soc.h"
|
||||||
@@ -18,6 +19,7 @@
|
|||||||
#include "camera_main.h"
|
#include "camera_main.h"
|
||||||
|
|
||||||
static struct cam_isp_hw_intf_data cam_sfe_hw_list[CAM_SFE_HW_NUM_MAX];
|
static struct cam_isp_hw_intf_data cam_sfe_hw_list[CAM_SFE_HW_NUM_MAX];
|
||||||
|
static uint32_t g_num_sfe_hws;
|
||||||
|
|
||||||
static int cam_sfe_component_bind(struct device *dev,
|
static int cam_sfe_component_bind(struct device *dev,
|
||||||
struct device *master_dev, void *data)
|
struct device *master_dev, void *data)
|
||||||
@@ -30,18 +32,28 @@ static int cam_sfe_component_bind(struct device *dev,
|
|||||||
struct cam_sfe_hw_info *hw_info = NULL;
|
struct cam_sfe_hw_info *hw_info = NULL;
|
||||||
struct platform_device *pdev = NULL;
|
struct platform_device *pdev = NULL;
|
||||||
struct cam_sfe_soc_private *soc_priv;
|
struct cam_sfe_soc_private *soc_priv;
|
||||||
|
uint32_t sfe_dev_idx;
|
||||||
int i, rc = 0;
|
int i, rc = 0;
|
||||||
|
|
||||||
pdev = to_platform_device(dev);
|
pdev = to_platform_device(dev);
|
||||||
|
|
||||||
|
rc = of_property_read_u32(pdev->dev.of_node, "cell-index", &sfe_dev_idx);
|
||||||
|
if (rc) {
|
||||||
|
CAM_ERR(CAM_SFE, "Failed to read cell-index of SFE HW, rc: %d", rc);
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!cam_cpas_is_feature_supported(CAM_CPAS_SFE_FUSE, BIT(sfe_dev_idx), NULL)) {
|
||||||
|
CAM_DBG(CAM_SFE, "SFE:%d is not supported", sfe_dev_idx);
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
|
||||||
sfe_hw_intf = kzalloc(sizeof(struct cam_hw_intf), GFP_KERNEL);
|
sfe_hw_intf = kzalloc(sizeof(struct cam_hw_intf), GFP_KERNEL);
|
||||||
if (!sfe_hw_intf) {
|
if (!sfe_hw_intf) {
|
||||||
rc = -ENOMEM;
|
rc = -ENOMEM;
|
||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
|
|
||||||
of_property_read_u32(pdev->dev.of_node,
|
|
||||||
"cell-index", &sfe_hw_intf->hw_idx);
|
|
||||||
|
|
||||||
sfe_info = kzalloc(sizeof(struct cam_hw_info), GFP_KERNEL);
|
sfe_info = kzalloc(sizeof(struct cam_hw_info), GFP_KERNEL);
|
||||||
if (!sfe_info) {
|
if (!sfe_info) {
|
||||||
rc = -ENOMEM;
|
rc = -ENOMEM;
|
||||||
@@ -52,6 +64,7 @@ static int cam_sfe_component_bind(struct device *dev,
|
|||||||
sfe_info->soc_info.dev = &pdev->dev;
|
sfe_info->soc_info.dev = &pdev->dev;
|
||||||
sfe_info->soc_info.dev_name = pdev->name;
|
sfe_info->soc_info.dev_name = pdev->name;
|
||||||
sfe_hw_intf->hw_priv = sfe_info;
|
sfe_hw_intf->hw_priv = sfe_info;
|
||||||
|
sfe_hw_intf->hw_idx = sfe_dev_idx;
|
||||||
sfe_hw_intf->hw_ops.get_hw_caps = cam_sfe_get_hw_caps;
|
sfe_hw_intf->hw_ops.get_hw_caps = cam_sfe_get_hw_caps;
|
||||||
sfe_hw_intf->hw_ops.init = cam_sfe_init_hw;
|
sfe_hw_intf->hw_ops.init = cam_sfe_init_hw;
|
||||||
sfe_hw_intf->hw_ops.deinit = cam_sfe_deinit_hw;
|
sfe_hw_intf->hw_ops.deinit = cam_sfe_deinit_hw;
|
||||||
@@ -196,11 +209,21 @@ const static struct component_ops cam_sfe_component_ops = {
|
|||||||
.unbind = cam_sfe_component_unbind,
|
.unbind = cam_sfe_component_unbind,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
void cam_sfe_get_num_hws(uint32_t *sfe_num)
|
||||||
|
{
|
||||||
|
if (sfe_num)
|
||||||
|
*sfe_num = g_num_sfe_hws;
|
||||||
|
else
|
||||||
|
CAM_ERR(CAM_SFE, "Invalid argument, g_num_sfe_hws: %u", g_num_sfe_hws);
|
||||||
|
}
|
||||||
|
|
||||||
int cam_sfe_probe(struct platform_device *pdev)
|
int cam_sfe_probe(struct platform_device *pdev)
|
||||||
{
|
{
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
|
|
||||||
CAM_DBG(CAM_SFE, "Adding SFE component");
|
CAM_DBG(CAM_SFE, "Adding SFE component");
|
||||||
|
g_num_sfe_hws++;
|
||||||
|
|
||||||
rc = component_add(&pdev->dev, &cam_sfe_component_ops);
|
rc = component_add(&pdev->dev, &cam_sfe_component_ops);
|
||||||
if (rc)
|
if (rc)
|
||||||
CAM_ERR(CAM_SFE, "failed to add component rc: %d", rc);
|
CAM_ERR(CAM_SFE, "failed to add component rc: %d", rc);
|
||||||
|
@@ -1,6 +1,7 @@
|
|||||||
// SPDX-License-Identifier: GPL-2.0-only
|
// SPDX-License-Identifier: GPL-2.0-only
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2017-2021, The Linux Foundation. All rights reserved.
|
* Copyright (c) 2017-2021, The Linux Foundation. All rights reserved.
|
||||||
|
* Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
@@ -9,13 +10,13 @@
|
|||||||
#include <linux/of_device.h>
|
#include <linux/of_device.h>
|
||||||
#include <linux/component.h>
|
#include <linux/component.h>
|
||||||
|
|
||||||
#include "cam_vfe_dev.h"
|
|
||||||
#include "cam_vfe_core.h"
|
#include "cam_vfe_core.h"
|
||||||
#include "cam_vfe_soc.h"
|
#include "cam_vfe_soc.h"
|
||||||
#include "cam_debug_util.h"
|
#include "cam_debug_util.h"
|
||||||
#include <dt-bindings/msm-camera.h>
|
#include <dt-bindings/msm-camera.h>
|
||||||
|
|
||||||
static struct cam_isp_hw_intf_data cam_vfe_hw_list[CAM_VFE_HW_NUM_MAX];
|
static struct cam_isp_hw_intf_data cam_vfe_hw_list[CAM_VFE_HW_NUM_MAX];
|
||||||
|
static uint32_t g_num_ife_hws, g_num_ife_lite_hws;
|
||||||
|
|
||||||
static int cam_vfe_component_bind(struct device *dev,
|
static int cam_vfe_component_bind(struct device *dev,
|
||||||
struct device *master_dev, void *data)
|
struct device *master_dev, void *data)
|
||||||
@@ -28,26 +29,28 @@ static int cam_vfe_component_bind(struct device *dev,
|
|||||||
int rc = 0;
|
int rc = 0;
|
||||||
struct platform_device *pdev = to_platform_device(dev);
|
struct platform_device *pdev = to_platform_device(dev);
|
||||||
struct cam_vfe_soc_private *vfe_soc_priv;
|
struct cam_vfe_soc_private *vfe_soc_priv;
|
||||||
|
uint32_t vfe_dev_idx;
|
||||||
uint32_t i;
|
uint32_t i;
|
||||||
|
|
||||||
|
rc = of_property_read_u32(pdev->dev.of_node, "cell-index", &vfe_dev_idx);
|
||||||
|
if (rc) {
|
||||||
|
CAM_ERR(CAM_ISP, "Failed to read cell-index of IFE HW, rc: %d", rc);
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!cam_cpas_is_feature_supported(CAM_CPAS_ISP_FUSE, BIT(vfe_dev_idx), NULL) ||
|
||||||
|
!cam_cpas_is_feature_supported(CAM_CPAS_ISP_LITE_FUSE,
|
||||||
|
BIT(vfe_dev_idx), NULL)) {
|
||||||
|
CAM_DBG(CAM_ISP, "IFE:%d is not supported", vfe_dev_idx);
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
|
||||||
vfe_hw_intf = kzalloc(sizeof(struct cam_hw_intf), GFP_KERNEL);
|
vfe_hw_intf = kzalloc(sizeof(struct cam_hw_intf), GFP_KERNEL);
|
||||||
if (!vfe_hw_intf) {
|
if (!vfe_hw_intf) {
|
||||||
rc = -ENOMEM;
|
rc = -ENOMEM;
|
||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
|
|
||||||
of_property_read_u32(pdev->dev.of_node,
|
|
||||||
"cell-index", &vfe_hw_intf->hw_idx);
|
|
||||||
|
|
||||||
if (!cam_cpas_is_feature_supported(CAM_CPAS_ISP_FUSE,
|
|
||||||
(1 << vfe_hw_intf->hw_idx), 0) ||
|
|
||||||
!cam_cpas_is_feature_supported(CAM_CPAS_ISP_LITE_FUSE,
|
|
||||||
(1 << vfe_hw_intf->hw_idx), 0)) {
|
|
||||||
CAM_DBG(CAM_ISP, "IFE:%d is not supported",
|
|
||||||
vfe_hw_intf->hw_idx);
|
|
||||||
goto free_vfe_hw_intf;
|
|
||||||
}
|
|
||||||
|
|
||||||
vfe_hw = kzalloc(sizeof(struct cam_hw_info), GFP_KERNEL);
|
vfe_hw = kzalloc(sizeof(struct cam_hw_info), GFP_KERNEL);
|
||||||
if (!vfe_hw) {
|
if (!vfe_hw) {
|
||||||
rc = -ENOMEM;
|
rc = -ENOMEM;
|
||||||
@@ -58,6 +61,7 @@ static int cam_vfe_component_bind(struct device *dev,
|
|||||||
vfe_hw->soc_info.dev = &pdev->dev;
|
vfe_hw->soc_info.dev = &pdev->dev;
|
||||||
vfe_hw->soc_info.dev_name = pdev->name;
|
vfe_hw->soc_info.dev_name = pdev->name;
|
||||||
vfe_hw_intf->hw_priv = vfe_hw;
|
vfe_hw_intf->hw_priv = vfe_hw;
|
||||||
|
vfe_hw_intf->hw_idx = vfe_dev_idx;
|
||||||
vfe_hw_intf->hw_ops.get_hw_caps = cam_vfe_get_hw_caps;
|
vfe_hw_intf->hw_ops.get_hw_caps = cam_vfe_get_hw_caps;
|
||||||
vfe_hw_intf->hw_ops.init = cam_vfe_init_hw;
|
vfe_hw_intf->hw_ops.init = cam_vfe_init_hw;
|
||||||
vfe_hw_intf->hw_ops.deinit = cam_vfe_deinit_hw;
|
vfe_hw_intf->hw_ops.deinit = cam_vfe_deinit_hw;
|
||||||
@@ -199,11 +203,44 @@ const static struct component_ops cam_vfe_component_ops = {
|
|||||||
.unbind = cam_vfe_component_unbind,
|
.unbind = cam_vfe_component_unbind,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
void cam_vfe_get_num_ifes(uint32_t *num_ifes)
|
||||||
|
{
|
||||||
|
if (num_ifes)
|
||||||
|
*num_ifes = g_num_ife_hws;
|
||||||
|
else
|
||||||
|
CAM_ERR(CAM_ISP, "Invalid argument, g_num_ife_hws: %u", g_num_ife_hws);
|
||||||
|
}
|
||||||
|
|
||||||
|
void cam_vfe_get_num_ife_lites(uint32_t *num_ife_lites)
|
||||||
|
{
|
||||||
|
if (num_ife_lites)
|
||||||
|
*num_ife_lites = g_num_ife_lite_hws;
|
||||||
|
else
|
||||||
|
CAM_ERR(CAM_ISP, "Invalid argument, g_num_ife_lite_hws: %u", g_num_ife_lite_hws);
|
||||||
|
}
|
||||||
|
|
||||||
int cam_vfe_probe(struct platform_device *pdev)
|
int cam_vfe_probe(struct platform_device *pdev)
|
||||||
{
|
{
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
|
const char *compatible_name;
|
||||||
|
struct device_node *of_node = NULL;
|
||||||
|
|
||||||
CAM_DBG(CAM_ISP, "Adding VFE component");
|
CAM_DBG(CAM_ISP, "Adding VFE component");
|
||||||
|
of_node = pdev->dev.of_node;
|
||||||
|
|
||||||
|
rc = of_property_read_string_index(of_node, "compatible", 0,
|
||||||
|
(const char **)&compatible_name);
|
||||||
|
if (rc)
|
||||||
|
CAM_ERR(CAM_ISP, "No compatible string present for: %s, rc: %d",
|
||||||
|
pdev->name, rc);
|
||||||
|
|
||||||
|
if (strnstr(compatible_name, "lite", strlen(compatible_name)) != NULL)
|
||||||
|
g_num_ife_lite_hws++;
|
||||||
|
else if (strnstr(compatible_name, "vfe", strlen(compatible_name)) != NULL)
|
||||||
|
g_num_ife_hws++;
|
||||||
|
else
|
||||||
|
CAM_ERR(CAM_ISP, "Failed to increment number of IFEs/IFE-LITEs");
|
||||||
|
|
||||||
rc = component_add(&pdev->dev, &cam_vfe_component_ops);
|
rc = component_add(&pdev->dev, &cam_vfe_component_ops);
|
||||||
if (rc)
|
if (rc)
|
||||||
CAM_ERR(CAM_ISP, "failed to add component rc: %d", rc);
|
CAM_ERR(CAM_ISP, "failed to add component rc: %d", rc);
|
||||||
|
@@ -10,6 +10,7 @@
|
|||||||
#include <linux/slab.h>
|
#include <linux/slab.h>
|
||||||
|
|
||||||
#include <soc/qcom/rpmh.h>
|
#include <soc/qcom/rpmh.h>
|
||||||
|
#include <soc/qcom/socinfo.h>
|
||||||
|
|
||||||
#include "cam_compat.h"
|
#include "cam_compat.h"
|
||||||
#include "cam_debug_util.h"
|
#include "cam_debug_util.h"
|
||||||
@@ -819,3 +820,33 @@ bool cam_secure_get_vfe_fd_port_config(void)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if KERNEL_VERSION(5, 10, 0) <= LINUX_VERSION_CODE
|
||||||
|
int cam_get_subpart_info(uint32_t *part_info, uint32_t max_num_cam)
|
||||||
|
{
|
||||||
|
int rc = 0;
|
||||||
|
int num_cam;
|
||||||
|
|
||||||
|
num_cam = socinfo_get_part_count(PART_CAMERA);
|
||||||
|
if (num_cam != max_num_cam) {
|
||||||
|
CAM_ERR(CAM_CPAS, "Unsupported number of parts: %d", num_cam);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If bit value in part_info is "0" then HW is available.
|
||||||
|
* If bit value in part_info is "1" then HW is unavailable.
|
||||||
|
*/
|
||||||
|
rc = socinfo_get_subpart_info(PART_CAMERA, part_info, num_cam);
|
||||||
|
if (rc) {
|
||||||
|
CAM_ERR(CAM_CPAS, "Failed while getting subpart_info, rc = %d.", rc);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
int cam_get_subpart_info(uint32_t *part_info, uint32_t max_num_cam)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
@@ -113,4 +113,6 @@ unsigned long cam_update_dma_map_attributes(unsigned long attr);
|
|||||||
|
|
||||||
size_t cam_align_dma_buf_size(size_t len);
|
size_t cam_align_dma_buf_size(size_t len);
|
||||||
|
|
||||||
|
int cam_get_subpart_info(uint32_t *part_info, uint32_t max_num_cam);
|
||||||
|
|
||||||
#endif /* _CAM_COMPAT_H_ */
|
#endif /* _CAM_COMPAT_H_ */
|
||||||
|
@@ -115,7 +115,10 @@
|
|||||||
#define CAM_CPAS_ISP_LITE_FUSE 6
|
#define CAM_CPAS_ISP_LITE_FUSE 6
|
||||||
#define CAM_CPAS_CSIPHY_FUSE 7
|
#define CAM_CPAS_CSIPHY_FUSE 7
|
||||||
#define CAM_CPAS_IPE_VID_OUT_8BPP_LIMIT_ENABLE 8
|
#define CAM_CPAS_IPE_VID_OUT_8BPP_LIMIT_ENABLE 8
|
||||||
#define CAM_CPAS_FUSE_FEATURE_MAX 9
|
#define CAM_CPAS_SFE_FUSE 9
|
||||||
|
#define CAM_CPAS_CUSTOM_FUSE 10
|
||||||
|
#define CAM_CPAS_CAM_FUSE 11
|
||||||
|
#define CAM_CPAS_FUSE_FEATURE_MAX 12
|
||||||
|
|
||||||
#define CCI_MASTER_0 0
|
#define CCI_MASTER_0 0
|
||||||
#define CCI_MASTER_1 1
|
#define CCI_MASTER_1 1
|
||||||
|
@@ -99,6 +99,9 @@
|
|||||||
#define CAM_CPAS_NON_SECURE_DOMAIN 0
|
#define CAM_CPAS_NON_SECURE_DOMAIN 0
|
||||||
#define CAM_CPAS_SECURE_DOMAIN 1
|
#define CAM_CPAS_SECURE_DOMAIN 1
|
||||||
|
|
||||||
|
/* sysfs entry of camera subparts info */
|
||||||
|
#define CAM_SYSFS_SUBPARTS_INFO_FILENAME "subparts_info"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* struct cam_cpas_fuse_value - CPAS fuse value
|
* struct cam_cpas_fuse_value - CPAS fuse value
|
||||||
*
|
*
|
||||||
|
Reference in New Issue
Block a user