127 lines
3.9 KiB
C
127 lines
3.9 KiB
C
|
/*
|
||
|
ac97_plugin_ad1980.c Copyright (C) 2003 Red Hat, Inc. All rights reserved.
|
||
|
|
||
|
The contents of this file are subject to the Open Software License version 1.1
|
||
|
that can be found at http://www.opensource.org/licenses/osl-1.1.txt and is
|
||
|
included herein by reference.
|
||
|
|
||
|
Alternatively, the contents of this file may be used under the
|
||
|
terms of the GNU General Public License version 2 (the "GPL") as
|
||
|
distributed in the kernel source COPYING file, in which
|
||
|
case the provisions of the GPL are applicable instead of the
|
||
|
above. If you wish to allow the use of your version of this file
|
||
|
only under the terms of the GPL and not to allow others to use
|
||
|
your version of this file under the OSL, indicate your decision
|
||
|
by deleting the provisions above and replace them with the notice
|
||
|
and other provisions required by the GPL. If you do not delete
|
||
|
the provisions above, a recipient may use your version of this
|
||
|
file under either the OSL or the GPL.
|
||
|
|
||
|
Authors: Alan Cox <alan@redhat.com>
|
||
|
|
||
|
This is an example codec plugin. This one switches the connections
|
||
|
around to match the setups some vendors use with audio switched to
|
||
|
non standard front connectors not the normal rear ones
|
||
|
|
||
|
This code primarily exists to demonstrate how to use the codec
|
||
|
interface
|
||
|
|
||
|
*/
|
||
|
|
||
|
#include <linux/config.h>
|
||
|
#include <linux/module.h>
|
||
|
#include <linux/init.h>
|
||
|
#include <linux/kernel.h>
|
||
|
#include <linux/ac97_codec.h>
|
||
|
|
||
|
/**
|
||
|
* ad1980_remove - codec remove callback
|
||
|
* @codec: The codec that is being removed
|
||
|
*
|
||
|
* This callback occurs when an AC97 codec is being removed. A
|
||
|
* codec remove call will not occur for a codec during that codec
|
||
|
* probe callback.
|
||
|
*
|
||
|
* Most drivers will need to lock their remove versus their
|
||
|
* use of the codec after the probe function.
|
||
|
*/
|
||
|
|
||
|
static void __devexit ad1980_remove(struct ac97_codec *codec, struct ac97_driver *driver)
|
||
|
{
|
||
|
/* Nothing to do in the simple example */
|
||
|
}
|
||
|
|
||
|
|
||
|
/**
|
||
|
* ad1980_probe - codec found callback
|
||
|
* @codec: ac97 codec matching the idents
|
||
|
* @driver: ac97_driver it matched
|
||
|
*
|
||
|
* This entry point is called when a codec is found which matches
|
||
|
* the driver. At the point it is called the codec is basically
|
||
|
* operational, mixer operations have been initialised and can
|
||
|
* be overriden. Called in process context. The field driver_private
|
||
|
* is available for the driver to use to store stuff.
|
||
|
*
|
||
|
* The caller can claim the device by returning zero, or return
|
||
|
* a negative error code.
|
||
|
*/
|
||
|
|
||
|
static int ad1980_probe(struct ac97_codec *codec, struct ac97_driver *driver)
|
||
|
{
|
||
|
u16 control;
|
||
|
|
||
|
#define AC97_AD_MISC 0x76
|
||
|
|
||
|
/* Switch the inputs/outputs over (from Dell code) */
|
||
|
control = codec->codec_read(codec, AC97_AD_MISC);
|
||
|
codec->codec_write(codec, AC97_AD_MISC, control | 0x4420);
|
||
|
|
||
|
/* We could refuse the device since we dont need to hang around,
|
||
|
but we will claim it */
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
|
||
|
static struct ac97_driver ad1980_driver = {
|
||
|
.codec_id = 0x41445370,
|
||
|
.codec_mask = 0xFFFFFFFF,
|
||
|
.name = "AD1980 example",
|
||
|
.probe = ad1980_probe,
|
||
|
.remove = __devexit_p(ad1980_remove),
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* ad1980_exit - module exit path
|
||
|
*
|
||
|
* Our module is being unloaded. At this point unregister_driver
|
||
|
* will call back our remove handler for any existing codecs. You
|
||
|
* may not unregister_driver from interrupt context or from a
|
||
|
* probe/remove callback.
|
||
|
*/
|
||
|
|
||
|
static void ad1980_exit(void)
|
||
|
{
|
||
|
ac97_unregister_driver(&ad1980_driver);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* ad1980_init - set up ad1980 handlers
|
||
|
*
|
||
|
* After we call the register function it will call our probe
|
||
|
* function for each existing matching device before returning to us.
|
||
|
* Any devices appearing afterwards whose id's match the codec_id
|
||
|
* will also cause the probe function to be called.
|
||
|
* You may not register_driver from interrupt context or from a
|
||
|
* probe/remove callback.
|
||
|
*/
|
||
|
|
||
|
static int ad1980_init(void)
|
||
|
{
|
||
|
return ac97_register_driver(&ad1980_driver);
|
||
|
}
|
||
|
|
||
|
module_init(ad1980_init);
|
||
|
module_exit(ad1980_exit);
|
||
|
MODULE_LICENSE("GPL");
|