0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #include <linux/delay.h>
0011 #include <linux/module.h>
0012 #include <linux/slab.h>
0013 MODULE_AUTHOR("Johannes Berg <johannes@sipsolutions.net>");
0014 MODULE_LICENSE("GPL");
0015 MODULE_DESCRIPTION("toonie codec driver for snd-aoa");
0016
0017 #include "../aoa.h"
0018 #include "../soundbus/soundbus.h"
0019
0020
0021 #define PFX "snd-aoa-codec-toonie: "
0022
0023 struct toonie {
0024 struct aoa_codec codec;
0025 };
0026 #define codec_to_toonie(c) container_of(c, struct toonie, codec)
0027
0028 static int toonie_dev_register(struct snd_device *dev)
0029 {
0030 return 0;
0031 }
0032
0033 static const struct snd_device_ops ops = {
0034 .dev_register = toonie_dev_register,
0035 };
0036
0037 static struct transfer_info toonie_transfers[] = {
0038
0039
0040
0041 {
0042 .formats = SNDRV_PCM_FMTBIT_S16_BE |
0043 SNDRV_PCM_FMTBIT_S24_BE,
0044 .rates = SNDRV_PCM_RATE_32000 |
0045 SNDRV_PCM_RATE_44100 |
0046 SNDRV_PCM_RATE_48000 |
0047 SNDRV_PCM_RATE_88200 |
0048 SNDRV_PCM_RATE_96000,
0049 },
0050 {}
0051 };
0052
0053 static int toonie_usable(struct codec_info_item *cii,
0054 struct transfer_info *ti,
0055 struct transfer_info *out)
0056 {
0057 return 1;
0058 }
0059
0060 #ifdef CONFIG_PM
0061 static int toonie_suspend(struct codec_info_item *cii, pm_message_t state)
0062 {
0063
0064 return 0;
0065 }
0066
0067 static int toonie_resume(struct codec_info_item *cii)
0068 {
0069 return 0;
0070 }
0071 #endif
0072
0073 static struct codec_info toonie_codec_info = {
0074 .transfers = toonie_transfers,
0075 .sysclock_factor = 256,
0076 .bus_factor = 64,
0077 .owner = THIS_MODULE,
0078 .usable = toonie_usable,
0079 #ifdef CONFIG_PM
0080 .suspend = toonie_suspend,
0081 .resume = toonie_resume,
0082 #endif
0083 };
0084
0085 static int toonie_init_codec(struct aoa_codec *codec)
0086 {
0087 struct toonie *toonie = codec_to_toonie(codec);
0088
0089
0090 if (toonie->codec.connected != 1)
0091 return -ENOTCONN;
0092
0093 if (aoa_snd_device_new(SNDRV_DEV_CODEC, toonie, &ops)) {
0094 printk(KERN_ERR PFX "failed to create toonie snd device!\n");
0095 return -ENODEV;
0096 }
0097
0098 if (toonie->codec.soundbus_dev->attach_codec(toonie->codec.soundbus_dev,
0099 aoa_get_card(),
0100 &toonie_codec_info, toonie)) {
0101 printk(KERN_ERR PFX "error creating toonie pcm\n");
0102 snd_device_free(aoa_get_card(), toonie);
0103 return -ENODEV;
0104 }
0105
0106 return 0;
0107 }
0108
0109 static void toonie_exit_codec(struct aoa_codec *codec)
0110 {
0111 struct toonie *toonie = codec_to_toonie(codec);
0112
0113 if (!toonie->codec.soundbus_dev) {
0114 printk(KERN_ERR PFX "toonie_exit_codec called without soundbus_dev!\n");
0115 return;
0116 }
0117 toonie->codec.soundbus_dev->detach_codec(toonie->codec.soundbus_dev, toonie);
0118 }
0119
0120 static struct toonie *toonie;
0121
0122 static int __init toonie_init(void)
0123 {
0124 toonie = kzalloc(sizeof(struct toonie), GFP_KERNEL);
0125
0126 if (!toonie)
0127 return -ENOMEM;
0128
0129 strscpy(toonie->codec.name, "toonie", sizeof(toonie->codec.name));
0130 toonie->codec.owner = THIS_MODULE;
0131 toonie->codec.init = toonie_init_codec;
0132 toonie->codec.exit = toonie_exit_codec;
0133
0134 if (aoa_codec_register(&toonie->codec)) {
0135 kfree(toonie);
0136 return -EINVAL;
0137 }
0138
0139 return 0;
0140 }
0141
0142 static void __exit toonie_exit(void)
0143 {
0144 aoa_codec_unregister(&toonie->codec);
0145 kfree(toonie);
0146 }
0147
0148 module_init(toonie_init);
0149 module_exit(toonie_exit);