camera: manage csi power [1/2]

PD#SWPL-180124

Problem:
CSI module needs to enter a low power state when not in use

Solution:
1.enable pm runtime of csi device
2.power off when csi fe close
3.power on when csi fe open
4.get clock pointer in probe function
5.set clock rate and enable clock when csi fe open
6.disable clock when csi fe close

Verify:
s6&sm1

Change-Id: I40309a0e740231fddf143b7b40576bd21d1f2914
Signed-off-by: shuanshuan.jiang <shuanshuan.jiang@amlogic.com>
This commit is contained in:
shuanshuan.jiang
2024-08-13 18:32:36 +08:00
committed by gerrit autosubmit
parent 418865a55e
commit e8ca27af46
4 changed files with 54 additions and 24 deletions
+13 -2
View File
@@ -20,6 +20,9 @@
#include <linux/amlogic/media/mipi/am_mipi_csi2.h>
#include <linux/pm_runtime.h>
#include <linux/pm_domain.h>
#include "../tvin_global.h"
#include "../vdin/vdin_regs.h"
#include "../vdin/vdin_drv.h"
@@ -362,8 +365,6 @@ static int amcsi_feopen(struct tvin_frontend_s *fe, enum tvin_port_e port,
return -1;
}
init_am_mipi_csi2_clock();
csi_devp->para.port = port;
memcpy(&csi_devp->csi_parm,
@@ -374,8 +375,11 @@ static int amcsi_feopen(struct tvin_frontend_s *fe, enum tvin_port_e port,
csi_devp->csi_parm.lanes = g_sensor_info.nlanes;
csi_devp->reset = 0;
csi_devp->reset_count = 0;
if (csi_devp->dev)
pm_runtime_get_sync(csi_devp->dev);
cal_csi_para(csi_devp);
enable_am_mipi_csi2_clk();
am_mipi_csi2_init(csi_devp);
csi_devp->fe_status = CAMERA_FE_OPEN;
DPRINT("%s camera fe open\n", __func__);
@@ -402,6 +406,9 @@ static void amcsi_feclose(struct tvin_frontend_s *fe, enum tvin_port_type_e port
devp->fe_status = CAMERA_FE_CLOSE;
}
am_mipi_csi2_uninit(devp);
disable_am_mipi_csi2_clk();
if (devp->dev)
pm_runtime_put_sync(devp->dev);
memset(&devp->para, 0, sizeof(struct vdin_parm_s));
}
@@ -519,6 +526,7 @@ static int amvdec_csi_probe(struct platform_device *pdev)
// keep this assignment first.
// other initialization may depends on chip info.
devp->csi_chip_info = &g_csi_chip_info;
devp->dev = &pdev->dev;
ret = csi_add_cdev(&devp->cdev, &amcsi_fops, 0);
if (ret != 0) {
@@ -543,6 +551,8 @@ static int amvdec_csi_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, devp);
am_mipi_csi2_para_init(pdev);
init_am_mipi_csi2_clock();
pm_runtime_enable(&pdev->dev);
pr_info("amvdec_csi probe ok.\n");
return ret;
@@ -561,6 +571,7 @@ static int amvdec_csi_remove(struct platform_device *pdev)
tvin_unreg_frontend(&devp->frontend);
device_remove_file(devp->dev, &dev_attr_hw_info);
pm_runtime_disable(devp->dev);
deinit_am_mipi_csi2_clock();
csi_delete_device(pdev->id);
cdev_del(&devp->cdev);
+2
View File
@@ -102,6 +102,8 @@ u32 READ_CSI_ADPT_REG_BIT(int addr,
// phy clk & adapt clk;
void init_am_mipi_csi2_clock(void);
void deinit_am_mipi_csi2_clock(void);
void enable_am_mipi_csi2_clk(void);
void disable_am_mipi_csi2_clk(void);
void am_mipi_csi2_init(struct amcsi_dev_s *csi_dev);
void cal_csi_para(struct amcsi_dev_s *csi_dev);
+38 -21
View File
@@ -15,6 +15,7 @@
#include <linux/of_irq.h>
#include <linux/delay.h>
#include <linux/clk.h>
#include <linux/clk-provider.h>
#include <linux/platform_device.h>
#include <linux/amlogic/power_domain.h>
#include <linux/io.h>
@@ -131,10 +132,6 @@ void mipi_phy_reg_wr_and_check(s32 addr, s32 data)
void init_am_mipi_csi2_clock(void)
{
s32 rc = 0;
u32 csi_rate = 200000000;
u32 adapt_rate = 666666667;
g_csi.csi_clk = devm_clk_get(&g_csi.p_dev->dev,
"cts_csi_phy_clk_composite");
if (IS_ERR(g_csi.csi_clk)) {
@@ -143,13 +140,6 @@ void init_am_mipi_csi2_clock(void)
g_csi.csi_clk = NULL;
return;
}
if (clk_set_rate(g_csi.csi_clk, csi_rate) < 0)
pr_err("%s :Failed to set csi rate\n", __func__);
rc = clk_prepare_enable(g_csi.csi_clk);
if (rc != 0) {
pr_err("Failed to enable csi clk\n");
return;
}
g_csi.adapt_clk = devm_clk_get(&g_csi.p_dev->dev,
"cts_csi_adapt_clk_composite");
@@ -159,19 +149,47 @@ void init_am_mipi_csi2_clock(void)
g_csi.adapt_clk = NULL;
return;
}
if (clk_set_rate(g_csi.adapt_clk, adapt_rate))
pr_err("%s: Failed to set adapt rate\n", __func__);
rc = clk_prepare_enable(g_csi.adapt_clk);
if (rc != 0) {
pr_err("Failed to enable adapt clk\n");
return;
}
}
void enable_am_mipi_csi2_clk(void)
{
int rtn = 0;
u32 csi_rate = 200000000;
u32 adapt_rate = 666666667;
if (!IS_ERR_OR_NULL(g_csi.csi_clk)) {
if (clk_set_rate(g_csi.csi_clk, csi_rate) < 0)
pr_err("%s :Failed to set csi rate\n", __func__);
if (!__clk_is_enabled(g_csi.csi_clk)) {
rtn = clk_prepare_enable(g_csi.csi_clk);
if (rtn) {
pr_err("Error to enable csi_clk\n");
return;
}
}
}
if (!IS_ERR_OR_NULL(g_csi.adapt_clk)) {
if (clk_set_rate(g_csi.adapt_clk, adapt_rate))
pr_err("%s: Failed to set adapt rate\n", __func__);
if (!__clk_is_enabled(g_csi.adapt_clk)) {
rtn = clk_prepare_enable(g_csi.adapt_clk);
if (rtn) {
pr_err("Error to enable adapt_clk\n");
return;
}
}
}
}
void disable_am_mipi_csi2_clk(void)
{
clk_disable_unprepare(g_csi.csi_clk);
clk_disable_unprepare(g_csi.adapt_clk);
if (!IS_ERR_OR_NULL(g_csi.csi_clk)) {
if (__clk_is_enabled(g_csi.csi_clk))
clk_disable_unprepare(g_csi.csi_clk);
}
if (!IS_ERR_OR_NULL(g_csi.adapt_clk)) {
if (__clk_is_enabled(g_csi.adapt_clk))
clk_disable_unprepare(g_csi.adapt_clk);
}
}
void deinit_am_mipi_csi2_clock(void)
@@ -448,7 +466,6 @@ void am_mipi_csi2_uninit(struct amcsi_dev_s *csi_dev)
reset_am_mipi_phy(csi_dev, &g_csi);
reset_am_mipi_csi2_host(csi_dev, &g_csi);
reset_am_mipi_csi2_adapter(csi_dev, &g_csi);
disable_am_mipi_csi2_clk();
if (get_csi_chip_type(csi_dev) == CSI_ON_SM1)
powerdown_csi_analog_sm1(&g_csi);
else if (get_csi_chip_type(csi_dev) == CSI_ON_S6)
+1 -1
View File
@@ -798,7 +798,7 @@ static struct sec_pm_private_domain s6_pm_domains[] __initdata = {
[PDID_S6_AUCPU] = POWER_DOMAIN(aucpu, PDID_S6_AUCPU,
DOMAIN_INIT_ON, GENPD_FLAG_ALWAYS_ON),
[PDID_S6_ADAPT] = POWER_DOMAIN(adapt, PDID_S6_ADAPT,
DOMAIN_INIT_ON, GENPD_FLAG_ALWAYS_ON),
DOMAIN_INIT_OFF, 0),
};
static struct sec_pm_domain_data s6_pm_domain_data __initdata = {