1 /* 2 * Helper routines for R-Car sound ADG. 3 * 4 * Copyright (C) 2013 Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> 5 * 6 * This file is subject to the terms and conditions of the GNU General Public 7 * License. See the file "COPYING" in the main directory of this archive 8 * for more details. 9 */ 10 #include <linux/sh_clk.h> 11 #include "rsnd.h" 12 13 #define CLKA 0 14 #define CLKB 1 15 #define CLKC 2 16 #define CLKI 3 17 #define CLKMAX 4 18 19 struct rsnd_adg { 20 struct clk *clk[CLKMAX]; 21 22 int rate_of_441khz_div_6; 23 int rate_of_48khz_div_6; 24 u32 ckr; 25 }; 26 27 #define for_each_rsnd_clk(pos, adg, i) \ 28 for (i = 0, (pos) = adg->clk[i]; \ 29 i < CLKMAX; \ 30 i++, (pos) = adg->clk[i]) 31 #define rsnd_priv_to_adg(priv) ((struct rsnd_adg *)(priv)->adg) 32 33 static enum rsnd_reg rsnd_adg_ssi_reg_get(int id) 34 { 35 enum rsnd_reg reg; 36 37 /* 38 * SSI 8 is not connected to ADG. 39 * it works with SSI 7 40 */ 41 if (id == 8) 42 return RSND_REG_MAX; 43 44 if (0 <= id && id <= 3) 45 reg = RSND_REG_AUDIO_CLK_SEL0; 46 else if (4 <= id && id <= 7) 47 reg = RSND_REG_AUDIO_CLK_SEL1; 48 else 49 reg = RSND_REG_AUDIO_CLK_SEL2; 50 51 return reg; 52 } 53 54 int rsnd_adg_ssi_clk_stop(struct rsnd_mod *mod) 55 { 56 struct rsnd_priv *priv = rsnd_mod_to_priv(mod); 57 enum rsnd_reg reg; 58 int id; 59 60 /* 61 * "mod" = "ssi" here. 62 * we can get "ssi id" from mod 63 */ 64 id = rsnd_mod_id(mod); 65 reg = rsnd_adg_ssi_reg_get(id); 66 67 rsnd_write(priv, mod, reg, 0); 68 69 return 0; 70 } 71 72 int rsnd_adg_ssi_clk_try_start(struct rsnd_mod *mod, unsigned int rate) 73 { 74 struct rsnd_priv *priv = rsnd_mod_to_priv(mod); 75 struct rsnd_adg *adg = rsnd_priv_to_adg(priv); 76 struct device *dev = rsnd_priv_to_dev(priv); 77 struct clk *clk; 78 enum rsnd_reg reg; 79 int id, shift, i; 80 u32 data; 81 int sel_table[] = { 82 [CLKA] = 0x1, 83 [CLKB] = 0x2, 84 [CLKC] = 0x3, 85 [CLKI] = 0x0, 86 }; 87 88 dev_dbg(dev, "request clock = %d\n", rate); 89 90 /* 91 * find suitable clock from 92 * AUDIO_CLKA/AUDIO_CLKB/AUDIO_CLKC/AUDIO_CLKI. 93 */ 94 data = 0; 95 for_each_rsnd_clk(clk, adg, i) { 96 if (rate == clk_get_rate(clk)) { 97 data = sel_table[i]; 98 goto found_clock; 99 } 100 } 101 102 /* 103 * find 1/6 clock from BRGA/BRGB 104 */ 105 if (rate == adg->rate_of_441khz_div_6) { 106 data = 0x10; 107 goto found_clock; 108 } 109 110 if (rate == adg->rate_of_48khz_div_6) { 111 data = 0x20; 112 goto found_clock; 113 } 114 115 return -EIO; 116 117 found_clock: 118 119 /* see rsnd_adg_ssi_clk_init() */ 120 rsnd_mod_bset(mod, SSICKR, 0x00FF0000, adg->ckr); 121 rsnd_mod_write(mod, BRRA, 0x00000002); /* 1/6 */ 122 rsnd_mod_write(mod, BRRB, 0x00000002); /* 1/6 */ 123 124 /* 125 * This "mod" = "ssi" here. 126 * we can get "ssi id" from mod 127 */ 128 id = rsnd_mod_id(mod); 129 reg = rsnd_adg_ssi_reg_get(id); 130 131 dev_dbg(dev, "ADG: ssi%d selects clk%d = %d", id, i, rate); 132 133 /* 134 * Enable SSIx clock 135 */ 136 shift = (id % 4) * 8; 137 138 rsnd_bset(priv, mod, reg, 139 0xFF << shift, 140 data << shift); 141 142 return 0; 143 } 144 145 static void rsnd_adg_ssi_clk_init(struct rsnd_priv *priv, struct rsnd_adg *adg) 146 { 147 struct clk *clk; 148 unsigned long rate; 149 u32 ckr; 150 int i; 151 int brg_table[] = { 152 [CLKA] = 0x0, 153 [CLKB] = 0x1, 154 [CLKC] = 0x4, 155 [CLKI] = 0x2, 156 }; 157 158 /* 159 * This driver is assuming that AUDIO_CLKA/AUDIO_CLKB/AUDIO_CLKC 160 * have 44.1kHz or 48kHz base clocks for now. 161 * 162 * SSI itself can divide parent clock by 1/1 - 1/16 163 * So, BRGA outputs 44.1kHz base parent clock 1/32, 164 * and, BRGB outputs 48.0kHz base parent clock 1/32 here. 165 * see 166 * rsnd_adg_ssi_clk_try_start() 167 */ 168 ckr = 0; 169 adg->rate_of_441khz_div_6 = 0; 170 adg->rate_of_48khz_div_6 = 0; 171 for_each_rsnd_clk(clk, adg, i) { 172 rate = clk_get_rate(clk); 173 174 if (0 == rate) /* not used */ 175 continue; 176 177 /* RBGA */ 178 if (!adg->rate_of_441khz_div_6 && (0 == rate % 44100)) { 179 adg->rate_of_441khz_div_6 = rate / 6; 180 ckr |= brg_table[i] << 20; 181 } 182 183 /* RBGB */ 184 if (!adg->rate_of_48khz_div_6 && (0 == rate % 48000)) { 185 adg->rate_of_48khz_div_6 = rate / 6; 186 ckr |= brg_table[i] << 16; 187 } 188 } 189 190 adg->ckr = ckr; 191 } 192 193 int rsnd_adg_probe(struct platform_device *pdev, 194 struct rcar_snd_info *info, 195 struct rsnd_priv *priv) 196 { 197 struct rsnd_adg *adg; 198 struct device *dev = rsnd_priv_to_dev(priv); 199 struct clk *clk; 200 int i; 201 202 adg = devm_kzalloc(dev, sizeof(*adg), GFP_KERNEL); 203 if (!adg) { 204 dev_err(dev, "ADG allocate failed\n"); 205 return -ENOMEM; 206 } 207 208 adg->clk[CLKA] = clk_get(NULL, "audio_clk_a"); 209 adg->clk[CLKB] = clk_get(NULL, "audio_clk_b"); 210 adg->clk[CLKC] = clk_get(NULL, "audio_clk_c"); 211 adg->clk[CLKI] = clk_get(NULL, "audio_clk_internal"); 212 for_each_rsnd_clk(clk, adg, i) { 213 if (IS_ERR(clk)) { 214 dev_err(dev, "Audio clock failed\n"); 215 return -EIO; 216 } 217 } 218 219 rsnd_adg_ssi_clk_init(priv, adg); 220 221 priv->adg = adg; 222 223 dev_dbg(dev, "adg probed\n"); 224 225 return 0; 226 } 227 228 void rsnd_adg_remove(struct platform_device *pdev, 229 struct rsnd_priv *priv) 230 { 231 struct rsnd_adg *adg = priv->adg; 232 struct clk *clk; 233 int i; 234 235 for_each_rsnd_clk(clk, adg, i) 236 clk_put(clk); 237 } 238