msm: camera: common: Add support for DRV config
Add DRV config blob handling for programming required registers per request. Also, add debugfs entry for disabling DRV feature from ife hw manager. Update existing BW voting logs to reflect DRV vote level info. Add support for communicating with rsc device upon update in MNOC BW. Also, update BW voting logic in cpas to accommodate DRV voting to interconnect framework. CRs-Fixed: 3065551 Change-Id: I8ac4820b7af824f5ff46614ae6804001deca9b01 Signed-off-by: Mukund Madhusudan Atre <quic_matre@quicinc.com>
This commit is contained in:

committato da
Camera Software Integration

parent
c73578236c
commit
65878f05bb
@@ -9,11 +9,107 @@
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
#include <soc/qcom/rpmh.h>
|
||||
|
||||
#include "cam_compat.h"
|
||||
#include "cam_debug_util.h"
|
||||
#include "cam_cpas_api.h"
|
||||
#include "camera_main.h"
|
||||
|
||||
#if IS_ENABLED(CONFIG_USE_RPMH_DRV_API)
|
||||
#define CAM_RSC_DRV_IDENTIFIER "cam_rsc"
|
||||
|
||||
const struct device *cam_cpas_get_rsc_dev_for_drv(uint32_t index)
|
||||
{
|
||||
const struct device *rsc_dev;
|
||||
|
||||
rsc_dev = rpmh_get_device(CAM_RSC_DRV_IDENTIFIER, index);
|
||||
if (!rsc_dev) {
|
||||
CAM_ERR(CAM_CPAS, "Invalid dev for index: %u", index);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return rsc_dev;
|
||||
}
|
||||
|
||||
int cam_cpas_start_drv_for_dev(const struct device *dev)
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
if (!dev) {
|
||||
CAM_ERR(CAM_CPAS, "Invalid dev for DRV enable");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
rc = rpmh_drv_start(dev);
|
||||
if (rc) {
|
||||
CAM_ERR(CAM_CPAS, "[%s] Failed in DRV start", dev_name(dev));
|
||||
return rc;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
int cam_cpas_stop_drv_for_dev(const struct device *dev)
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
if (!dev) {
|
||||
CAM_ERR(CAM_CPAS, "Invalid dev for DRV disable");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
rc = rpmh_drv_stop(dev);
|
||||
if (rc) {
|
||||
CAM_ERR(CAM_CPAS, "[%s] Failed in DRV stop", dev_name(dev));
|
||||
return rc;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
int cam_cpas_drv_channel_switch_for_dev(const struct device *dev)
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
if (!dev) {
|
||||
CAM_ERR(CAM_CPAS, "Invalid dev for DRV channel switch");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
rc = rpmh_write_sleep_and_wake_no_child(dev);
|
||||
if (rc) {
|
||||
CAM_ERR(CAM_CPAS, "[%s] Failed in DRV channel switch", dev_name(dev));
|
||||
return rc;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
#else
|
||||
const struct device *cam_cpas_get_rsc_dev_for_drv(uint32_t index)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int cam_cpas_start_drv_for_dev(const struct device *dev)
|
||||
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int cam_cpas_stop_drv_for_dev(const struct device *dev)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int cam_cpas_drv_channel_switch_for_dev(const struct device *dev)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 4, 0)
|
||||
int cam_reserve_icp_fw(struct cam_fw_alloc_info *icp_fw, size_t fw_length)
|
||||
{
|
||||
|
@@ -55,6 +55,14 @@ void cam_compat_util_put_dmabuf_va(struct dma_buf *dmabuf, void *vaddr);
|
||||
void cam_smmu_util_iommu_custom(struct device *dev,
|
||||
dma_addr_t discard_start, size_t discard_length);
|
||||
|
||||
const struct device *cam_cpas_get_rsc_dev_for_drv(uint32_t index);
|
||||
|
||||
int cam_cpas_start_drv_for_dev(const struct device *dev);
|
||||
|
||||
int cam_cpas_stop_drv_for_dev(const struct device *dev);
|
||||
|
||||
int cam_cpas_drv_channel_switch_for_dev(const struct device *dev);
|
||||
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 15, 0)
|
||||
int cam_req_mgr_ordered_list_cmp(void *priv,
|
||||
const struct list_head *head_1, const struct list_head *head_2);
|
||||
|
@@ -1,6 +1,7 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright (c) 2019-2020, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <linux/msm-bus.h>
|
||||
@@ -65,7 +66,8 @@ end:
|
||||
return rc;
|
||||
}
|
||||
|
||||
int cam_soc_bus_client_update_bw(void *client, uint64_t ab, uint64_t ib)
|
||||
int cam_soc_bus_client_update_bw(void *client, uint64_t ab, uint64_t ib,
|
||||
enum cam_soc_bus_path_data bus_path_data)
|
||||
{
|
||||
int idx = 0;
|
||||
struct msm_bus_paths *path;
|
||||
|
@@ -1,6 +1,7 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2019, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef _CAM_SOC_BUS_H_
|
||||
@@ -10,9 +11,17 @@
|
||||
#include <linux/slab.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include "cam_debug_util.h"
|
||||
#include "cam_cpas.h"
|
||||
|
||||
#define CAM_SOC_BUS_MAX_NUM_USECASES 8
|
||||
|
||||
enum cam_soc_bus_path_data {
|
||||
CAM_SOC_BUS_PATH_DATA_HLOS,
|
||||
CAM_SOC_BUS_PATH_DATA_DRV_HIGH,
|
||||
CAM_SOC_BUS_PATH_DATA_DRV_LOW,
|
||||
CAM_SOC_BUS_PATH_DATA_MAX,
|
||||
};
|
||||
|
||||
/**
|
||||
* struct cam_soc_bus_client_ab_ib : Bandwidth values for selected usecase
|
||||
*
|
||||
@@ -30,6 +39,7 @@ struct cam_soc_bus_client_ab_ib {
|
||||
* @name: Name of bus client
|
||||
* @src_id: Bus master/src id
|
||||
* @dst_id: Bus slave/dst id
|
||||
* @is_drv_port: If DRV bus client
|
||||
* @num_usecases: Number of use cases for this client
|
||||
* @bw_pair: Bandwidth values for applicable usecases
|
||||
*/
|
||||
@@ -37,6 +47,7 @@ struct cam_soc_bus_client_common_data {
|
||||
const char *name;
|
||||
uint32_t src_id;
|
||||
uint32_t dst_id;
|
||||
bool is_drv_port;
|
||||
int num_usecases;
|
||||
struct cam_soc_bus_client_ab_ib bw_pair[CAM_SOC_BUS_MAX_NUM_USECASES];
|
||||
};
|
||||
@@ -56,10 +67,12 @@ struct cam_soc_bus_client {
|
||||
#if IS_REACHABLE(CONFIG_QCOM_BUS_SCALING) || \
|
||||
IS_REACHABLE(CONFIG_INTERCONNECT_QCOM)
|
||||
|
||||
const char *cam_soc_bus_path_data_to_str(enum cam_soc_bus_path_data bus_path_data);
|
||||
|
||||
int cam_soc_bus_client_update_request(void *client, unsigned int idx);
|
||||
|
||||
int cam_soc_bus_client_update_bw(void *client, uint64_t ab,
|
||||
uint64_t ib);
|
||||
int cam_soc_bus_client_update_bw(void *client, uint64_t ab, uint64_t ib,
|
||||
enum cam_soc_bus_path_data bus_path_data);
|
||||
|
||||
int cam_soc_bus_client_register(struct platform_device *pdev,
|
||||
struct device_node *dev_node, void **client,
|
||||
@@ -68,14 +81,20 @@ int cam_soc_bus_client_register(struct platform_device *pdev,
|
||||
void cam_soc_bus_client_unregister(void **client);
|
||||
|
||||
#else
|
||||
|
||||
static const char *cam_soc_bus_path_data_to_str(enum cam_soc_bus_path_data bus_path_data)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static inline int cam_soc_bus_client_update_request(void *client,
|
||||
unsigned int idx)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int cam_soc_bus_client_update_bw(void *client,
|
||||
uint64_t ab, uint64_t ib)
|
||||
int cam_soc_bus_client_update_bw(void *client, uint64_t ab, uint64_t ib,
|
||||
enum cam_soc_bus_path_data bus_path_data)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
@@ -1,9 +1,11 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright (c) 2019-2021, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <linux/interconnect.h>
|
||||
#include <dt-bindings/interconnect/qcom,icc.h>
|
||||
#include "cam_soc_bus.h"
|
||||
|
||||
/**
|
||||
@@ -12,9 +14,22 @@
|
||||
* @icc_data: Bus icc path information
|
||||
*/
|
||||
struct cam_soc_bus_client_data {
|
||||
struct icc_path *icc_data;
|
||||
struct icc_path *icc_data[CAM_SOC_BUS_PATH_DATA_MAX];
|
||||
};
|
||||
|
||||
const char *cam_soc_bus_path_data_to_str(enum cam_soc_bus_path_data bus_path_data)
|
||||
{
|
||||
switch (bus_path_data) {
|
||||
case CAM_SOC_BUS_PATH_DATA_HLOS:
|
||||
return "BUS_PATH_HLOS";
|
||||
case CAM_SOC_BUS_PATH_DATA_DRV_HIGH:
|
||||
return "BUS_PATH_DRV_HIGH";
|
||||
case CAM_SOC_BUS_PATH_DATA_DRV_LOW:
|
||||
return "BUS_PATH_DRV_LOW";
|
||||
default:
|
||||
return "BUS_PATH_INVALID";
|
||||
}
|
||||
}
|
||||
int cam_soc_bus_client_update_request(void *client, unsigned int idx)
|
||||
{
|
||||
int rc = 0;
|
||||
@@ -37,7 +52,7 @@ int cam_soc_bus_client_update_request(void *client, unsigned int idx)
|
||||
CAM_DBG(CAM_PERF, "Bus client=[%s] index[%d] ab[%llu] ib[%llu]",
|
||||
bus_client->common_data->name, idx, ab, ib);
|
||||
|
||||
rc = icc_set_bw(bus_client_data->icc_data, Bps_to_icc(ab),
|
||||
rc = icc_set_bw(bus_client_data->icc_data[CAM_SOC_BUS_PATH_DATA_HLOS], Bps_to_icc(ab),
|
||||
Bps_to_icc(ib));
|
||||
if (rc) {
|
||||
CAM_ERR(CAM_UTIL,
|
||||
@@ -50,26 +65,29 @@ end:
|
||||
return rc;
|
||||
}
|
||||
|
||||
int cam_soc_bus_client_update_bw(void *client, uint64_t ab, uint64_t ib)
|
||||
int cam_soc_bus_client_update_bw(void *client, uint64_t ab, uint64_t ib,
|
||||
enum cam_soc_bus_path_data bus_path_data)
|
||||
{
|
||||
struct cam_soc_bus_client *bus_client =
|
||||
(struct cam_soc_bus_client *) client;
|
||||
struct cam_soc_bus_client_data *bus_client_data =
|
||||
(struct cam_soc_bus_client_data *) bus_client->client_data;
|
||||
int rc = 0;
|
||||
struct cam_soc_bus_client *bus_client =
|
||||
(struct cam_soc_bus_client *) client;
|
||||
struct cam_soc_bus_client_data *bus_client_data =
|
||||
(struct cam_soc_bus_client_data *) bus_client->client_data;
|
||||
int rc = 0;
|
||||
|
||||
CAM_DBG(CAM_PERF, "Bus client=[%s] :ab[%llu] ib[%llu]",
|
||||
bus_client->common_data->name, ab, ib);
|
||||
rc = icc_set_bw(bus_client_data->icc_data, Bps_to_icc(ab),
|
||||
Bps_to_icc(ib));
|
||||
if (rc) {
|
||||
CAM_ERR(CAM_UTIL, "Update request failed, client[%s]",
|
||||
bus_client->common_data->name);
|
||||
goto end;
|
||||
}
|
||||
CAM_DBG(CAM_PERF, "Bus client=[%s] [%s] :ab[%llu] ib[%llu]",
|
||||
bus_client->common_data->name, cam_soc_bus_path_data_to_str(bus_path_data),
|
||||
ab, ib);
|
||||
rc = icc_set_bw(bus_client_data->icc_data[bus_path_data], Bps_to_icc(ab),
|
||||
Bps_to_icc(ib));
|
||||
if (rc) {
|
||||
CAM_ERR(CAM_UTIL, "Update request failed, client[%s]",
|
||||
bus_client->common_data->name);
|
||||
goto end;
|
||||
}
|
||||
|
||||
end:
|
||||
return rc;
|
||||
|
||||
}
|
||||
|
||||
int cam_soc_bus_client_register(struct platform_device *pdev,
|
||||
@@ -89,8 +107,7 @@ int cam_soc_bus_client_register(struct platform_device *pdev,
|
||||
|
||||
*client = bus_client;
|
||||
|
||||
bus_client_data = kzalloc(sizeof(struct cam_soc_bus_client_data),
|
||||
GFP_KERNEL);
|
||||
bus_client_data = kzalloc(sizeof(struct cam_soc_bus_client_data), GFP_KERNEL);
|
||||
if (!bus_client_data) {
|
||||
kfree(bus_client);
|
||||
*client = NULL;
|
||||
@@ -100,30 +117,80 @@ int cam_soc_bus_client_register(struct platform_device *pdev,
|
||||
|
||||
bus_client->client_data = bus_client_data;
|
||||
bus_client->common_data = common_data;
|
||||
bus_client_data->icc_data = icc_get(&pdev->dev,
|
||||
bus_client->common_data->src_id,
|
||||
bus_client->common_data->dst_id);
|
||||
if (IS_ERR_OR_NULL(bus_client_data->icc_data)) {
|
||||
CAM_ERR(CAM_UTIL, "failed in register bus client");
|
||||
rc = -EINVAL;
|
||||
goto error;
|
||||
if (bus_client->common_data->is_drv_port) {
|
||||
bus_client_data->icc_data[CAM_SOC_BUS_PATH_DATA_DRV_HIGH] = icc_get(&pdev->dev,
|
||||
bus_client->common_data->src_id, bus_client->common_data->dst_id);
|
||||
if (IS_ERR_OR_NULL(bus_client_data->icc_data[CAM_SOC_BUS_PATH_DATA_DRV_HIGH])) {
|
||||
CAM_ERR(CAM_UTIL,
|
||||
"Failed to register DRV bus client Bus Client=[%s] : src=%d, dst=%d bus_path:%d",
|
||||
bus_client->common_data->src_id, bus_client->common_data->dst_id,
|
||||
CAM_SOC_BUS_PATH_DATA_DRV_HIGH);
|
||||
rc = -EINVAL;
|
||||
goto error;
|
||||
}
|
||||
|
||||
bus_client_data->icc_data[CAM_SOC_BUS_PATH_DATA_DRV_LOW] = icc_get(&pdev->dev,
|
||||
bus_client->common_data->src_id, bus_client->common_data->dst_id);
|
||||
if (IS_ERR_OR_NULL(bus_client_data->icc_data[CAM_SOC_BUS_PATH_DATA_DRV_LOW])) {
|
||||
CAM_ERR(CAM_UTIL,
|
||||
"Failed to register DRV bus client Bus Client=[%s] : src=%d, dst=%d bus_path:%d",
|
||||
bus_client->common_data->src_id, bus_client->common_data->dst_id,
|
||||
CAM_SOC_BUS_PATH_DATA_DRV_LOW);
|
||||
rc = -EINVAL;
|
||||
goto error;
|
||||
}
|
||||
|
||||
/* Set appropriate tags for HIGH and LOW vote paths */
|
||||
icc_set_tag(bus_client_data->icc_data[CAM_SOC_BUS_PATH_DATA_DRV_HIGH],
|
||||
QCOM_ICC_TAG_ACTIVE_ONLY);
|
||||
icc_set_tag(bus_client_data->icc_data[CAM_SOC_BUS_PATH_DATA_DRV_LOW],
|
||||
QCOM_ICC_TAG_SLEEP);
|
||||
|
||||
rc = icc_set_bw(bus_client_data->icc_data[CAM_SOC_BUS_PATH_DATA_DRV_HIGH], 0, 0);
|
||||
if (rc) {
|
||||
CAM_ERR(CAM_UTIL, "Bus client[%s] update request failed, rc = %d",
|
||||
bus_client->common_data->name, rc);
|
||||
goto fail_unregister_client;
|
||||
}
|
||||
|
||||
rc = icc_set_bw(bus_client_data->icc_data[CAM_SOC_BUS_PATH_DATA_DRV_LOW], 0, 0);
|
||||
if (rc) {
|
||||
CAM_ERR(CAM_UTIL, "Bus client[%s] update request failed, rc = %d",
|
||||
bus_client->common_data->name, rc);
|
||||
goto fail_unregister_client;
|
||||
}
|
||||
} else {
|
||||
bus_client_data->icc_data[CAM_SOC_BUS_PATH_DATA_HLOS] = icc_get(&pdev->dev,
|
||||
bus_client->common_data->src_id, bus_client->common_data->dst_id);
|
||||
if (IS_ERR_OR_NULL(bus_client_data->icc_data[CAM_SOC_BUS_PATH_DATA_HLOS])) {
|
||||
CAM_ERR(CAM_UTIL, "failed to register HLOS bus client");
|
||||
rc = -EINVAL;
|
||||
goto error;
|
||||
}
|
||||
|
||||
rc = icc_set_bw(bus_client_data->icc_data[CAM_SOC_BUS_PATH_DATA_HLOS], 0, 0);
|
||||
if (rc) {
|
||||
CAM_ERR(CAM_UTIL, "Bus client[%s] update request failed, rc = %d",
|
||||
bus_client->common_data->name, rc);
|
||||
goto fail_unregister_client;
|
||||
}
|
||||
}
|
||||
|
||||
rc = icc_set_bw(bus_client_data->icc_data, 0, 0);
|
||||
if (rc) {
|
||||
CAM_ERR(CAM_UTIL, "Bus client update request failed, rc = %d",
|
||||
rc);
|
||||
goto fail_unregister_client;
|
||||
}
|
||||
|
||||
CAM_DBG(CAM_PERF, "Register Bus Client=[%s] : src=%d, dst=%d",
|
||||
CAM_DBG(CAM_PERF, "Register Bus Client=[%s] : src=%d, dst=%d is_drv_port:%s",
|
||||
bus_client->common_data->name, bus_client->common_data->src_id,
|
||||
bus_client->common_data->dst_id);
|
||||
bus_client->common_data->dst_id,
|
||||
CAM_BOOL_TO_YESNO(bus_client->common_data->is_drv_port));
|
||||
|
||||
return 0;
|
||||
|
||||
fail_unregister_client:
|
||||
icc_put(bus_client_data->icc_data);
|
||||
if (bus_client->common_data->is_drv_port) {
|
||||
icc_put(bus_client_data->icc_data[CAM_SOC_BUS_PATH_DATA_DRV_HIGH]);
|
||||
icc_put(bus_client_data->icc_data[CAM_SOC_BUS_PATH_DATA_DRV_LOW]);
|
||||
} else {
|
||||
icc_put(bus_client_data->icc_data[CAM_SOC_BUS_PATH_DATA_HLOS]);
|
||||
}
|
||||
|
||||
error:
|
||||
kfree(bus_client_data);
|
||||
bus_client->client_data = NULL;
|
||||
@@ -141,7 +208,13 @@ void cam_soc_bus_client_unregister(void **client)
|
||||
struct cam_soc_bus_client_data *bus_client_data =
|
||||
(struct cam_soc_bus_client_data *) bus_client->client_data;
|
||||
|
||||
icc_put(bus_client_data->icc_data);
|
||||
if (bus_client->common_data->is_drv_port) {
|
||||
icc_put(bus_client_data->icc_data[CAM_SOC_BUS_PATH_DATA_DRV_HIGH]);
|
||||
icc_put(bus_client_data->icc_data[CAM_SOC_BUS_PATH_DATA_DRV_LOW]);
|
||||
} else {
|
||||
icc_put(bus_client_data->icc_data[CAM_SOC_BUS_PATH_DATA_HLOS]);
|
||||
}
|
||||
|
||||
kfree(bus_client_data);
|
||||
bus_client->client_data = NULL;
|
||||
kfree(bus_client);
|
||||
|
Fai riferimento in un nuovo problema
Block a user