toonie.c (3370B)
1// SPDX-License-Identifier: GPL-2.0-only 2/* 3 * Apple Onboard Audio driver for Toonie codec 4 * 5 * Copyright 2006 Johannes Berg <johannes@sipsolutions.net> 6 * 7 * This is a driver for the toonie codec chip. This chip is present 8 * on the Mac Mini and is nothing but a DAC. 9 */ 10#include <linux/delay.h> 11#include <linux/module.h> 12#include <linux/slab.h> 13MODULE_AUTHOR("Johannes Berg <johannes@sipsolutions.net>"); 14MODULE_LICENSE("GPL"); 15MODULE_DESCRIPTION("toonie codec driver for snd-aoa"); 16 17#include "../aoa.h" 18#include "../soundbus/soundbus.h" 19 20 21#define PFX "snd-aoa-codec-toonie: " 22 23struct toonie { 24 struct aoa_codec codec; 25}; 26#define codec_to_toonie(c) container_of(c, struct toonie, codec) 27 28static int toonie_dev_register(struct snd_device *dev) 29{ 30 return 0; 31} 32 33static const struct snd_device_ops ops = { 34 .dev_register = toonie_dev_register, 35}; 36 37static struct transfer_info toonie_transfers[] = { 38 /* This thing *only* has analog output, 39 * the rates are taken from Info.plist 40 * from Darwin. */ 41 { 42 .formats = SNDRV_PCM_FMTBIT_S16_BE | 43 SNDRV_PCM_FMTBIT_S24_BE, 44 .rates = SNDRV_PCM_RATE_32000 | 45 SNDRV_PCM_RATE_44100 | 46 SNDRV_PCM_RATE_48000 | 47 SNDRV_PCM_RATE_88200 | 48 SNDRV_PCM_RATE_96000, 49 }, 50 {} 51}; 52 53static int toonie_usable(struct codec_info_item *cii, 54 struct transfer_info *ti, 55 struct transfer_info *out) 56{ 57 return 1; 58} 59 60#ifdef CONFIG_PM 61static int toonie_suspend(struct codec_info_item *cii, pm_message_t state) 62{ 63 /* can we turn it off somehow? */ 64 return 0; 65} 66 67static int toonie_resume(struct codec_info_item *cii) 68{ 69 return 0; 70} 71#endif /* CONFIG_PM */ 72 73static struct codec_info toonie_codec_info = { 74 .transfers = toonie_transfers, 75 .sysclock_factor = 256, 76 .bus_factor = 64, 77 .owner = THIS_MODULE, 78 .usable = toonie_usable, 79#ifdef CONFIG_PM 80 .suspend = toonie_suspend, 81 .resume = toonie_resume, 82#endif 83}; 84 85static int toonie_init_codec(struct aoa_codec *codec) 86{ 87 struct toonie *toonie = codec_to_toonie(codec); 88 89 /* nothing connected? what a joke! */ 90 if (toonie->codec.connected != 1) 91 return -ENOTCONN; 92 93 if (aoa_snd_device_new(SNDRV_DEV_CODEC, toonie, &ops)) { 94 printk(KERN_ERR PFX "failed to create toonie snd device!\n"); 95 return -ENODEV; 96 } 97 98 if (toonie->codec.soundbus_dev->attach_codec(toonie->codec.soundbus_dev, 99 aoa_get_card(), 100 &toonie_codec_info, toonie)) { 101 printk(KERN_ERR PFX "error creating toonie pcm\n"); 102 snd_device_free(aoa_get_card(), toonie); 103 return -ENODEV; 104 } 105 106 return 0; 107} 108 109static void toonie_exit_codec(struct aoa_codec *codec) 110{ 111 struct toonie *toonie = codec_to_toonie(codec); 112 113 if (!toonie->codec.soundbus_dev) { 114 printk(KERN_ERR PFX "toonie_exit_codec called without soundbus_dev!\n"); 115 return; 116 } 117 toonie->codec.soundbus_dev->detach_codec(toonie->codec.soundbus_dev, toonie); 118} 119 120static struct toonie *toonie; 121 122static int __init toonie_init(void) 123{ 124 toonie = kzalloc(sizeof(struct toonie), GFP_KERNEL); 125 126 if (!toonie) 127 return -ENOMEM; 128 129 strscpy(toonie->codec.name, "toonie", sizeof(toonie->codec.name)); 130 toonie->codec.owner = THIS_MODULE; 131 toonie->codec.init = toonie_init_codec; 132 toonie->codec.exit = toonie_exit_codec; 133 134 if (aoa_codec_register(&toonie->codec)) { 135 kfree(toonie); 136 return -EINVAL; 137 } 138 139 return 0; 140} 141 142static void __exit toonie_exit(void) 143{ 144 aoa_codec_unregister(&toonie->codec); 145 kfree(toonie); 146} 147 148module_init(toonie_init); 149module_exit(toonie_exit);