linux/drivers/media/platform/s5p-mfc/s5p_mfc_pm.c
<<
>>
Prefs
   1/*
   2 * linux/drivers/media/platform/s5p-mfc/s5p_mfc_pm.c
   3 *
   4 * Copyright (c) 2010 Samsung Electronics Co., Ltd.
   5 *              http://www.samsung.com/
   6 *
   7 * This program is free software; you can redistribute it and/or modify
   8 * it under the terms of the GNU General Public License as published by
   9 * the Free Software Foundation; either version 2 of the License, or
  10 * (at your option) any later version.
  11 */
  12
  13#include <linux/clk.h>
  14#include <linux/err.h>
  15#include <linux/platform_device.h>
  16#include <linux/pm_runtime.h>
  17#include "s5p_mfc_common.h"
  18#include "s5p_mfc_debug.h"
  19#include "s5p_mfc_pm.h"
  20
  21#define MFC_GATE_CLK_NAME       "mfc"
  22#define MFC_SCLK_NAME           "sclk_mfc"
  23#define MFC_SCLK_RATE           (200 * 1000000)
  24
  25#define CLK_DEBUG
  26
  27static struct s5p_mfc_pm *pm;
  28static struct s5p_mfc_dev *p_dev;
  29
  30#ifdef CLK_DEBUG
  31static atomic_t clk_ref;
  32#endif
  33
  34int s5p_mfc_init_pm(struct s5p_mfc_dev *dev)
  35{
  36        int ret = 0;
  37
  38        pm = &dev->pm;
  39        p_dev = dev;
  40        pm->clock_gate = clk_get(&dev->plat_dev->dev, MFC_GATE_CLK_NAME);
  41        if (IS_ERR(pm->clock_gate)) {
  42                mfc_err("Failed to get clock-gating control\n");
  43                ret = PTR_ERR(pm->clock_gate);
  44                goto err_g_ip_clk;
  45        }
  46
  47        ret = clk_prepare(pm->clock_gate);
  48        if (ret) {
  49                mfc_err("Failed to prepare clock-gating control\n");
  50                goto err_p_ip_clk;
  51        }
  52
  53        if (dev->variant->version != MFC_VERSION_V6) {
  54                pm->clock = clk_get(&dev->plat_dev->dev, MFC_SCLK_NAME);
  55                if (IS_ERR(pm->clock)) {
  56                        mfc_info("Failed to get MFC special clock control\n");
  57                } else {
  58                        clk_set_rate(pm->clock, MFC_SCLK_RATE);
  59                        ret = clk_prepare_enable(pm->clock);
  60                        if (ret) {
  61                                mfc_err("Failed to enable MFC special clock\n");
  62                                goto err_s_clk;
  63                        }
  64                }
  65        }
  66
  67        atomic_set(&pm->power, 0);
  68#ifdef CONFIG_PM
  69        pm->device = &dev->plat_dev->dev;
  70        pm_runtime_enable(pm->device);
  71#endif
  72#ifdef CLK_DEBUG
  73        atomic_set(&clk_ref, 0);
  74#endif
  75        return 0;
  76
  77err_s_clk:
  78        clk_put(pm->clock);
  79err_p_ip_clk:
  80        clk_put(pm->clock_gate);
  81err_g_ip_clk:
  82        return ret;
  83}
  84
  85void s5p_mfc_final_pm(struct s5p_mfc_dev *dev)
  86{
  87        if (dev->variant->version != MFC_VERSION_V6 &&
  88            pm->clock) {
  89                clk_disable_unprepare(pm->clock);
  90                clk_put(pm->clock);
  91        }
  92        clk_unprepare(pm->clock_gate);
  93        clk_put(pm->clock_gate);
  94#ifdef CONFIG_PM
  95        pm_runtime_disable(pm->device);
  96#endif
  97}
  98
  99int s5p_mfc_clock_on(void)
 100{
 101        int ret;
 102#ifdef CLK_DEBUG
 103        atomic_inc(&clk_ref);
 104        mfc_debug(3, "+ %d\n", atomic_read(&clk_ref));
 105#endif
 106        ret = clk_enable(pm->clock_gate);
 107        return ret;
 108}
 109
 110void s5p_mfc_clock_off(void)
 111{
 112#ifdef CLK_DEBUG
 113        atomic_dec(&clk_ref);
 114        mfc_debug(3, "- %d\n", atomic_read(&clk_ref));
 115#endif
 116        clk_disable(pm->clock_gate);
 117}
 118
 119int s5p_mfc_power_on(void)
 120{
 121#ifdef CONFIG_PM
 122        return pm_runtime_get_sync(pm->device);
 123#else
 124        atomic_set(&pm->power, 1);
 125        return 0;
 126#endif
 127}
 128
 129int s5p_mfc_power_off(void)
 130{
 131#ifdef CONFIG_PM
 132        return pm_runtime_put_sync(pm->device);
 133#else
 134        atomic_set(&pm->power, 0);
 135        return 0;
 136#endif
 137}
 138
 139
 140