mirror of
https://github.com/hardkernel/kernel_common_drivers.git
synced 2026-06-25 12:03:48 +09:00
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:
committed by
gerrit autosubmit
parent
418865a55e
commit
e8ca27af46
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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 = {
|
||||
|
||||
Reference in New Issue
Block a user