GNU Linux-libre 5.19-rc6-gnu
[releases.git] / drivers / media / platform / mediatek / vcodec / mtk_vcodec_enc_pm.c
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3 * Copyright (c) 2016 MediaTek Inc.
4 * Author: Tiffany Lin <tiffany.lin@mediatek.com>
5 */
6
7 #include <linux/clk.h>
8 #include <linux/of_address.h>
9 #include <linux/of_platform.h>
10 #include <linux/pm_runtime.h>
11
12 #include "mtk_vcodec_enc_pm.h"
13 #include "mtk_vcodec_util.h"
14
15 int mtk_vcodec_init_enc_clk(struct mtk_vcodec_dev *mtkdev)
16 {
17         struct platform_device *pdev;
18         struct mtk_vcodec_pm *pm;
19         struct mtk_vcodec_clk *enc_clk;
20         struct mtk_vcodec_clk_info *clk_info;
21         int ret, i;
22
23         pdev = mtkdev->plat_dev;
24         pm = &mtkdev->pm;
25         memset(pm, 0, sizeof(struct mtk_vcodec_pm));
26         pm->dev = &pdev->dev;
27         enc_clk = &pm->venc_clk;
28
29         enc_clk->clk_num = of_property_count_strings(pdev->dev.of_node,
30                 "clock-names");
31         if (enc_clk->clk_num > 0) {
32                 enc_clk->clk_info = devm_kcalloc(&pdev->dev,
33                         enc_clk->clk_num, sizeof(*clk_info),
34                         GFP_KERNEL);
35                 if (!enc_clk->clk_info)
36                         return -ENOMEM;
37         } else {
38                 mtk_v4l2_err("Failed to get venc clock count");
39                 return -EINVAL;
40         }
41
42         for (i = 0; i < enc_clk->clk_num; i++) {
43                 clk_info = &enc_clk->clk_info[i];
44                 ret = of_property_read_string_index(pdev->dev.of_node,
45                         "clock-names", i, &clk_info->clk_name);
46                 if (ret) {
47                         mtk_v4l2_err("venc failed to get clk name %d", i);
48                         return ret;
49                 }
50                 clk_info->vcodec_clk = devm_clk_get(&pdev->dev,
51                         clk_info->clk_name);
52                 if (IS_ERR(clk_info->vcodec_clk)) {
53                         mtk_v4l2_err("venc devm_clk_get (%d)%s fail", i,
54                                 clk_info->clk_name);
55                         return PTR_ERR(clk_info->vcodec_clk);
56                 }
57         }
58
59         return 0;
60 }
61
62 void mtk_vcodec_enc_clock_on(struct mtk_vcodec_pm *pm)
63 {
64         struct mtk_vcodec_clk *enc_clk = &pm->venc_clk;
65         int ret, i = 0;
66
67         for (i = 0; i < enc_clk->clk_num; i++) {
68                 ret = clk_prepare_enable(enc_clk->clk_info[i].vcodec_clk);
69                 if (ret) {
70                         mtk_v4l2_err("venc clk_prepare_enable %d %s fail %d", i,
71                                 enc_clk->clk_info[i].clk_name, ret);
72                         goto clkerr;
73                 }
74         }
75
76         return;
77
78 clkerr:
79         for (i -= 1; i >= 0; i--)
80                 clk_disable_unprepare(enc_clk->clk_info[i].vcodec_clk);
81 }
82
83 void mtk_vcodec_enc_clock_off(struct mtk_vcodec_pm *pm)
84 {
85         struct mtk_vcodec_clk *enc_clk = &pm->venc_clk;
86         int i = 0;
87
88         for (i = enc_clk->clk_num - 1; i >= 0; i--)
89                 clk_disable_unprepare(enc_clk->clk_info[i].vcodec_clk);
90 }