Merge tag 'regmap-fix-v5.11-rc2' of git://git.kernel.org/pub/scm/linux/kernel/git...
[linux/fpc-iii.git] / drivers / media / platform / s5p-mfc / s5p_mfc_pm.c
blob62d2320a72186364bcd61d5feb8f413389aff295
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3 * linux/drivers/media/platform/s5p-mfc/s5p_mfc_pm.c
5 * Copyright (c) 2010 Samsung Electronics Co., Ltd.
6 * http://www.samsung.com/
7 */
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"
17 static struct s5p_mfc_pm *pm;
18 static struct s5p_mfc_dev *p_dev;
19 static atomic_t clk_ref;
21 int s5p_mfc_init_pm(struct s5p_mfc_dev *dev)
23 int i;
25 pm = &dev->pm;
26 p_dev = dev;
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;
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;
42 mfc_err("Failed to get clock: %s\n",
43 pm->clk_names[i]);
44 return PTR_ERR(pm->clocks[i]);
48 if (dev->variant->use_clock_gating)
49 pm->clock_gate = pm->clocks[0];
51 pm_runtime_enable(pm->device);
52 atomic_set(&clk_ref, 0);
53 return 0;
56 void s5p_mfc_final_pm(struct s5p_mfc_dev *dev)
58 pm_runtime_disable(pm->device);
61 int s5p_mfc_clock_on(void)
63 atomic_inc(&clk_ref);
64 mfc_debug(3, "+ %d\n", atomic_read(&clk_ref));
66 return clk_enable(pm->clock_gate);
69 void s5p_mfc_clock_off(void)
71 atomic_dec(&clk_ref);
72 mfc_debug(3, "- %d\n", atomic_read(&clk_ref));
74 clk_disable(pm->clock_gate);
77 int s5p_mfc_power_on(void)
79 int i, ret = 0;
81 ret = pm_runtime_get_sync(pm->device);
82 if (ret < 0) {
83 pm_runtime_put_noidle(pm->device);
84 return ret;
87 /* clock control */
88 for (i = 0; i < pm->num_clocks; i++) {
89 ret = clk_prepare_enable(pm->clocks[i]);
90 if (ret < 0) {
91 mfc_err("clock prepare failed for clock: %s\n",
92 pm->clk_names[i]);
93 i++;
94 goto err;
98 /* prepare for software clock gating */
99 clk_disable(pm->clock_gate);
101 return 0;
102 err:
103 while (--i > 0)
104 clk_disable_unprepare(pm->clocks[i]);
105 pm_runtime_put(pm->device);
106 return ret;
109 int s5p_mfc_power_off(void)
111 int i;
113 /* finish software clock gating */
114 clk_enable(pm->clock_gate);
116 for (i = 0; i < pm->num_clocks; i++)
117 clk_disable_unprepare(pm->clocks[i]);
119 return pm_runtime_put_sync(pm->device);