1 // SPDX-License-Identifier: GPL-2.0
3 * Copyright (c) 2016 MediaTek Inc.
4 * Author: Tiffany Lin <tiffany.lin@mediatek.com>
8 #include <linux/interrupt.h>
9 #include <linux/of_address.h>
10 #include <linux/of_platform.h>
11 #include <linux/pm_runtime.h>
13 #include "mtk_vcodec_dec_hw.h"
14 #include "mtk_vcodec_dec_pm.h"
15 #include "mtk_vcodec_util.h"
17 int mtk_vcodec_init_dec_clk(struct platform_device *pdev, struct mtk_vcodec_pm *pm)
19 struct mtk_vcodec_clk *dec_clk;
20 struct mtk_vcodec_clk_info *clk_info;
23 dec_clk = &pm->vdec_clk;
27 of_property_count_strings(pdev->dev.of_node, "clock-names");
28 if (dec_clk->clk_num > 0) {
29 dec_clk->clk_info = devm_kcalloc(&pdev->dev,
30 dec_clk->clk_num, sizeof(*clk_info),
32 if (!dec_clk->clk_info)
35 mtk_v4l2_err("Failed to get vdec clock count");
39 for (i = 0; i < dec_clk->clk_num; i++) {
40 clk_info = &dec_clk->clk_info[i];
41 ret = of_property_read_string_index(pdev->dev.of_node,
42 "clock-names", i, &clk_info->clk_name);
44 mtk_v4l2_err("Failed to get clock name id = %d", i);
47 clk_info->vcodec_clk = devm_clk_get(&pdev->dev,
49 if (IS_ERR(clk_info->vcodec_clk)) {
50 mtk_v4l2_err("devm_clk_get (%d)%s fail", i,
52 return PTR_ERR(clk_info->vcodec_clk);
58 EXPORT_SYMBOL_GPL(mtk_vcodec_init_dec_clk);
60 static int mtk_vcodec_dec_pw_on(struct mtk_vcodec_pm *pm)
64 ret = pm_runtime_resume_and_get(pm->dev);
66 mtk_v4l2_err("pm_runtime_resume_and_get fail %d", ret);
71 static void mtk_vcodec_dec_pw_off(struct mtk_vcodec_pm *pm)
75 ret = pm_runtime_put_sync(pm->dev);
77 mtk_v4l2_err("pm_runtime_put_sync fail %d", ret);
80 static void mtk_vcodec_dec_clock_on(struct mtk_vcodec_pm *pm)
82 struct mtk_vcodec_clk *dec_clk;
85 dec_clk = &pm->vdec_clk;
86 for (i = 0; i < dec_clk->clk_num; i++) {
87 ret = clk_prepare_enable(dec_clk->clk_info[i].vcodec_clk);
89 mtk_v4l2_err("clk_prepare_enable %d %s fail %d", i,
90 dec_clk->clk_info[i].clk_name, ret);
97 for (i -= 1; i >= 0; i--)
98 clk_disable_unprepare(dec_clk->clk_info[i].vcodec_clk);
101 static void mtk_vcodec_dec_clock_off(struct mtk_vcodec_pm *pm)
103 struct mtk_vcodec_clk *dec_clk;
106 dec_clk = &pm->vdec_clk;
107 for (i = dec_clk->clk_num - 1; i >= 0; i--)
108 clk_disable_unprepare(dec_clk->clk_info[i].vcodec_clk);
111 static void mtk_vcodec_dec_enable_irq(struct mtk_vcodec_dev *vdec_dev, int hw_idx)
113 struct mtk_vdec_hw_dev *subdev_dev;
115 if (!test_bit(hw_idx, vdec_dev->subdev_bitmap))
118 if (vdec_dev->vdec_pdata->is_subdev_supported) {
119 subdev_dev = mtk_vcodec_get_hw_dev(vdec_dev, hw_idx);
121 enable_irq(subdev_dev->dec_irq);
123 mtk_v4l2_err("Failed to get hw dev\n");
125 enable_irq(vdec_dev->dec_irq);
129 static void mtk_vcodec_dec_disable_irq(struct mtk_vcodec_dev *vdec_dev, int hw_idx)
131 struct mtk_vdec_hw_dev *subdev_dev;
133 if (!test_bit(hw_idx, vdec_dev->subdev_bitmap))
136 if (vdec_dev->vdec_pdata->is_subdev_supported) {
137 subdev_dev = mtk_vcodec_get_hw_dev(vdec_dev, hw_idx);
139 disable_irq(subdev_dev->dec_irq);
141 mtk_v4l2_err("Failed to get hw dev\n");
143 disable_irq(vdec_dev->dec_irq);
147 static struct mtk_vcodec_pm *mtk_vcodec_dec_get_pm(struct mtk_vcodec_dev *vdec_dev,
150 struct mtk_vdec_hw_dev *subdev_dev;
152 if (!test_bit(hw_idx, vdec_dev->subdev_bitmap))
155 if (vdec_dev->vdec_pdata->is_subdev_supported) {
156 subdev_dev = mtk_vcodec_get_hw_dev(vdec_dev, hw_idx);
158 return &subdev_dev->pm;
160 mtk_v4l2_err("Failed to get hw dev\n");
164 return &vdec_dev->pm;
167 static void mtk_vcodec_dec_child_dev_on(struct mtk_vcodec_dev *vdec_dev,
170 struct mtk_vcodec_pm *pm;
172 pm = mtk_vcodec_dec_get_pm(vdec_dev, hw_idx);
174 mtk_vcodec_dec_pw_on(pm);
175 mtk_vcodec_dec_clock_on(pm);
179 static void mtk_vcodec_dec_child_dev_off(struct mtk_vcodec_dev *vdec_dev,
182 struct mtk_vcodec_pm *pm;
184 pm = mtk_vcodec_dec_get_pm(vdec_dev, hw_idx);
186 mtk_vcodec_dec_clock_off(pm);
187 mtk_vcodec_dec_pw_off(pm);
191 void mtk_vcodec_dec_enable_hardware(struct mtk_vcodec_ctx *ctx, int hw_idx)
193 mutex_lock(&ctx->dev->dec_mutex[hw_idx]);
195 if (IS_VDEC_LAT_ARCH(ctx->dev->vdec_pdata->hw_arch) &&
196 hw_idx == MTK_VDEC_CORE)
197 mtk_vcodec_dec_child_dev_on(ctx->dev, MTK_VDEC_LAT0);
198 mtk_vcodec_dec_child_dev_on(ctx->dev, hw_idx);
200 mtk_vcodec_dec_enable_irq(ctx->dev, hw_idx);
202 EXPORT_SYMBOL_GPL(mtk_vcodec_dec_enable_hardware);
204 void mtk_vcodec_dec_disable_hardware(struct mtk_vcodec_ctx *ctx, int hw_idx)
206 mtk_vcodec_dec_disable_irq(ctx->dev, hw_idx);
208 mtk_vcodec_dec_child_dev_off(ctx->dev, hw_idx);
209 if (IS_VDEC_LAT_ARCH(ctx->dev->vdec_pdata->hw_arch) &&
210 hw_idx == MTK_VDEC_CORE)
211 mtk_vcodec_dec_child_dev_off(ctx->dev, MTK_VDEC_LAT0);
213 mutex_unlock(&ctx->dev->dec_mutex[hw_idx]);
215 EXPORT_SYMBOL_GPL(mtk_vcodec_dec_disable_hardware);