1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * linux/drivers/media/platform/s5p-mfc/s5p_mfc_pm.c
5 * Copyright (c) 2010 Samsung Electronics Co., Ltd.
6 * http://www.samsung.com/
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
)
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
;
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
) {
42 mfc_err("Failed to get clock: %s\n",
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);
56 void s5p_mfc_final_pm(struct s5p_mfc_dev
*dev
)
58 pm_runtime_disable(pm
->device
);
61 int s5p_mfc_clock_on(void)
64 mfc_debug(3, "+ %d\n", atomic_read(&clk_ref
));
66 return clk_enable(pm
->clock_gate
);
69 void s5p_mfc_clock_off(void)
72 mfc_debug(3, "- %d\n", atomic_read(&clk_ref
));
74 clk_disable(pm
->clock_gate
);
77 int s5p_mfc_power_on(void)
81 ret
= pm_runtime_get_sync(pm
->device
);
83 pm_runtime_put_noidle(pm
->device
);
88 for (i
= 0; i
< pm
->num_clocks
; i
++) {
89 ret
= clk_prepare_enable(pm
->clocks
[i
]);
91 mfc_err("clock prepare failed for clock: %s\n",
98 /* prepare for software clock gating */
99 clk_disable(pm
->clock_gate
);
104 clk_disable_unprepare(pm
->clocks
[i
]);
105 pm_runtime_put(pm
->device
);
109 int s5p_mfc_power_off(void)
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
);