<informalexample>
<programlisting>
<![CDATA[
- struct mychip *chip = (struct mychip *)card->private_data;
+ struct mychip *chip = card->private_data;
]]>
</programlisting>
</informalexample>
<para>
For a device which allows hotplugging, you can use
- <function>snd_card_free_in_thread</function>. This one will
- postpone the destruction and wait in a kernel-thread until all
- devices are closed.
+ <function>snd_card_free_when_closed</function>. This one will
+ postpone the destruction until all devices are closed.
</para>
</section>
/* release the irq */
if (chip->irq >= 0)
- free_irq(chip->irq, (void *)chip);
+ free_irq(chip->irq, chip);
/* release the i/o ports & memory */
pci_release_regions(chip->pci);
/* disable the PCI entry */
if ((err = pci_enable_device(pci)) < 0)
return err;
/* check PCI availability (28bit DMA) */
- if (pci_set_dma_mask(pci, 0x0fffffff) < 0 ||
- pci_set_consistent_dma_mask(pci, 0x0fffffff) < 0) {
+ if (pci_set_dma_mask(pci, DMA_28BIT_MASK) < 0 ||
+ pci_set_consistent_dma_mask(pci, DMA_28BIT_MASK) < 0) {
printk(KERN_ERR "error to set 28bit mask DMA\n");
pci_disable_device(pci);
return -ENXIO;
}
chip->port = pci_resource_start(pci, 0);
if (request_irq(pci->irq, snd_mychip_interrupt,
- SA_INTERRUPT|SA_SHIRQ, "My Chip", chip)) {
+ IRQF_SHARED, "My Chip", chip)) {
printk(KERN_ERR "cannot grab irq %d\n", pci->irq);
snd_mychip_free(chip);
return -EBUSY;
The allocation of PCI resources is done in the
<function>probe()</function> function, and usually an extra
<function>xxx_create()</function> function is written for this
- purpose.
+ purpose.
</para>
<para>
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 <function>pci_set_master()</function> function,
- too.
+ too.
</para>
<para>
<![CDATA[
if ((err = pci_enable_device(pci)) < 0)
return err;
- if (pci_set_dma_mask(pci, 0x0fffffff) < 0 ||
- pci_set_consistent_dma_mask(pci, 0x0fffffff) < 0) {
+ if (pci_set_dma_mask(pci, DMA_28BIT_MASK) < 0 ||
+ pci_set_consistent_dma_mask(pci, DMA_28BIT_MASK) < 0) {
printk(KERN_ERR "error to set 28bit mask DMA\n");
pci_disable_device(pci);
return -ENXIO;
functions. Unlike ALSA ver.0.5.x., there are no helpers for
that. And these resources must be released in the destructor
function (see below). Also, on ALSA 0.9.x, you don't need to
- allocate (pseudo-)DMA for PCI like ALSA 0.5.x.
+ allocate (pseudo-)DMA for PCI like ALSA 0.5.x.
</para>
<para>
Now assume that this PCI device has an I/O port with 8 bytes
and an interrupt. Then struct <structname>mychip</structname> will have the
- following fields:
+ following fields:
<informalexample>
<programlisting>
<programlisting>
<![CDATA[
if (request_irq(pci->irq, snd_mychip_interrupt,
- SA_INTERRUPT|SA_SHIRQ, "My Chip", chip)) {
+ IRQF_DISABLED|IRQF_SHARED, "My Chip", chip)) {
printk(KERN_ERR "cannot grab irq %d\n", pci->irq);
snd_mychip_free(chip);
return -EBUSY;
<para>
On the PCI bus, the interrupts can be shared. Thus,
- <constant>SA_SHIRQ</constant> is given as the interrupt flag of
+ <constant>IRQF_SHARED</constant> is given as the interrupt flag of
<function>request_irq()</function>.
</para>
<programlisting>
<![CDATA[
if (chip->irq >= 0)
- free_irq(chip->irq, (void *)chip);
+ free_irq(chip->irq, chip);
]]>
</programlisting>
</informalexample>
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;
<para>
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.
</para>
<para>
</para>
<para>
- If you aquire a spinlock in the interrupt handler, and the
+ If you acquire a spinlock in the interrupt handler, and the
lock is used in other pcm callbacks, too, then you have to
release the lock before calling
<function>snd_pcm_period_elapsed()</function>, because
.name = "PCM Playback Switch",
.index = 0,
.access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
- .private_values = 0xffff,
+ .private_value = 0xffff,
.info = my_control_info,
.get = my_control_get,
.put = my_control_put
</para>
<para>
- The <structfield>private_values</structfield> field contains
+ The <structfield>private_value</structfield> field contains
an arbitrary long integer value for this record. When using
generic <structfield>info</structfield>,
<structfield>get</structfield> and
<programlisting>
<![CDATA[
struct snd_rawmidi *rmidi;
- snd_mpu401_uart_new(card, 0, MPU401_HW_MPU401, port, integrated,
+ snd_mpu401_uart_new(card, 0, MPU401_HW_MPU401, port, info_flags,
irq, irq_flags, &rmidi);
]]>
</programlisting>
</para>
<para>
+ The 5th argument is bitflags for additional information.
When the i/o port address above is a part of the PCI i/o
region, the MPU401 i/o port might have been already allocated
- (reserved) by the driver itself. In such a case, pass non-zero
- to the 5th argument
- (<parameter>integrated</parameter>). Otherwise, pass 0 to it,
+ (reserved) by the driver itself. In such a case, pass a bit flag
+ <constant>MPU401_INFO_INTEGRATED</constant>,
and
the mpu401-uart layer will allocate the i/o ports by itself.
</para>
+ <para>
+ When the controller supports only the input or output MIDI stream,
+ pass <constant>MPU401_INFO_INPUT</constant> or
+ <constant>MPU401_INFO_OUTPUT</constant> bitflag, respectively.
+ Then the rawmidi instance is created as a single stream.
+ </para>
+
+ <para>
+ <constant>MPU401_INFO_MMIO</constant> bitflag is used to change
+ the access method to MMIO (via readb and writeb) instead of
+ iob and outb. In this case, you have to pass the iomapped address
+ to <function>snd_mpu401_uart_new()</function>.
+ </para>
+
+ <para>
+ When <constant>MPU401_INFO_TX_IRQ</constant> is set, the output
+ stream isn't checked in the default interrupt handler. The driver
+ needs to call <function>snd_mpu401_uart_interrupt_tx()</function>
+ by itself to start processing the output stream in irq handler.
+ </para>
+
<para>
Usually, the port address corresponds to the command port and
port + 1 corresponds to the data port. If not, you may change
<informalexample>
<programlisting>
<![CDATA[
- snd_info_set_text_ops(entry, chip, read_size, my_proc_read);
+ snd_info_set_text_ops(entry, chip, my_proc_read);
]]>
</programlisting>
</informalexample>
<informalexample>
<programlisting>
<![CDATA[
- entry->c.text.write_size = 256;
entry->c.text.write = my_proc_write;
]]>
</programlisting>
</informalexample>
</para>
- <para>
- The buffer size for read is set to 1024 implicitly by
- <function>snd_info_set_text_ops()</function>. It should suffice
- in most cases (the size will be aligned to
- <constant>PAGE_SIZE</constant> anyway), but if you need to handle
- very large text files, you can set it explicitly, too.
-
- <informalexample>
- <programlisting>
-<![CDATA[
- entry->c.text.read_size = 65536;
-]]>
- </programlisting>
- </informalexample>
- </para>
-
<para>
For the write callback, you can use
<function>snd_info_get_line()</function> to get a text line, and
<chapter id="power-management">
<title>Power Management</title>
<para>
- If the chip is supposed to work with with suspend/resume
+ If the chip is supposed to work with suspend/resume
functions, you need to add the power-management codes to the
driver. The additional codes for the power-management should be
<function>ifdef</function>'ed with
power status.</para></listitem>
<listitem><para>Call <function>snd_pcm_suspend_all()</function> to suspend the running PCM streams.</para></listitem>
<listitem><para>If AC97 codecs are used, call
- <function>snd_ac97_resume()</function> for each codec.</para></listitem>
+ <function>snd_ac97_suspend()</function> for each codec.</para></listitem>
<listitem><para>Save the register values if necessary.</para></listitem>
<listitem><para>Stop the hardware if necessary.</para></listitem>
<listitem><para>Disable the PCI device by calling