aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc/codecs/jz4740.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/soc/codecs/jz4740.c')
-rw-r--r--sound/soc/codecs/jz4740.c137
1 files changed, 34 insertions, 103 deletions
diff --git a/sound/soc/codecs/jz4740.c b/sound/soc/codecs/jz4740.c
index 66557de1e4fe..e373f8f06907 100644
--- a/sound/soc/codecs/jz4740.c
+++ b/sound/soc/codecs/jz4740.c
@@ -22,7 +22,6 @@
22#include <sound/pcm.h> 22#include <sound/pcm.h>
23#include <sound/pcm_params.h> 23#include <sound/pcm_params.h>
24#include <sound/initval.h> 24#include <sound/initval.h>
25#include <sound/soc-dapm.h>
26#include <sound/soc.h> 25#include <sound/soc.h>
27 26
28#define JZ4740_REG_CODEC_1 0x0 27#define JZ4740_REG_CODEC_1 0x0
@@ -74,29 +73,22 @@ static const uint32_t jz4740_codec_regs[] = {
74struct jz4740_codec { 73struct jz4740_codec {
75 void __iomem *base; 74 void __iomem *base;
76 struct resource *mem; 75 struct resource *mem;
77
78 uint32_t reg_cache[2];
79 struct snd_soc_codec codec;
80}; 76};
81 77
82static inline struct jz4740_codec *codec_to_jz4740(struct snd_soc_codec *codec)
83{
84 return container_of(codec, struct jz4740_codec, codec);
85}
86
87static unsigned int jz4740_codec_read(struct snd_soc_codec *codec, 78static unsigned int jz4740_codec_read(struct snd_soc_codec *codec,
88 unsigned int reg) 79 unsigned int reg)
89{ 80{
90 struct jz4740_codec *jz4740_codec = codec_to_jz4740(codec); 81 struct jz4740_codec *jz4740_codec = snd_soc_codec_get_drvdata(codec);
91 return readl(jz4740_codec->base + (reg << 2)); 82 return readl(jz4740_codec->base + (reg << 2));
92} 83}
93 84
94static int jz4740_codec_write(struct snd_soc_codec *codec, unsigned int reg, 85static int jz4740_codec_write(struct snd_soc_codec *codec, unsigned int reg,
95 unsigned int val) 86 unsigned int val)
96{ 87{
97 struct jz4740_codec *jz4740_codec = codec_to_jz4740(codec); 88 struct jz4740_codec *jz4740_codec = snd_soc_codec_get_drvdata(codec);
89 u32 *cache = codec->reg_cache;
98 90
99 jz4740_codec->reg_cache[reg] = val; 91 cache[reg] = val;
100 writel(val, jz4740_codec->base + (reg << 2)); 92 writel(val, jz4740_codec->base + (reg << 2));
101 93
102 return 0; 94 return 0;
@@ -172,8 +164,7 @@ static int jz4740_codec_hw_params(struct snd_pcm_substream *substream,
172{ 164{
173 uint32_t val; 165 uint32_t val;
174 struct snd_soc_pcm_runtime *rtd = substream->private_data; 166 struct snd_soc_pcm_runtime *rtd = substream->private_data;
175 struct snd_soc_device *socdev = rtd->socdev; 167 struct snd_soc_codec *codec =rtd->codec;
176 struct snd_soc_codec *codec = socdev->card->codec;
177 168
178 switch (params_rate(params)) { 169 switch (params_rate(params)) {
179 case 8000: 170 case 8000:
@@ -219,8 +210,8 @@ static struct snd_soc_dai_ops jz4740_codec_dai_ops = {
219 .hw_params = jz4740_codec_hw_params, 210 .hw_params = jz4740_codec_hw_params,
220}; 211};
221 212
222struct snd_soc_dai jz4740_codec_dai = { 213static struct snd_soc_dai_driver jz4740_codec_dai = {
223 .name = "jz4740", 214 .name = "jz4740-hifi",
224 .playback = { 215 .playback = {
225 .stream_name = "Playback", 216 .stream_name = "Playback",
226 .channels_min = 2, 217 .channels_min = 2,
@@ -238,7 +229,6 @@ struct snd_soc_dai jz4740_codec_dai = {
238 .ops = &jz4740_codec_dai_ops, 229 .ops = &jz4740_codec_dai_ops,
239 .symmetric_rates = 1, 230 .symmetric_rates = 1,
240}; 231};
241EXPORT_SYMBOL_GPL(jz4740_codec_dai);
242 232
243static void jz4740_codec_wakeup(struct snd_soc_codec *codec) 233static void jz4740_codec_wakeup(struct snd_soc_codec *codec)
244{ 234{
@@ -275,7 +265,7 @@ static int jz4740_codec_set_bias_level(struct snd_soc_codec *codec,
275 break; 265 break;
276 case SND_SOC_BIAS_STANDBY: 266 case SND_SOC_BIAS_STANDBY:
277 /* The only way to clear the suspend flag is to reset the codec */ 267 /* The only way to clear the suspend flag is to reset the codec */
278 if (codec->bias_level == SND_SOC_BIAS_OFF) 268 if (codec->dapm.bias_level == SND_SOC_BIAS_OFF)
279 jz4740_codec_wakeup(codec); 269 jz4740_codec_wakeup(codec);
280 270
281 mask = JZ4740_CODEC_1_VREF_DISABLE | 271 mask = JZ4740_CODEC_1_VREF_DISABLE |
@@ -297,68 +287,37 @@ static int jz4740_codec_set_bias_level(struct snd_soc_codec *codec,
297 break; 287 break;
298 } 288 }
299 289
300 codec->bias_level = level; 290 codec->dapm.bias_level = level;
301 291
302 return 0; 292 return 0;
303} 293}
304 294
305static struct snd_soc_codec *jz4740_codec_codec; 295static int jz4740_codec_dev_probe(struct snd_soc_codec *codec)
306
307static int jz4740_codec_dev_probe(struct platform_device *pdev)
308{ 296{
309 int ret; 297 snd_soc_update_bits(codec, JZ4740_REG_CODEC_1,
310 struct snd_soc_device *socdev = platform_get_drvdata(pdev); 298 JZ4740_CODEC_1_SW2_ENABLE, JZ4740_CODEC_1_SW2_ENABLE);
311 struct snd_soc_codec *codec = jz4740_codec_codec;
312
313 BUG_ON(!codec);
314
315 socdev->card->codec = codec;
316
317 ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
318 if (ret) {
319 dev_err(&pdev->dev, "Failed to create pcms: %d\n", ret);
320 return ret;
321 }
322
323 snd_soc_add_controls(codec, jz4740_codec_controls,
324 ARRAY_SIZE(jz4740_codec_controls));
325
326 snd_soc_dapm_new_controls(codec, jz4740_codec_dapm_widgets,
327 ARRAY_SIZE(jz4740_codec_dapm_widgets));
328
329 snd_soc_dapm_add_routes(codec, jz4740_codec_dapm_routes,
330 ARRAY_SIZE(jz4740_codec_dapm_routes));
331 299
332 snd_soc_dapm_new_widgets(codec); 300 jz4740_codec_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
333 301
334 return 0; 302 return 0;
335} 303}
336 304
337static int jz4740_codec_dev_remove(struct platform_device *pdev) 305static int jz4740_codec_dev_remove(struct snd_soc_codec *codec)
338{ 306{
339 struct snd_soc_device *socdev = platform_get_drvdata(pdev); 307 jz4740_codec_set_bias_level(codec, SND_SOC_BIAS_OFF);
340
341 snd_soc_free_pcms(socdev);
342 snd_soc_dapm_free(socdev);
343 308
344 return 0; 309 return 0;
345} 310}
346 311
347#ifdef CONFIG_PM_SLEEP 312#ifdef CONFIG_PM_SLEEP
348 313
349static int jz4740_codec_suspend(struct platform_device *pdev, pm_message_t state) 314static int jz4740_codec_suspend(struct snd_soc_codec *codec, pm_message_t state)
350{ 315{
351 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
352 struct snd_soc_codec *codec = socdev->card->codec;
353
354 return jz4740_codec_set_bias_level(codec, SND_SOC_BIAS_OFF); 316 return jz4740_codec_set_bias_level(codec, SND_SOC_BIAS_OFF);
355} 317}
356 318
357static int jz4740_codec_resume(struct platform_device *pdev) 319static int jz4740_codec_resume(struct snd_soc_codec *codec)
358{ 320{
359 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
360 struct snd_soc_codec *codec = socdev->card->codec;
361
362 return jz4740_codec_set_bias_level(codec, SND_SOC_BIAS_STANDBY); 321 return jz4740_codec_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
363} 322}
364 323
@@ -367,19 +326,30 @@ static int jz4740_codec_resume(struct platform_device *pdev)
367#define jz4740_codec_resume NULL 326#define jz4740_codec_resume NULL
368#endif 327#endif
369 328
370struct snd_soc_codec_device soc_codec_dev_jz4740_codec = { 329static struct snd_soc_codec_driver soc_codec_dev_jz4740_codec = {
371 .probe = jz4740_codec_dev_probe, 330 .probe = jz4740_codec_dev_probe,
372 .remove = jz4740_codec_dev_remove, 331 .remove = jz4740_codec_dev_remove,
373 .suspend = jz4740_codec_suspend, 332 .suspend = jz4740_codec_suspend,
374 .resume = jz4740_codec_resume, 333 .resume = jz4740_codec_resume,
334 .read = jz4740_codec_read,
335 .write = jz4740_codec_write,
336 .set_bias_level = jz4740_codec_set_bias_level,
337 .reg_cache_default = jz4740_codec_regs,
338 .reg_word_size = sizeof(u32),
339 .reg_cache_size = 2,
340
341 .controls = jz4740_codec_controls,
342 .num_controls = ARRAY_SIZE(jz4740_codec_controls),
343 .dapm_widgets = jz4740_codec_dapm_widgets,
344 .num_dapm_widgets = ARRAY_SIZE(jz4740_codec_dapm_widgets),
345 .dapm_routes = jz4740_codec_dapm_routes,
346 .num_dapm_routes = ARRAY_SIZE(jz4740_codec_dapm_routes),
375}; 347};
376EXPORT_SYMBOL_GPL(soc_codec_dev_jz4740_codec);
377 348
378static int __devinit jz4740_codec_probe(struct platform_device *pdev) 349static int __devinit jz4740_codec_probe(struct platform_device *pdev)
379{ 350{
380 int ret; 351 int ret;
381 struct jz4740_codec *jz4740_codec; 352 struct jz4740_codec *jz4740_codec;
382 struct snd_soc_codec *codec;
383 struct resource *mem; 353 struct resource *mem;
384 354
385 jz4740_codec = kzalloc(sizeof(*jz4740_codec), GFP_KERNEL); 355 jz4740_codec = kzalloc(sizeof(*jz4740_codec), GFP_KERNEL);
@@ -408,55 +378,17 @@ static int __devinit jz4740_codec_probe(struct platform_device *pdev)
408 } 378 }
409 jz4740_codec->mem = mem; 379 jz4740_codec->mem = mem;
410 380
411 jz4740_codec_dai.dev = &pdev->dev;
412
413 codec = &jz4740_codec->codec;
414
415 codec->dev = &pdev->dev;
416 codec->name = "jz4740";
417 codec->owner = THIS_MODULE;
418
419 codec->read = jz4740_codec_read;
420 codec->write = jz4740_codec_write;
421 codec->set_bias_level = jz4740_codec_set_bias_level;
422 codec->bias_level = SND_SOC_BIAS_OFF;
423
424 codec->dai = &jz4740_codec_dai;
425 codec->num_dai = 1;
426
427 codec->reg_cache = jz4740_codec->reg_cache;
428 codec->reg_cache_size = 2;
429 memcpy(codec->reg_cache, jz4740_codec_regs, sizeof(jz4740_codec_regs));
430
431 mutex_init(&codec->mutex);
432 INIT_LIST_HEAD(&codec->dapm_widgets);
433 INIT_LIST_HEAD(&codec->dapm_paths);
434
435 jz4740_codec_codec = codec;
436
437 snd_soc_update_bits(codec, JZ4740_REG_CODEC_1,
438 JZ4740_CODEC_1_SW2_ENABLE, JZ4740_CODEC_1_SW2_ENABLE);
439
440 platform_set_drvdata(pdev, jz4740_codec); 381 platform_set_drvdata(pdev, jz4740_codec);
441 382
442 ret = snd_soc_register_codec(codec); 383 ret = snd_soc_register_codec(&pdev->dev,
384 &soc_codec_dev_jz4740_codec, &jz4740_codec_dai, 1);
443 if (ret) { 385 if (ret) {
444 dev_err(&pdev->dev, "Failed to register codec\n"); 386 dev_err(&pdev->dev, "Failed to register codec\n");
445 goto err_iounmap; 387 goto err_iounmap;
446 } 388 }
447 389
448 ret = snd_soc_register_dai(&jz4740_codec_dai);
449 if (ret) {
450 dev_err(&pdev->dev, "Failed to register codec dai\n");
451 goto err_unregister_codec;
452 }
453
454 jz4740_codec_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
455
456 return 0; 390 return 0;
457 391
458err_unregister_codec:
459 snd_soc_unregister_codec(codec);
460err_iounmap: 392err_iounmap:
461 iounmap(jz4740_codec->base); 393 iounmap(jz4740_codec->base);
462err_release_mem_region: 394err_release_mem_region:
@@ -472,8 +404,7 @@ static int __devexit jz4740_codec_remove(struct platform_device *pdev)
472 struct jz4740_codec *jz4740_codec = platform_get_drvdata(pdev); 404 struct jz4740_codec *jz4740_codec = platform_get_drvdata(pdev);
473 struct resource *mem = jz4740_codec->mem; 405 struct resource *mem = jz4740_codec->mem;
474 406
475 snd_soc_unregister_dai(&jz4740_codec_dai); 407 snd_soc_unregister_codec(&pdev->dev);
476 snd_soc_unregister_codec(&jz4740_codec->codec);
477 408
478 iounmap(jz4740_codec->base); 409 iounmap(jz4740_codec->base);
479 release_mem_region(mem->start, resource_size(mem)); 410 release_mem_region(mem->start, resource_size(mem));