Loading...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 | // SPDX-License-Identifier: GPL-2.0 /* * Copyright (c) 2016 MediaTek Inc. * Author: Tiffany Lin <tiffany.lin@mediatek.com> */ #include <linux/clk.h> #include <linux/of.h> #include <linux/pm_runtime.h> #include "mtk_vcodec_enc_drv.h" #include "mtk_vcodec_enc_pm.h" int mtk_vcodec_init_enc_clk(struct mtk_vcodec_enc_dev *mtkdev) { struct platform_device *pdev; struct mtk_vcodec_pm *pm; struct mtk_vcodec_clk *enc_clk; struct mtk_vcodec_clk_info *clk_info; int ret, i; pdev = mtkdev->plat_dev; pm = &mtkdev->pm; memset(pm, 0, sizeof(struct mtk_vcodec_pm)); pm->dev = &pdev->dev; enc_clk = &pm->venc_clk; enc_clk->clk_num = of_property_count_strings(pdev->dev.of_node, "clock-names"); if (enc_clk->clk_num > 0) { 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 { dev_err(pm->dev, "[MTK VCODEC] Failed to get venc clock count"); return -EINVAL; } for (i = 0; i < enc_clk->clk_num; i++) { clk_info = &enc_clk->clk_info[i]; ret = of_property_read_string_index(pdev->dev.of_node, "clock-names", i, &clk_info->clk_name); if (ret) { dev_err(pm->dev, "[MTK VCODEC] venc failed to get clk name %d", i); return ret; } clk_info->vcodec_clk = devm_clk_get(&pdev->dev, clk_info->clk_name); if (IS_ERR(clk_info->vcodec_clk)) { dev_err(pm->dev, "[MTK VCODEC] venc devm_clk_get (%d)%s fail", i, clk_info->clk_name); return PTR_ERR(clk_info->vcodec_clk); } } return 0; } int mtk_vcodec_enc_pw_on(struct mtk_vcodec_pm *pm) { int ret; ret = pm_runtime_resume_and_get(pm->dev); if (ret) dev_err(pm->dev, "pm_runtime_resume_and_get fail: %d", ret); return ret; } void mtk_vcodec_enc_pw_off(struct mtk_vcodec_pm *pm) { int ret; ret = pm_runtime_put(pm->dev); if (ret && ret != -EAGAIN) dev_err(pm->dev, "pm_runtime_put fail %d", ret); } void mtk_vcodec_enc_clock_on(struct mtk_vcodec_pm *pm) { struct mtk_vcodec_clk *enc_clk = &pm->venc_clk; int ret, i = 0; for (i = 0; i < enc_clk->clk_num; i++) { ret = clk_prepare_enable(enc_clk->clk_info[i].vcodec_clk); if (ret) { dev_err(pm->dev, "[MTK VCODEC] venc clk_prepare_enable %d %s fail %d", i, enc_clk->clk_info[i].clk_name, ret); goto clkerr; } } return; 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) { struct mtk_vcodec_clk *enc_clk = &pm->venc_clk; int i = 0; for (i = enc_clk->clk_num - 1; i >= 0; i--) clk_disable_unprepare(enc_clk->clk_info[i].vcodec_clk); } |