linux/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_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_enc_pm.h"
  14#include "mtk_vcodec_util.h"
  15
  16int mtk_vcodec_init_enc_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 *enc_clk;
  22        struct mtk_vcodec_clk_info *clk_info;
  23        int ret = 0, i = 0;
  24        struct device *dev;
  25
  26        pdev = mtkdev->plat_dev;
  27        pm = &mtkdev->pm;
  28        memset(pm, 0, sizeof(struct mtk_vcodec_pm));
  29        pm->mtkdev = mtkdev;
  30        pm->dev = &pdev->dev;
  31        dev = &pdev->dev;
  32        enc_clk = &pm->venc_clk;
  33
  34        node = of_parse_phandle(dev->of_node, "mediatek,larb", 0);
  35        if (!node) {
  36                mtk_v4l2_err("no mediatek,larb found");
  37                return -ENODEV;
  38        }
  39        pdev = of_find_device_by_node(node);
  40        of_node_put(node);
  41        if (!pdev) {
  42                mtk_v4l2_err("no mediatek,larb device found");
  43                return -ENODEV;
  44        }
  45        pm->larbvenc = &pdev->dev;
  46        pdev = mtkdev->plat_dev;
  47        pm->dev = &pdev->dev;
  48
  49        enc_clk->clk_num = of_property_count_strings(pdev->dev.of_node,
  50                "clock-names");
  51        if (enc_clk->clk_num > 0) {
  52                enc_clk->clk_info = devm_kcalloc(&pdev->dev,
  53                        enc_clk->clk_num, sizeof(*clk_info),
  54                        GFP_KERNEL);
  55                if (!enc_clk->clk_info) {
  56                        ret = -ENOMEM;
  57                        goto put_larbvenc;
  58                }
  59        } else {
  60                mtk_v4l2_err("Failed to get venc clock count");
  61                ret = -EINVAL;
  62                goto put_larbvenc;
  63        }
  64
  65        for (i = 0; i < enc_clk->clk_num; i++) {
  66                clk_info = &enc_clk->clk_info[i];
  67                ret = of_property_read_string_index(pdev->dev.of_node,
  68                        "clock-names", i, &clk_info->clk_name);
  69                if (ret) {
  70                        mtk_v4l2_err("venc failed to get clk name %d", i);
  71                        goto put_larbvenc;
  72                }
  73                clk_info->vcodec_clk = devm_clk_get(&pdev->dev,
  74                        clk_info->clk_name);
  75                if (IS_ERR(clk_info->vcodec_clk)) {
  76                        mtk_v4l2_err("venc devm_clk_get (%d)%s fail", i,
  77                                clk_info->clk_name);
  78                        ret = PTR_ERR(clk_info->vcodec_clk);
  79                        goto put_larbvenc;
  80                }
  81        }
  82
  83        return 0;
  84
  85put_larbvenc:
  86        put_device(pm->larbvenc);
  87        return ret;
  88}
  89
  90void mtk_vcodec_release_enc_pm(struct mtk_vcodec_dev *mtkdev)
  91{
  92        pm_runtime_disable(mtkdev->pm.dev);
  93        put_device(mtkdev->pm.larbvenc);
  94}
  95
  96
  97void mtk_vcodec_enc_clock_on(struct mtk_vcodec_pm *pm)
  98{
  99        struct mtk_vcodec_clk *enc_clk = &pm->venc_clk;
 100        int ret, i = 0;
 101
 102        for (i = 0; i < enc_clk->clk_num; i++) {
 103                ret = clk_prepare_enable(enc_clk->clk_info[i].vcodec_clk);
 104                if (ret) {
 105                        mtk_v4l2_err("venc clk_prepare_enable %d %s fail %d", i,
 106                                enc_clk->clk_info[i].clk_name, ret);
 107                        goto clkerr;
 108                }
 109        }
 110
 111        ret = mtk_smi_larb_get(pm->larbvenc);
 112        if (ret) {
 113                mtk_v4l2_err("mtk_smi_larb_get larb3 fail %d", ret);
 114                goto clkerr;
 115        }
 116        return;
 117
 118clkerr:
 119        for (i -= 1; i >= 0; i--)
 120                clk_disable_unprepare(enc_clk->clk_info[i].vcodec_clk);
 121}
 122
 123void mtk_vcodec_enc_clock_off(struct mtk_vcodec_pm *pm)
 124{
 125        struct mtk_vcodec_clk *enc_clk = &pm->venc_clk;
 126        int i = 0;
 127
 128        mtk_smi_larb_put(pm->larbvenc);
 129        for (i = enc_clk->clk_num - 1; i >= 0; i--)
 130                clk_disable_unprepare(enc_clk->clk_info[i].vcodec_clk);
 131}
 132