root/sound/soc/tegra/tegra_asoc_utils.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. tegra_asoc_utils_set_rate
  2. tegra_asoc_utils_set_ac97_rate
  3. tegra_asoc_utils_init
  4. tegra_asoc_utils_fini

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /*
   3  * tegra_asoc_utils.c - Harmony machine ASoC driver
   4  *
   5  * Author: Stephen Warren <swarren@nvidia.com>
   6  * Copyright (C) 2010,2012 - NVIDIA, Inc.
   7  */
   8 
   9 #include <linux/clk.h>
  10 #include <linux/device.h>
  11 #include <linux/err.h>
  12 #include <linux/kernel.h>
  13 #include <linux/module.h>
  14 #include <linux/of.h>
  15 
  16 #include "tegra_asoc_utils.h"
  17 
  18 int tegra_asoc_utils_set_rate(struct tegra_asoc_utils_data *data, int srate,
  19                               int mclk)
  20 {
  21         int new_baseclock;
  22         bool clk_change;
  23         int err;
  24 
  25         switch (srate) {
  26         case 11025:
  27         case 22050:
  28         case 44100:
  29         case 88200:
  30                 if (data->soc == TEGRA_ASOC_UTILS_SOC_TEGRA20)
  31                         new_baseclock = 56448000;
  32                 else if (data->soc == TEGRA_ASOC_UTILS_SOC_TEGRA30)
  33                         new_baseclock = 564480000;
  34                 else
  35                         new_baseclock = 282240000;
  36                 break;
  37         case 8000:
  38         case 16000:
  39         case 32000:
  40         case 48000:
  41         case 64000:
  42         case 96000:
  43                 if (data->soc == TEGRA_ASOC_UTILS_SOC_TEGRA20)
  44                         new_baseclock = 73728000;
  45                 else if (data->soc == TEGRA_ASOC_UTILS_SOC_TEGRA30)
  46                         new_baseclock = 552960000;
  47                 else
  48                         new_baseclock = 368640000;
  49                 break;
  50         default:
  51                 return -EINVAL;
  52         }
  53 
  54         clk_change = ((new_baseclock != data->set_baseclock) ||
  55                         (mclk != data->set_mclk));
  56         if (!clk_change)
  57                 return 0;
  58 
  59         data->set_baseclock = 0;
  60         data->set_mclk = 0;
  61 
  62         clk_disable_unprepare(data->clk_cdev1);
  63         clk_disable_unprepare(data->clk_pll_a_out0);
  64         clk_disable_unprepare(data->clk_pll_a);
  65 
  66         err = clk_set_rate(data->clk_pll_a, new_baseclock);
  67         if (err) {
  68                 dev_err(data->dev, "Can't set pll_a rate: %d\n", err);
  69                 return err;
  70         }
  71 
  72         err = clk_set_rate(data->clk_pll_a_out0, mclk);
  73         if (err) {
  74                 dev_err(data->dev, "Can't set pll_a_out0 rate: %d\n", err);
  75                 return err;
  76         }
  77 
  78         /* Don't set cdev1/extern1 rate; it's locked to pll_a_out0 */
  79 
  80         err = clk_prepare_enable(data->clk_pll_a);
  81         if (err) {
  82                 dev_err(data->dev, "Can't enable pll_a: %d\n", err);
  83                 return err;
  84         }
  85 
  86         err = clk_prepare_enable(data->clk_pll_a_out0);
  87         if (err) {
  88                 dev_err(data->dev, "Can't enable pll_a_out0: %d\n", err);
  89                 return err;
  90         }
  91 
  92         err = clk_prepare_enable(data->clk_cdev1);
  93         if (err) {
  94                 dev_err(data->dev, "Can't enable cdev1: %d\n", err);
  95                 return err;
  96         }
  97 
  98         data->set_baseclock = new_baseclock;
  99         data->set_mclk = mclk;
 100 
 101         return 0;
 102 }
 103 EXPORT_SYMBOL_GPL(tegra_asoc_utils_set_rate);
 104 
 105 int tegra_asoc_utils_set_ac97_rate(struct tegra_asoc_utils_data *data)
 106 {
 107         const int pll_rate = 73728000;
 108         const int ac97_rate = 24576000;
 109         int err;
 110 
 111         clk_disable_unprepare(data->clk_cdev1);
 112         clk_disable_unprepare(data->clk_pll_a_out0);
 113         clk_disable_unprepare(data->clk_pll_a);
 114 
 115         /*
 116          * AC97 rate is fixed at 24.576MHz and is used for both the host
 117          * controller and the external codec
 118          */
 119         err = clk_set_rate(data->clk_pll_a, pll_rate);
 120         if (err) {
 121                 dev_err(data->dev, "Can't set pll_a rate: %d\n", err);
 122                 return err;
 123         }
 124 
 125         err = clk_set_rate(data->clk_pll_a_out0, ac97_rate);
 126         if (err) {
 127                 dev_err(data->dev, "Can't set pll_a_out0 rate: %d\n", err);
 128                 return err;
 129         }
 130 
 131         /* Don't set cdev1/extern1 rate; it's locked to pll_a_out0 */
 132 
 133         err = clk_prepare_enable(data->clk_pll_a);
 134         if (err) {
 135                 dev_err(data->dev, "Can't enable pll_a: %d\n", err);
 136                 return err;
 137         }
 138 
 139         err = clk_prepare_enable(data->clk_pll_a_out0);
 140         if (err) {
 141                 dev_err(data->dev, "Can't enable pll_a_out0: %d\n", err);
 142                 return err;
 143         }
 144 
 145         err = clk_prepare_enable(data->clk_cdev1);
 146         if (err) {
 147                 dev_err(data->dev, "Can't enable cdev1: %d\n", err);
 148                 return err;
 149         }
 150 
 151         data->set_baseclock = pll_rate;
 152         data->set_mclk = ac97_rate;
 153 
 154         return 0;
 155 }
 156 EXPORT_SYMBOL_GPL(tegra_asoc_utils_set_ac97_rate);
 157 
 158 int tegra_asoc_utils_init(struct tegra_asoc_utils_data *data,
 159                           struct device *dev)
 160 {
 161         int ret;
 162 
 163         data->dev = dev;
 164 
 165         if (of_machine_is_compatible("nvidia,tegra20"))
 166                 data->soc = TEGRA_ASOC_UTILS_SOC_TEGRA20;
 167         else if (of_machine_is_compatible("nvidia,tegra30"))
 168                 data->soc = TEGRA_ASOC_UTILS_SOC_TEGRA30;
 169         else if (of_machine_is_compatible("nvidia,tegra114"))
 170                 data->soc = TEGRA_ASOC_UTILS_SOC_TEGRA114;
 171         else if (of_machine_is_compatible("nvidia,tegra124"))
 172                 data->soc = TEGRA_ASOC_UTILS_SOC_TEGRA124;
 173         else {
 174                 dev_err(data->dev, "SoC unknown to Tegra ASoC utils\n");
 175                 return -EINVAL;
 176         }
 177 
 178         data->clk_pll_a = clk_get(dev, "pll_a");
 179         if (IS_ERR(data->clk_pll_a)) {
 180                 dev_err(data->dev, "Can't retrieve clk pll_a\n");
 181                 ret = PTR_ERR(data->clk_pll_a);
 182                 goto err;
 183         }
 184 
 185         data->clk_pll_a_out0 = clk_get(dev, "pll_a_out0");
 186         if (IS_ERR(data->clk_pll_a_out0)) {
 187                 dev_err(data->dev, "Can't retrieve clk pll_a_out0\n");
 188                 ret = PTR_ERR(data->clk_pll_a_out0);
 189                 goto err_put_pll_a;
 190         }
 191 
 192         data->clk_cdev1 = clk_get(dev, "mclk");
 193         if (IS_ERR(data->clk_cdev1)) {
 194                 dev_err(data->dev, "Can't retrieve clk cdev1\n");
 195                 ret = PTR_ERR(data->clk_cdev1);
 196                 goto err_put_pll_a_out0;
 197         }
 198 
 199         ret = tegra_asoc_utils_set_rate(data, 44100, 256 * 44100);
 200         if (ret)
 201                 goto err_put_cdev1;
 202 
 203         return 0;
 204 
 205 err_put_cdev1:
 206         clk_put(data->clk_cdev1);
 207 err_put_pll_a_out0:
 208         clk_put(data->clk_pll_a_out0);
 209 err_put_pll_a:
 210         clk_put(data->clk_pll_a);
 211 err:
 212         return ret;
 213 }
 214 EXPORT_SYMBOL_GPL(tegra_asoc_utils_init);
 215 
 216 void tegra_asoc_utils_fini(struct tegra_asoc_utils_data *data)
 217 {
 218         clk_put(data->clk_cdev1);
 219         clk_put(data->clk_pll_a_out0);
 220         clk_put(data->clk_pll_a);
 221 }
 222 EXPORT_SYMBOL_GPL(tegra_asoc_utils_fini);
 223 
 224 MODULE_AUTHOR("Stephen Warren <swarren@nvidia.com>");
 225 MODULE_DESCRIPTION("Tegra ASoC utility code");
 226 MODULE_LICENSE("GPL");

/* [<][>][^][v][top][bottom][index][help] */