mirror of
https://github.com/edk2-porting/linux-next.git
synced 2024-12-23 12:43:55 +08:00
media: mtk-vcodec: Using common interface to manage vdec/venc clock
Vdec: Using standard CCF interface to set parent clock and clock rate in dtsi and using common interface to open/close video decoder clock. Venc: Using standard CCF interface to set parent clock in dtsi and using common interface to open/close video encoder clock. Signed-off-by: Yunfei Dong <yunfei.dong@mediatek.com> Signed-off-by: Qianqian Yan <qianqian.yan@mediatek.com> Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl> Signed-off-by: Mauro Carvalho Chehab <mchehab+samsung@kernel.org>
This commit is contained in:
parent
d8501cc850
commit
04bde67410
@ -27,11 +27,14 @@ int mtk_vcodec_init_dec_pm(struct mtk_vcodec_dev *mtkdev)
|
|||||||
struct device_node *node;
|
struct device_node *node;
|
||||||
struct platform_device *pdev;
|
struct platform_device *pdev;
|
||||||
struct mtk_vcodec_pm *pm;
|
struct mtk_vcodec_pm *pm;
|
||||||
int ret = 0;
|
struct mtk_vcodec_clk *dec_clk;
|
||||||
|
struct mtk_vcodec_clk_info *clk_info;
|
||||||
|
int i = 0, ret = 0;
|
||||||
|
|
||||||
pdev = mtkdev->plat_dev;
|
pdev = mtkdev->plat_dev;
|
||||||
pm = &mtkdev->pm;
|
pm = &mtkdev->pm;
|
||||||
pm->mtkdev = mtkdev;
|
pm->mtkdev = mtkdev;
|
||||||
|
dec_clk = &pm->vdec_clk;
|
||||||
node = of_parse_phandle(pdev->dev.of_node, "mediatek,larb", 0);
|
node = of_parse_phandle(pdev->dev.of_node, "mediatek,larb", 0);
|
||||||
if (!node) {
|
if (!node) {
|
||||||
mtk_v4l2_err("of_parse_phandle mediatek,larb fail!");
|
mtk_v4l2_err("of_parse_phandle mediatek,larb fail!");
|
||||||
@ -47,52 +50,34 @@ int mtk_vcodec_init_dec_pm(struct mtk_vcodec_dev *mtkdev)
|
|||||||
pdev = mtkdev->plat_dev;
|
pdev = mtkdev->plat_dev;
|
||||||
pm->dev = &pdev->dev;
|
pm->dev = &pdev->dev;
|
||||||
|
|
||||||
pm->vcodecpll = devm_clk_get(&pdev->dev, "vcodecpll");
|
dec_clk->clk_num =
|
||||||
if (IS_ERR(pm->vcodecpll)) {
|
of_property_count_strings(pdev->dev.of_node, "clock-names");
|
||||||
mtk_v4l2_err("devm_clk_get vcodecpll fail");
|
if (dec_clk->clk_num > 0) {
|
||||||
ret = PTR_ERR(pm->vcodecpll);
|
dec_clk->clk_info = devm_kcalloc(&pdev->dev,
|
||||||
|
dec_clk->clk_num, sizeof(*clk_info),
|
||||||
|
GFP_KERNEL);
|
||||||
|
if (!dec_clk->clk_info)
|
||||||
|
return -ENOMEM;
|
||||||
|
} else {
|
||||||
|
mtk_v4l2_err("Failed to get vdec clock count");
|
||||||
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
pm->univpll_d2 = devm_clk_get(&pdev->dev, "univpll_d2");
|
for (i = 0; i < dec_clk->clk_num; i++) {
|
||||||
if (IS_ERR(pm->univpll_d2)) {
|
clk_info = &dec_clk->clk_info[i];
|
||||||
mtk_v4l2_err("devm_clk_get univpll_d2 fail");
|
ret = of_property_read_string_index(pdev->dev.of_node,
|
||||||
ret = PTR_ERR(pm->univpll_d2);
|
"clock-names", i, &clk_info->clk_name);
|
||||||
}
|
if (ret) {
|
||||||
|
mtk_v4l2_err("Failed to get clock name id = %d", i);
|
||||||
pm->clk_cci400_sel = devm_clk_get(&pdev->dev, "clk_cci400_sel");
|
return ret;
|
||||||
if (IS_ERR(pm->clk_cci400_sel)) {
|
}
|
||||||
mtk_v4l2_err("devm_clk_get clk_cci400_sel fail");
|
clk_info->vcodec_clk = devm_clk_get(&pdev->dev,
|
||||||
ret = PTR_ERR(pm->clk_cci400_sel);
|
clk_info->clk_name);
|
||||||
}
|
if (IS_ERR(clk_info->vcodec_clk)) {
|
||||||
|
mtk_v4l2_err("devm_clk_get (%d)%s fail", i,
|
||||||
pm->vdec_sel = devm_clk_get(&pdev->dev, "vdec_sel");
|
clk_info->clk_name);
|
||||||
if (IS_ERR(pm->vdec_sel)) {
|
return PTR_ERR(clk_info->vcodec_clk);
|
||||||
mtk_v4l2_err("devm_clk_get vdec_sel fail");
|
}
|
||||||
ret = PTR_ERR(pm->vdec_sel);
|
|
||||||
}
|
|
||||||
|
|
||||||
pm->vdecpll = devm_clk_get(&pdev->dev, "vdecpll");
|
|
||||||
if (IS_ERR(pm->vdecpll)) {
|
|
||||||
mtk_v4l2_err("devm_clk_get vdecpll fail");
|
|
||||||
ret = PTR_ERR(pm->vdecpll);
|
|
||||||
}
|
|
||||||
|
|
||||||
pm->vencpll = devm_clk_get(&pdev->dev, "vencpll");
|
|
||||||
if (IS_ERR(pm->vencpll)) {
|
|
||||||
mtk_v4l2_err("devm_clk_get vencpll fail");
|
|
||||||
ret = PTR_ERR(pm->vencpll);
|
|
||||||
}
|
|
||||||
|
|
||||||
pm->venc_lt_sel = devm_clk_get(&pdev->dev, "venc_lt_sel");
|
|
||||||
if (IS_ERR(pm->venc_lt_sel)) {
|
|
||||||
mtk_v4l2_err("devm_clk_get venc_lt_sel fail");
|
|
||||||
ret = PTR_ERR(pm->venc_lt_sel);
|
|
||||||
}
|
|
||||||
|
|
||||||
pm->vdec_bus_clk_src = devm_clk_get(&pdev->dev, "vdec_bus_clk_src");
|
|
||||||
if (IS_ERR(pm->vdec_bus_clk_src)) {
|
|
||||||
mtk_v4l2_err("devm_clk_get vdec_bus_clk_src");
|
|
||||||
ret = PTR_ERR(pm->vdec_bus_clk_src);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pm_runtime_enable(&pdev->dev);
|
pm_runtime_enable(&pdev->dev);
|
||||||
@ -125,78 +110,36 @@ void mtk_vcodec_dec_pw_off(struct mtk_vcodec_pm *pm)
|
|||||||
|
|
||||||
void mtk_vcodec_dec_clock_on(struct mtk_vcodec_pm *pm)
|
void mtk_vcodec_dec_clock_on(struct mtk_vcodec_pm *pm)
|
||||||
{
|
{
|
||||||
int ret;
|
struct mtk_vcodec_clk *dec_clk = &pm->vdec_clk;
|
||||||
|
int ret, i = 0;
|
||||||
|
|
||||||
ret = clk_set_rate(pm->vcodecpll, 1482 * 1000000);
|
for (i = 0; i < dec_clk->clk_num; i++) {
|
||||||
if (ret)
|
ret = clk_prepare_enable(dec_clk->clk_info[i].vcodec_clk);
|
||||||
mtk_v4l2_err("clk_set_rate vcodecpll fail %d", ret);
|
if (ret) {
|
||||||
|
mtk_v4l2_err("clk_prepare_enable %d %s fail %d", i,
|
||||||
ret = clk_set_rate(pm->vencpll, 800 * 1000000);
|
dec_clk->clk_info[i].clk_name, ret);
|
||||||
if (ret)
|
goto error;
|
||||||
mtk_v4l2_err("clk_set_rate vencpll fail %d", ret);
|
}
|
||||||
|
}
|
||||||
ret = clk_prepare_enable(pm->vcodecpll);
|
|
||||||
if (ret)
|
|
||||||
mtk_v4l2_err("clk_prepare_enable vcodecpll fail %d", ret);
|
|
||||||
|
|
||||||
ret = clk_prepare_enable(pm->vencpll);
|
|
||||||
if (ret)
|
|
||||||
mtk_v4l2_err("clk_prepare_enable vencpll fail %d", ret);
|
|
||||||
|
|
||||||
ret = clk_prepare_enable(pm->vdec_bus_clk_src);
|
|
||||||
if (ret)
|
|
||||||
mtk_v4l2_err("clk_prepare_enable vdec_bus_clk_src fail %d",
|
|
||||||
ret);
|
|
||||||
|
|
||||||
ret = clk_prepare_enable(pm->venc_lt_sel);
|
|
||||||
if (ret)
|
|
||||||
mtk_v4l2_err("clk_prepare_enable venc_lt_sel fail %d", ret);
|
|
||||||
|
|
||||||
ret = clk_set_parent(pm->venc_lt_sel, pm->vdec_bus_clk_src);
|
|
||||||
if (ret)
|
|
||||||
mtk_v4l2_err("clk_set_parent venc_lt_sel vdec_bus_clk_src fail %d",
|
|
||||||
ret);
|
|
||||||
|
|
||||||
ret = clk_prepare_enable(pm->univpll_d2);
|
|
||||||
if (ret)
|
|
||||||
mtk_v4l2_err("clk_prepare_enable univpll_d2 fail %d", ret);
|
|
||||||
|
|
||||||
ret = clk_prepare_enable(pm->clk_cci400_sel);
|
|
||||||
if (ret)
|
|
||||||
mtk_v4l2_err("clk_prepare_enable clk_cci400_sel fail %d", ret);
|
|
||||||
|
|
||||||
ret = clk_set_parent(pm->clk_cci400_sel, pm->univpll_d2);
|
|
||||||
if (ret)
|
|
||||||
mtk_v4l2_err("clk_set_parent clk_cci400_sel univpll_d2 fail %d",
|
|
||||||
ret);
|
|
||||||
|
|
||||||
ret = clk_prepare_enable(pm->vdecpll);
|
|
||||||
if (ret)
|
|
||||||
mtk_v4l2_err("clk_prepare_enable vdecpll fail %d", ret);
|
|
||||||
|
|
||||||
ret = clk_prepare_enable(pm->vdec_sel);
|
|
||||||
if (ret)
|
|
||||||
mtk_v4l2_err("clk_prepare_enable vdec_sel fail %d", ret);
|
|
||||||
|
|
||||||
ret = clk_set_parent(pm->vdec_sel, pm->vdecpll);
|
|
||||||
if (ret)
|
|
||||||
mtk_v4l2_err("clk_set_parent vdec_sel vdecpll fail %d", ret);
|
|
||||||
|
|
||||||
ret = mtk_smi_larb_get(pm->larbvdec);
|
ret = mtk_smi_larb_get(pm->larbvdec);
|
||||||
if (ret)
|
if (ret) {
|
||||||
mtk_v4l2_err("mtk_smi_larb_get larbvdec fail %d", ret);
|
mtk_v4l2_err("mtk_smi_larb_get larbvdec fail %d", ret);
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
|
||||||
|
error:
|
||||||
|
for (i -= 1; i >= 0; i--)
|
||||||
|
clk_disable_unprepare(dec_clk->clk_info[i].vcodec_clk);
|
||||||
}
|
}
|
||||||
|
|
||||||
void mtk_vcodec_dec_clock_off(struct mtk_vcodec_pm *pm)
|
void mtk_vcodec_dec_clock_off(struct mtk_vcodec_pm *pm)
|
||||||
{
|
{
|
||||||
|
struct mtk_vcodec_clk *dec_clk = &pm->vdec_clk;
|
||||||
|
int i = 0;
|
||||||
|
|
||||||
mtk_smi_larb_put(pm->larbvdec);
|
mtk_smi_larb_put(pm->larbvdec);
|
||||||
clk_disable_unprepare(pm->vdec_sel);
|
for (i = dec_clk->clk_num - 1; i >= 0; i--)
|
||||||
clk_disable_unprepare(pm->vdecpll);
|
clk_disable_unprepare(dec_clk->clk_info[i].vcodec_clk);
|
||||||
clk_disable_unprepare(pm->univpll_d2);
|
|
||||||
clk_disable_unprepare(pm->clk_cci400_sel);
|
|
||||||
clk_disable_unprepare(pm->venc_lt_sel);
|
|
||||||
clk_disable_unprepare(pm->vdec_bus_clk_src);
|
|
||||||
clk_disable_unprepare(pm->vencpll);
|
|
||||||
clk_disable_unprepare(pm->vcodecpll);
|
|
||||||
}
|
}
|
||||||
|
@ -175,23 +175,30 @@ struct mtk_enc_params {
|
|||||||
unsigned int force_intra;
|
unsigned int force_intra;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* struct mtk_vcodec_clk_info - Structure used to store clock name
|
||||||
|
*/
|
||||||
|
struct mtk_vcodec_clk_info {
|
||||||
|
const char *clk_name;
|
||||||
|
struct clk *vcodec_clk;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* struct mtk_vcodec_clk - Structure used to store vcodec clock information
|
||||||
|
*/
|
||||||
|
struct mtk_vcodec_clk {
|
||||||
|
struct mtk_vcodec_clk_info *clk_info;
|
||||||
|
int clk_num;
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* struct mtk_vcodec_pm - Power management data structure
|
* struct mtk_vcodec_pm - Power management data structure
|
||||||
*/
|
*/
|
||||||
struct mtk_vcodec_pm {
|
struct mtk_vcodec_pm {
|
||||||
struct clk *vdec_bus_clk_src;
|
struct mtk_vcodec_clk vdec_clk;
|
||||||
struct clk *vencpll;
|
|
||||||
|
|
||||||
struct clk *vcodecpll;
|
|
||||||
struct clk *univpll_d2;
|
|
||||||
struct clk *clk_cci400_sel;
|
|
||||||
struct clk *vdecpll;
|
|
||||||
struct clk *vdec_sel;
|
|
||||||
struct clk *vencpll_d2;
|
|
||||||
struct clk *venc_sel;
|
|
||||||
struct clk *univpll1_d2;
|
|
||||||
struct clk *venc_lt_sel;
|
|
||||||
struct device *larbvdec;
|
struct device *larbvdec;
|
||||||
|
|
||||||
|
struct mtk_vcodec_clk venc_clk;
|
||||||
struct device *larbvenc;
|
struct device *larbvenc;
|
||||||
struct device *larbvenclt;
|
struct device *larbvenclt;
|
||||||
struct device *dev;
|
struct device *dev;
|
||||||
|
@ -27,9 +27,11 @@ int mtk_vcodec_init_enc_pm(struct mtk_vcodec_dev *mtkdev)
|
|||||||
{
|
{
|
||||||
struct device_node *node;
|
struct device_node *node;
|
||||||
struct platform_device *pdev;
|
struct platform_device *pdev;
|
||||||
struct device *dev;
|
|
||||||
struct mtk_vcodec_pm *pm;
|
struct mtk_vcodec_pm *pm;
|
||||||
int ret = 0;
|
struct mtk_vcodec_clk *enc_clk;
|
||||||
|
struct mtk_vcodec_clk_info *clk_info;
|
||||||
|
int ret = 0, i = 0;
|
||||||
|
struct device *dev;
|
||||||
|
|
||||||
pdev = mtkdev->plat_dev;
|
pdev = mtkdev->plat_dev;
|
||||||
pm = &mtkdev->pm;
|
pm = &mtkdev->pm;
|
||||||
@ -37,6 +39,7 @@ int mtk_vcodec_init_enc_pm(struct mtk_vcodec_dev *mtkdev)
|
|||||||
pm->mtkdev = mtkdev;
|
pm->mtkdev = mtkdev;
|
||||||
pm->dev = &pdev->dev;
|
pm->dev = &pdev->dev;
|
||||||
dev = &pdev->dev;
|
dev = &pdev->dev;
|
||||||
|
enc_clk = &pm->venc_clk;
|
||||||
|
|
||||||
node = of_parse_phandle(dev->of_node, "mediatek,larb", 0);
|
node = of_parse_phandle(dev->of_node, "mediatek,larb", 0);
|
||||||
if (!node) {
|
if (!node) {
|
||||||
@ -68,28 +71,34 @@ int mtk_vcodec_init_enc_pm(struct mtk_vcodec_dev *mtkdev)
|
|||||||
pdev = mtkdev->plat_dev;
|
pdev = mtkdev->plat_dev;
|
||||||
pm->dev = &pdev->dev;
|
pm->dev = &pdev->dev;
|
||||||
|
|
||||||
pm->vencpll_d2 = devm_clk_get(&pdev->dev, "venc_sel_src");
|
enc_clk->clk_num = of_property_count_strings(pdev->dev.of_node,
|
||||||
if (IS_ERR(pm->vencpll_d2)) {
|
"clock-names");
|
||||||
mtk_v4l2_err("devm_clk_get vencpll_d2 fail");
|
if (enc_clk->clk_num > 0) {
|
||||||
ret = PTR_ERR(pm->vencpll_d2);
|
enc_clk->clk_info = devm_kcalloc(&pdev->dev,
|
||||||
|
enc_clk->clk_num, sizeof(*clk_info),
|
||||||
|
GFP_KERNEL);
|
||||||
|
if (!enc_clk->clk_info)
|
||||||
|
return -ENOMEM;
|
||||||
|
} else {
|
||||||
|
mtk_v4l2_err("Failed to get venc clock count");
|
||||||
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
pm->venc_sel = devm_clk_get(&pdev->dev, "venc_sel");
|
for (i = 0; i < enc_clk->clk_num; i++) {
|
||||||
if (IS_ERR(pm->venc_sel)) {
|
clk_info = &enc_clk->clk_info[i];
|
||||||
mtk_v4l2_err("devm_clk_get venc_sel fail");
|
ret = of_property_read_string_index(pdev->dev.of_node,
|
||||||
ret = PTR_ERR(pm->venc_sel);
|
"clock-names", i, &clk_info->clk_name);
|
||||||
}
|
if (ret) {
|
||||||
|
mtk_v4l2_err("venc failed to get clk name %d", i);
|
||||||
pm->univpll1_d2 = devm_clk_get(&pdev->dev, "venc_lt_sel_src");
|
return ret;
|
||||||
if (IS_ERR(pm->univpll1_d2)) {
|
}
|
||||||
mtk_v4l2_err("devm_clk_get univpll1_d2 fail");
|
clk_info->vcodec_clk = devm_clk_get(&pdev->dev,
|
||||||
ret = PTR_ERR(pm->univpll1_d2);
|
clk_info->clk_name);
|
||||||
}
|
if (IS_ERR(clk_info->vcodec_clk)) {
|
||||||
|
mtk_v4l2_err("venc devm_clk_get (%d)%s fail", i,
|
||||||
pm->venc_lt_sel = devm_clk_get(&pdev->dev, "venc_lt_sel");
|
clk_info->clk_name);
|
||||||
if (IS_ERR(pm->venc_lt_sel)) {
|
return PTR_ERR(clk_info->vcodec_clk);
|
||||||
mtk_v4l2_err("devm_clk_get venc_lt_sel fail");
|
}
|
||||||
ret = PTR_ERR(pm->venc_lt_sel);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
@ -102,38 +111,45 @@ void mtk_vcodec_release_enc_pm(struct mtk_vcodec_dev *mtkdev)
|
|||||||
|
|
||||||
void mtk_vcodec_enc_clock_on(struct mtk_vcodec_pm *pm)
|
void mtk_vcodec_enc_clock_on(struct mtk_vcodec_pm *pm)
|
||||||
{
|
{
|
||||||
int ret;
|
struct mtk_vcodec_clk *enc_clk = &pm->venc_clk;
|
||||||
|
int ret, i = 0;
|
||||||
|
|
||||||
ret = clk_prepare_enable(pm->venc_sel);
|
for (i = 0; i < enc_clk->clk_num; i++) {
|
||||||
if (ret)
|
ret = clk_prepare_enable(enc_clk->clk_info[i].vcodec_clk);
|
||||||
mtk_v4l2_err("clk_prepare_enable fail %d", ret);
|
if (ret) {
|
||||||
|
mtk_v4l2_err("venc clk_prepare_enable %d %s fail %d", i,
|
||||||
ret = clk_set_parent(pm->venc_sel, pm->vencpll_d2);
|
enc_clk->clk_info[i].clk_name, ret);
|
||||||
if (ret)
|
goto clkerr;
|
||||||
mtk_v4l2_err("clk_set_parent fail %d", ret);
|
}
|
||||||
|
}
|
||||||
ret = clk_prepare_enable(pm->venc_lt_sel);
|
|
||||||
if (ret)
|
|
||||||
mtk_v4l2_err("clk_prepare_enable fail %d", ret);
|
|
||||||
|
|
||||||
ret = clk_set_parent(pm->venc_lt_sel, pm->univpll1_d2);
|
|
||||||
if (ret)
|
|
||||||
mtk_v4l2_err("clk_set_parent fail %d", ret);
|
|
||||||
|
|
||||||
ret = mtk_smi_larb_get(pm->larbvenc);
|
ret = mtk_smi_larb_get(pm->larbvenc);
|
||||||
if (ret)
|
if (ret) {
|
||||||
mtk_v4l2_err("mtk_smi_larb_get larb3 fail %d", ret);
|
mtk_v4l2_err("mtk_smi_larb_get larb3 fail %d", ret);
|
||||||
|
goto larbvencerr;
|
||||||
|
}
|
||||||
ret = mtk_smi_larb_get(pm->larbvenclt);
|
ret = mtk_smi_larb_get(pm->larbvenclt);
|
||||||
if (ret)
|
if (ret) {
|
||||||
mtk_v4l2_err("mtk_smi_larb_get larb4 fail %d", ret);
|
mtk_v4l2_err("mtk_smi_larb_get larb4 fail %d", ret);
|
||||||
|
goto larbvenclterr;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
|
||||||
|
larbvenclterr:
|
||||||
|
mtk_smi_larb_put(pm->larbvenc);
|
||||||
|
larbvencerr:
|
||||||
|
clkerr:
|
||||||
|
for (i -= 1; i >= 0; i--)
|
||||||
|
clk_disable_unprepare(enc_clk->clk_info[i].vcodec_clk);
|
||||||
}
|
}
|
||||||
|
|
||||||
void mtk_vcodec_enc_clock_off(struct mtk_vcodec_pm *pm)
|
void mtk_vcodec_enc_clock_off(struct mtk_vcodec_pm *pm)
|
||||||
{
|
{
|
||||||
|
struct mtk_vcodec_clk *enc_clk = &pm->venc_clk;
|
||||||
|
int i = 0;
|
||||||
|
|
||||||
mtk_smi_larb_put(pm->larbvenc);
|
mtk_smi_larb_put(pm->larbvenc);
|
||||||
mtk_smi_larb_put(pm->larbvenclt);
|
mtk_smi_larb_put(pm->larbvenclt);
|
||||||
clk_disable_unprepare(pm->venc_lt_sel);
|
for (i = enc_clk->clk_num - 1; i >= 0; i--)
|
||||||
clk_disable_unprepare(pm->venc_sel);
|
clk_disable_unprepare(enc_clk->clk_info[i].vcodec_clk);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user