⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 wm9705.c

📁 Wolfson9712和Wolfson9705的驱动
💻 C
📖 第 1 页 / 共 2 页
字号:

 228 

 229                 return cache[reg];

 230         }

 231 }

 232 

 233 static int ac97_write(struct snd_soc_codec *codec, unsigned int reg,

 234         unsigned int val)

 235 {

 236         u16 *cache = codec->reg_cache;

 237 

 238         soc_ac97_ops.write(codec->ac97, reg, val);

 239         reg = reg >> 1;

 240         if (reg < (ARRAY_SIZE(wm9705_reg)))

 241                 cache[reg] = val;

 242 

 243         return 0;

 244 }

 245 

 246 static int ac97_prepare(struct snd_pcm_substream *substream,

 247                         struct snd_soc_dai *dai)

 248 {

 249         struct snd_pcm_runtime *runtime = substream->runtime;

 250         struct snd_soc_pcm_runtime *rtd = substream->private_data;

 251         struct snd_soc_device *socdev = rtd->socdev;

 252         struct snd_soc_codec *codec = socdev->card->codec;

 253         int reg;

 254         u16 vra;

 255 

 256         vra = ac97_read(codec, AC97_EXTENDED_STATUS);

 257         ac97_write(codec, AC97_EXTENDED_STATUS, vra | 0x1);

 258 

 259         if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)

 260                 reg = AC97_PCM_FRONT_DAC_RATE;

 261         else

 262                 reg = AC97_PCM_LR_ADC_RATE;

 263 

 264         return ac97_write(codec, reg, runtime->rate);

 265 }

 266 

 267 #define WM9705_AC97_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 | \

 268                         SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 | \

 269                         SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | \

 270                         SNDRV_PCM_RATE_48000)

 271 

 272 static struct snd_soc_dai_ops wm9705_dai_ops = {

 273         .prepare        = ac97_prepare,

 274 };

 275 

 276 struct snd_soc_dai wm9705_dai[] = {

 277         {

 278                 .name = "AC97 HiFi",

 279                 .ac97_control = 1,

 280                 .playback = {

 281                         .stream_name = "HiFi Playback",

 282                         .channels_min = 1,

 283                         .channels_max = 2,

 284                         .rates = WM9705_AC97_RATES,

 285                         .formats = SND_SOC_STD_AC97_FMTS,

 286                 },

 287                 .capture = {

 288                         .stream_name = "HiFi Capture",

 289                         .channels_min = 1,

 290                         .channels_max = 2,

 291                         .rates = WM9705_AC97_RATES,

 292                         .formats = SND_SOC_STD_AC97_FMTS,

 293                 },

 294                 .ops = &wm9705_dai_ops,

 295         },

 296         {

 297                 .name = "AC97 Aux",

 298                 .playback = {

 299                         .stream_name = "Aux Playback",

 300                         .channels_min = 1,

 301                         .channels_max = 1,

 302                         .rates = WM9705_AC97_RATES,

 303                         .formats = SNDRV_PCM_FMTBIT_S16_LE,

 304                 },

 305         }

 306 };

 307 EXPORT_SYMBOL_GPL(wm9705_dai);

 308 

 309 static int wm9705_reset(struct snd_soc_codec *codec)

 310 {

 311         if (soc_ac97_ops.reset) {

 312                 soc_ac97_ops.reset(codec->ac97);

 313                 if (ac97_read(codec, 0) == wm9705_reg[0])

 314                         return 0; /* Success */

 315         }

 316 

 317         return -EIO;

 318 }

 319 

 320 #ifdef CONFIG_PM

 321 static int wm9705_soc_suspend(struct platform_device *pdev, pm_message_t msg)

 322 {

 323         struct snd_soc_device *socdev = platform_get_drvdata(pdev);

 324         struct snd_soc_codec *codec = socdev->card->codec;

 325 

 326         soc_ac97_ops.write(codec->ac97, AC97_POWERDOWN, 0xffff);

 327 

 328         return 0;

 329 }

 330 

 331 static int wm9705_soc_resume(struct platform_device *pdev)

 332 {

 333         struct snd_soc_device *socdev = platform_get_drvdata(pdev);

 334         struct snd_soc_codec *codec = socdev->card->codec;

 335         int i, ret;

 336         u16 *cache = codec->reg_cache;

 337 

 338         ret = wm9705_reset(codec);

 339         if (ret < 0) {

 340                 printk(KERN_ERR "could not reset AC97 codec\n");

 341                 return ret;

 342         }

 343 

 344         for (i = 2; i < ARRAY_SIZE(wm9705_reg) << 1; i += 2) {

 345                 soc_ac97_ops.write(codec->ac97, i, cache[i>>1]);

 346         }

 347 

 348         return 0;

 349 }

 350 #else

 351 #define wm9705_soc_suspend NULL

 352 #define wm9705_soc_resume NULL

 353 #endif

 354 

 355 static int wm9705_soc_probe(struct platform_device *pdev)

 356 {

 357         struct snd_soc_device *socdev = platform_get_drvdata(pdev);

 358         struct snd_soc_codec *codec;

 359         int ret = 0;

 360 

 361         printk(KERN_INFO "WM9705 SoC Audio Codec\n");

 362 

 363         socdev->card->codec = kzalloc(sizeof(struct snd_soc_codec),

 364                                       GFP_KERNEL);

 365         if (socdev->card->codec == NULL)

 366                 return -ENOMEM;

 367         codec = socdev->card->codec;

 368         mutex_init(&codec->mutex);

 369 

 370         codec->reg_cache = kmemdup(wm9705_reg, sizeof(wm9705_reg), GFP_KERNEL);

 371         if (codec->reg_cache == NULL) {

 372                 ret = -ENOMEM;

 373                 goto cache_err;

 374         }

 375         codec->reg_cache_size = sizeof(wm9705_reg);

 376         codec->reg_cache_step = 2;

 377 

 378         codec->name = "WM9705";

 379         codec->owner = THIS_MODULE;

 380         codec->dai = wm9705_dai;

 381         codec->num_dai = ARRAY_SIZE(wm9705_dai);

 382         codec->write = ac97_write;

 383         codec->read = ac97_read;

 384         INIT_LIST_HEAD(&codec->dapm_widgets);

 385         INIT_LIST_HEAD(&codec->dapm_paths);

 386 

 387         ret = snd_soc_new_ac97_codec(codec, &soc_ac97_ops, 0);

 388         if (ret < 0) {

 389                 printk(KERN_ERR "wm9705: failed to register AC97 codec\n");

 390                 goto codec_err;

 391         }

 392 

 393         /* register pcms */

 394         ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);

 395         if (ret < 0)

 396                 goto pcm_err;

 397 

 398         ret = wm9705_reset(codec);

 399         if (ret)

 400                 goto reset_err;

 401 

 402         snd_soc_add_controls(codec, wm9705_snd_ac97_controls,

 403                                 ARRAY_SIZE(wm9705_snd_ac97_controls));

 404         wm9705_add_widgets(codec);

 405 

 406         ret = snd_soc_init_card(socdev);

 407         if (ret < 0) {

 408                 printk(KERN_ERR "wm9705: failed to register card\n");

 409                 goto pcm_err;

 410         }

 411 

 412         return 0;

 413 

 414 reset_err:

 415         snd_soc_free_pcms(socdev);

 416 pcm_err:

 417         snd_soc_free_ac97_codec(codec);

 418 codec_err:

 419         kfree(codec->reg_cache);

 420 cache_err:

 421         kfree(socdev->card->codec);

 422         socdev->card->codec = NULL;

 423         return ret;

 424 }

 425 

 426 static int wm9705_soc_remove(struct platform_device *pdev)

 427 {

 428         struct snd_soc_device *socdev = platform_get_drvdata(pdev);

 429         struct snd_soc_codec *codec = socdev->card->codec;

 430 

 431         if (codec == NULL)

 432                 return 0;

 433 

 434         snd_soc_dapm_free(socdev);

 435         snd_soc_free_pcms(socdev);

 436         snd_soc_free_ac97_codec(codec);

 437         kfree(codec->reg_cache);

 438         kfree(codec);

 439         return 0;

 440 }

 441 

 442 struct snd_soc_codec_device soc_codec_dev_wm9705 = {

 443         .probe =        wm9705_soc_probe,

 444         .remove =       wm9705_soc_remove,

 445         .suspend =      wm9705_soc_suspend,

 446         .resume =       wm9705_soc_resume,

 447 };

 448 EXPORT_SYMBOL_GPL(soc_codec_dev_wm9705);

 449 

 450 MODULE_DESCRIPTION("ASoC WM9705 driver");

 451 MODULE_AUTHOR("Ian Molton");

 452 MODULE_LICENSE("GPL v2");

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -