|
发表于 2021-6-24 19:19:45
10009 浏览 0 回复
[FAQ22659] [Android Q] Camera Sensor Regulator Restricting voltage 的处理...
[DESCRIPTION]
Linux regulator framework允许针对某个LDO取得多个consumer regulator instance,并且会纪录该LDO使用的consumer list,安全起见会使用该list中电压设值最小的来供电,因此当不同regulator instance设定为不同电压时就会出现Restricting voltage这样的错误log:
关键log为 "Restricting voltage":
01-01 00:05:54.771655 517 517 E [ 124.722793].(0)[517:camerahalserver][name:core&]vcamd: Restricting voltage, 1200000-1100000uV
[SOLUTION]
Power off时一并释放regulator(Call regulator_put()),然后于power on时重新取得regulator。用这个做法时,需要注意确保thread safe,regulator取得与释放时需要互斥锁定。
当前的FAQ中提供了Android Q下MT6873和MT6765平台上的修改方案,其他平台可参考修改。
Android P下该问题的解决办法可以参考FAQ20676 [Android P] Camera Sensor Regulator Restricting voltage 的处理方法。
MT6873
- diff --git a/drivers/misc/mediatek/imgsensor/src/mt6873/camera_hw/regulator/regulator.c b/drivers/misc/mediatek/imgsensor/src/mt6873/camera_hw/regulator/regulator.c
- index 2132cc748f08..9de92138cd66
- --- a/drivers/misc/mediatek/imgsensor/src/mt6873/camera_hw/regulator/regulator.c
- +++ b/drivers/misc/mediatek/imgsensor/src/mt6873/camera_hw/regulator/regulator.c
- @@ -13,7 +13,17 @@
- #include "regulator.h"
- +static bool regulator_status[IMGSENSOR_SENSOR_IDX_MAX_NUM][
- + REGULATOR_TYPE_MAX_NUM] = {{false}};
- +static void check_for_regulator_get(struct REGULATOR *preg,
- + struct device *pdevice, unsigned int sensor_index,
- + unsigned int regulator_index);
- +static void check_for_regulator_put(struct REGULATOR *preg,
- + unsigned int sensor_index, unsigned int regulator_index);
- +static struct device_node *of_node_record;
- +static struct IMGSENSOR_HW_DEVICE_COMMON *ghw_device_common;
- +static DEFINE_MUTEX(g_regulator_state_mutex);
- static const int regulator_voltage[] = {
- REGULATOR_VOLTAGE_0,
- REGULATOR_VOLTAGE_1000,
- @@ -43,7 +53,10 @@ static enum IMGSENSOR_RETURN regulator_init(
- struct REGULATOR *preg = (struct REGULATOR *)pinstance;
- int type, idx;
- char str_regulator_name[LENGTH_FOR_SNPRINTF];
- -
- +
- + ghw_device_common = pcommon;
- + of_node_record = pcommon->pplatform_device->dev.of_node;
- +
- for (idx = IMGSENSOR_SENSOR_IDX_MIN_NUM;
- idx < IMGSENSOR_SENSOR_IDX_MAX_NUM;
- idx++) {
- @@ -113,7 +126,11 @@ static enum IMGSENSOR_RETURN regulator_set(
- return IMGSENSOR_RETURN_ERROR;
- reg_type_offset = REGULATOR_TYPE_VCAMA;
- -
- +
- + if (ghw_device_common)
- + check_for_regulator_get(preg, &ghw_device_common->pplatform_device->dev, sensor_idx,
- + (reg_type_offset + pin - IMGSENSOR_HW_PIN_AVDD));
- +
- pregulator =
- preg->pregulator[sensor_idx][
- reg_type_offset + pin - IMGSENSOR_HW_PIN_AVDD];
- @@ -142,6 +159,10 @@ static enum IMGSENSOR_RETURN regulator_set(
- pin,
- regulator_voltage[
- pin_state - IMGSENSOR_HW_PIN_STATE_LEVEL_0]);
- +
- + check_for_regulator_put(preg, sensor_idx,
- + (reg_type_offset + pin - IMGSENSOR_HW_PIN_AVDD));
- +
- return IMGSENSOR_RETURN_ERROR;
- }
- atomic_inc(enable_cnt);
- @@ -153,8 +174,16 @@ static enum IMGSENSOR_RETURN regulator_set(
- PK_PR_ERR(
- "[regulator]fail to regulator_disable, powertype: %d\n",
- pin);
- +
- + check_for_regulator_put(preg, sensor_idx,
- + (reg_type_offset + pin - IMGSENSOR_HW_PIN_AVDD));
- +
- return IMGSENSOR_RETURN_ERROR;
- }
- +
- + check_for_regulator_put(preg, sensor_idx,
- + (reg_type_offset + pin - IMGSENSOR_HW_PIN_AVDD));
- +
- atomic_dec(enable_cnt);
- }
- } else {
- @@ -166,7 +195,77 @@ static enum IMGSENSOR_RETURN regulator_set(
- return IMGSENSOR_RETURN_SUCCESS;
- }
- +static void check_for_regulator_get(struct REGULATOR *preg,
- + struct device *pdevice, unsigned int sensor_index,
- + unsigned int regulator_index)
- +{
- + struct device_node *pof_node = NULL;
- + char str_regulator_name[LENGTH_FOR_SNPRINTF];
- +
- + if (!preg || !pdevice) {
- + pr_err("Fatal: Null ptr.preg:%pK,pdevice:%pK\n", preg, pdevice);
- + return;
- + }
- +
- + if (sensor_index >= IMGSENSOR_SENSOR_IDX_MAX_NUM ||
- + regulator_index >= REGULATOR_TYPE_MAX_NUM ) {
- + pr_err("[%s]Invalid sensor_idx:%d regulator_idx: %d\n",
- + __func__, sensor_index, regulator_index);
- + return;
- + }
- +
- + mutex_lock(&g_regulator_state_mutex);
- +
- + if (regulator_status[sensor_index][regulator_index] == false) {
- + pof_node = pdevice->of_node;
- + pdevice->of_node = of_node_record;
- +
- + snprintf(str_regulator_name,
- + sizeof(str_regulator_name),
- + "cam%d_%s",
- + sensor_index,
- + regulator_control[regulator_index].pregulator_type);
- + preg->pregulator[sensor_index][regulator_index] =
- + regulator_get(pdevice, str_regulator_name);
- +
- + if (preg != NULL)
- + regulator_status[sensor_index][regulator_index] = true;
- + else
- + pr_err("get regulator failed.\n");
- + pdevice->of_node = pof_node;
- + }
- +
- + mutex_unlock(&g_regulator_state_mutex);
- + return;
- +}
- +
- +static void check_for_regulator_put(struct REGULATOR *preg,
- + unsigned int sensor_index, unsigned int regulator_index)
- +{
- + if (!preg) {
- + pr_err("Fatal: Null ptr.\n");
- + return;
- + }
- +
- + if (sensor_index >= IMGSENSOR_SENSOR_IDX_MAX_NUM ||
- + regulator_index >= REGULATOR_TYPE_MAX_NUM ) {
- + pr_err("[%s]Invalid sensor_idx:%d regulator_idx: %d\n",
- + __func__, sensor_index, regulator_index);
- + return;
- + }
- +
- + mutex_lock(&g_regulator_state_mutex);
- +
- + if (regulator_status[sensor_index][regulator_index] == true) {
- + regulator_put(preg->pregulator[sensor_index][regulator_index]);
- + preg->pregulator[sensor_index][regulator_index] = NULL;
- + regulator_status[sensor_index][regulator_index] = false;
- + }
- +
- + mutex_unlock(&g_regulator_state_mutex);
- +
- + return;
- +}
- static enum IMGSENSOR_RETURN regulator_dump(void *pinstance)
- {
- struct REGULATOR *preg = (struct REGULATOR *)pinstance;
复制代码
MT6765
- +static bool regulator_status[IMGSENSOR_SENSOR_IDX_MAX_NUM][
- + REGULATOR_TYPE_MAX_NUM] = {false};
- +static void check_for_regulator_get(struct REGULATOR *preg,
- + struct device *pdevice, unsigned int sensor_index,
- + unsigned int regulator_index);
- +static void check_for_regulator_put(struct REGULATOR *preg,
- + unsigned int sensor_index, unsigned int regulator_index);
- +static struct device_node *of_node_record = NULL;
- +
- +static DEFINE_MUTEX(g_regulator_state_mutex);
- +
- static const int regulator_voltage[] = {
- REGULATOR_VOLTAGE_0,
- REGULATOR_VOLTAGE_1000,
- @@ -183,12 +194,12 @@
- pof_node = pdevice->of_node;
- pdevice->of_node =
- of_find_compatible_node(NULL, NULL, "mediatek,camera_hw");
- -
- if (pdevice->of_node == NULL) {
- pr_err("regulator get cust camera node failed!\n");
- pdevice->of_node = pof_node;
- return IMGSENSOR_RETURN_ERROR;
- }
- + of_node_record = pdevice->of_node;
- for (j = IMGSENSOR_SENSOR_IDX_MIN_NUM;
- j < IMGSENSOR_SENSOR_IDX_MAX_NUM;
- @@ -207,6 +218,7 @@
- j, i, str_regulator_name);
- atomic_set(&preg->enable_cnt[j][i], 0);
- + regulator_status[j][i] = true;
- }
- }
- pdevice->of_node = pof_node;
- @@ -257,7 +269,8 @@
- return IMGSENSOR_RETURN_ERROR;
- reg_type_offset = REGULATOR_TYPE_VCAMA;
- -
- + check_for_regulator_get(preg, gimgsensor_device, sensor_idx,
- + (reg_type_offset + pin - IMGSENSOR_HW_PIN_AVDD));
- pregulator =
- preg->pregulator[sensor_idx][
- reg_type_offset + pin - IMGSENSOR_HW_PIN_AVDD];
- @@ -300,7 +313,8 @@
- pin,
- regulator_voltage[
- pin_state - IMGSENSOR_HW_PIN_STATE_LEVEL_0]);
- -
- + check_for_regulator_put(preg, sensor_idx,
- + (reg_type_offset + pin - IMGSENSOR_HW_PIN_AVDD));
- return IMGSENSOR_RETURN_ERROR;
- }
- atomic_inc(enable_cnt);
- @@ -312,9 +326,13 @@
- pr_err(
- "[regulator]fail to regulator_disable, powertype: %d\n",
- pin);
- + check_for_regulator_put(preg, sensor_idx,
- + (reg_type_offset + pin - IMGSENSOR_HW_PIN_AVDD));
- return IMGSENSOR_RETURN_ERROR;
- }
- }
- + check_for_regulator_put(preg, sensor_idx,
- + (reg_type_offset + pin - IMGSENSOR_HW_PIN_AVDD));
- atomic_dec(enable_cnt);
- }
- } else {
- @@ -327,6 +345,78 @@
- return IMGSENSOR_RETURN_SUCCESS;
- }
- +static void check_for_regulator_get(struct REGULATOR *preg,
- + struct device *pdevice, unsigned int sensor_index,
- + unsigned int regulator_index)
- +{
- + struct device_node *pof_node = NULL;
- + char str_regulator_name[LENGTH_FOR_SNPRINTF];
- +
- + if (!preg || !pdevice) {
- + pr_err("Fatal: Null ptr.preg:%pK,pdevice:%pK\n", preg, pdevice);
- + return;
- + }
- +
- + if (sensor_index >= IMGSENSOR_SENSOR_IDX_MAX_NUM ||
- + regulator_index >= REGULATOR_TYPE_MAX_NUM ) {
- + pr_err("[%s]Invalid sensor_idx:%d regulator_idx: %d\n",
- + __func__, sensor_index, regulator_index);
- + return;
- + }
- +
- + mutex_lock(&g_regulator_state_mutex);
- +
- + if (regulator_status[sensor_index][regulator_index] == false) {
- + pof_node = pdevice->of_node;
- + pdevice->of_node = of_node_record;
- +
- + snprintf(str_regulator_name,
- + sizeof(str_regulator_name),
- + "cam%d_%s",
- + sensor_index,
- + regulator_control[regulator_index].pregulator_type);
- + preg->pregulator[sensor_index][regulator_index] =
- + regulator_get(pdevice, str_regulator_name);
- +
- + if (preg != NULL)
- + regulator_status[sensor_index][regulator_index] = true;
- + else
- + pr_err("get regulator failed.\n");
- + pdevice->of_node = pof_node;
- + }
- +
- + mutex_unlock(&g_regulator_state_mutex);
- +
- + return;
- +}
- +
- +static void check_for_regulator_put(struct REGULATOR *preg,
- + unsigned int sensor_index, unsigned int regulator_index)
- +{
- + if (!preg) {
- + pr_err("Fatal: Null ptr.\n");
- + return;
- + }
- +
- + if (sensor_index >= IMGSENSOR_SENSOR_IDX_MAX_NUM ||
- + regulator_index >= REGULATOR_TYPE_MAX_NUM ) {
- + pr_err("[%s]Invalid sensor_idx:%d regulator_idx: %d\n",
- + __func__, sensor_index, regulator_index);
- + return;
- + }
- +
- + mutex_lock(&g_regulator_state_mutex);
- +
- + if (regulator_status[sensor_index][regulator_index] == true) {
- + regulator_put(preg->pregulator[sensor_index][regulator_index]);
- + preg->pregulator[sensor_index][regulator_index] = NULL;
- + regulator_status[sensor_index][regulator_index] = false;
- + }
- +
- + mutex_unlock(&g_regulator_state_mutex);
- +
- + return;
- +}
- +
- static struct IMGSENSOR_HW_DEVICE device = {
- .pinstance = (void *)®_instance,
- .init = regulator_init,
复制代码
|
本帖子中包含更多资源
您需要 登录 才可以下载或查看,没有帐号?立即注册
x
|