root/drivers/media/platform/s5p-mfc/s5p_mfc_pm.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. s5p_mfc_init_pm
  2. s5p_mfc_final_pm
  3. s5p_mfc_clock_on
  4. s5p_mfc_clock_off
  5. s5p_mfc_power_on
  6. s5p_mfc_power_off

   1 // SPDX-License-Identifier: GPL-2.0-or-later
   2 /*
   3  * linux/drivers/media/platform/s5p-mfc/s5p_mfc_pm.c
   4  *
   5  * Copyright (c) 2010 Samsung Electronics Co., Ltd.
   6  *              http://www.samsung.com/
   7  */
   8 
   9 #include <linux/clk.h>
  10 #include <linux/err.h>
  11 #include <linux/platform_device.h>
  12 #include <linux/pm_runtime.h>
  13 #include "s5p_mfc_common.h"
  14 #include "s5p_mfc_debug.h"
  15 #include "s5p_mfc_pm.h"
  16 
  17 static struct s5p_mfc_pm *pm;
  18 static struct s5p_mfc_dev *p_dev;
  19 static atomic_t clk_ref;
  20 
  21 int s5p_mfc_init_pm(struct s5p_mfc_dev *dev)
  22 {
  23         int i;
  24 
  25         pm = &dev->pm;
  26         p_dev = dev;
  27 
  28         pm->num_clocks = dev->variant->num_clocks;
  29         pm->clk_names = dev->variant->clk_names;
  30         pm->device = &dev->plat_dev->dev;
  31         pm->clock_gate = NULL;
  32 
  33         /* clock control */
  34         for (i = 0; i < pm->num_clocks; i++) {
  35                 pm->clocks[i] = devm_clk_get(pm->device, pm->clk_names[i]);
  36                 if (IS_ERR(pm->clocks[i])) {
  37                         /* additional clocks are optional */
  38                         if (i && PTR_ERR(pm->clocks[i]) == -ENOENT) {
  39                                 pm->clocks[i] = NULL;
  40                                 continue;
  41                         }
  42                         mfc_err("Failed to get clock: %s\n",
  43                                 pm->clk_names[i]);
  44                         return PTR_ERR(pm->clocks[i]);
  45                 }
  46         }
  47 
  48         if (dev->variant->use_clock_gating)
  49                 pm->clock_gate = pm->clocks[0];
  50 
  51         pm_runtime_enable(pm->device);
  52         atomic_set(&clk_ref, 0);
  53         return 0;
  54 }
  55 
  56 void s5p_mfc_final_pm(struct s5p_mfc_dev *dev)
  57 {
  58         pm_runtime_disable(pm->device);
  59 }
  60 
  61 int s5p_mfc_clock_on(void)
  62 {
  63         atomic_inc(&clk_ref);
  64         mfc_debug(3, "+ %d\n", atomic_read(&clk_ref));
  65 
  66         return clk_enable(pm->clock_gate);
  67 }
  68 
  69 void s5p_mfc_clock_off(void)
  70 {
  71         atomic_dec(&clk_ref);
  72         mfc_debug(3, "- %d\n", atomic_read(&clk_ref));
  73 
  74         clk_disable(pm->clock_gate);
  75 }
  76 
  77 int s5p_mfc_power_on(void)
  78 {
  79         int i, ret = 0;
  80 
  81         ret = pm_runtime_get_sync(pm->device);
  82         if (ret < 0)
  83                 return ret;
  84 
  85         /* clock control */
  86         for (i = 0; i < pm->num_clocks; i++) {
  87                 ret = clk_prepare_enable(pm->clocks[i]);
  88                 if (ret < 0) {
  89                         mfc_err("clock prepare failed for clock: %s\n",
  90                                 pm->clk_names[i]);
  91                         i++;
  92                         goto err;
  93                 }
  94         }
  95 
  96         /* prepare for software clock gating */
  97         clk_disable(pm->clock_gate);
  98 
  99         return 0;
 100 err:
 101         while (--i > 0)
 102                 clk_disable_unprepare(pm->clocks[i]);
 103         pm_runtime_put(pm->device);
 104         return ret;
 105 }
 106 
 107 int s5p_mfc_power_off(void)
 108 {
 109         int i;
 110 
 111         /* finish software clock gating */
 112         clk_enable(pm->clock_gate);
 113 
 114         for (i = 0; i < pm->num_clocks; i++)
 115                 clk_disable_unprepare(pm->clocks[i]);
 116 
 117         return pm_runtime_put_sync(pm->device);
 118 }
 119 

/* [<][>][^][v][top][bottom][index][help] */