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 <mach/clock.h> 12 #include "rsnd.h" 13 14 #define CLKA 0 15 #define CLKB 1 16 #define CLKC 2 17 #define CLKI 3 18 #define CLKMAX 4 19 20 struct rsnd_adg { 21 struct clk *clk[CLKMAX]; 22 23 int rate_of_441khz_div_6; 24 int rate_of_48khz_div_6; 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 /* 120 * This "mod" = "ssi" here. 121 * we can get "ssi id" from mod 122 */ 123 id = rsnd_mod_id(mod); 124 reg = rsnd_adg_ssi_reg_get(id); 125 126 dev_dbg(dev, "ADG: ssi%d selects clk%d = %d", id, i, rate); 127 128 /* 129 * Enable SSIx clock 130 */ 131 shift = (id % 4) * 8; 132 133 rsnd_bset(priv, mod, reg, 134 0xFF << shift, 135 data << shift); 136 137 return 0; 138 } 139 140 static void rsnd_adg_ssi_clk_init(struct rsnd_priv *priv, struct rsnd_adg *adg) 141 { 142 struct clk *clk; 143 unsigned long rate; 144 u32 ckr; 145 int i; 146 int brg_table[] = { 147 [CLKA] = 0x0, 148 [CLKB] = 0x1, 149 [CLKC] = 0x4, 150 [CLKI] = 0x2, 151 }; 152 153 /* 154 * This driver is assuming that AUDIO_CLKA/AUDIO_CLKB/AUDIO_CLKC 155 * have 44.1kHz or 48kHz base clocks for now. 156 * 157 * SSI itself can divide parent clock by 1/1 - 1/16 158 * So, BRGA outputs 44.1kHz base parent clock 1/32, 159 * and, BRGB outputs 48.0kHz base parent clock 1/32 here. 160 * see 161 * rsnd_adg_ssi_clk_try_start() 162 */ 163 ckr = 0; 164 adg->rate_of_441khz_div_6 = 0; 165 adg->rate_of_48khz_div_6 = 0; 166 for_each_rsnd_clk(clk, adg, i) { 167 rate = clk_get_rate(clk); 168 169 if (0 == rate) /* not used */ 170 continue; 171 172 /* RBGA */ 173 if (!adg->rate_of_441khz_div_6 && (0 == rate % 44100)) { 174 adg->rate_of_441khz_div_6 = rate / 6; 175 ckr |= brg_table[i] << 20; 176 } 177 178 /* RBGB */ 179 if (!adg->rate_of_48khz_div_6 && (0 == rate % 48000)) { 180 adg->rate_of_48khz_div_6 = rate / 6; 181 ckr |= brg_table[i] << 16; 182 } 183 } 184 185 rsnd_priv_bset(priv, SSICKR, 0x00FF0000, ckr); 186 rsnd_priv_write(priv, BRRA, 0x00000002); /* 1/6 */ 187 rsnd_priv_write(priv, BRRB, 0x00000002); /* 1/6 */ 188 } 189 190 int rsnd_adg_probe(struct platform_device *pdev, 191 struct rcar_snd_info *info, 192 struct rsnd_priv *priv) 193 { 194 struct rsnd_adg *adg; 195 struct device *dev = rsnd_priv_to_dev(priv); 196 struct clk *clk; 197 int i; 198 199 adg = devm_kzalloc(dev, sizeof(*adg), GFP_KERNEL); 200 if (!adg) { 201 dev_err(dev, "ADG allocate failed\n"); 202 return -ENOMEM; 203 } 204 205 adg->clk[CLKA] = clk_get(NULL, "audio_clk_a"); 206 adg->clk[CLKB] = clk_get(NULL, "audio_clk_b"); 207 adg->clk[CLKC] = clk_get(NULL, "audio_clk_c"); 208 adg->clk[CLKI] = clk_get(NULL, "audio_clk_internal"); 209 for_each_rsnd_clk(clk, adg, i) { 210 if (IS_ERR(clk)) { 211 dev_err(dev, "Audio clock failed\n"); 212 return -EIO; 213 } 214 } 215 216 rsnd_adg_ssi_clk_init(priv, adg); 217 218 priv->adg = adg; 219 220 dev_dbg(dev, "adg probed\n"); 221 222 return 0; 223 } 224 225 void rsnd_adg_remove(struct platform_device *pdev, 226 struct rsnd_priv *priv) 227 { 228 struct rsnd_adg *adg = priv->adg; 229 struct clk *clk; 230 int i; 231 232 for_each_rsnd_clk(clk, adg, i) 233 clk_put(clk); 234 } 235