| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1 | /* | 
|  | 2 | ac97_plugin_ad1980.c  Copyright (C) 2003 Red Hat, Inc. All rights reserved. | 
|  | 3 |  | 
|  | 4 | The contents of this file are subject to the Open Software License version 1.1 | 
|  | 5 | that can be found at http://www.opensource.org/licenses/osl-1.1.txt and is | 
|  | 6 | included herein by reference. | 
|  | 7 |  | 
|  | 8 | Alternatively, the contents of this file may be used under the | 
|  | 9 | terms of the GNU General Public License version 2 (the "GPL") as | 
|  | 10 | distributed in the kernel source COPYING file, in which | 
|  | 11 | case the provisions of the GPL are applicable instead of the | 
|  | 12 | above.  If you wish to allow the use of your version of this file | 
|  | 13 | only under the terms of the GPL and not to allow others to use | 
|  | 14 | your version of this file under the OSL, indicate your decision | 
|  | 15 | by deleting the provisions above and replace them with the notice | 
|  | 16 | and other provisions required by the GPL.  If you do not delete | 
|  | 17 | the provisions above, a recipient may use your version of this | 
|  | 18 | file under either the OSL or the GPL. | 
|  | 19 |  | 
|  | 20 | Authors: 	Alan Cox <alan@redhat.com> | 
|  | 21 |  | 
|  | 22 | This is an example codec plugin. This one switches the connections | 
|  | 23 | around to match the setups some vendors use with audio switched to | 
|  | 24 | non standard front connectors not the normal rear ones | 
|  | 25 |  | 
|  | 26 | This code primarily exists to demonstrate how to use the codec | 
|  | 27 | interface | 
|  | 28 |  | 
|  | 29 | */ | 
|  | 30 |  | 
|  | 31 | #include <linux/config.h> | 
|  | 32 | #include <linux/module.h> | 
|  | 33 | #include <linux/init.h> | 
|  | 34 | #include <linux/kernel.h> | 
|  | 35 | #include <linux/ac97_codec.h> | 
|  | 36 |  | 
|  | 37 | /** | 
|  | 38 | *	ad1980_remove		-	codec remove callback | 
|  | 39 | *	@codec: The codec that is being removed | 
|  | 40 | * | 
|  | 41 | *	This callback occurs when an AC97 codec is being removed. A | 
|  | 42 | *	codec remove call will not occur for a codec during that codec | 
|  | 43 | *	probe callback. | 
|  | 44 | * | 
|  | 45 | *	Most drivers will need to lock their remove versus their | 
|  | 46 | *	use of the codec after the probe function. | 
|  | 47 | */ | 
|  | 48 |  | 
|  | 49 | static void __devexit ad1980_remove(struct ac97_codec *codec, struct ac97_driver *driver) | 
|  | 50 | { | 
|  | 51 | /* Nothing to do in the simple example */ | 
|  | 52 | } | 
|  | 53 |  | 
|  | 54 |  | 
|  | 55 | /** | 
|  | 56 | *	ad1980_probe		-	codec found callback | 
|  | 57 | *	@codec: ac97 codec matching the idents | 
|  | 58 | *	@driver: ac97_driver it matched | 
|  | 59 | * | 
|  | 60 | *	This entry point is called when a codec is found which matches | 
|  | 61 | *	the driver. At the point it is called the codec is basically | 
|  | 62 | *	operational, mixer operations have been initialised and can | 
|  | 63 | *	be overriden. Called in process context. The field driver_private | 
|  | 64 | *	is available for the driver to use to store stuff. | 
|  | 65 | * | 
|  | 66 | *	The caller can claim the device by returning zero, or return | 
|  | 67 | *	a negative error code. | 
|  | 68 | */ | 
|  | 69 |  | 
|  | 70 | static int ad1980_probe(struct ac97_codec *codec, struct ac97_driver *driver) | 
|  | 71 | { | 
|  | 72 | u16 control; | 
|  | 73 |  | 
|  | 74 | #define AC97_AD_MISC	0x76 | 
|  | 75 |  | 
|  | 76 | /* Switch the inputs/outputs over (from Dell code) */ | 
|  | 77 | control = codec->codec_read(codec, AC97_AD_MISC); | 
|  | 78 | codec->codec_write(codec, AC97_AD_MISC, control | 0x4420); | 
|  | 79 |  | 
|  | 80 | /* We could refuse the device since we dont need to hang around, | 
|  | 81 | but we will claim it */ | 
|  | 82 | return 0; | 
|  | 83 | } | 
|  | 84 |  | 
|  | 85 |  | 
|  | 86 | static struct ac97_driver ad1980_driver = { | 
|  | 87 | .codec_id	= 0x41445370, | 
|  | 88 | .codec_mask	= 0xFFFFFFFF, | 
|  | 89 | .name		= "AD1980 example", | 
|  | 90 | .probe		= ad1980_probe, | 
|  | 91 | .remove		= __devexit_p(ad1980_remove), | 
|  | 92 | }; | 
|  | 93 |  | 
|  | 94 | /** | 
|  | 95 | *	ad1980_exit		-	module exit path | 
|  | 96 | * | 
|  | 97 | *	Our module is being unloaded. At this point unregister_driver | 
|  | 98 | *	will call back our remove handler for any existing codecs. You | 
|  | 99 | *	may not unregister_driver from interrupt context or from a | 
|  | 100 | *	probe/remove callback. | 
|  | 101 | */ | 
|  | 102 |  | 
|  | 103 | static void ad1980_exit(void) | 
|  | 104 | { | 
|  | 105 | ac97_unregister_driver(&ad1980_driver); | 
|  | 106 | } | 
|  | 107 |  | 
|  | 108 | /** | 
|  | 109 | *	ad1980_init		-	set up ad1980 handlers | 
|  | 110 | * | 
|  | 111 | *	After we call the register function it will call our probe | 
|  | 112 | *	function for each existing matching device before returning to us. | 
|  | 113 | *	Any devices appearing afterwards whose id's match the codec_id | 
|  | 114 | *	will also cause the probe function to be called. | 
|  | 115 | *	You may not register_driver from interrupt context or from a | 
|  | 116 | *	probe/remove callback. | 
|  | 117 | */ | 
|  | 118 |  | 
|  | 119 | static int ad1980_init(void) | 
|  | 120 | { | 
|  | 121 | return ac97_register_driver(&ad1980_driver); | 
|  | 122 | } | 
|  | 123 |  | 
|  | 124 | module_init(ad1980_init); | 
|  | 125 | module_exit(ad1980_exit); | 
|  | 126 | MODULE_LICENSE("GPL"); |