Path: blob/master/sound/soc/tegra/tegra_asoc_utils.c
10817 views
/*1* tegra_asoc_utils.c - Harmony machine ASoC driver2*3* Author: Stephen Warren <[email protected]>4* Copyright (C) 2010 - NVIDIA, Inc.5*6* This program is free software; you can redistribute it and/or7* modify it under the terms of the GNU General Public License8* version 2 as published by the Free Software Foundation.9*10* This program is distributed in the hope that it will be useful, but11* WITHOUT ANY WARRANTY; without even the implied warranty of12* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU13* General Public License for more details.14*15* You should have received a copy of the GNU General Public License16* along with this program; if not, write to the Free Software17* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA18* 02110-1301 USA19*20*/2122#include <linux/clk.h>23#include <linux/device.h>24#include <linux/err.h>25#include <linux/kernel.h>2627#include "tegra_asoc_utils.h"2829int tegra_asoc_utils_set_rate(struct tegra_asoc_utils_data *data, int srate,30int mclk)31{32int new_baseclock;33bool clk_change;34int err;3536switch (srate) {37case 11025:38case 22050:39case 44100:40case 88200:41new_baseclock = 56448000;42break;43case 8000:44case 16000:45case 32000:46case 48000:47case 64000:48case 96000:49new_baseclock = 73728000;50break;51default:52return -EINVAL;53}5455clk_change = ((new_baseclock != data->set_baseclock) ||56(mclk != data->set_mclk));57if (!clk_change)58return 0;5960data->set_baseclock = 0;61data->set_mclk = 0;6263clk_disable(data->clk_cdev1);64clk_disable(data->clk_pll_a_out0);65clk_disable(data->clk_pll_a);6667err = clk_set_rate(data->clk_pll_a, new_baseclock);68if (err) {69dev_err(data->dev, "Can't set pll_a rate: %d\n", err);70return err;71}7273err = clk_set_rate(data->clk_pll_a_out0, mclk);74if (err) {75dev_err(data->dev, "Can't set pll_a_out0 rate: %d\n", err);76return err;77}7879/* Don't set cdev1 rate; its locked to pll_a_out0 */8081err = clk_enable(data->clk_pll_a);82if (err) {83dev_err(data->dev, "Can't enable pll_a: %d\n", err);84return err;85}8687err = clk_enable(data->clk_pll_a_out0);88if (err) {89dev_err(data->dev, "Can't enable pll_a_out0: %d\n", err);90return err;91}9293err = clk_enable(data->clk_cdev1);94if (err) {95dev_err(data->dev, "Can't enable cdev1: %d\n", err);96return err;97}9899data->set_baseclock = new_baseclock;100data->set_mclk = mclk;101102return 0;103}104EXPORT_SYMBOL_GPL(tegra_asoc_utils_set_rate);105106int tegra_asoc_utils_init(struct tegra_asoc_utils_data *data,107struct device *dev)108{109int ret;110111data->dev = dev;112113data->clk_pll_a = clk_get_sys(NULL, "pll_a");114if (IS_ERR(data->clk_pll_a)) {115dev_err(data->dev, "Can't retrieve clk pll_a\n");116ret = PTR_ERR(data->clk_pll_a);117goto err;118}119120data->clk_pll_a_out0 = clk_get_sys(NULL, "pll_a_out0");121if (IS_ERR(data->clk_pll_a_out0)) {122dev_err(data->dev, "Can't retrieve clk pll_a_out0\n");123ret = PTR_ERR(data->clk_pll_a_out0);124goto err_put_pll_a;125}126127data->clk_cdev1 = clk_get_sys(NULL, "cdev1");128if (IS_ERR(data->clk_cdev1)) {129dev_err(data->dev, "Can't retrieve clk cdev1\n");130ret = PTR_ERR(data->clk_cdev1);131goto err_put_pll_a_out0;132}133134return 0;135136err_put_pll_a_out0:137clk_put(data->clk_pll_a_out0);138err_put_pll_a:139clk_put(data->clk_pll_a);140err:141return ret;142}143EXPORT_SYMBOL_GPL(tegra_asoc_utils_init);144145void tegra_asoc_utils_fini(struct tegra_asoc_utils_data *data)146{147clk_put(data->clk_cdev1);148clk_put(data->clk_pll_a_out0);149clk_put(data->clk_pll_a);150}151EXPORT_SYMBOL_GPL(tegra_asoc_utils_fini);152153MODULE_AUTHOR("Stephen Warren <[email protected]>");154MODULE_DESCRIPTION("Tegra ASoC utility code");155MODULE_LICENSE("GPL");156157158