X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=Documentation%2Fsound%2Falsa%2FDocBook%2Fwriting-an-alsa-driver.tmpl;fp=Documentation%2Fsound%2Falsa%2FDocBook%2Fwriting-an-alsa-driver.tmpl;h=1faf76383babd26875c9e5d303685a29c6096531;hb=43bc926fffd92024b46cafaf7350d669ba9ca884;hp=e789475304b6e03b8b8e5c60c72fd8f445f65a5b;hpb=cee37fe97739d85991964371c1f3a745c00dd236;p=linux-2.6.git
diff --git a/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl b/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl
index e78947530..1faf76383 100644
--- a/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl
+++ b/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl
@@ -18,8 +18,8 @@
- March 6, 2005
- 0.3.4
+ November 17, 2005
+ 0.3.6
@@ -30,7 +30,7 @@
- Copyright (c) 2002-2004 Takashi Iwai tiwai@suse.de
+ Copyright (c) 2002-2005 Takashi Iwai tiwai@suse.de
@@ -371,7 +371,7 @@
create probe() callback.create remove() callback.create pci_driver table which contains the three pointers above.
- create init() function just calling pci_module_init() to register the pci_driver table defined above.
+ create init() function just calling pci_register_driver() to register the pci_driver table defined above.create exit() function to call pci_unregister_driver() function.
@@ -403,9 +403,8 @@
static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;
/* definition of the chip-specific record */
- typedef struct snd_mychip mychip_t;
- struct snd_mychip {
- snd_card_t *card;
+ struct mychip {
+ struct snd_card *card;
// rest of implementation will be in the section
// "PCI Resource Managements"
};
@@ -413,7 +412,7 @@
/* chip-specific destructor
* (see "PCI Resource Managements")
*/
- static int snd_mychip_free(mychip_t *chip)
+ static int snd_mychip_free(struct mychip *chip)
{
.... // will be implemented later...
}
@@ -421,22 +420,21 @@
/* component-destructor
* (see "Management of Cards and Components")
*/
- static int snd_mychip_dev_free(snd_device_t *device)
+ static int snd_mychip_dev_free(struct snd_device *device)
{
- mychip_t *chip = device->device_data;
- return snd_mychip_free(chip);
+ return snd_mychip_free(device->device_data);
}
/* chip-specific constructor
* (see "Management of Cards and Components")
*/
- static int __devinit snd_mychip_create(snd_card_t *card,
+ static int __devinit snd_mychip_create(struct snd_card *card,
struct pci_dev *pci,
- mychip_t **rchip)
+ struct mychip **rchip)
{
- mychip_t *chip;
+ struct mychip *chip;
int err;
- static snd_device_ops_t ops = {
+ static struct snd_device_ops ops = {
.dev_free = snd_mychip_dev_free,
};
@@ -447,7 +445,7 @@
....
/* allocate a chip-specific data with zero filled */
- chip = kcalloc(1, sizeof(*chip), GFP_KERNEL);
+ chip = kzalloc(sizeof(*chip), GFP_KERNEL);
if (chip == NULL)
return -ENOMEM;
@@ -474,8 +472,8 @@
const struct pci_device_id *pci_id)
{
static int dev;
- snd_card_t *card;
- mychip_t *chip;
+ struct snd_card *card;
+ struct mychip *chip;
int err;
/* (1) */
@@ -582,7 +580,7 @@
@@ -605,7 +603,7 @@
@@ -830,7 +828,7 @@
After the card is created, you can attach the components
(devices) to the card instance. On ALSA driver, a component is
- represented as a snd_device_t object.
+ represented as a struct snd_device object.
A component can be a PCM instance, a control interface, a raw
MIDI interface, etc. Each of such instances has one component
entry.
@@ -891,14 +889,11 @@
The chip-specific information, e.g. the i/o port address, its
resource pointer, or the irq number, is stored in the
chip-specific record.
- Usually, the chip-specific record is typedef'ed as
- xxx_t like the following:
@@ -918,12 +913,12 @@
- whether mychip_t is the type of the chip record.
+ whether struct mychip is the type of the chip record.
@@ -932,7 +927,7 @@
private_data;
+ struct mychip *chip = (struct mychip *)card->private_data;
]]>
@@ -949,16 +944,16 @@
After allocating a card instance via
snd_card_new() (with
NULL on the 4th arg), call
- kcalloc().
+ kzalloc().
@@ -971,8 +966,8 @@
@@ -1000,7 +995,7 @@
device_data;
- return snd_mychip_free(chip);
+ return snd_mychip_free(device->device_data);
}
]]>
@@ -1087,15 +1081,15 @@
PCI Resource Managements Example
port = pci_resource_start(pci, 0);
if (request_irq(pci->irq, snd_mychip_interrupt,
- SA_INTERRUPT|SA_SHIRQ, "My Chip",
- (void *)chip)) {
+ SA_INTERRUPT|SA_SHIRQ, "My Chip", chip)) {
printk(KERN_ERR "cannot grab irq %d\n", pci->irq);
snd_mychip_free(chip);
return -EBUSY;
@@ -1179,7 +1172,7 @@
}
/* PCI IDs */
- static struct pci_device_id snd_mychip_ids[] = {
+ static struct pci_device_id snd_mychip_ids[] __devinitdata = {
{ PCI_VENDOR_ID_FOO, PCI_DEVICE_ID_BAR,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, },
....
@@ -1198,7 +1191,7 @@
/* initialization of the module */
static int __init alsa_card_mychip_init(void)
{
- return pci_module_init(&driver);
+ return pci_register_driver(&driver);
}
/* clean up the module */
@@ -1223,7 +1216,7 @@
The allocation of PCI resources is done in the
probe() function, and usually an extra
xxx_create() function is written for this
- purpose.
+ purpose.
@@ -1232,7 +1225,7 @@
allocating resources. Also, you need to set the proper PCI DMA
mask to limit the accessed i/o range. In some cases, you might
need to call pci_set_master() function,
- too.
+ too.
@@ -1243,8 +1236,8 @@
Now assume that this PCI device has an I/O port with 8 bytes
- and an interrupt. Then mychip_t will have the
- following fields:
+ and an interrupt. Then struct mychip will have the
+ following fields:
kcalloc() automatically, so you
+ kzalloc() automatically, so you
don't have to take care of resetting them.
@@ -1330,8 +1323,7 @@
irq, snd_mychip_interrupt,
- SA_INTERRUPT|SA_SHIRQ, "My Chip",
- (void *)chip)) {
+ SA_INTERRUPT|SA_SHIRQ, "My Chip", chip)) {
printk(KERN_ERR "cannot grab irq %d\n", pci->irq);
snd_mychip_free(chip);
return -EBUSY;
@@ -1372,7 +1364,7 @@
static irqreturn_t snd_mychip_interrupt(int irq, void *dev_id,
struct pt_regs *regs)
{
- mychip_t *chip = dev_id;
+ struct mychip *chip = dev_id;
....
return IRQ_HANDLED;
}
@@ -1433,25 +1425,10 @@
res_port) {
- release_resource(chip->res_port);
- kfree_nocheck(chip->res_port);
- }
+ release_and_free_resource(chip->res_port);
]]>
-
- As you can see, the resource pointer is also to be freed
- via kfree_nocheck() after
- release_resource() is called. You
- cannot use kfree() here, because on ALSA,
- kfree() may be a wrapper to its own
- allocator with the memory debugging. Since the resource pointer
- is allocated externally outside the ALSA, it must be released
- via the native
- kfree().
- kfree_nocheck() is used for that; it calls
- the native kfree() without wrapper.
@@ -1502,7 +1479,7 @@
iobase_virt)
@@ -1552,7 +1529,7 @@
Registration of Device Struct
At some point, typically after calling snd_device_new(),
- you need to register the struct device of the chip
+ you need to register the struct device of the chip
you're handling for udev and co. ALSA provides a macro for compatibility with
older kernels. Simply call like the following:
@@ -1588,7 +1565,7 @@
runtime;
+ struct mychip *chip = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
runtime->hw = snd_mychip_playback_hw;
// more hardware-initialization will be done here
@@ -1803,19 +1780,19 @@
}
/* close callback */
- static int snd_mychip_playback_close(snd_pcm_substream_t *substream)
+ static int snd_mychip_playback_close(struct snd_pcm_substream *substream)
{
- mychip_t *chip = snd_pcm_substream_chip(substream);
+ struct mychip *chip = snd_pcm_substream_chip(substream);
// the hardware-specific codes will be here
return 0;
}
/* open callback */
- static int snd_mychip_capture_open(snd_pcm_substream_t *substream)
+ static int snd_mychip_capture_open(struct snd_pcm_substream *substream)
{
- mychip_t *chip = snd_pcm_substream_chip(substream);
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct mychip *chip = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
runtime->hw = snd_mychip_capture_hw;
// more hardware-initialization will be done here
@@ -1823,33 +1800,33 @@
}
/* close callback */
- static int snd_mychip_capture_close(snd_pcm_substream_t *substream)
+ static int snd_mychip_capture_close(struct snd_pcm_substream *substream)
{
- mychip_t *chip = snd_pcm_substream_chip(substream);
+ struct mychip *chip = snd_pcm_substream_chip(substream);
// the hardware-specific codes will be here
return 0;
}
/* hw_params callback */
- static int snd_mychip_pcm_hw_params(snd_pcm_substream_t *substream,
- snd_pcm_hw_params_t * hw_params)
+ static int snd_mychip_pcm_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *hw_params)
{
return snd_pcm_lib_malloc_pages(substream,
params_buffer_bytes(hw_params));
}
/* hw_free callback */
- static int snd_mychip_pcm_hw_free(snd_pcm_substream_t *substream)
+ static int snd_mychip_pcm_hw_free(struct snd_pcm_substream *substream)
{
return snd_pcm_lib_free_pages(substream);
}
/* prepare callback */
- static int snd_mychip_pcm_prepare(snd_pcm_substream_t *substream)
+ static int snd_mychip_pcm_prepare(struct snd_pcm_substream *substream)
{
- mychip_t *chip = snd_pcm_substream_chip(substream);
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct mychip *chip = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
/* set up the hardware with the current configuration
* for example...
@@ -1857,14 +1834,14 @@
mychip_set_sample_format(chip, runtime->format);
mychip_set_sample_rate(chip, runtime->rate);
mychip_set_channels(chip, runtime->channels);
- mychip_set_dma_setup(chip, runtime->dma_area,
+ mychip_set_dma_setup(chip, runtime->dma_addr,
chip->buffer_size,
chip->period_size);
return 0;
}
/* trigger callback */
- static int snd_mychip_pcm_trigger(snd_pcm_substream_t *substream,
+ static int snd_mychip_pcm_trigger(struct snd_pcm_substream *substream,
int cmd)
{
switch (cmd) {
@@ -1881,9 +1858,9 @@
/* pointer callback */
static snd_pcm_uframes_t
- snd_mychip_pcm_pointer(snd_pcm_substream_t *substream)
+ snd_mychip_pcm_pointer(struct snd_pcm_substream *substream)
{
- mychip_t *chip = snd_pcm_substream_chip(substream);
+ struct mychip *chip = snd_pcm_substream_chip(substream);
unsigned int current_ptr;
/* get the current hardware pointer */
@@ -1892,7 +1869,7 @@
}
/* operators */
- static snd_pcm_ops_t snd_mychip_playback_ops = {
+ static struct snd_pcm_ops snd_mychip_playback_ops = {
.open = snd_mychip_playback_open,
.close = snd_mychip_playback_close,
.ioctl = snd_pcm_lib_ioctl,
@@ -1904,7 +1881,7 @@
};
/* operators */
- static snd_pcm_ops_t snd_mychip_capture_ops = {
+ static struct snd_pcm_ops snd_mychip_capture_ops = {
.open = snd_mychip_capture_open,
.close = snd_mychip_capture_close,
.ioctl = snd_pcm_lib_ioctl,
@@ -1920,9 +1897,9 @@
*/
/* create a pcm device */
- static int __devinit snd_mychip_new_pcm(mychip_t *chip)
+ static int __devinit snd_mychip_new_pcm(struct mychip *chip)
{
- snd_pcm_t *pcm;
+ struct snd_pcm *pcm;
int err;
if ((err = snd_pcm_new(chip->card, "My Chip", 0, 1, 1,
@@ -1959,9 +1936,9 @@
card, "My Chip", 0, 1, 1,
@@ -2004,13 +1981,13 @@
specify more numbers, but they must be handled properly in
open/close, etc. callbacks. When you need to know which
substream you are referring to, then it can be obtained from
- snd_pcm_substream_t data passed to each callback
+ struct snd_pcm_substream data passed to each callback
as follows:
number;
]]>
@@ -2039,7 +2016,7 @@
PCM Instance with a Destructor
my_private_pcm_data);
// do what you like else
....
}
- static int __devinit snd_mychip_new_pcm(mychip_t *chip)
+ static int __devinit snd_mychip_new_pcm(struct mychip *chip)
{
- snd_pcm_t *pcm;
+ struct snd_pcm *pcm;
....
/* allocate your own data */
chip->my_private_pcm_data = kmalloc(...);
@@ -2164,7 +2141,7 @@
@@ -2268,7 +2244,7 @@ struct _snd_pcm_runtime {
Hardware Description
- The hardware descriptor (snd_pcm_hardware_t)
+ The hardware descriptor (struct snd_pcm_hardware)
contains the definitions of the fundamental hardware
configuration. Above all, you'll need to define this in
@@ -2283,7 +2259,7 @@ struct _snd_pcm_runtime {
runtime;
+ struct snd_pcm_runtime *runtime = substream->runtime;
...
runtime->hw = snd_mychip_playback_hw; /* common definition */
if (chip->model == VERY_OLD_ONE)
@@ -2298,7 +2274,7 @@ struct _snd_pcm_runtime {
PAUSE bit means that the pcm supports the
pause operation, while the
RESUME bit means that the pcm supports
- the suspend/resume operation. If these flags
- are set, the trigger callback below
- must handle the corresponding commands.
+ the full suspend/resume operation.
+ If PAUSE flag is set,
+ the trigger callback below
+ must handle the corresponding (pause push/release) commands.
+ The suspend/resume trigger commands can be defined even without
+ RESUME flag. See
+ Power Management section for details.
@@ -2528,7 +2509,7 @@ struct _snd_pcm_runtime {
Running Status
The running status can be referred via runtime->status.
- This is the pointer to snd_pcm_mmap_status_t
+ This is the pointer to struct snd_pcm_mmap_status
record. For example, you can get the current DMA hardware
pointer via runtime->status->hw_ptr.
@@ -2536,7 +2517,7 @@ struct _snd_pcm_runtime {
The DMA application pointer can be referred via
runtime->control, which points
- snd_pcm_mmap_control_t record.
+ struct snd_pcm_mmap_control record.
However, accessing directly to this value is not recommended.
@@ -2558,9 +2539,9 @@ struct _snd_pcm_runtime {
runtime->private_data = data;
@@ -2602,7 +2583,7 @@ struct _snd_pcm_runtime {
The callback function takes at least the argument with
- snd_pcm_substream_t pointer. For retrieving the
+ snd_pcm_substream pointer. For retrieving the
chip record from the given substream instance, you can use the
following macro.
@@ -2610,7 +2591,7 @@ struct _snd_pcm_runtime {
@@ -2632,7 +2613,7 @@ struct _snd_pcm_runtime {
@@ -2647,10 +2628,10 @@ struct _snd_pcm_runtime {
runtime;
+ struct mychip *chip = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
runtime->hw = snd_mychip_playback_hw;
return 0;
@@ -2683,7 +2664,7 @@ struct _snd_pcm_runtime {
@@ -2698,7 +2679,7 @@ struct _snd_pcm_runtime {
runtime->private_data);
@@ -2725,8 +2706,8 @@ struct _snd_pcm_runtime {
@@ -2801,7 +2782,7 @@ struct _snd_pcm_runtime {
@@ -2836,7 +2817,7 @@ struct _snd_pcm_runtime {
@@ -2855,7 +2836,7 @@ struct _snd_pcm_runtime {
Note that this callback became non-atomic since the recent version.
- You can use schedule-related fucntions safely in this callback now.
+ You can use schedule-related functions safely in this callback now.
@@ -2885,7 +2866,7 @@ struct _snd_pcm_runtime {
@@ -2927,8 +2908,8 @@ struct _snd_pcm_runtime {
- When the pcm supports the suspend/resume operation
- (i.e. SNDRV_PCM_INFO_RESUME flag is set),
+ When the pcm supports the suspend/resume operation,
+ regardless of full or partial suspend/resume support,
SUSPEND and RESUME
commands must be handled, too.
These commands are issued when the power-management status is
@@ -2937,6 +2918,8 @@ struct _snd_pcm_runtime {
do suspend and resume of the pcm substream, and usually, they
are identical with STOP and
START commands, respectively.
+ See
+ Power Management section for details.
@@ -2955,7 +2938,7 @@ struct _snd_pcm_runtime {
@@ -3083,7 +3066,7 @@ struct _snd_pcm_runtime {
static irqreturn_t snd_mychip_interrupt(int irq, void *dev_id,
struct pt_regs *regs)
{
- mychip_t *chip = dev_id;
+ struct mychip *chip = dev_id;
spin_lock(&chip->lock);
....
if (pcm_irq_invoked(chip)) {
@@ -3127,7 +3110,7 @@ struct _snd_pcm_runtime {
static irqreturn_t snd_mychip_interrupt(int irq, void *dev_id,
struct pt_regs *regs)
{
- mychip_t *chip = dev_id;
+ struct mychip *chip = dev_id;
spin_lock(&chip->lock);
....
if (pcm_irq_invoked(chip)) {
@@ -3237,13 +3220,13 @@ struct _snd_pcm_runtime {
snd_pcm_hardware_t stucture (or in any
+ specified in the snd_pcm_hardware stucture (or in any
other constraint_list). You can build a rule like this:
Example of Hardware Constraints for Channels
min < 2) {
@@ -3314,12 +3298,13 @@ struct _snd_pcm_runtime {
Example of Hardware Constraints for Channels
bits[0] == SNDRV_PCM_FMTBIT_S16_LE) {
@@ -3392,18 +3377,18 @@ struct _snd_pcm_runtime {
callbacks: info,
get and
put. Then, define a
- snd_kcontrol_new_t record, such as:
+ struct snd_kcontrol_new record, such as:
Definition of a Control
The iface field specifies the type of
- the control,
- SNDRV_CTL_ELEM_IFACE_XXX. There are
- MIXER, PCM,
- CARD, etc.
+ the control, SNDRV_CTL_ELEM_IFACE_XXX, which
+ is usually MIXER.
+ Use CARD for global controls that are not
+ logically part of the mixer.
+ If the control is closely associated with some specific device on
+ the sound card, use HWDEP,
+ PCM, RAWMIDI,
+ TIMER, or SEQUENCER, and
+ specify the device number with the
+ device and
+ subdevice fields.
@@ -3457,7 +3449,7 @@ struct _snd_pcm_runtime {
- The private_values field contains
+ The private_value field contains
an arbitrary long integer value for this record. When using
generic info,
get and
@@ -3608,7 +3600,7 @@ struct _snd_pcm_runtime {
The info callback is used to get
the detailed information of this control. This must store the
- values of the given snd_ctl_elem_info_t
+ values of the given struct snd_ctl_elem_info
object. For example, for a boolean control with a single
element will be:
@@ -3616,8 +3608,8 @@ struct _snd_pcm_runtime {
Example of info callback
type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
uinfo->count = 1;
@@ -3651,8 +3643,8 @@ struct _snd_pcm_runtime {
Example of get callback
value.integer.value[0] = get_some_value(chip);
return 0;
}
@@ -3702,8 +3694,7 @@ struct _snd_pcm_runtime {
Here, the chip instance is retrieved via
snd_kcontrol_chip() macro. This macro
- converts from kcontrol->private_data to the type defined by
- chip_t. The
+ just accesses to kcontrol->private_data. The
kcontrol->private_data field is
given as the argument of snd_ctl_new()
(see the later subsection
@@ -3727,8 +3718,8 @@ struct _snd_pcm_runtime {
private_value & 0xff;
int shift = (kcontrol->private_value >> 16) & 0xff;
@@ -3764,10 +3755,10 @@ struct _snd_pcm_runtime {
Example of put callback
current_value !=
ucontrol->value.integer.value[0]) {
@@ -3824,7 +3815,7 @@ struct _snd_pcm_runtime {
where my_control is the
- snd_kcontrol_new_t object defined above, and chip
+ struct snd_kcontrol_new object defined above, and chip
is the object pointer to be passed to
kcontrol->private_data
which can be referred in callbacks.
@@ -3832,7 +3823,7 @@ struct _snd_pcm_runtime {
snd_ctl_new1() allocates a new
- snd_kcontrol_t instance (that's why the definition
+ snd_kcontrol instance (that's why the definition
of my_control can be with
__devinitdata
prefix), and snd_ctl_add assigns the given
@@ -3859,7 +3850,7 @@ struct _snd_pcm_runtime {
control id pointer for the notification. The event-mask
specifies the types of notification, for example, in the above
example, the change of control values is notified.
- The id pointer is the pointer of snd_ctl_elem_id_t
+ The id pointer is the pointer of struct snd_ctl_elem_id
to be notified.
You can find some examples in es1938.c or
es1968.c for hardware volume interrupts.
@@ -3892,35 +3883,35 @@ struct _snd_pcm_runtime {
Example of AC97 Interface
private_data;
+ struct mychip *chip = ac97->private_data;
....
// read a register value here from the codec
return the_register_value;
}
- static void snd_mychip_ac97_write(ac97_t *ac97,
+ static void snd_mychip_ac97_write(struct snd_ac97 *ac97,
unsigned short reg, unsigned short val)
{
- mychip_t *chip = ac97->private_data;
+ struct mychip *chip = ac97->private_data;
....
// write the given register value to the codec
}
- static int snd_mychip_ac97(mychip_t *chip)
+ static int snd_mychip_ac97(struct mychip *chip)
{
- ac97_bus_t *bus;
- ac97_template_t ac97;
+ struct snd_ac97_bus *bus;
+ struct snd_ac97_template ac97;
int err;
- static ac97_bus_ops_t ops = {
+ static struct snd_ac97_bus_ops ops = {
.write = snd_mychip_ac97_write,
.read = snd_mychip_ac97_read,
};
@@ -3947,8 +3938,8 @@ struct _snd_pcm_runtime {
- And then call snd_ac97_mixer() with an ac97_template_t
+ And then call snd_ac97_mixer() with an
+ struct snd_ac97_template
record together with the bus pointer created above.
private_data;
+ struct mychip *chip = ac97->private_data;
....
return the_register_value;
}
@@ -4026,7 +4018,7 @@ struct _snd_pcm_runtime {
@@ -4173,7 +4165,7 @@ struct _snd_pcm_runtime {
Multiple Codecs
When there are several codecs on the same card, you need to
- call snd_ac97_new() multiple times with
+ call snd_ac97_mixer() multiple times with
ac97.num=1 or greater. The num field
specifies the codec
number.
@@ -4222,7 +4214,7 @@ struct _snd_pcm_runtime {
@@ -4263,17 +4255,17 @@ struct _snd_pcm_runtime {
Usually, the port address corresponds to the command port and
port + 1 corresponds to the data port. If not, you may change
the cport field of
- mpu401_t manually
- afterward. However, mpu401_t pointer is not
+ struct snd_mpu401 manually
+ afterward. However, snd_mpu401 pointer is not
returned explicitly by
snd_mpu401_uart_new(). You need to cast
rmidi->private_data to
- mpu401_t explicitly,
+ snd_mpu401 explicitly,
private_data;
]]>
@@ -4369,7 +4361,7 @@ struct _snd_pcm_runtime {
card, "MyMIDI", 0, outs, ins, &rmidi);
if (err < 0)
return err;
@@ -4429,7 +4421,7 @@ struct _snd_pcm_runtime {
streams[SNDRV_RAWMIDI_STREAM_OUTPUT].substreams) {
- substream = list_entry(list, snd_rawmidi_substream_t, list);
+ substream = list_entry(list, struct snd_rawmidi_substream, list);
sprintf(substream->name, "My MIDI Port %d", substream->number + 1);
}
/* same for SNDRV_RAWMIDI_STREAM_INPUT */
@@ -4473,12 +4465,12 @@ struct _snd_pcm_runtime {
If there is more than one port, your callbacks can determine the
- port index from the snd_rawmidi_substream_t data passed to each
+ port index from the struct snd_rawmidi_substream data passed to each
callback:
number;
]]>
@@ -4491,7 +4483,7 @@ struct _snd_pcm_runtime {
@@ -4509,7 +4501,7 @@ struct _snd_pcm_runtime {
@@ -4532,7 +4524,7 @@ struct _snd_pcm_runtime {
@@ -4557,7 +4549,7 @@ struct _snd_pcm_runtime {
@@ -4613,7 +4605,7 @@ struct _snd_pcm_runtime {
@@ -4657,7 +4649,7 @@ struct _snd_pcm_runtime {
@@ -4671,7 +4663,7 @@ struct _snd_pcm_runtime {
This callback is optional. If you do not set
- drain in the snd_rawmidi_ops_t
+ drain in the struct snd_rawmidi_ops
structure, ALSA will simply wait for 50 milliseconds
instead.
@@ -4713,7 +4705,7 @@ struct _snd_pcm_runtime {
@@ -4746,7 +4738,7 @@ struct _snd_pcm_runtime {
@@ -4777,7 +4769,7 @@ struct _snd_pcm_runtime {
@@ -4814,7 +4806,7 @@ struct _snd_pcm_runtime {
@@ -4833,7 +4825,7 @@ struct _snd_pcm_runtime {
private_data = p;
hw->private_free = mydata_free;
]]>
@@ -4845,9 +4837,9 @@ struct _snd_pcm_runtime {
private_data;
+ struct mydata *p = hw->private_data;
kfree(p);
}
]]>
@@ -5071,9 +5063,9 @@ struct _snd_pcm_runtime {
@@ -5154,7 +5146,7 @@ struct _snd_pcm_runtime {
@@ -5214,14 +5206,14 @@ struct _snd_pcm_runtime {
You need to pass the snd_dma_pci_data(pci),
where pci is the struct pci_dev pointer
of the chip as well.
- The snd_sg_buf_t instance is created as
+ The struct snd_sg_buf instance is created as
substream->dma_private. You can cast
the pointer like:
dma_private;
+ struct snd_sg_buf *sgbuf = (struct snd_sg_buf *)substream->dma_private;
]]>
@@ -5276,7 +5268,7 @@ struct _snd_pcm_runtime {
#include
/* get the physical page pointer on the given offset */
- static struct page *mychip_page(snd_pcm_substream_t *substream,
+ static struct page *mychip_page(struct snd_pcm_substream *substream,
unsigned long offset)
{
void *pageptr = substream->runtime->dma_area + offset;
@@ -5311,7 +5303,7 @@ struct _snd_pcm_runtime {
@@ -5355,8 +5347,8 @@ struct _snd_pcm_runtime {
@@ -5371,10 +5363,10 @@ struct _snd_pcm_runtime {
private_data;
+ struct my_chip *chip = entry->private_data;
snd_iprintf(buffer, "This is my chip!\n");
snd_iprintf(buffer, "Port = %ld\n", chip->port);
@@ -5463,7 +5455,7 @@ struct _snd_pcm_runtime {
CONFIG_PM.
+
+ If the driver supports the suspend/resume
+ fully, that is, the device can be
+ properly resumed to the status at the suspend is called,
+ you can set SNDRV_PCM_INFO_RESUME flag
+ to pcm info field. Usually, this is possible when the
+ registers of ths chip can be safely saved and restored to the
+ RAM. If this is set, the trigger callback is called with
+ SNDRV_PCM_TRIGGER_RESUME after resume
+ callback is finished.
+
+
+
+ Even if the driver doesn't support PM fully but only the
+ partial suspend/resume is possible, it's still worthy to
+ implement suspend/resume callbacks. In such a case, applications
+ would reset the status by calling
+ snd_pcm_prepare() and restart the stream
+ appropriately. Hence, you can define suspend/resume callbacks
+ below but don't set SNDRV_PCM_INFO_RESUME
+ info flag to the PCM.
+
+
+
+ Note that the trigger with SUSPEND can be always called when
+ snd_pcm_suspend_all is called,
+ regardless of SNDRV_PCM_INFO_RESUME flag.
+ The RESUME flag affects only the behavior
+ of snd_pcm_resume().
+ (Thus, in theory,
+ SNDRV_PCM_TRIGGER_RESUME isn't needed
+ to be handled in the trigger callback when no
+ SNDRV_PCM_INFO_RESUME flag is set. But,
+ it's better to keep it for compatibility reason.)
+
- ALSA provides the common power-management layer. Each card driver
- needs to have only low-level suspend and resume callbacks.
+ In the earlier version of ALSA drivers, a common
+ power-management layer was provided, but it has been removed.
+ The driver needs to define the suspend/resume hooks according to
+ the bus the device is assigned. In the case of PCI driver, the
+ callbacks look like below:
- Retrieve the chip data from pm_private_data field.
+ Retrieve the card and the chip data.
+ Call snd_power_change_state() with
+ SNDRV_CTL_POWER_D3hot to change the
+ power status.Call snd_pcm_suspend_all() to suspend the running PCM streams.
+ If AC97 codecs are used, call
+ snd_ac97_resume() for each codec.Save the register values if necessary.Stop the hardware if necessary.
- Disable the PCI device by calling pci_disable_device().
+ Disable the PCI device by calling
+ pci_disable_device(). Then, call
+ pci_save_state() at last.
@@ -5540,18 +5577,24 @@ struct _snd_pcm_runtime {
pm_private_data;
+ struct snd_card *card = pci_get_drvdata(pci);
+ struct mychip *chip = card->private_data;
/* (2) */
- snd_pcm_suspend_all(chip->pcm);
+ snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
/* (3) */
- snd_mychip_save_registers(chip);
+ snd_pcm_suspend_all(chip->pcm);
/* (4) */
- snd_mychip_stop_hardware(chip);
+ snd_ac97_suspend(chip->ac97);
/* (5) */
- pci_disable_device(chip->pci);
+ snd_mychip_save_registers(chip);
+ /* (6) */
+ snd_mychip_stop_hardware(chip);
+ /* (7) */
+ pci_disable_device(pci);
+ pci_save_state(pci);
return 0;
}
]]>
@@ -5563,14 +5606,17 @@ struct _snd_pcm_runtime {
The scheme of the real resume job is as following.
- Retrieve the chip data from pm_private_data field.
- Enable the pci device again by calling
- pci_enable_device().
+ Retrieve the card and the chip data.
+ Set up PCI. First, call pci_restore_state().
+ Then enable the pci device again by calling pci_enable_device().
+ Call pci_set_master() if necessary, too.Re-initialize the chip.Restore the saved registers if necessary.Resume the mixer, e.g. calling
snd_ac97_resume().Restart the hardware (if any).
+ Call snd_power_change_state() with
+ SNDRV_CTL_POWER_D0 to notify the processes.
@@ -5580,12 +5626,15 @@ struct _snd_pcm_runtime {
pm_private_data;
+ struct snd_card *card = pci_get_drvdata(pci);
+ struct mychip *chip = card->private_data;
/* (2) */
- pci_enable_device(chip->pci);
+ pci_restore_state(pci);
+ pci_enable_device(pci);
+ pci_set_master(pci);
/* (3) */
snd_mychip_reinit_chip(chip);
/* (4) */
@@ -5594,6 +5643,8 @@ struct _snd_pcm_runtime {
snd_ac97_resume(chip->ac97);
/* (6) */
snd_mychip_restart_chip(chip);
+ /* (7) */
+ snd_power_change_state(card, SNDRV_CTL_POWER_D0);
return 0;
}
]]>
@@ -5602,8 +5653,23 @@ struct _snd_pcm_runtime {
- OK, we have all callbacks now. Let's set up them now. In the
- initialization of the card, add the following:
+ As shown in the above, it's better to save registers after
+ suspending the PCM operations via
+ snd_pcm_suspend_all() or
+ snd_pcm_suspend(). It means that the PCM
+ streams are already stoppped when the register snapshot is
+ taken. But, remind that you don't have to restart the PCM
+ stream in the resume callback. It'll be restarted via
+ trigger call with SNDRV_PCM_TRIGGER_RESUME
+ when necessary.
+
+
+
+ OK, we have all callbacks now. Let's set them up. In the
+ initialization of the card, make sure that you can get the chip
+ data from the card instance, typically via
+ private_data field, in case you
+ created the chip data individually.
@@ -5612,33 +5678,56 @@ struct _snd_pcm_runtime {
const struct pci_device_id *pci_id)
{
....
- snd_card_t *card;
- mychip_t *chip;
+ struct snd_card *card;
+ struct mychip *chip;
+ ....
+ card = snd_card_new(index[dev], id[dev], THIS_MODULE, NULL);
....
- snd_card_set_pm_callback(card, snd_my_suspend, snd_my_resume, chip);
+ chip = kzalloc(sizeof(*chip), GFP_KERNEL);
+ ....
+ card->private_data = chip;
+ ....
+ }
+]]>
+
+
+
+ When you created the chip data with
+ snd_card_new(), it's anyway accessible
+ via private_data field.
+
+
+
+private_data;
....
}
]]>
- Here you don't have to put ifdef CONFIG_PM around, since it's already
- checked in the header and expanded to empty if not needed.
- If you need a space for saving the registers, you'll need to
- allocate the buffer for it here, too, since it would be fatal
+ If you need a space for saving the registers, allocate the
+ buffer for it here, too, since it would be fatal
if you cannot allocate a memory in the suspend phase.
The allocated buffer should be released in the corresponding
destructor.
- And next, set suspend/resume callbacks to the pci_driver,
- This can be done by passing a macro SND_PCI_PM_CALLBACKS
- in the pci_driver struct. This macro is expanded to the correct
- (global) callbacks if CONFIG_PM is set.
+ And next, set suspend/resume callbacks to the pci_driver.
@@ -5648,7 +5737,10 @@ struct _snd_pcm_runtime {
.id_table = snd_my_ids,
.probe = snd_my_probe,
.remove = __devexit_p(snd_my_remove),
- SND_PCI_PM_CALLBACKS
+ #ifdef CONFIG_PM
+ .suspend = snd_my_suspend,
+ .resume = snd_my_resume,
+ #endif
};
]]>
@@ -5991,32 +6083,23 @@ struct _snd_pcm_runtime {
The first argument is the expression to evaluate, and the
second argument is the action if it fails. When
CONFIG_SND_DEBUG, is set, it will show an
- error message such as BUG? (xxx) (called from
- yyy). When no debug flag is set, this is
- ignored.
+ error message such as BUG? (xxx)
+ together with stack trace.
-
-
-
- snd_runtime_check()
- This macro is quite similar with
- snd_assert(). Unlike
- snd_assert(), the expression is always
- evaluated regardless of
- CONFIG_SND_DEBUG. When
- CONFIG_SND_DEBUG is set, the macro will
- show a message like ERROR (xx) (called from
- yyy).
+ When no debug flag is set, this macro is ignored.
snd_BUG()
- It calls snd_assert(0,) -- that is, just
- prints the error message at the point. It's useful to show that
- a fatal error happens there.
+ It shows BUG? message and
+ stack trace as well as snd_assert at the point.
+ It's useful to show that a fatal error happens there.
+
+
+ When no debug flag is set, this macro is ignored.