linux/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_pm.c
<<
>>
Prefs
   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#include <soc/mediatek/smi.h>
  12
  13#include "mtk_vcodec_dec_pm.h"
  14#include "mtk_vcodec_util.h"
  15
  16int mtk_vcodec_init_dec_pm(struct mtk_vcodec_dev *mtkdev)
  17{
  18        struct device_node *node;
  19        struct platform_device *pdev;
  20        struct mtk_vcodec_pm *pm;
  21        struct mtk_vcodec_clk *dec_clk;
  22        struct mtk_vcodec_clk_info *clk_info;
  23        int i = 0, ret = 0;
  24
  25        pdev = mtkdev->plat_dev;
  26        pm = &mtkdev->pm;
  27        pm->mtkdev = mtkdev;
  28        dec_clk = &pm->vdec_clk;
  29        node = of_parse_phandle(pdev->dev.of_node, "mediatek,larb", 0);
  30        if (!node) {
  31                mtk_v4l2_err("of_parse_phandle mediatek,larb fail!");
  32                return -1;
  33        }
  34
  35        pdev = of_find_device_by_node(node);
  36        of_node_put(node);
  37        if (WARN_ON(!pdev)) {
  38                return -1;
  39        }
  40        pm->larbvdec = &pdev->dev;
  41        pdev = mtkdev->plat_dev;
  42        pm->dev = &pdev->dev;
  43
  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;
  58        }
  59
  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                }
  76        }
  77
  78        pm_runtime_enable(&pdev->dev);
  79        return 0;
  80put_device:
  81        put_device(pm->larbvdec);
  82        return ret;
  83}
  84
  85void mtk_vcodec_release_dec_pm(struct mtk_vcodec_dev *dev)
  86{
  87        pm_runtime_disable(dev->pm.dev);
  88        put_device(dev->pm.larbvdec);
  89}
  90
  91int mtk_vcodec_dec_pw_on(struct mtk_vcodec_pm *pm)
  92{
  93        int ret;
  94
  95        ret = pm_runtime_resume_and_get(pm->dev);
  96        if (ret)
  97                mtk_v4l2_err("pm_runtime_resume_and_get fail %d", ret);
  98
  99        return ret;
 100}
 101
 102void mtk_vcodec_dec_pw_off(struct mtk_vcodec_pm *pm)
 103{
 104        int ret;
 105
 106        ret = pm_runtime_put_sync(pm->dev);
 107        if (ret)
 108                mtk_v4l2_err("pm_runtime_put_sync fail %d", ret);
 109}
 110
 111void mtk_vcodec_dec_clock_on(struct mtk_vcodec_pm *pm)
 112{
 113        struct mtk_vcodec_clk *dec_clk = &pm->vdec_clk;
 114        int ret, i = 0;
 115
 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        }
 124
 125        ret = mtk_smi_larb_get(pm->larbvdec);
 126        if (ret) {
 127                mtk_v4l2_err("mtk_smi_larb_get larbvdec fail %d", ret);
 128                goto error;
 129        }
 130        return;
 131
 132error:
 133        for (i -= 1; i >= 0; i--)
 134                clk_disable_unprepare(dec_clk->clk_info[i].vcodec_clk);
 135}
 136
 137void mtk_vcodec_dec_clock_off(struct mtk_vcodec_pm *pm)
 138{
 139        struct mtk_vcodec_clk *dec_clk = &pm->vdec_clk;
 140        int i = 0;
 141
 142        mtk_smi_larb_put(pm->larbvdec);
 143        for (i = dec_clk->clk_num - 1; i >= 0; i--)
 144                clk_disable_unprepare(dec_clk->clk_info[i].vcodec_clk);
 145}
 146