aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc/codecs/wm8974.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/soc/codecs/wm8974.c')
-rw-r--r--sound/soc/codecs/wm8974.c36
1 files changed, 15 insertions, 21 deletions
diff --git a/sound/soc/codecs/wm8974.c b/sound/soc/codecs/wm8974.c
index 98d663afc97d..81c57b5c591c 100644
--- a/sound/soc/codecs/wm8974.c
+++ b/sound/soc/codecs/wm8974.c
@@ -276,41 +276,42 @@ static int wm8974_add_widgets(struct snd_soc_codec *codec)
276 276
277 snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map)); 277 snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map));
278 278
279 snd_soc_dapm_new_widgets(codec);
280 return 0; 279 return 0;
281} 280}
282 281
283struct pll_ { 282struct pll_ {
284 unsigned int pre_div:4; /* prescale - 1 */ 283 unsigned int pre_div:1;
285 unsigned int n:4; 284 unsigned int n:4;
286 unsigned int k; 285 unsigned int k;
287}; 286};
288 287
289static struct pll_ pll_div;
290
291/* The size in bits of the pll divide multiplied by 10 288/* The size in bits of the pll divide multiplied by 10
292 * to allow rounding later */ 289 * to allow rounding later */
293#define FIXED_PLL_SIZE ((1 << 24) * 10) 290#define FIXED_PLL_SIZE ((1 << 24) * 10)
294 291
295static void pll_factors(unsigned int target, unsigned int source) 292static void pll_factors(struct pll_ *pll_div,
293 unsigned int target, unsigned int source)
296{ 294{
297 unsigned long long Kpart; 295 unsigned long long Kpart;
298 unsigned int K, Ndiv, Nmod; 296 unsigned int K, Ndiv, Nmod;
299 297
298 /* There is a fixed divide by 4 in the output path */
299 target *= 4;
300
300 Ndiv = target / source; 301 Ndiv = target / source;
301 if (Ndiv < 6) { 302 if (Ndiv < 6) {
302 source >>= 1; 303 source /= 2;
303 pll_div.pre_div = 1; 304 pll_div->pre_div = 1;
304 Ndiv = target / source; 305 Ndiv = target / source;
305 } else 306 } else
306 pll_div.pre_div = 0; 307 pll_div->pre_div = 0;
307 308
308 if ((Ndiv < 6) || (Ndiv > 12)) 309 if ((Ndiv < 6) || (Ndiv > 12))
309 printk(KERN_WARNING 310 printk(KERN_WARNING
310 "WM8974 N value %u outwith recommended range!\n", 311 "WM8974 N value %u outwith recommended range!\n",
311 Ndiv); 312 Ndiv);
312 313
313 pll_div.n = Ndiv; 314 pll_div->n = Ndiv;
314 Nmod = target % source; 315 Nmod = target % source;
315 Kpart = FIXED_PLL_SIZE * (long long)Nmod; 316 Kpart = FIXED_PLL_SIZE * (long long)Nmod;
316 317
@@ -325,13 +326,14 @@ static void pll_factors(unsigned int target, unsigned int source)
325 /* Move down to proper range now rounding is done */ 326 /* Move down to proper range now rounding is done */
326 K /= 10; 327 K /= 10;
327 328
328 pll_div.k = K; 329 pll_div->k = K;
329} 330}
330 331
331static int wm8974_set_dai_pll(struct snd_soc_dai *codec_dai, 332static int wm8974_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id,
332 int pll_id, unsigned int freq_in, unsigned int freq_out) 333 int source, unsigned int freq_in, unsigned int freq_out)
333{ 334{
334 struct snd_soc_codec *codec = codec_dai->codec; 335 struct snd_soc_codec *codec = codec_dai->codec;
336 struct pll_ pll_div;
335 u16 reg; 337 u16 reg;
336 338
337 if (freq_in == 0 || freq_out == 0) { 339 if (freq_in == 0 || freq_out == 0) {
@@ -345,7 +347,7 @@ static int wm8974_set_dai_pll(struct snd_soc_dai *codec_dai,
345 return 0; 347 return 0;
346 } 348 }
347 349
348 pll_factors(freq_out*4, freq_in); 350 pll_factors(&pll_div, freq_out, freq_in);
349 351
350 snd_soc_write(codec, WM8974_PLLN, (pll_div.pre_div << 4) | pll_div.n); 352 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); 353 snd_soc_write(codec, WM8974_PLLK1, pll_div.k >> 18);
@@ -638,17 +640,9 @@ static int wm8974_probe(struct platform_device *pdev)
638 snd_soc_add_controls(codec, wm8974_snd_controls, 640 snd_soc_add_controls(codec, wm8974_snd_controls,
639 ARRAY_SIZE(wm8974_snd_controls)); 641 ARRAY_SIZE(wm8974_snd_controls));
640 wm8974_add_widgets(codec); 642 wm8974_add_widgets(codec);
641 ret = snd_soc_init_card(socdev);
642 if (ret < 0) {
643 dev_err(codec->dev, "failed to register card: %d\n", ret);
644 goto card_err;
645 }
646 643
647 return ret; 644 return ret;
648 645
649card_err:
650 snd_soc_free_pcms(socdev);
651 snd_soc_dapm_free(socdev);
652pcm_err: 646pcm_err:
653 return ret; 647 return ret;
654} 648}