Linux Audio

Check our new training course

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