Loading...
1// SPDX-License-Identifier: GPL-2.0-or-later
2/*
3 * linux/drivers/media/platform/samsung/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
17int s5p_mfc_init_pm(struct s5p_mfc_dev *dev)
18{
19 struct s5p_mfc_pm *pm = &dev->pm;
20 int i;
21
22 pm->num_clocks = dev->variant->num_clocks;
23 pm->clk_names = dev->variant->clk_names;
24 pm->device = &dev->plat_dev->dev;
25 pm->clock_gate = NULL;
26
27 /* clock control */
28 for (i = 0; i < pm->num_clocks; i++) {
29 pm->clocks[i] = devm_clk_get(pm->device, pm->clk_names[i]);
30 if (IS_ERR(pm->clocks[i])) {
31 /* additional clocks are optional */
32 if (i && PTR_ERR(pm->clocks[i]) == -ENOENT) {
33 pm->clocks[i] = NULL;
34 continue;
35 }
36 mfc_err("Failed to get clock: %s\n",
37 pm->clk_names[i]);
38 return PTR_ERR(pm->clocks[i]);
39 }
40 }
41
42 if (dev->variant->use_clock_gating)
43 pm->clock_gate = pm->clocks[0];
44
45 pm_runtime_enable(pm->device);
46 return 0;
47}
48
49void s5p_mfc_final_pm(struct s5p_mfc_dev *dev)
50{
51 pm_runtime_disable(dev->pm.device);
52}
53
54int s5p_mfc_clock_on(struct s5p_mfc_dev *dev)
55{
56 return clk_enable(dev->pm.clock_gate);
57}
58
59void s5p_mfc_clock_off(struct s5p_mfc_dev *dev)
60{
61 clk_disable(dev->pm.clock_gate);
62}
63
64int s5p_mfc_power_on(struct s5p_mfc_dev *dev)
65{
66 int i, ret = 0;
67
68 ret = pm_runtime_resume_and_get(dev->pm.device);
69 if (ret < 0)
70 return ret;
71
72 /* clock control */
73 for (i = 0; i < dev->pm.num_clocks; i++) {
74 ret = clk_prepare_enable(dev->pm.clocks[i]);
75 if (ret < 0) {
76 mfc_err("clock prepare failed for clock: %s\n",
77 dev->pm.clk_names[i]);
78 goto err;
79 }
80 }
81
82 /* prepare for software clock gating */
83 clk_disable(dev->pm.clock_gate);
84
85 return 0;
86err:
87 while (--i >= 0)
88 clk_disable_unprepare(dev->pm.clocks[i]);
89 pm_runtime_put(dev->pm.device);
90 return ret;
91}
92
93int s5p_mfc_power_off(struct s5p_mfc_dev *dev)
94{
95 int i;
96
97 /* finish software clock gating */
98 clk_enable(dev->pm.clock_gate);
99
100 for (i = 0; i < dev->pm.num_clocks; i++)
101 clk_disable_unprepare(dev->pm.clocks[i]);
102
103 return pm_runtime_put_sync(dev->pm.device);
104}
105