aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc/codecs
diff options
context:
space:
mode:
authorMark Brown <broonie@opensource.wolfsonmicro.com>2009-09-30 10:48:38 -0400
committerMark Brown <broonie@opensource.wolfsonmicro.com>2009-09-30 10:48:38 -0400
commit4c0bccbe66ffe34f7bc88d29c345f9a7888656eb (patch)
tree9f1a76c0cabf40505f5c719fb1df615e6e28865a /sound/soc/codecs
parent4fa9c1a5953441e06dbde7b6a655cbf6618e61dd (diff)
parentc36b2fc73a6c0e7b185b17d594b38398ce1f7fff (diff)
Merge branch 'upstream/wm8974' into for-2.6.33
Diffstat (limited to 'sound/soc/codecs')
-rw-r--r--sound/soc/codecs/wm8974.c23
1 files changed, 13 insertions, 10 deletions
diff --git a/sound/soc/codecs/wm8974.c b/sound/soc/codecs/wm8974.c
index 93d66e30f109..eff29331235b 100644
--- a/sound/soc/codecs/wm8974.c
+++ b/sound/soc/codecs/wm8974.c
@@ -281,36 +281,38 @@ static int wm8974_add_widgets(struct snd_soc_codec *codec)
281} 281}
282 282
283struct pll_ { 283struct pll_ {
284 unsigned int pre_div:4; /* prescale - 1 */ 284 unsigned int pre_div:1;
285 unsigned int n:4; 285 unsigned int n:4;
286 unsigned int k; 286 unsigned int k;
287}; 287};
288 288
289static struct pll_ pll_div;
290
291/* The size in bits of the pll divide multiplied by 10 289/* The size in bits of the pll divide multiplied by 10
292 * to allow rounding later */ 290 * to allow rounding later */
293#define FIXED_PLL_SIZE ((1 << 24) * 10) 291#define FIXED_PLL_SIZE ((1 << 24) * 10)
294 292
295static void pll_factors(unsigned int target, unsigned int source) 293static void pll_factors(struct pll_ *pll_div,
294 unsigned int target, unsigned int source)
296{ 295{
297 unsigned long long Kpart; 296 unsigned long long Kpart;
298 unsigned int K, Ndiv, Nmod; 297 unsigned int K, Ndiv, Nmod;
299 298
299 /* There is a fixed divide by 4 in the output path */
300 target *= 4;
301
300 Ndiv = target / source; 302 Ndiv = target / source;
301 if (Ndiv < 6) { 303 if (Ndiv < 6) {
302 source >>= 1; 304 source /= 2;
303 pll_div.pre_div = 1; 305 pll_div->pre_div = 1;
304 Ndiv = target / source; 306 Ndiv = target / source;
305 } else 307 } else
306 pll_div.pre_div = 0; 308 pll_div->pre_div = 0;
307 309
308 if ((Ndiv < 6) || (Ndiv > 12)) 310 if ((Ndiv < 6) || (Ndiv > 12))
309 printk(KERN_WARNING 311 printk(KERN_WARNING
310 "WM8974 N value %u outwith recommended range!\n", 312 "WM8974 N value %u outwith recommended range!\n",
311 Ndiv); 313 Ndiv);
312 314
313 pll_div.n = Ndiv; 315 pll_div->n = Ndiv;
314 Nmod = target % source; 316 Nmod = target % source;
315 Kpart = FIXED_PLL_SIZE * (long long)Nmod; 317 Kpart = FIXED_PLL_SIZE * (long long)Nmod;
316 318
@@ -325,13 +327,14 @@ static void pll_factors(unsigned int target, unsigned int source)
325 /* Move down to proper range now rounding is done */ 327 /* Move down to proper range now rounding is done */
326 K /= 10; 328 K /= 10;
327 329
328 pll_div.k = K; 330 pll_div->k = K;
329} 331}
330 332
331static int wm8974_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id, 333static int wm8974_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id,
332 int source, unsigned int freq_in, unsigned int freq_out) 334 int source, unsigned int freq_in, unsigned int freq_out)
333{ 335{
334 struct snd_soc_codec *codec = codec_dai->codec; 336 struct snd_soc_codec *codec = codec_dai->codec;
337 struct pll_ pll_div;
335 u16 reg; 338 u16 reg;
336 339
337 if (freq_in == 0 || freq_out == 0) { 340 if (freq_in == 0 || freq_out == 0) {
@@ -345,7 +348,7 @@ static int wm8974_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id,
345 return 0; 348 return 0;
346 } 349 }
347 350
348 pll_factors(freq_out*4, freq_in); 351 pll_factors(&pll_div, freq_out, freq_in);
349 352
350 snd_soc_write(codec, WM8974_PLLN, (pll_div.pre_div << 4) | pll_div.n); 353 snd_soc_write(codec, WM8974_PLLN, (pll_div.pre_div << 4) | pll_div.n);
351 snd_soc_write(codec, WM8974_PLLK1, pll_div.k >> 18); 354 snd_soc_write(codec, WM8974_PLLK1, pll_div.k >> 18);