.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0 |
---|
1 | 2 | /* |
---|
2 | 3 | * Copyright (c) 2016 MediaTek Inc. |
---|
3 | 4 | * Author: Tiffany Lin <tiffany.lin@mediatek.com> |
---|
4 | | - * |
---|
5 | | - * This program is free software; you can redistribute it and/or modify |
---|
6 | | - * it under the terms of the GNU General Public License version 2 as |
---|
7 | | - * published by the Free Software Foundation. |
---|
8 | | - * |
---|
9 | | - * This program is distributed in the hope that it will be useful, |
---|
10 | | - * but WITHOUT ANY WARRANTY; without even the implied warranty of |
---|
11 | | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
---|
12 | | - * GNU General Public License for more details. |
---|
13 | 5 | */ |
---|
14 | 6 | |
---|
15 | 7 | #include <linux/clk.h> |
---|
.. | .. |
---|
20 | 12 | |
---|
21 | 13 | #include "mtk_vcodec_dec_pm.h" |
---|
22 | 14 | #include "mtk_vcodec_util.h" |
---|
23 | | -#include "mtk_vpu.h" |
---|
24 | 15 | |
---|
25 | 16 | int mtk_vcodec_init_dec_pm(struct mtk_vcodec_dev *mtkdev) |
---|
26 | 17 | { |
---|
27 | 18 | struct device_node *node; |
---|
28 | 19 | struct platform_device *pdev; |
---|
29 | 20 | struct mtk_vcodec_pm *pm; |
---|
30 | | - int ret = 0; |
---|
| 21 | + struct mtk_vcodec_clk *dec_clk; |
---|
| 22 | + struct mtk_vcodec_clk_info *clk_info; |
---|
| 23 | + int i = 0, ret = 0; |
---|
31 | 24 | |
---|
32 | 25 | pdev = mtkdev->plat_dev; |
---|
33 | 26 | pm = &mtkdev->pm; |
---|
34 | 27 | pm->mtkdev = mtkdev; |
---|
| 28 | + dec_clk = &pm->vdec_clk; |
---|
35 | 29 | node = of_parse_phandle(pdev->dev.of_node, "mediatek,larb", 0); |
---|
36 | 30 | if (!node) { |
---|
37 | 31 | mtk_v4l2_err("of_parse_phandle mediatek,larb fail!"); |
---|
.. | .. |
---|
39 | 33 | } |
---|
40 | 34 | |
---|
41 | 35 | pdev = of_find_device_by_node(node); |
---|
| 36 | + of_node_put(node); |
---|
42 | 37 | if (WARN_ON(!pdev)) { |
---|
43 | | - of_node_put(node); |
---|
44 | 38 | return -1; |
---|
45 | 39 | } |
---|
46 | 40 | pm->larbvdec = &pdev->dev; |
---|
47 | 41 | pdev = mtkdev->plat_dev; |
---|
48 | 42 | pm->dev = &pdev->dev; |
---|
49 | 43 | |
---|
50 | | - pm->vcodecpll = devm_clk_get(&pdev->dev, "vcodecpll"); |
---|
51 | | - if (IS_ERR(pm->vcodecpll)) { |
---|
52 | | - mtk_v4l2_err("devm_clk_get vcodecpll fail"); |
---|
53 | | - ret = PTR_ERR(pm->vcodecpll); |
---|
| 44 | + dec_clk->clk_num = |
---|
| 45 | + of_property_count_strings(pdev->dev.of_node, "clock-names"); |
---|
| 46 | + if (dec_clk->clk_num > 0) { |
---|
| 47 | + dec_clk->clk_info = devm_kcalloc(&pdev->dev, |
---|
| 48 | + dec_clk->clk_num, sizeof(*clk_info), |
---|
| 49 | + GFP_KERNEL); |
---|
| 50 | + if (!dec_clk->clk_info) { |
---|
| 51 | + ret = -ENOMEM; |
---|
| 52 | + goto put_device; |
---|
| 53 | + } |
---|
| 54 | + } else { |
---|
| 55 | + mtk_v4l2_err("Failed to get vdec clock count"); |
---|
| 56 | + ret = -EINVAL; |
---|
| 57 | + goto put_device; |
---|
54 | 58 | } |
---|
55 | 59 | |
---|
56 | | - pm->univpll_d2 = devm_clk_get(&pdev->dev, "univpll_d2"); |
---|
57 | | - if (IS_ERR(pm->univpll_d2)) { |
---|
58 | | - mtk_v4l2_err("devm_clk_get univpll_d2 fail"); |
---|
59 | | - ret = PTR_ERR(pm->univpll_d2); |
---|
60 | | - } |
---|
61 | | - |
---|
62 | | - pm->clk_cci400_sel = devm_clk_get(&pdev->dev, "clk_cci400_sel"); |
---|
63 | | - if (IS_ERR(pm->clk_cci400_sel)) { |
---|
64 | | - mtk_v4l2_err("devm_clk_get clk_cci400_sel fail"); |
---|
65 | | - ret = PTR_ERR(pm->clk_cci400_sel); |
---|
66 | | - } |
---|
67 | | - |
---|
68 | | - pm->vdec_sel = devm_clk_get(&pdev->dev, "vdec_sel"); |
---|
69 | | - if (IS_ERR(pm->vdec_sel)) { |
---|
70 | | - mtk_v4l2_err("devm_clk_get vdec_sel fail"); |
---|
71 | | - ret = PTR_ERR(pm->vdec_sel); |
---|
72 | | - } |
---|
73 | | - |
---|
74 | | - pm->vdecpll = devm_clk_get(&pdev->dev, "vdecpll"); |
---|
75 | | - if (IS_ERR(pm->vdecpll)) { |
---|
76 | | - mtk_v4l2_err("devm_clk_get vdecpll fail"); |
---|
77 | | - ret = PTR_ERR(pm->vdecpll); |
---|
78 | | - } |
---|
79 | | - |
---|
80 | | - pm->vencpll = devm_clk_get(&pdev->dev, "vencpll"); |
---|
81 | | - if (IS_ERR(pm->vencpll)) { |
---|
82 | | - mtk_v4l2_err("devm_clk_get vencpll fail"); |
---|
83 | | - ret = PTR_ERR(pm->vencpll); |
---|
84 | | - } |
---|
85 | | - |
---|
86 | | - pm->venc_lt_sel = devm_clk_get(&pdev->dev, "venc_lt_sel"); |
---|
87 | | - if (IS_ERR(pm->venc_lt_sel)) { |
---|
88 | | - mtk_v4l2_err("devm_clk_get venc_lt_sel fail"); |
---|
89 | | - ret = PTR_ERR(pm->venc_lt_sel); |
---|
90 | | - } |
---|
91 | | - |
---|
92 | | - pm->vdec_bus_clk_src = devm_clk_get(&pdev->dev, "vdec_bus_clk_src"); |
---|
93 | | - if (IS_ERR(pm->vdec_bus_clk_src)) { |
---|
94 | | - mtk_v4l2_err("devm_clk_get vdec_bus_clk_src"); |
---|
95 | | - ret = PTR_ERR(pm->vdec_bus_clk_src); |
---|
| 60 | + for (i = 0; i < dec_clk->clk_num; i++) { |
---|
| 61 | + clk_info = &dec_clk->clk_info[i]; |
---|
| 62 | + ret = of_property_read_string_index(pdev->dev.of_node, |
---|
| 63 | + "clock-names", i, &clk_info->clk_name); |
---|
| 64 | + if (ret) { |
---|
| 65 | + mtk_v4l2_err("Failed to get clock name id = %d", i); |
---|
| 66 | + goto put_device; |
---|
| 67 | + } |
---|
| 68 | + clk_info->vcodec_clk = devm_clk_get(&pdev->dev, |
---|
| 69 | + clk_info->clk_name); |
---|
| 70 | + if (IS_ERR(clk_info->vcodec_clk)) { |
---|
| 71 | + mtk_v4l2_err("devm_clk_get (%d)%s fail", i, |
---|
| 72 | + clk_info->clk_name); |
---|
| 73 | + ret = PTR_ERR(clk_info->vcodec_clk); |
---|
| 74 | + goto put_device; |
---|
| 75 | + } |
---|
96 | 76 | } |
---|
97 | 77 | |
---|
98 | 78 | pm_runtime_enable(&pdev->dev); |
---|
99 | | - |
---|
| 79 | + return 0; |
---|
| 80 | +put_device: |
---|
| 81 | + put_device(pm->larbvdec); |
---|
100 | 82 | return ret; |
---|
101 | 83 | } |
---|
102 | 84 | |
---|
.. | .. |
---|
106 | 88 | put_device(dev->pm.larbvdec); |
---|
107 | 89 | } |
---|
108 | 90 | |
---|
109 | | -void mtk_vcodec_dec_pw_on(struct mtk_vcodec_pm *pm) |
---|
| 91 | +int mtk_vcodec_dec_pw_on(struct mtk_vcodec_pm *pm) |
---|
110 | 92 | { |
---|
111 | 93 | int ret; |
---|
112 | 94 | |
---|
113 | | - ret = pm_runtime_get_sync(pm->dev); |
---|
| 95 | + ret = pm_runtime_resume_and_get(pm->dev); |
---|
114 | 96 | if (ret) |
---|
115 | | - mtk_v4l2_err("pm_runtime_get_sync fail %d", ret); |
---|
| 97 | + mtk_v4l2_err("pm_runtime_resume_and_get fail %d", ret); |
---|
| 98 | + |
---|
| 99 | + return ret; |
---|
116 | 100 | } |
---|
117 | 101 | |
---|
118 | 102 | void mtk_vcodec_dec_pw_off(struct mtk_vcodec_pm *pm) |
---|
.. | .. |
---|
126 | 110 | |
---|
127 | 111 | void mtk_vcodec_dec_clock_on(struct mtk_vcodec_pm *pm) |
---|
128 | 112 | { |
---|
129 | | - int ret; |
---|
| 113 | + struct mtk_vcodec_clk *dec_clk = &pm->vdec_clk; |
---|
| 114 | + int ret, i = 0; |
---|
130 | 115 | |
---|
131 | | - ret = clk_set_rate(pm->vcodecpll, 1482 * 1000000); |
---|
132 | | - if (ret) |
---|
133 | | - mtk_v4l2_err("clk_set_rate vcodecpll fail %d", ret); |
---|
134 | | - |
---|
135 | | - ret = clk_set_rate(pm->vencpll, 800 * 1000000); |
---|
136 | | - if (ret) |
---|
137 | | - mtk_v4l2_err("clk_set_rate vencpll fail %d", ret); |
---|
138 | | - |
---|
139 | | - ret = clk_prepare_enable(pm->vcodecpll); |
---|
140 | | - if (ret) |
---|
141 | | - mtk_v4l2_err("clk_prepare_enable vcodecpll fail %d", ret); |
---|
142 | | - |
---|
143 | | - ret = clk_prepare_enable(pm->vencpll); |
---|
144 | | - if (ret) |
---|
145 | | - mtk_v4l2_err("clk_prepare_enable vencpll fail %d", ret); |
---|
146 | | - |
---|
147 | | - ret = clk_prepare_enable(pm->vdec_bus_clk_src); |
---|
148 | | - if (ret) |
---|
149 | | - mtk_v4l2_err("clk_prepare_enable vdec_bus_clk_src fail %d", |
---|
150 | | - ret); |
---|
151 | | - |
---|
152 | | - ret = clk_prepare_enable(pm->venc_lt_sel); |
---|
153 | | - if (ret) |
---|
154 | | - mtk_v4l2_err("clk_prepare_enable venc_lt_sel fail %d", ret); |
---|
155 | | - |
---|
156 | | - ret = clk_set_parent(pm->venc_lt_sel, pm->vdec_bus_clk_src); |
---|
157 | | - if (ret) |
---|
158 | | - mtk_v4l2_err("clk_set_parent venc_lt_sel vdec_bus_clk_src fail %d", |
---|
159 | | - ret); |
---|
160 | | - |
---|
161 | | - ret = clk_prepare_enable(pm->univpll_d2); |
---|
162 | | - if (ret) |
---|
163 | | - mtk_v4l2_err("clk_prepare_enable univpll_d2 fail %d", ret); |
---|
164 | | - |
---|
165 | | - ret = clk_prepare_enable(pm->clk_cci400_sel); |
---|
166 | | - if (ret) |
---|
167 | | - mtk_v4l2_err("clk_prepare_enable clk_cci400_sel fail %d", ret); |
---|
168 | | - |
---|
169 | | - ret = clk_set_parent(pm->clk_cci400_sel, pm->univpll_d2); |
---|
170 | | - if (ret) |
---|
171 | | - mtk_v4l2_err("clk_set_parent clk_cci400_sel univpll_d2 fail %d", |
---|
172 | | - ret); |
---|
173 | | - |
---|
174 | | - ret = clk_prepare_enable(pm->vdecpll); |
---|
175 | | - if (ret) |
---|
176 | | - mtk_v4l2_err("clk_prepare_enable vdecpll fail %d", ret); |
---|
177 | | - |
---|
178 | | - ret = clk_prepare_enable(pm->vdec_sel); |
---|
179 | | - if (ret) |
---|
180 | | - mtk_v4l2_err("clk_prepare_enable vdec_sel fail %d", ret); |
---|
181 | | - |
---|
182 | | - ret = clk_set_parent(pm->vdec_sel, pm->vdecpll); |
---|
183 | | - if (ret) |
---|
184 | | - mtk_v4l2_err("clk_set_parent vdec_sel vdecpll fail %d", ret); |
---|
| 116 | + for (i = 0; i < dec_clk->clk_num; i++) { |
---|
| 117 | + ret = clk_prepare_enable(dec_clk->clk_info[i].vcodec_clk); |
---|
| 118 | + if (ret) { |
---|
| 119 | + mtk_v4l2_err("clk_prepare_enable %d %s fail %d", i, |
---|
| 120 | + dec_clk->clk_info[i].clk_name, ret); |
---|
| 121 | + goto error; |
---|
| 122 | + } |
---|
| 123 | + } |
---|
185 | 124 | |
---|
186 | 125 | ret = mtk_smi_larb_get(pm->larbvdec); |
---|
187 | | - if (ret) |
---|
| 126 | + if (ret) { |
---|
188 | 127 | mtk_v4l2_err("mtk_smi_larb_get larbvdec fail %d", ret); |
---|
| 128 | + goto error; |
---|
| 129 | + } |
---|
| 130 | + return; |
---|
189 | 131 | |
---|
| 132 | +error: |
---|
| 133 | + for (i -= 1; i >= 0; i--) |
---|
| 134 | + clk_disable_unprepare(dec_clk->clk_info[i].vcodec_clk); |
---|
190 | 135 | } |
---|
191 | 136 | |
---|
192 | 137 | void mtk_vcodec_dec_clock_off(struct mtk_vcodec_pm *pm) |
---|
193 | 138 | { |
---|
| 139 | + struct mtk_vcodec_clk *dec_clk = &pm->vdec_clk; |
---|
| 140 | + int i = 0; |
---|
| 141 | + |
---|
194 | 142 | mtk_smi_larb_put(pm->larbvdec); |
---|
195 | | - clk_disable_unprepare(pm->vdec_sel); |
---|
196 | | - clk_disable_unprepare(pm->vdecpll); |
---|
197 | | - clk_disable_unprepare(pm->univpll_d2); |
---|
198 | | - clk_disable_unprepare(pm->clk_cci400_sel); |
---|
199 | | - clk_disable_unprepare(pm->venc_lt_sel); |
---|
200 | | - clk_disable_unprepare(pm->vdec_bus_clk_src); |
---|
201 | | - clk_disable_unprepare(pm->vencpll); |
---|
202 | | - clk_disable_unprepare(pm->vcodecpll); |
---|
| 143 | + for (i = dec_clk->clk_num - 1; i >= 0; i--) |
---|
| 144 | + clk_disable_unprepare(dec_clk->clk_info[i].vcodec_clk); |
---|
203 | 145 | } |
---|