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"); |