| OLD | NEW |
| 1 /* | 1 /* |
| 2 * tegra_asoc_utils.c - Harmony machine ASoC driver | 2 * tegra_asoc_utils.c - Harmony machine ASoC driver |
| 3 * | 3 * |
| 4 * Author: Stephen Warren <swarren@nvidia.com> | 4 * Author: Stephen Warren <swarren@nvidia.com> |
| 5 * Copyright (C) 2010 - NVIDIA, Inc. | 5 * Copyright (C) 2010 - NVIDIA, Inc. |
| 6 * | 6 * |
| 7 * This program is free software; you can redistribute it and/or | 7 * This program is free software; you can redistribute it and/or |
| 8 * modify it under the terms of the GNU General Public License | 8 * modify it under the terms of the GNU General Public License |
| 9 * version 2 as published by the Free Software Foundation. | 9 * version 2 as published by the Free Software Foundation. |
| 10 * | 10 * |
| 11 * This program is distributed in the hope that it will be useful, but | 11 * This program is distributed in the hope that it will be useful, but |
| 12 * WITHOUT ANY WARRANTY; without even the implied warranty of | 12 * WITHOUT ANY WARRANTY; without even the implied warranty of |
| 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| 14 * General Public License for more details. | 14 * General Public License for more details. |
| 15 * | 15 * |
| 16 * You should have received a copy of the GNU General Public License | 16 * You should have received a copy of the GNU General Public License |
| 17 * along with this program; if not, write to the Free Software | 17 * along with this program; if not, write to the Free Software |
| 18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA | 18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA |
| 19 * 02110-1301 USA | 19 * 02110-1301 USA |
| 20 * | 20 * |
| 21 */ | 21 */ |
| 22 | 22 |
| 23 #include <linux/clk.h> | 23 #include <linux/clk.h> |
| 24 #include <linux/device.h> |
| 24 #include <linux/err.h> | 25 #include <linux/err.h> |
| 25 #include <linux/kernel.h> | 26 #include <linux/kernel.h> |
| 26 | 27 |
| 27 #include "tegra_asoc_utils.h" | 28 #include "tegra_asoc_utils.h" |
| 28 | 29 |
| 29 #define PREFIX "ASoC Tegra: " | 30 int tegra_asoc_utils_set_rate(struct tegra_asoc_utils_data *data, int srate, |
| 30 | 31 » » » int mclk, int *mclk_change) |
| 31 static struct clk *clk_pll_a; | |
| 32 static struct clk *clk_pll_a_out0; | |
| 33 static struct clk *clk_cdev1; | |
| 34 | |
| 35 static int set_baseclock, set_mclk; | |
| 36 | |
| 37 int tegra_asoc_utils_set_rate(int srate, int mclk, int *mclk_change) | |
| 38 { | 32 { |
| 39 int new_baseclock; | 33 int new_baseclock; |
| 40 int err; | 34 int err; |
| 41 | 35 |
| 42 switch (srate) { | 36 switch (srate) { |
| 43 case 11025: | 37 case 11025: |
| 44 case 22050: | 38 case 22050: |
| 45 case 44100: | 39 case 44100: |
| 46 case 88200: | 40 case 88200: |
| 47 new_baseclock = 56448000; | 41 new_baseclock = 56448000; |
| 48 break; | 42 break; |
| 49 case 8000: | 43 case 8000: |
| 50 case 16000: | 44 case 16000: |
| 51 case 32000: | 45 case 32000: |
| 52 case 48000: | 46 case 48000: |
| 53 case 64000: | 47 case 64000: |
| 54 case 96000: | 48 case 96000: |
| 55 new_baseclock = 73728000; | 49 new_baseclock = 73728000; |
| 56 break; | 50 break; |
| 57 default: | 51 default: |
| 58 return -EINVAL; | 52 return -EINVAL; |
| 59 } | 53 } |
| 60 | 54 |
| 61 » *mclk_change = ((new_baseclock != set_baseclock) || | 55 » *mclk_change = ((new_baseclock != data->set_baseclock) || |
| 62 » » » (mclk != set_mclk)); | 56 » » » (mclk != data->set_mclk)); |
| 63 if (!*mclk_change) | 57 if (!*mclk_change) |
| 64 return 0; | 58 return 0; |
| 65 | 59 |
| 66 » set_baseclock = 0; | 60 » data->set_baseclock = 0; |
| 67 » set_mclk = 0; | 61 » data->set_mclk = 0; |
| 68 | 62 |
| 69 » clk_disable(clk_cdev1); | 63 » clk_disable(data->clk_cdev1); |
| 70 » clk_disable(clk_pll_a_out0); | 64 » clk_disable(data->clk_pll_a_out0); |
| 71 » clk_disable(clk_pll_a); | 65 » clk_disable(data->clk_pll_a); |
| 72 | 66 |
| 73 » err = clk_set_rate(clk_pll_a, new_baseclock); | 67 » err = clk_set_rate(data->clk_pll_a, new_baseclock); |
| 74 if (err) { | 68 if (err) { |
| 75 » » pr_err(PREFIX "Can't set pll_a rate: %d\n", err); | 69 » » dev_err(data->dev, "Can't set pll_a rate: %d\n", err); |
| 76 return err; | 70 return err; |
| 77 } | 71 } |
| 78 | 72 |
| 79 » err = clk_set_rate(clk_pll_a_out0, mclk); | 73 » err = clk_set_rate(data->clk_pll_a_out0, mclk); |
| 80 if (err) { | 74 if (err) { |
| 81 » » pr_err(PREFIX "Can't set pll_a_out0 rate: %d\n", err); | 75 » » dev_err(data->dev, "Can't set pll_a_out0 rate: %d\n", err); |
| 82 return err; | 76 return err; |
| 83 } | 77 } |
| 84 | 78 |
| 85 /* Don't set cdev1 rate; its locked to pll_a_out0 */ | 79 /* Don't set cdev1 rate; its locked to pll_a_out0 */ |
| 86 | 80 |
| 87 » err = clk_enable(clk_pll_a); | 81 » err = clk_enable(data->clk_pll_a); |
| 88 if (err) { | 82 if (err) { |
| 89 » » pr_err(PREFIX "Can't enable pll_a: %d\n", err); | 83 » » dev_err(data->dev, "Can't enable pll_a: %d\n", err); |
| 90 return err; | 84 return err; |
| 91 } | 85 } |
| 92 | 86 |
| 93 » err = clk_enable(clk_pll_a_out0); | 87 » err = clk_enable(data->clk_pll_a_out0); |
| 94 if (err) { | 88 if (err) { |
| 95 » » pr_err(PREFIX "Can't enable pll_a_out0: %d\n", err); | 89 » » dev_err(data->dev, "Can't enable pll_a_out0: %d\n", err); |
| 96 return err; | 90 return err; |
| 97 } | 91 } |
| 98 | 92 |
| 99 » err = clk_enable(clk_cdev1); | 93 » err = clk_enable(data->clk_cdev1); |
| 100 if (err) { | 94 if (err) { |
| 101 » » pr_err(PREFIX "Can't enable cdev1: %d\n", err); | 95 » » dev_err(data->dev, "Can't enable cdev1: %d\n", err); |
| 102 return err; | 96 return err; |
| 103 } | 97 } |
| 104 | 98 |
| 105 » set_baseclock = new_baseclock; | 99 » data->set_baseclock = new_baseclock; |
| 106 » set_mclk = mclk; | 100 » data->set_mclk = mclk; |
| 107 | 101 |
| 108 return 0; | 102 return 0; |
| 109 } | 103 } |
| 110 | 104 |
| 111 int tegra_asoc_utils_init(void) | 105 int tegra_asoc_utils_init(struct tegra_asoc_utils_data *data, |
| 106 » » » struct device *dev) |
| 112 { | 107 { |
| 113 int ret; | 108 int ret; |
| 114 | 109 |
| 115 » clk_pll_a = clk_get_sys(NULL, "pll_a"); | 110 » data->dev = dev; |
| 116 » if (IS_ERR(clk_pll_a)) { | 111 |
| 117 » » pr_err(PREFIX "Can't retrieve clk pll_a\n"); | 112 » data->clk_pll_a = clk_get_sys(NULL, "pll_a"); |
| 118 » » ret = PTR_ERR(clk_pll_a); | 113 » if (IS_ERR(data->clk_pll_a)) { |
| 114 » » dev_err(data->dev, "Can't retrieve clk pll_a\n"); |
| 115 » » ret = PTR_ERR(data->clk_pll_a); |
| 119 goto err; | 116 goto err; |
| 120 } | 117 } |
| 121 | 118 |
| 122 » clk_pll_a_out0 = clk_get_sys(NULL, "pll_a_out0"); | 119 » data->clk_pll_a_out0 = clk_get_sys(NULL, "pll_a_out0"); |
| 123 » if (IS_ERR(clk_pll_a_out0)) { | 120 » if (IS_ERR(data->clk_pll_a_out0)) { |
| 124 » » pr_err(PREFIX "Can't retrieve clk pll_a_out0\n"); | 121 » » dev_err(data->dev, "Can't retrieve clk pll_a_out0\n"); |
| 125 » » ret = PTR_ERR(clk_pll_a_out0); | 122 » » ret = PTR_ERR(data->clk_pll_a_out0); |
| 126 goto err_put_pll_a; | 123 goto err_put_pll_a; |
| 127 } | 124 } |
| 128 | 125 |
| 129 » clk_cdev1 = clk_get_sys(NULL, "cdev1"); | 126 » data->clk_cdev1 = clk_get_sys(NULL, "cdev1"); |
| 130 » if (IS_ERR(clk_cdev1)) { | 127 » if (IS_ERR(data->clk_cdev1)) { |
| 131 » » pr_err(PREFIX "Can't retrieve clk cdev1\n"); | 128 » » dev_err(data->dev, "Can't retrieve clk cdev1\n"); |
| 132 » » ret = PTR_ERR(clk_cdev1); | 129 » » ret = PTR_ERR(data->clk_cdev1); |
| 133 goto err_put_pll_a_out0; | 130 goto err_put_pll_a_out0; |
| 134 } | 131 } |
| 135 | 132 |
| 136 return 0; | 133 return 0; |
| 137 | 134 |
| 138 err_put_pll_a_out0: | 135 err_put_pll_a_out0: |
| 139 » clk_put(clk_pll_a_out0); | 136 » clk_put(data->clk_pll_a_out0); |
| 140 err_put_pll_a: | 137 err_put_pll_a: |
| 141 » clk_put(clk_pll_a); | 138 » clk_put(data->clk_pll_a); |
| 142 err: | 139 err: |
| 143 return ret; | 140 return ret; |
| 144 } | 141 } |
| 145 | 142 |
| 146 void tegra_asoc_utils_fini(void) | 143 void tegra_asoc_utils_fini(struct tegra_asoc_utils_data *data) |
| 147 { | 144 { |
| 148 » clk_put(clk_cdev1); | 145 » clk_put(data->clk_cdev1); |
| 149 » clk_put(clk_pll_a_out0); | 146 » clk_put(data->clk_pll_a_out0); |
| 150 » clk_put(clk_pll_a); | 147 » clk_put(data->clk_pll_a); |
| 151 } | 148 } |
| 152 | 149 |
| OLD | NEW |